Merge
authorcoleenp
Thu, 18 Oct 2012 12:29:56 -0400
changeset 14084 0c5d0a560e8e
parent 14077 a7060dec741b (current diff)
parent 14083 103054a71a30 (diff)
child 14085 57dfd29e4742
Merge
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Thu Oct 18 12:29:56 2012 -0400
@@ -67,7 +67,7 @@
 
 #define JAVA_CLASSFILE_MAGIC              0xCAFEBABE
 #define JAVA_MIN_SUPPORTED_VERSION        45
-#define JAVA_MAX_SUPPORTED_VERSION        51
+#define JAVA_MAX_SUPPORTED_VERSION        52
 #define JAVA_MAX_SUPPORTED_MINOR_VERSION  0
 
 // Used for two backward compatibility reasons:
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Thu Oct 18 12:29:56 2012 -0400
@@ -413,8 +413,7 @@
 }
 
 bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
-  assert(SharedSkipVerify ||
-         java_string->klass() == SystemDictionary::String_klass(),
+  assert(java_string->klass() == SystemDictionary::String_klass(),
          "must be java_string");
   typeArrayOop value  = java_lang_String::value(java_string);
   int          offset = java_lang_String::offset(java_string);
--- a/hotspot/src/share/vm/memory/allocation.cpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/memory/allocation.cpp	Thu Oct 18 12:29:56 2012 -0400
@@ -92,6 +92,26 @@
   return res;
 }
 
+void* ResourceObj::operator new(size_t size, const std::nothrow_t&  nothrow_constant,
+    allocation_type type, MEMFLAGS flags) {
+  //should only call this with std::nothrow, use other operator new() otherwise
+  address res;
+  switch (type) {
+   case C_HEAP:
+    res = (address)AllocateHeap(size, flags, CALLER_PC, AllocFailStrategy::RETURN_NULL);
+    DEBUG_ONLY(if (res!= NULL) set_allocation_type(res, C_HEAP);)
+    break;
+   case RESOURCE_AREA:
+    // new(size) sets allocation type RESOURCE_AREA.
+    res = (address)operator new(size, std::nothrow);
+    break;
+   default:
+    ShouldNotReachHere();
+  }
+  return res;
+}
+
+
 void ResourceObj::operator delete(void* p) {
   assert(((ResourceObj *)p)->allocated_on_C_heap(),
          "delete only allowed for C_HEAP objects");
@@ -506,7 +526,7 @@
 }
 
 // Grow a new Chunk
-void* Arena::grow( size_t x ) {
+void* Arena::grow(size_t x, AllocFailType alloc_failmode) {
   // Get minimal required size.  Either real big, or even bigger for giant objs
   size_t len = MAX2(x, (size_t) Chunk::size);
 
@@ -514,7 +534,10 @@
   _chunk = new (len) Chunk(len);
 
   if (_chunk == NULL) {
-    signal_out_of_memory(len * Chunk::aligned_overhead_size(), "Arena::grow");
+    if (alloc_failmode == AllocFailStrategy::EXIT_OOM) {
+      signal_out_of_memory(len * Chunk::aligned_overhead_size(), "Arena::grow");
+    }
+    return NULL;
   }
   if (k) k->set_next(_chunk);   // Append new chunk to end of linked list
   else _first = _chunk;
@@ -529,13 +552,16 @@
 
 
 // Reallocate storage in Arena.
-void *Arena::Arealloc(void* old_ptr, size_t old_size, size_t new_size) {
+void *Arena::Arealloc(void* old_ptr, size_t old_size, size_t new_size, AllocFailType alloc_failmode) {
   assert(new_size >= 0, "bad size");
   if (new_size == 0) return NULL;
 #ifdef ASSERT
   if (UseMallocOnly) {
     // always allocate a new object  (otherwise we'll free this one twice)
-    char* copy = (char*)Amalloc(new_size);
+    char* copy = (char*)Amalloc(new_size, alloc_failmode);
+    if (copy == NULL) {
+      return NULL;
+    }
     size_t n = MIN2(old_size, new_size);
     if (n > 0) memcpy(copy, old_ptr, n);
     Afree(old_ptr,old_size);    // Mostly done to keep stats accurate
@@ -561,7 +587,10 @@
   }
 
   // Oops, got to relocate guts
-  void *new_ptr = Amalloc(new_size);
+  void *new_ptr = Amalloc(new_size, alloc_failmode);
+  if (new_ptr == NULL) {
+    return NULL;
+  }
   memcpy( new_ptr, c_old, old_size );
   Afree(c_old,old_size);        // Mostly done to keep stats accurate
   return new_ptr;
--- a/hotspot/src/share/vm/memory/allocation.hpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/memory/allocation.hpp	Thu Oct 18 12:29:56 2012 -0400
@@ -53,6 +53,12 @@
   #endif
 #endif
 
+class AllocFailStrategy {
+public:
+  enum AllocFailEnum { EXIT_OOM, RETURN_NULL };
+};
+typedef AllocFailStrategy::AllocFailEnum AllocFailType;
+
 // All classes in the virtual machine must be subclassed
 // by one of the following allocation classes:
 //
@@ -315,7 +321,8 @@
   Chunk *_first;                // First chunk
   Chunk *_chunk;                // current chunk
   char *_hwm, *_max;            // High water mark and max in current chunk
-  void* grow(size_t x);         // Get a new Chunk of at least size x
+  // Get a new Chunk of at least size x
+  void* grow(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
   size_t _size_in_bytes;        // Size of arena (used for native memory tracking)
 
   NOT_PRODUCT(static julong _bytes_allocated;) // total #bytes allocated since start
@@ -350,14 +357,14 @@
   void  operator delete(void* p);
 
   // Fast allocate in the arena.  Common case is: pointer test + increment.
-  void* Amalloc(size_t x) {
+  void* Amalloc(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
     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);
+      return grow(x, alloc_failmode);
     } else {
       char *old = _hwm;
       _hwm += x;
@@ -365,13 +372,13 @@
     }
   }
   // Further assume size is padded out to words
-  void *Amalloc_4(size_t x) {
+  void *Amalloc_4(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
     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);
+      return grow(x, alloc_failmode);
     } else {
       char *old = _hwm;
       _hwm += x;
@@ -381,7 +388,7 @@
 
   // Allocate with 'double' alignment. It is 8 bytes on sparc.
   // In other cases Amalloc_D() should be the same as Amalloc_4().
-  void* Amalloc_D(size_t x) {
+  void* Amalloc_D(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
     assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" );
     debug_only(if (UseMallocOnly) return malloc(x);)
 #if defined(SPARC) && !defined(_LP64)
@@ -392,7 +399,7 @@
     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.
+      return grow(x, alloc_failmode); // grow() returns a result aligned >= 8 bytes.
     } else {
       char *old = _hwm;
       _hwm += x;
@@ -412,7 +419,8 @@
     if (((char*)ptr) + size == _hwm) _hwm = (char*)ptr;
   }
 
-  void *Arealloc( void *old_ptr, size_t old_size, size_t new_size );
+  void *Arealloc( void *old_ptr, size_t old_size, size_t new_size,
+      AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
 
   // Move contents of this arena into an empty arena
   Arena *move_contents(Arena *empty_arena);
@@ -458,9 +466,12 @@
 
 
 //%note allocation_1
-extern char* resource_allocate_bytes(size_t size);
-extern char* resource_allocate_bytes(Thread* thread, size_t size);
-extern char* resource_reallocate_bytes( char *old, size_t old_size, size_t new_size);
+extern char* resource_allocate_bytes(size_t size,
+    AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
+extern char* resource_allocate_bytes(Thread* thread, size_t size,
+    AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
+extern char* resource_reallocate_bytes( char *old, size_t old_size, size_t new_size,
+    AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
 extern void resource_free_bytes( char *old, size_t size );
 
 //----------------------------------------------------------------------
@@ -496,6 +507,8 @@
 
  public:
   void* operator new(size_t size, allocation_type type, MEMFLAGS flags);
+  void* operator new(size_t size, const std::nothrow_t&  nothrow_constant,
+      allocation_type type, MEMFLAGS flags);
   void* operator new(size_t size, Arena *arena) {
       address res = (address)arena->Amalloc(size);
       DEBUG_ONLY(set_allocation_type(res, ARENA);)
@@ -506,6 +519,13 @@
       DEBUG_ONLY(set_allocation_type(res, RESOURCE_AREA);)
       return res;
   }
+
+  void* operator new(size_t size, const std::nothrow_t& nothrow_constant) {
+      address res = (address)resource_allocate_bytes(size, AllocFailStrategy::RETURN_NULL);
+      DEBUG_ONLY(if (res != NULL) set_allocation_type(res, RESOURCE_AREA);)
+      return res;
+  }
+
   void  operator delete(void* p);
 };
 
--- a/hotspot/src/share/vm/memory/allocation.inline.hpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/memory/allocation.inline.hpp	Thu Oct 18 12:29:56 2012 -0400
@@ -48,7 +48,8 @@
 #endif
 
 // allocate using malloc; will fail if no memory available
-inline char* AllocateHeap(size_t size, MEMFLAGS flags, address pc = 0) {
+inline char* AllocateHeap(size_t size, MEMFLAGS flags, address pc = 0,
+    AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
   if (pc == 0) {
     pc = CURRENT_PC;
   }
@@ -56,16 +57,17 @@
   #ifdef ASSERT
   if (PrintMallocFree) trace_heap_malloc(size, "AllocateHeap", p);
   #endif
-  if (p == NULL) vm_exit_out_of_memory(size, "AllocateHeap");
+  if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) vm_exit_out_of_memory(size, "AllocateHeap");
   return p;
 }
 
-inline char* ReallocateHeap(char *old, size_t size, MEMFLAGS flags) {
+inline char* ReallocateHeap(char *old, size_t size, MEMFLAGS flags,
+    AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
   char* p = (char*) os::realloc(old, size, flags, CURRENT_PC);
   #ifdef ASSERT
   if (PrintMallocFree) trace_heap_malloc(size, "ReallocateHeap", p);
   #endif
-  if (p == NULL) vm_exit_out_of_memory(size, "ReallocateHeap");
+  if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) vm_exit_out_of_memory(size, "ReallocateHeap");
   return p;
 }
 
@@ -91,11 +93,13 @@
 template <MEMFLAGS F> void* CHeapObj<F>::operator new (size_t size,
   const std::nothrow_t&  nothrow_constant, address caller_pc) {
 #ifdef ASSERT
-    void* p = os::malloc(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC));
+  void* p = (void*)AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC),
+      AllocFailStrategy::RETURN_NULL);
     if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p);
     return p;
 #else
-    return os::malloc(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC));
+  return (void *) AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC),
+      AllocFailStrategy::RETURN_NULL);
 #endif
 }
 
--- a/hotspot/src/share/vm/memory/resourceArea.cpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/memory/resourceArea.cpp	Thu Oct 18 12:29:56 2012 -0400
@@ -45,15 +45,15 @@
 // The following routines are declared in allocation.hpp and used everywhere:
 
 // Allocation in thread-local resource area
-extern char* resource_allocate_bytes(size_t size) {
-  return Thread::current()->resource_area()->allocate_bytes(size);
+extern char* resource_allocate_bytes(size_t size, AllocFailType alloc_failmode) {
+  return Thread::current()->resource_area()->allocate_bytes(size, alloc_failmode);
 }
-extern char* resource_allocate_bytes(Thread* thread, size_t size) {
-  return thread->resource_area()->allocate_bytes(size);
+extern char* resource_allocate_bytes(Thread* thread, size_t size, AllocFailType alloc_failmode) {
+  return thread->resource_area()->allocate_bytes(size, alloc_failmode);
 }
 
-extern char* resource_reallocate_bytes( char *old, size_t old_size, size_t new_size){
-  return (char*)Thread::current()->resource_area()->Arealloc(old, old_size, new_size);
+extern char* resource_reallocate_bytes( char *old, size_t old_size, size_t new_size, AllocFailType alloc_failmode){
+  return (char*)Thread::current()->resource_area()->Arealloc(old, old_size, new_size, alloc_failmode);
 }
 
 extern void resource_free_bytes( char *old, size_t size ) {
--- a/hotspot/src/share/vm/memory/resourceArea.hpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/memory/resourceArea.hpp	Thu Oct 18 12:29:56 2012 -0400
@@ -68,7 +68,7 @@
     debug_only(_nesting = 0;);
   }
 
-  char* allocate_bytes(size_t size) {
+  char* allocate_bytes(size_t size, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
 #ifdef ASSERT
     if (_nesting < 1 && !_warned++)
       fatal("memory leak: allocating without ResourceMark");
@@ -78,7 +78,7 @@
       return (*save = (char*)os::malloc(size, mtThread));
     }
 #endif
-    return (char*)Amalloc(size);
+    return (char*)Amalloc(size, alloc_failmode);
   }
 
   debug_only(int nesting() const { return _nesting; });
--- a/hotspot/src/share/vm/memory/universe.cpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/memory/universe.cpp	Thu Oct 18 12:29:56 2012 -0400
@@ -1268,10 +1268,6 @@
 }
 
 void Universe::verify(bool silent, VerifyOption option) {
-  if (SharedSkipVerify) {
-    return;
-  }
-
   // The use of _verify_in_progress is a temporary work around for
   // 6320749.  Don't bother with a creating a class to set and clear
   // it since it is only used in this method and the control flow is
--- a/hotspot/src/share/vm/oops/klass.cpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/oops/klass.cpp	Thu Oct 18 12:29:56 2012 -0400
@@ -356,12 +356,11 @@
 }
 
 void Klass::append_to_sibling_list() {
-  debug_only(if (!SharedSkipVerify) verify();)
+  debug_only(verify();)
   // add ourselves to superklass' subklass list
   InstanceKlass* super = superklass();
   if (super == NULL) return;        // special case: class Object
-  assert(SharedSkipVerify ||
-         (!super->is_interface()    // interfaces cannot be supers
+  assert((!super->is_interface()    // interfaces cannot be supers
           && (super->superklass() == NULL || !is_interface())),
          "an interface can only be a subklass of Object");
   Klass* prev_first_subklass = super->subklass_oop();
@@ -371,7 +370,7 @@
   }
   // make ourselves the superklass' first subklass
   super->set_subklass(this);
-  debug_only(if (!SharedSkipVerify) verify();)
+  debug_only(verify();)
 }
 
 void Klass::remove_from_sibling_list() {
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Thu Oct 18 12:29:56 2012 -0400
@@ -1135,7 +1135,7 @@
 
     // get offset and field value
     int offset = field->field_offset();
-    address addr = (address)klass + offset;
+    address addr = (address)klass->java_mirror() + offset;
     jvalue value;
     copy_to_jvalue(&value, addr, value_type);
 
--- a/hotspot/src/share/vm/runtime/globals.hpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Thu Oct 18 12:29:56 2012 -0400
@@ -3539,10 +3539,6 @@
   product(uintx, SharedDummyBlockSize, 0,                                   \
           "Size of dummy block used to shift heap addresses (in bytes)")    \
                                                                             \
-  diagnostic(bool, SharedSkipVerify, false,                                 \
-          "Skip assert() and verify() which page-in unwanted shared "       \
-          "objects. ")                                                      \
-                                                                            \
   diagnostic(bool, EnableInvokeDynamic, true,                               \
           "support JSR 292 (method handles, invokedynamic, "                \
           "anonymous classes")                                              \
--- a/hotspot/src/share/vm/runtime/handles.cpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/runtime/handles.cpp	Thu Oct 18 12:29:56 2012 -0400
@@ -48,7 +48,7 @@
 oop* HandleArea::allocate_handle(oop obj) {
   assert(_handle_mark_nesting > 1, "memory leak: allocating handle outside HandleMark");
   assert(_no_handle_mark_nesting == 0, "allocating handle inside NoHandleMark");
-  assert(SharedSkipVerify || obj->is_oop(), "sanity check");
+  assert(obj->is_oop(), "sanity check");
   return real_allocate_handle(obj);
 }
 
--- a/hotspot/src/share/vm/runtime/handles.hpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/runtime/handles.hpp	Thu Oct 18 12:29:56 2012 -0400
@@ -110,11 +110,11 @@
     /* Constructors */                           \
     type##Handle ()                              : Handle()                 {} \
     type##Handle (type##Oop obj) : Handle((oop)obj) {                         \
-      assert(SharedSkipVerify || is_null() || ((oop)obj)->is_a(),             \
+      assert(is_null() || ((oop)obj)->is_a(),                                 \
              "illegal type");                                                 \
     }                                                                         \
     type##Handle (Thread* thread, type##Oop obj) : Handle(thread, (oop)obj) { \
-      assert(SharedSkipVerify || is_null() || ((oop)obj)->is_a(), "illegal type");  \
+      assert(is_null() || ((oop)obj)->is_a(), "illegal type");                \
     }                                                                         \
     \
     /* Operators for ease of use */              \
@@ -201,11 +201,11 @@
   /* Constructors */
   instanceKlassHandle () : KlassHandle() {}
   instanceKlassHandle (const Klass* k) : KlassHandle(k) {
-    assert(SharedSkipVerify || k == NULL || k->oop_is_instance(),
+    assert(k == NULL || k->oop_is_instance(),
            "illegal type");
   }
   instanceKlassHandle (Thread* thread, const Klass* k) : KlassHandle(thread, k) {
-    assert(SharedSkipVerify || k == NULL || k->oop_is_instance(),
+    assert(k == NULL || k->oop_is_instance(),
            "illegal type");
   }
   /* Access to klass part */
--- a/hotspot/src/share/vm/runtime/thread.cpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Thu Oct 18 12:29:56 2012 -0400
@@ -177,7 +177,8 @@
     const int alignment = markOopDesc::biased_lock_alignment;
     size_t aligned_size = size + (alignment - sizeof(intptr_t));
     void* real_malloc_addr = throw_excpt? AllocateHeap(aligned_size, flags, CURRENT_PC)
-                                          : os::malloc(aligned_size, flags, CURRENT_PC);
+                                          : AllocateHeap(aligned_size, flags, CURRENT_PC,
+                                              AllocFailStrategy::RETURN_NULL);
     void* aligned_addr     = (void*) align_size_up((intptr_t) real_malloc_addr, alignment);
     assert(((uintptr_t) aligned_addr + (uintptr_t) size) <=
            ((uintptr_t) real_malloc_addr + (uintptr_t) aligned_size),
@@ -191,7 +192,7 @@
     return aligned_addr;
   } else {
     return throw_excpt? AllocateHeap(size, flags, CURRENT_PC)
-                       : os::malloc(size, flags, CURRENT_PC);
+                       : AllocateHeap(size, flags, CURRENT_PC, AllocFailStrategy::RETURN_NULL);
   }
 }
 
--- a/hotspot/src/share/vm/runtime/thread.hpp	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/src/share/vm/runtime/thread.hpp	Thu Oct 18 12:29:56 2012 -0400
@@ -110,7 +110,7 @@
   void*       _real_malloc_address;
  public:
   void* operator new(size_t size) { return allocate(size, true); }
-  void* operator new(size_t size, std::nothrow_t& nothrow_constant) { return allocate(size, false); }
+  void* operator new(size_t size, const std::nothrow_t& nothrow_constant) { return allocate(size, false); }
   void  operator delete(void* p);
 
  protected:
--- a/hotspot/test/runtime/6929067/Test6929067.sh	Wed Oct 17 13:59:57 2012 -0700
+++ b/hotspot/test/runtime/6929067/Test6929067.sh	Thu Oct 18 12:29:56 2012 -0400
@@ -4,6 +4,7 @@
 ## @test Test6929067.sh
 ## @bug 6929067
 ## @summary Stack guard pages should be removed when thread is detached
+## @compile T.java
 ## @run shell Test6929067.sh
 ##
 
@@ -33,31 +34,97 @@
     ;;
 esac
 
-# Choose arch: i386 or amd64 (test is Linux-specific)
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Xinternalversion > vm_version.out 2>&1 
+
+# Bitness:
 # Cannot simply look at TESTVMOPTS as -d64 is not
 # passed if there is only a 64-bit JVM available.
 
-${TESTJAVA}/bin/java ${TESTVMOPTS} -version 2>1 | grep "64-Bit" >/dev/null
+grep "64-Bit" vm_version.out > ${NULL}
 if [ "$?" = "0" ]
 then
-  ARCH=amd64
+  COMP_FLAG="-m64"
 else
-  ARCH=i386
+  COMP_FLAG="-m32"
 fi
 
-LD_LIBRARY_PATH=.:${TESTJAVA}/jre/lib/${ARCH}/client:/usr/openwin/lib:/usr/dt/lib:/usr/lib:$LD_LIBRARY_PATH
+
+# Architecture:
+# Translate uname output to JVM directory name, but permit testing
+# 32-bit x86 on an x64 platform.
+ARCH=`uname -m`
+case "$ARCH" in
+  x86_64)
+    if [ "$COMP_FLAG" = "-m32" ]; then
+      ARCH=i386
+    else 
+      ARCH=amd64
+    fi
+    ;;
+  ppc64)
+    if [ "$COMP_FLAG" = "-m32" ]; then
+      ARCH=ppc
+    else 
+      ARCH=ppc64
+    fi
+    ;;
+  sparc64)
+    if [ "$COMP_FLAG" = "-m32" ]; then
+      ARCH=sparc
+    else 
+      ARCH=sparc64
+    fi
+    ;;
+  arm*)
+    # 32-bit ARM machine: compiler may not recognise -m32
+    COMP_FLAG=""
+    ARCH=arm
+    ;;
+  aarch64)
+    # 64-bit arm machine, could be testing 32 or 64-bit:
+    if [ "$COMP_FLAG" = "-m32" ]; then
+      ARCH=arm
+    else 
+      ARCH=aarch64
+    fi
+    ;;
+  i586)
+    ARCH=i386
+    ;;
+  i686)
+    ARCH=i386
+    ;;
+  # Assuming other ARCH values need no translation
+esac
+
+
+# VM type: need to know server or client
+VMTYPE=client
+grep Server vm_version.out > ${NULL}
+if [ "$?" = "0" ]
+then
+  VMTYPE=server
+fi
+
+
+LD_LIBRARY_PATH=.:${TESTJAVA}/jre/lib/${ARCH}/${VMTYPE}:/usr/lib:$LD_LIBRARY_PATH
 export LD_LIBRARY_PATH
 
-THIS_DIR=`pwd`
+cp ${TESTSRC}${FS}invoke.c .
 
-cp ${TESTSRC}${FS}invoke.c ${THIS_DIR}
-cp ${TESTSRC}${FS}T.java ${THIS_DIR}
-
+# Copy the result of our @compile action:
+cp ${TESTCLASSES}${FS}T.class .
 
 ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -fullversion
 
-${TESTJAVA}${FS}bin${FS}javac T.java
+echo "Architecture: ${ARCH}"
+echo "Compilation flag: ${COMP_FLAG}"
+echo "VM type: ${VMTYPE}"
 
-gcc -o invoke -I${TESTJAVA}/include -I${TESTJAVA}/include/linux invoke.c ${TESTJAVA}/jre/lib/${ARCH}/client/libjvm.so
+gcc -DLINUX ${COMP_FLAG} -o invoke \
+  -I${TESTJAVA}/include -I${TESTJAVA}/include/linux \
+  -L${TESTJAVA}/jre/lib/${ARCH}/${VMTYPE} \
+  -ljvm -lpthread invoke.c
+
 ./invoke
 exit $?