Merge

Mon, 27 Jul 2009 06:15:29 -0700

author
twisti
date
Mon, 27 Jul 2009 06:15:29 -0700
changeset 1331
1cef5ec3ca56
parent 1330
94b6d06fd759
parent 1329
665be97e8704
child 1332
52898b0c43e9

Merge

src/share/vm/opto/library_call.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/.hgtags	Mon Jul 20 08:20:00 2009 -0700
     1.2 +++ b/.hgtags	Mon Jul 27 06:15:29 2009 -0700
     1.3 @@ -37,3 +37,5 @@
     1.4  a77eddcd510c3972717c025cfcef9a60bfa4ecac jdk7-b60
     1.5  27b728fd1281ab62e9d7e4424f8bbb6ca438d803 jdk7-b61
     1.6  a88386380bdaaa5ab4ffbedf22c57bac5dbec034 jdk7-b62
     1.7 +32c83fb84370a35344676991a48440378e6b6c8a jdk7-b63
     1.8 +ba36394eb84b949b31212bdb32a518a8f92bab5b jdk7-b64
     2.1 --- a/agent/make/saenv.sh	Mon Jul 20 08:20:00 2009 -0700
     2.2 +++ b/agent/make/saenv.sh	Mon Jul 27 06:15:29 2009 -0700
     2.3 @@ -48,6 +48,8 @@
     2.4       CPU=i386
     2.5     fi
     2.6  else
     2.7 +   LD_AUDIT_32=$STARTDIR/../src/os/solaris/proc/`uname -p`/libsaproc_audit.so
     2.8 +   export LD_AUDIT_32
     2.9     SA_LIBPATH=$STARTDIR/../src/os/solaris/proc/`uname -p`:$STARTDIR/solaris/`uname -p`
    2.10     OPTIONS="-Dsa.library.path=$SA_LIBPATH -Dsun.jvm.hotspot.debugger.useProcDebugger"
    2.11     CPU=sparc
     3.1 --- a/agent/make/saenv64.sh	Mon Jul 20 08:20:00 2009 -0700
     3.2 +++ b/agent/make/saenv64.sh	Mon Jul 27 06:15:29 2009 -0700
     3.3 @@ -43,6 +43,8 @@
     3.4    fi
     3.5  fi
     3.6  
     3.7 +LD_AUDIT_64=$STARTDIR/../src/os/solaris/proc/$CPU/libsaproc_audit.so
     3.8 +export LD_AUDIT_64
     3.9  SA_LIBPATH=$STARTDIR/../src/os/solaris/proc/$CPU:$STARTDIR/solaris/$CPU
    3.10  
    3.11  OPTIONS="-Dsa.library.path=$SA_LIBPATH -Dsun.jvm.hotspot.debugger.useProcDebugger"
     4.1 --- a/agent/src/os/solaris/proc/Makefile	Mon Jul 20 08:20:00 2009 -0700
     4.2 +++ b/agent/src/os/solaris/proc/Makefile	Mon Jul 27 06:15:29 2009 -0700
     4.3 @@ -56,24 +56,28 @@
     4.4  	@javah -classpath $(CLASSES_DIR) -jni sun.jvm.hotspot.debugger.proc.ProcDebuggerLocal
     4.5  	CC -G -KPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/solaris saproc.cpp \
     4.6             -M mapfile -o $@/libsaproc.so -ldemangle
     4.7 +	CC -o $@/libsaproc_audit.so -G -Kpic -z defs saproc_audit.cpp -lmapmalloc -ldl -lc 
     4.8  
     4.9  amd64:: javahomecheck
    4.10  	$(MKDIRS) $@
    4.11  	@javah -classpath $(CLASSES_DIR) -jni sun.jvm.hotspot.debugger.proc.ProcDebuggerLocal
    4.12  	CC -G -KPIC -xarch=amd64 -I${JAVA_HOME}/include -I${JAVA_HOME}/include/solaris saproc.cpp \
    4.13             -M mapfile -o $@/libsaproc.so -ldemangle
    4.14 +	CC -xarch=amd64 -o $@/libsaproc_audit.so -G -Kpic -z defs saproc_audit.cpp -lmapmalloc -ldl -lc 
    4.15  
    4.16  sparc:: javahomecheck
    4.17  	$(MKDIRS) $@
    4.18  	@javah -classpath $(CLASSES_DIR) -jni sun.jvm.hotspot.debugger.proc.ProcDebuggerLocal
    4.19  	CC -G -KPIC -xarch=v8  -I${JAVA_HOME}/include -I${JAVA_HOME}/include/solaris saproc.cpp \
    4.20             -M mapfile -o $@/libsaproc.so -ldemangle
    4.21 +	CC -xarch=v8 -o $@/libsaproc_audit.so -G -Kpic -z defs saproc_audit.cpp -lmapmalloc -ldl -lc 
    4.22  
    4.23  sparcv9:: javahomecheck
    4.24  	$(MKDIRS) $@
    4.25  	@javah -classpath $(CLASSES_DIR) -jni sun.jvm.hotspot.debugger.proc.ProcDebuggerLocal
    4.26  	CC -G -KPIC -xarch=v9 -I${JAVA_HOME}/include -I${JAVA_HOME}/include/solaris saproc.cpp \
    4.27             -M mapfile -o $@/libsaproc.so -ldemangle
    4.28 +	CC -xarch=v9 -o $@/libsaproc_audit.so -G -Kpic -z defs saproc_audit.cpp -lmapmalloc -ldl -lc 
    4.29  
    4.30  clean::
    4.31  	$(RM) -rf sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal.h
     5.1 --- a/agent/src/os/solaris/proc/mapfile	Mon Jul 20 08:20:00 2009 -0700
     5.2 +++ b/agent/src/os/solaris/proc/mapfile	Mon Jul 27 06:15:29 2009 -0700
     5.3 @@ -45,6 +45,8 @@
     5.4  		Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_resume0;
     5.5  		Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_suspend0;
     5.6  		Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_writeBytesToProcess0;
     5.7 +                # this is needed by saproc_audit.c to redirect opens in libproc.so
     5.8 +                libsaproc_open;
     5.9  local:
    5.10  	*;
    5.11  };
     6.1 --- a/agent/src/os/solaris/proc/saproc.cpp	Mon Jul 20 08:20:00 2009 -0700
     6.2 +++ b/agent/src/os/solaris/proc/saproc.cpp	Mon Jul 27 06:15:29 2009 -0700
     6.3 @@ -214,49 +214,58 @@
     6.4    }
     6.5  }
     6.6  
     6.7 -static int find_file_hook(const char * name, int elf_checksum) {
     6.8 -  init_alt_root();
     6.9 +// This function is a complete substitute for the open system call
    6.10 +// since it's also used to override open calls from libproc to
    6.11 +// implement as a pathmap style facility for the SA.  If libproc
    6.12 +// starts using other interfaces then this might have to extended to
    6.13 +// cover other calls.
    6.14 +extern "C" int libsaproc_open(const char * name, int oflag, ...) {
    6.15 +  if (oflag == O_RDONLY) {
    6.16 +    init_alt_root();
    6.17  
    6.18 -  if (_libsaproc_debug) {
    6.19 -    printf("libsaproc DEBUG: find_file_hook %s 0x%x\n", name, elf_checksum);
    6.20 -  }
    6.21 -
    6.22 -  if (alt_root_len > 0) {
    6.23 -    int fd = -1;
    6.24 -    char alt_path[PATH_MAX+1];
    6.25 -
    6.26 -    strcpy(alt_path, alt_root);
    6.27 -    strcat(alt_path, name);
    6.28 -    fd = open(alt_path, O_RDONLY);
    6.29 -    if (fd >= 0) {
    6.30 -      if (_libsaproc_debug) {
    6.31 -        printf("libsaproc DEBUG: find_file_hook substituted %s\n", alt_path);
    6.32 -      }
    6.33 -      return fd;
    6.34 +    if (_libsaproc_debug) {
    6.35 +      printf("libsaproc DEBUG: libsaproc_open %s\n", name);
    6.36      }
    6.37  
    6.38 -    if (strrchr(name, '/')) {
    6.39 +    if (alt_root_len > 0) {
    6.40 +      int fd = -1;
    6.41 +      char alt_path[PATH_MAX+1];
    6.42 +
    6.43        strcpy(alt_path, alt_root);
    6.44 -      strcat(alt_path, strrchr(name, '/'));
    6.45 +      strcat(alt_path, name);
    6.46        fd = open(alt_path, O_RDONLY);
    6.47        if (fd >= 0) {
    6.48          if (_libsaproc_debug) {
    6.49 -          printf("libsaproc DEBUG: find_file_hook substituted %s\n", alt_path);
    6.50 +          printf("libsaproc DEBUG: libsaproc_open substituted %s\n", alt_path);
    6.51          }
    6.52          return fd;
    6.53        }
    6.54 +
    6.55 +      if (strrchr(name, '/')) {
    6.56 +        strcpy(alt_path, alt_root);
    6.57 +        strcat(alt_path, strrchr(name, '/'));
    6.58 +        fd = open(alt_path, O_RDONLY);
    6.59 +        if (fd >= 0) {
    6.60 +          if (_libsaproc_debug) {
    6.61 +            printf("libsaproc DEBUG: libsaproc_open substituted %s\n", alt_path);
    6.62 +          }
    6.63 +          return fd;
    6.64 +        }
    6.65 +      }
    6.66      }
    6.67    }
    6.68 -  return -1;
    6.69 +
    6.70 +  {
    6.71 +    mode_t mode;
    6.72 +    va_list ap;
    6.73 +    va_start(ap, oflag);
    6.74 +    mode = va_arg(ap, mode_t);
    6.75 +    va_end(ap);
    6.76 +
    6.77 +    return open(name, oflag, mode);
    6.78 +  }
    6.79  }
    6.80  
    6.81 -static int pathmap_open(const char* name) {
    6.82 -  int fd = open(name, O_RDONLY);
    6.83 -  if (fd < 0) {
    6.84 -    fd = find_file_hook(name, 0);
    6.85 -  }
    6.86 -  return fd;
    6.87 -}
    6.88  
    6.89  static void * pathmap_dlopen(const char * name, int mode) {
    6.90    init_alt_root();
    6.91 @@ -608,7 +617,7 @@
    6.92    print_debug("looking for %s\n", classes_jsa);
    6.93  
    6.94    // open the classes[_g].jsa
    6.95 -  int fd = pathmap_open(classes_jsa);
    6.96 +  int fd = libsaproc_open(classes_jsa, O_RDONLY);
    6.97    if (fd < 0) {
    6.98      char errMsg[ERR_MSG_SIZE];
    6.99      sprintf(errMsg, "can't open shared archive file %s", classes_jsa);
   6.100 @@ -1209,8 +1218,6 @@
   6.101    return res;
   6.102  }
   6.103  
   6.104 -typedef int (*find_file_hook_t)(const char *, int elf_checksum);
   6.105 -
   6.106  /*
   6.107   * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
   6.108   * Method:      initIDs
   6.109 @@ -1230,16 +1237,6 @@
   6.110    if (libproc_handle == 0)
   6.111       THROW_NEW_DEBUGGER_EXCEPTION("can't load libproc.so, if you are using Solaris 5.7 or below, copy libproc.so from 5.8!");
   6.112  
   6.113 -  // If possible, set shared object find file hook.
   6.114 -  void (*set_hook)(find_file_hook_t) = (void(*)(find_file_hook_t))dlsym(libproc_handle, "Pset_find_file_hook");
   6.115 -  if (set_hook) {
   6.116 -    // we found find file hook symbol, set up our hook function.
   6.117 -    set_hook(find_file_hook);
   6.118 -  } else if (getenv(SA_ALTROOT)) {
   6.119 -    printf("libsaproc WARNING: %s set, but can't set file hook. " \
   6.120 -           "Did you use right version of libproc.so?\n", SA_ALTROOT);
   6.121 -  }
   6.122 -
   6.123    p_ps_prochandle_ID = env->GetFieldID(clazz, "p_ps_prochandle", "J");
   6.124    CHECK_EXCEPTION;
   6.125  
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/agent/src/os/solaris/proc/saproc_audit.cpp	Mon Jul 27 06:15:29 2009 -0700
     7.3 @@ -0,0 +1,98 @@
     7.4 +/*
     7.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
     7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 + *
     7.8 + * This code is free software; you can redistribute it and/or modify it
     7.9 + * under the terms of the GNU General Public License version 2 only, as
    7.10 + * published by the Free Software Foundation.
    7.11 + *
    7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.15 + * version 2 for more details (a copy is included in the LICENSE file that
    7.16 + * accompanied this code).
    7.17 + *
    7.18 + * You should have received a copy of the GNU General Public License version
    7.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.21 + *
    7.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    7.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    7.24 + * have any questions.
    7.25 + *
    7.26 + */
    7.27 +
    7.28 +#include <link.h>
    7.29 +#include <stdio.h>
    7.30 +#include <stdlib.h>
    7.31 +#include <string.h>
    7.32 +#include <sys/types.h>
    7.33 +#include <sys/stat.h>
    7.34 +#include <fcntl.h>
    7.35 +#include <limits.h>
    7.36 +#include <varargs.h>
    7.37 +
    7.38 +// This class sets up an interposer on open calls from libproc.so to
    7.39 +// support a pathmap facility in the SA.
    7.40 +
    7.41 +static uintptr_t* libproc_cookie;
    7.42 +static uintptr_t* libc_cookie;
    7.43 +static uintptr_t* libsaproc_cookie;
    7.44 +
    7.45 +
    7.46 +uint_t
    7.47 +la_version(uint_t version)
    7.48 +{
    7.49 +  return (LAV_CURRENT);
    7.50 +}
    7.51 +
    7.52 +
    7.53 +uint_t
    7.54 +la_objopen(Link_map * lmp, Lmid_t lmid, uintptr_t * cookie)
    7.55 +{
    7.56 +  if (strstr(lmp->l_name, "/libproc.so") != NULL) {
    7.57 +    libproc_cookie = cookie;
    7.58 +    return LA_FLG_BINDFROM;
    7.59 +  }
    7.60 +  if (strstr(lmp->l_name, "/libc.so") != NULL) {
    7.61 +    libc_cookie = cookie;
    7.62 +    return LA_FLG_BINDTO;
    7.63 +  }
    7.64 +  if (strstr(lmp->l_name, "/libsaproc.so") != NULL) {
    7.65 +    libsaproc_cookie = cookie;
    7.66 +    return LA_FLG_BINDTO | LA_FLG_BINDFROM;
    7.67 +  }
    7.68 +  return 0;
    7.69 +}
    7.70 +
    7.71 +
    7.72 +#if     defined(_LP64)
    7.73 +uintptr_t
    7.74 +la_symbind64(Elf64_Sym *symp, uint_t symndx, uintptr_t *refcook,
    7.75 +             uintptr_t *defcook, uint_t *sb_flags, const char *sym_name)
    7.76 +#else
    7.77 +uintptr_t
    7.78 +la_symbind32(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcook,
    7.79 +             uintptr_t *defcook, uint_t *sb_flags)
    7.80 +#endif
    7.81 +{
    7.82 +#if     !defined(_LP64)
    7.83 +  const char      *sym_name = (const char *)symp->st_name;
    7.84 +#endif
    7.85 +  if (strcmp(sym_name, "open") == 0 && refcook == libproc_cookie) {
    7.86 +    // redirect all open calls from libproc.so through libsaproc_open which will
    7.87 +    // try the alternate library locations first.
    7.88 +    void* handle = dlmopen(LM_ID_BASE, "libsaproc.so", RTLD_NOLOAD);
    7.89 +    if (handle == NULL) {
    7.90 +      fprintf(stderr, "libsaproc_audit.so: didn't find libsaproc.so during linking\n");
    7.91 +    } else {
    7.92 +      uintptr_t libsaproc_open = (uintptr_t)dlsym(handle, "libsaproc_open");
    7.93 +      if (libsaproc_open == 0) {
    7.94 +        fprintf(stderr, "libsaproc_audit.so: didn't find libsaproc_open during linking\n");
    7.95 +      } else {
    7.96 +        return libsaproc_open;
    7.97 +      }
    7.98 +    }
    7.99 +  }
   7.100 +  return symp->st_value;
   7.101 +}
     8.1 --- a/make/hotspot_version	Mon Jul 20 08:20:00 2009 -0700
     8.2 +++ b/make/hotspot_version	Mon Jul 27 06:15:29 2009 -0700
     8.3 @@ -35,7 +35,7 @@
     8.4  
     8.5  HS_MAJOR_VER=16
     8.6  HS_MINOR_VER=0
     8.7 -HS_BUILD_NUMBER=05
     8.8 +HS_BUILD_NUMBER=06
     8.9  
    8.10  JDK_MAJOR_VER=1
    8.11  JDK_MINOR_VER=7
     9.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp	Mon Jul 20 08:20:00 2009 -0700
     9.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp	Mon Jul 27 06:15:29 2009 -0700
     9.3 @@ -4208,6 +4208,7 @@
     9.4                    PtrQueue::byte_offset_of_active()),
     9.5           tmp);
     9.6    }
     9.7 +
     9.8    // Check on whether to annul.
     9.9    br_on_reg_cond(rc_z, /*annul*/false, Assembler::pt, tmp, filtered);
    9.10    delayed() -> nop();
    9.11 @@ -4215,13 +4216,13 @@
    9.12    // satb_log_barrier_work1(tmp, offset);
    9.13    if (index == noreg) {
    9.14      if (Assembler::is_simm13(offset)) {
    9.15 -      ld_ptr(obj, offset, tmp);
    9.16 +      load_heap_oop(obj, offset, tmp);
    9.17      } else {
    9.18        set(offset, tmp);
    9.19 -      ld_ptr(obj, tmp, tmp);
    9.20 +      load_heap_oop(obj, tmp, tmp);
    9.21      }
    9.22    } else {
    9.23 -    ld_ptr(obj, index, tmp);
    9.24 +    load_heap_oop(obj, index, tmp);
    9.25    }
    9.26  
    9.27    // satb_log_barrier_work2(obj, tmp, offset);
    10.1 --- a/src/cpu/x86/vm/assembler_x86.cpp	Mon Jul 20 08:20:00 2009 -0700
    10.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp	Mon Jul 27 06:15:29 2009 -0700
    10.3 @@ -6805,14 +6805,18 @@
    10.4    jcc(Assembler::equal, done);
    10.5  
    10.6    // if (x.f == NULL) goto done;
    10.7 -  cmpptr(Address(obj, 0), NULL_WORD);
    10.8 +#ifdef _LP64
    10.9 +  load_heap_oop(tmp2, Address(obj, 0));
   10.10 +#else
   10.11 +  movptr(tmp2, Address(obj, 0));
   10.12 +#endif
   10.13 +  cmpptr(tmp2, (int32_t) NULL_WORD);
   10.14    jcc(Assembler::equal, done);
   10.15  
   10.16    // Can we store original value in the thread's buffer?
   10.17  
   10.18 -  LP64_ONLY(movslq(tmp, index);)
   10.19 -  movptr(tmp2, Address(obj, 0));
   10.20  #ifdef _LP64
   10.21 +  movslq(tmp, index);
   10.22    cmpq(tmp, 0);
   10.23  #else
   10.24    cmpl(index, 0);
   10.25 @@ -6834,8 +6838,7 @@
   10.26    if(tosca_live) push(rax);
   10.27    push(obj);
   10.28  #ifdef _LP64
   10.29 -  movq(c_rarg0, Address(obj, 0));
   10.30 -  call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), c_rarg0, r15_thread);
   10.31 +  call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), tmp2, r15_thread);
   10.32  #else
   10.33    push(thread);
   10.34    call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), tmp2, thread);
    11.1 --- a/src/cpu/x86/vm/methodHandles_x86.cpp	Mon Jul 20 08:20:00 2009 -0700
    11.2 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp	Mon Jul 27 06:15:29 2009 -0700
    11.3 @@ -269,11 +269,11 @@
    11.4  
    11.5  #ifndef PRODUCT
    11.6  void trace_method_handle_stub(const char* adaptername,
    11.7 -                              oop mh,
    11.8 +                              oopDesc* mh,
    11.9                                intptr_t* entry_sp,
   11.10                                intptr_t* saved_sp) {
   11.11    // called as a leaf from native code: do not block the JVM!
   11.12 -  printf("MH %s "PTR_FORMAT" "PTR_FORMAT" "INTX_FORMAT"\n", adaptername, mh, entry_sp, entry_sp - saved_sp);
   11.13 +  printf("MH %s "PTR_FORMAT" "PTR_FORMAT" "INTX_FORMAT"\n", adaptername, (void*)mh, entry_sp, entry_sp - saved_sp);
   11.14  }
   11.15  #endif //PRODUCT
   11.16  
    12.1 --- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Mon Jul 20 08:20:00 2009 -0700
    12.2 +++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Mon Jul 27 06:15:29 2009 -0700
    12.3 @@ -709,7 +709,7 @@
    12.4    //
    12.5    //  Input:
    12.6    //     start   -  starting address
    12.7 -  //     end     -  element count
    12.8 +  //     count   -  element count
    12.9    void  gen_write_ref_array_pre_barrier(Register start, Register count) {
   12.10      assert_different_registers(start, count);
   12.11      BarrierSet* bs = Universe::heap()->barrier_set();
   12.12 @@ -757,7 +757,6 @@
   12.13            __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post)));
   12.14            __ addptr(rsp, 2*wordSize);
   12.15            __ popa();
   12.16 -
   12.17          }
   12.18          break;
   12.19  
    13.1 --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Mon Jul 20 08:20:00 2009 -0700
    13.2 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Mon Jul 27 06:15:29 2009 -0700
    13.3 @@ -1207,9 +1207,9 @@
    13.4            __ pusha();                      // push registers (overkill)
    13.5            // must compute element count unless barrier set interface is changed (other platforms supply count)
    13.6            assert_different_registers(start, end, scratch);
    13.7 -          __ lea(scratch, Address(end, wordSize));
    13.8 -          __ subptr(scratch, start);
    13.9 -          __ shrptr(scratch, LogBytesPerWord);
   13.10 +          __ lea(scratch, Address(end, BytesPerHeapOop));
   13.11 +          __ subptr(scratch, start);               // subtract start to get #bytes
   13.12 +          __ shrptr(scratch, LogBytesPerHeapOop);  // convert to element count
   13.13            __ mov(c_rarg0, start);
   13.14            __ mov(c_rarg1, scratch);
   13.15            __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post)));
   13.16 @@ -1225,6 +1225,7 @@
   13.17            Label L_loop;
   13.18  
   13.19             __ shrptr(start, CardTableModRefBS::card_shift);
   13.20 +           __ addptr(end, BytesPerHeapOop);
   13.21             __ shrptr(end, CardTableModRefBS::card_shift);
   13.22             __ subptr(end, start); // number of bytes to copy
   13.23  
   13.24 @@ -2251,6 +2252,7 @@
   13.25      // and report their number to the caller.
   13.26      assert_different_registers(rax, r14_length, count, to, end_to, rcx);
   13.27      __ lea(end_to, to_element_addr);
   13.28 +    __ addptr(end_to, -heapOopSize);      // make an inclusive end pointer
   13.29      gen_write_ref_array_post_barrier(to, end_to, rscratch1);
   13.30      __ movptr(rax, r14_length);           // original oops
   13.31      __ addptr(rax, count);                // K = (original - remaining) oops
   13.32 @@ -2259,7 +2261,7 @@
   13.33  
   13.34      // Come here on success only.
   13.35      __ BIND(L_do_card_marks);
   13.36 -    __ addptr(end_to, -wordSize);         // make an inclusive end pointer
   13.37 +    __ addptr(end_to, -heapOopSize);         // make an inclusive end pointer
   13.38      gen_write_ref_array_post_barrier(to, end_to, rscratch1);
   13.39      __ xorptr(rax, rax);                  // return 0 on success
   13.40  
    14.1 --- a/src/os/solaris/vm/os_solaris.cpp	Mon Jul 20 08:20:00 2009 -0700
    14.2 +++ b/src/os/solaris/vm/os_solaris.cpp	Mon Jul 27 06:15:29 2009 -0700
    14.3 @@ -1643,7 +1643,8 @@
    14.4  inline hrtime_t getTimeNanos() {
    14.5    if (VM_Version::supports_cx8()) {
    14.6      const hrtime_t now = gethrtime();
    14.7 -    const hrtime_t prev = max_hrtime;
    14.8 +    // Use atomic long load since 32-bit x86 uses 2 registers to keep long.
    14.9 +    const hrtime_t prev = Atomic::load((volatile jlong*)&max_hrtime);
   14.10      if (now <= prev)  return prev;   // same or retrograde time;
   14.11      const hrtime_t obsv = Atomic::cmpxchg(now, (volatile jlong*)&max_hrtime, prev);
   14.12      assert(obsv >= prev, "invariant");   // Monotonicity
    15.1 --- a/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp	Mon Jul 20 08:20:00 2009 -0700
    15.2 +++ b/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp	Mon Jul 27 06:15:29 2009 -0700
    15.3 @@ -46,6 +46,8 @@
    15.4  inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); }
    15.5  inline void Atomic::dec_ptr(volatile void*     dest) { (void)add_ptr(-1, dest); }
    15.6  
    15.7 +inline jlong Atomic::load(volatile jlong* src) { return *src; }
    15.8 +
    15.9  #ifdef _GNU_SOURCE
   15.10  
   15.11  inline jint     Atomic::add    (jint     add_value, volatile jint*     dest) {
    16.1 --- a/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp	Mon Jul 20 08:20:00 2009 -0700
    16.2 +++ b/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp	Mon Jul 27 06:15:29 2009 -0700
    16.3 @@ -99,6 +99,8 @@
    16.4    return (void*)_Atomic_cmpxchg_long((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, (int) os::is_MP());
    16.5  }
    16.6  
    16.7 +inline jlong Atomic::load(volatile jlong* src) { return *src; }
    16.8 +
    16.9  #else // !AMD64
   16.10  
   16.11  inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
   16.12 @@ -131,6 +133,15 @@
   16.13  inline void*    Atomic::cmpxchg_ptr(void*    exchange_value, volatile void*     dest, void*    compare_value) {
   16.14    return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
   16.15  }
   16.16 +
   16.17 +extern "C" void _Atomic_load_long(volatile jlong* src, volatile jlong* dst);
   16.18 +
   16.19 +inline jlong Atomic::load(volatile jlong* src) {
   16.20 +  volatile jlong dest;
   16.21 +  _Atomic_load_long(src, &dest);
   16.22 +  return dest;
   16.23 +}
   16.24 +
   16.25  #endif // AMD64
   16.26  
   16.27  #ifdef _GNU_SOURCE
    17.1 --- a/src/os_cpu/solaris_x86/vm/solaris_x86_32.il	Mon Jul 20 08:20:00 2009 -0700
    17.2 +++ b/src/os_cpu/solaris_x86/vm/solaris_x86_32.il	Mon Jul 27 06:15:29 2009 -0700
    17.3 @@ -97,6 +97,15 @@
    17.4        popl     %ebx
    17.5        .end
    17.6  
    17.7 +  // Support for void Atomic::load(volatile jlong* src, volatile jlong* dest).
    17.8 +      .inline _Atomic_load_long,2
    17.9 +      movl     0(%esp), %eax   // src
   17.10 +      fildll    (%eax)
   17.11 +      movl     4(%esp), %eax   // dest
   17.12 +      fistpll   (%eax)
   17.13 +      .end
   17.14 +
   17.15 +
   17.16    // Support for OrderAccess::acquire()
   17.17        .inline _OrderAccess_acquire,0
   17.18        movl     0(%esp), %eax
    18.1 --- a/src/share/vm/adlc/formssel.cpp	Mon Jul 20 08:20:00 2009 -0700
    18.2 +++ b/src/share/vm/adlc/formssel.cpp	Mon Jul 27 06:15:29 2009 -0700
    18.3 @@ -420,6 +420,13 @@
    18.4    return  _matrule->is_ideal_load();
    18.5  }
    18.6  
    18.7 +// Return 'true' if this instruction matches an ideal 'LoadKlass' node
    18.8 +bool InstructForm::skip_antidep_check() const {
    18.9 +  if( _matrule == NULL ) return false;
   18.10 +
   18.11 +  return  _matrule->skip_antidep_check();
   18.12 +}
   18.13 +
   18.14  // Return 'true' if this instruction matches an ideal 'Load?' node
   18.15  Form::DataType InstructForm::is_ideal_store() const {
   18.16    if( _matrule == NULL ) return Form::none;
   18.17 @@ -567,6 +574,8 @@
   18.18  
   18.19  // loads from memory, so must check for anti-dependence
   18.20  bool InstructForm::needs_anti_dependence_check(FormDict &globals) const {
   18.21 +  if ( skip_antidep_check() ) return false;
   18.22 +
   18.23    // Machine independent loads must be checked for anti-dependences
   18.24    if( is_ideal_load() != Form::none )  return true;
   18.25  
   18.26 @@ -3957,6 +3966,28 @@
   18.27  }
   18.28  
   18.29  
   18.30 +bool MatchRule::skip_antidep_check() const {
   18.31 +  // Some loads operate on what is effectively immutable memory so we
   18.32 +  // should skip the anti dep computations.  For some of these nodes
   18.33 +  // the rewritable field keeps the anti dep logic from triggering but
   18.34 +  // for certain kinds of LoadKlass it does not since they are
   18.35 +  // actually reading memory which could be rewritten by the runtime,
   18.36 +  // though never by generated code.  This disables it uniformly for
   18.37 +  // the nodes that behave like this: LoadKlass, LoadNKlass and
   18.38 +  // LoadRange.
   18.39 +  if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) {
   18.40 +    const char *opType = _rChild->_opType;
   18.41 +    if (strcmp("LoadKlass", opType) == 0 ||
   18.42 +        strcmp("LoadNKlass", opType) == 0 ||
   18.43 +        strcmp("LoadRange", opType) == 0) {
   18.44 +      return true;
   18.45 +    }
   18.46 +  }
   18.47 +
   18.48 +  return false;
   18.49 +}
   18.50 +
   18.51 +
   18.52  Form::DataType MatchRule::is_ideal_store() const {
   18.53    Form::DataType ideal_store = Form::none;
   18.54  
    19.1 --- a/src/share/vm/adlc/formssel.hpp	Mon Jul 20 08:20:00 2009 -0700
    19.2 +++ b/src/share/vm/adlc/formssel.hpp	Mon Jul 27 06:15:29 2009 -0700
    19.3 @@ -158,6 +158,9 @@
    19.4  
    19.5    virtual Form::CallType is_ideal_call() const; // matches ideal 'Call'
    19.6    virtual Form::DataType is_ideal_load() const; // node matches ideal 'LoadXNode'
    19.7 +  // Should antidep checks be disabled for this Instruct
    19.8 +  // See definition of MatchRule::skip_antidep_check
    19.9 +  bool skip_antidep_check() const;
   19.10    virtual Form::DataType is_ideal_store() const;// node matches ideal 'StoreXNode'
   19.11            bool        is_ideal_mem() const { return is_ideal_load() != Form::none || is_ideal_store() != Form::none; }
   19.12    virtual uint        two_address(FormDict &globals); // output reg must match input reg
   19.13 @@ -1003,6 +1006,9 @@
   19.14    bool       is_ideal_loopEnd() const; // node matches ideal 'LoopEnd'
   19.15    bool       is_ideal_bool() const;    // node matches ideal 'Bool'
   19.16    Form::DataType is_ideal_load() const;// node matches ideal 'LoadXNode'
   19.17 +  // Should antidep checks be disabled for this rule
   19.18 +  // See definition of MatchRule::skip_antidep_check
   19.19 +  bool skip_antidep_check() const;
   19.20    Form::DataType is_ideal_store() const;// node matches ideal 'StoreXNode'
   19.21  
   19.22    // Check if 'mRule2' is a cisc-spill variant of this MatchRule
    20.1 --- a/src/share/vm/classfile/classFileParser.cpp	Mon Jul 20 08:20:00 2009 -0700
    20.2 +++ b/src/share/vm/classfile/classFileParser.cpp	Mon Jul 27 06:15:29 2009 -0700
    20.3 @@ -3231,6 +3231,16 @@
    20.4      this_klass->set_minor_version(minor_version);
    20.5      this_klass->set_major_version(major_version);
    20.6  
    20.7 +    // Set up methodOop::intrinsic_id as soon as we know the names of methods.
    20.8 +    // (We used to do this lazily, but now we query it in Rewriter,
    20.9 +    // which is eagerly done for every method, so we might as well do it now,
   20.10 +    // when everything is fresh in memory.)
   20.11 +    if (methodOopDesc::klass_id_for_intrinsics(this_klass->as_klassOop()) != vmSymbols::NO_SID) {
   20.12 +      for (int j = 0; j < methods->length(); j++) {
   20.13 +        ((methodOop)methods->obj_at(j))->init_intrinsic_id();
   20.14 +      }
   20.15 +    }
   20.16 +
   20.17      if (cached_class_file_bytes != NULL) {
   20.18        // JVMTI: we have an instanceKlass now, tell it about the cached bytes
   20.19        this_klass->set_cached_class_file(cached_class_file_bytes,
    21.1 --- a/src/share/vm/classfile/vmSymbols.hpp	Mon Jul 20 08:20:00 2009 -0700
    21.2 +++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Jul 27 06:15:29 2009 -0700
    21.3 @@ -513,9 +513,6 @@
    21.4  //
    21.5  // for Emacs: (let ((c-backslash-column 120) (c-backslash-max-column 120)) (c-backslash-region (point) (point-max) nil t))
    21.6  #define VM_INTRINSICS_DO(do_intrinsic, do_class, do_name, do_signature, do_alias)                                       \
    21.7 -  do_intrinsic(_Object_init,              java_lang_Object, object_initializer_name, void_method_signature,      F_R)   \
    21.8 -  /*    (symbol object_initializer_name defined above) */                                                               \
    21.9 -                                                                                                                        \
   21.10    do_intrinsic(_hashCode,                 java_lang_Object,       hashCode_name, void_int_signature,             F_R)   \
   21.11     do_name(     hashCode_name,                                   "hashCode")                                            \
   21.12    do_intrinsic(_getClass,                 java_lang_Object,       getClass_name, void_class_signature,           F_R)   \
   21.13 @@ -635,9 +632,6 @@
   21.14    do_intrinsic(_equalsC,                  java_util_Arrays,       equals_name,    equalsC_signature,             F_S)   \
   21.15     do_signature(equalsC_signature,                               "([C[C)Z")                                             \
   21.16                                                                                                                          \
   21.17 -  do_intrinsic(_invoke,                   java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \
   21.18 -  /*   (symbols invoke_name and invoke_signature defined above) */                                                      \
   21.19 -                                                                                                                        \
   21.20    do_intrinsic(_compareTo,                java_lang_String,       compareTo_name, string_int_signature,          F_R)   \
   21.21     do_name(     compareTo_name,                                  "compareTo")                                           \
   21.22    do_intrinsic(_indexOf,                  java_lang_String,       indexOf_name, string_int_signature,            F_R)   \
   21.23 @@ -656,8 +650,6 @@
   21.24     do_name(     attemptUpdate_name,                                 "attemptUpdate")                                    \
   21.25     do_signature(attemptUpdate_signature,                            "(JJ)Z")                                            \
   21.26                                                                                                                          \
   21.27 -  do_intrinsic(_fillInStackTrace,         java_lang_Throwable, fillInStackTrace_name, void_throwable_signature,  F_RNY) \
   21.28 -                                                                                                                        \
   21.29    /* support for sun.misc.Unsafe */                                                                                     \
   21.30    do_class(sun_misc_Unsafe,               "sun/misc/Unsafe")                                                            \
   21.31                                                                                                                          \
   21.32 @@ -819,10 +811,22 @@
   21.33     do_name(     prefetchReadStatic_name,                         "prefetchReadStatic")                                  \
   21.34    do_intrinsic(_prefetchWriteStatic,      sun_misc_Unsafe,        prefetchWriteStatic_name, prefetch_signature,  F_SN)  \
   21.35     do_name(     prefetchWriteStatic_name,                        "prefetchWriteStatic")                                 \
   21.36 +    /*== LAST_COMPILER_INLINE*/                                                                                         \
   21.37 +    /*the compiler does have special inlining code for these; bytecode inline is just fine */                           \
   21.38 +                                                                                                                        \
   21.39 +  do_intrinsic(_fillInStackTrace,         java_lang_Throwable, fillInStackTrace_name, void_throwable_signature,  F_RNY) \
   21.40 +                                                                                                                        \
   21.41 +  do_intrinsic(_Object_init,              java_lang_Object, object_initializer_name, void_method_signature,      F_R)   \
   21.42 +  /*    (symbol object_initializer_name defined above) */                                                               \
   21.43 +                                                                                                                        \
   21.44 +  do_intrinsic(_invoke,                   java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \
   21.45 +  /*   (symbols invoke_name and invoke_signature defined above) */                                                      \
   21.46 +                                                                                                                        \
   21.47      /*end*/
   21.48  
   21.49  
   21.50  
   21.51 +
   21.52  // Class vmSymbols
   21.53  
   21.54  class vmSymbols: AllStatic {
   21.55 @@ -935,6 +939,7 @@
   21.56      #undef VM_INTRINSIC_ENUM
   21.57  
   21.58      ID_LIMIT,
   21.59 +    LAST_COMPILER_INLINE = _prefetchWriteStatic,
   21.60      FIRST_ID = _none + 1
   21.61    };
   21.62  
   21.63 @@ -972,4 +977,7 @@
   21.64    static Flags              flags_for(ID id);
   21.65  
   21.66    static const char* short_name_as_C_string(ID id, char* buf, int size);
   21.67 +
   21.68 +  // Access to intrinsic methods:
   21.69 +  static methodOop method_for(ID id);
   21.70  };
    22.1 --- a/src/share/vm/compiler/oopMap.cpp	Mon Jul 20 08:20:00 2009 -0700
    22.2 +++ b/src/share/vm/compiler/oopMap.cpp	Mon Jul 27 06:15:29 2009 -0700
    22.3 @@ -379,7 +379,15 @@
    22.4          if ( loc != NULL ) {
    22.5            oop *base_loc    = fr->oopmapreg_to_location(omv.content_reg(), reg_map);
    22.6            oop *derived_loc = loc;
    22.7 -          derived_oop_fn(base_loc, derived_loc);
    22.8 +          oop val = *base_loc;
    22.9 +          if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) {
   22.10 +            // Ignore NULL oops and decoded NULL narrow oops which
   22.11 +            // equal to Universe::narrow_oop_base when a narrow oop
   22.12 +            // implicit null check is used in compiled code.
   22.13 +            // The narrow_oop_base could be NULL or be the address
   22.14 +            // of the page below heap depending on compressed oops mode.
   22.15 +          } else
   22.16 +            derived_oop_fn(base_loc, derived_loc);
   22.17          }
   22.18          oms.next();
   22.19        }  while (!oms.is_done());
   22.20 @@ -394,6 +402,15 @@
   22.21        oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
   22.22        if ( loc != NULL ) {
   22.23          if ( omv.type() == OopMapValue::oop_value ) {
   22.24 +          oop val = *loc;
   22.25 +          if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) {
   22.26 +            // Ignore NULL oops and decoded NULL narrow oops which
   22.27 +            // equal to Universe::narrow_oop_base when a narrow oop
   22.28 +            // implicit null check is used in compiled code.
   22.29 +            // The narrow_oop_base could be NULL or be the address
   22.30 +            // of the page below heap depending on compressed oops mode.
   22.31 +            continue;
   22.32 +          }
   22.33  #ifdef ASSERT
   22.34            if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) ||
   22.35               !Universe::heap()->is_in_or_null(*loc)) {
   22.36 @@ -410,6 +427,8 @@
   22.37  #endif // ASSERT
   22.38            oop_fn->do_oop(loc);
   22.39          } else if ( omv.type() == OopMapValue::value_value ) {
   22.40 +          assert((*loc) == (oop)NULL || !Universe::is_narrow_oop_base(*loc),
   22.41 +                 "found invalid value pointer");
   22.42            value_fn->do_oop(loc);
   22.43          } else if ( omv.type() == OopMapValue::narrowoop_value ) {
   22.44            narrowOop *nl = (narrowOop*)loc;
    23.1 --- a/src/share/vm/compiler/oopMap.hpp	Mon Jul 20 08:20:00 2009 -0700
    23.2 +++ b/src/share/vm/compiler/oopMap.hpp	Mon Jul 27 06:15:29 2009 -0700
    23.3 @@ -233,6 +233,10 @@
    23.4    int heap_size() const;
    23.5    void copy_to(address addr);
    23.6  
    23.7 +  // Methods oops_do() and all_do() filter out NULL oops and
    23.8 +  // oop == Universe::narrow_oop_base() before passing oops
    23.9 +  // to closures.
   23.10 +
   23.11    // Iterates through frame for a compiled method
   23.12    static void oops_do            (const frame* fr,
   23.13                                    const RegisterMap* reg_map, OopClosure* f);
    24.1 --- a/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp	Mon Jul 20 08:20:00 2009 -0700
    24.2 +++ b/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp	Mon Jul 27 06:15:29 2009 -0700
    24.3 @@ -42,35 +42,40 @@
    24.4      BufferLength = 1024
    24.5    };
    24.6  
    24.7 -  oop          *_buffer[BufferLength];
    24.8 -  oop         **_buffer_top;
    24.9 -  oop         **_buffer_curr;
   24.10 +  StarTask  _buffer[BufferLength];
   24.11 +  StarTask* _buffer_top;
   24.12 +  StarTask* _buffer_curr;
   24.13  
   24.14 -  OopClosure  *_oc;
   24.15 -  double       _closure_app_seconds;
   24.16 +  OopClosure* _oc;
   24.17 +  double      _closure_app_seconds;
   24.18  
   24.19    void process_buffer () {
   24.20 -
   24.21      double start = os::elapsedTime();
   24.22 -    for (oop **curr = _buffer; curr < _buffer_curr; ++curr) {
   24.23 -      _oc->do_oop(*curr);
   24.24 +    for (StarTask* curr = _buffer; curr < _buffer_curr; ++curr) {
   24.25 +      if (curr->is_narrow()) {
   24.26 +        assert(UseCompressedOops, "Error");
   24.27 +        _oc->do_oop((narrowOop*)(*curr));
   24.28 +      } else {
   24.29 +        _oc->do_oop((oop*)(*curr));
   24.30 +      }
   24.31      }
   24.32      _buffer_curr = _buffer;
   24.33      _closure_app_seconds += (os::elapsedTime() - start);
   24.34    }
   24.35  
   24.36 -public:
   24.37 -  virtual void do_oop(narrowOop* p) {
   24.38 -    guarantee(false, "NYI");
   24.39 -  }
   24.40 -  virtual void do_oop(oop *p) {
   24.41 +  template <class T> inline void do_oop_work(T* p) {
   24.42      if (_buffer_curr == _buffer_top) {
   24.43        process_buffer();
   24.44      }
   24.45 -
   24.46 -    *_buffer_curr = p;
   24.47 +    StarTask new_ref(p);
   24.48 +    *_buffer_curr = new_ref;
   24.49      ++_buffer_curr;
   24.50    }
   24.51 +
   24.52 +public:
   24.53 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
   24.54 +  virtual void do_oop(oop* p)       { do_oop_work(p); }
   24.55 +
   24.56    void done () {
   24.57      if (_buffer_curr > _buffer) {
   24.58        process_buffer();
   24.59 @@ -88,18 +93,17 @@
   24.60  class BufferingOopsInGenClosure: public OopsInGenClosure {
   24.61    BufferingOopClosure _boc;
   24.62    OopsInGenClosure* _oc;
   24.63 -public:
   24.64 + protected:
   24.65 +  template <class T> inline void do_oop_work(T* p) {
   24.66 +    assert(generation()->is_in_reserved((void*)p), "Must be in!");
   24.67 +    _boc.do_oop(p);
   24.68 +  }
   24.69 + public:
   24.70    BufferingOopsInGenClosure(OopsInGenClosure *oc) :
   24.71      _boc(oc), _oc(oc) {}
   24.72  
   24.73 -  virtual void do_oop(narrowOop* p) {
   24.74 -    guarantee(false, "NYI");
   24.75 -  }
   24.76 -
   24.77 -  virtual void do_oop(oop* p) {
   24.78 -    assert(generation()->is_in_reserved(p), "Must be in!");
   24.79 -    _boc.do_oop(p);
   24.80 -  }
   24.81 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
   24.82 +  virtual void do_oop(oop* p)       { do_oop_work(p); }
   24.83  
   24.84    void done() {
   24.85      _boc.done();
   24.86 @@ -130,14 +134,14 @@
   24.87      BufferLength = 1024
   24.88    };
   24.89  
   24.90 -  oop                      *_buffer[BufferLength];
   24.91 -  oop                     **_buffer_top;
   24.92 -  oop                     **_buffer_curr;
   24.93 +  StarTask     _buffer[BufferLength];
   24.94 +  StarTask*    _buffer_top;
   24.95 +  StarTask*    _buffer_curr;
   24.96  
   24.97 -  HeapRegion               *_hr_buffer[BufferLength];
   24.98 -  HeapRegion              **_hr_curr;
   24.99 +  HeapRegion*  _hr_buffer[BufferLength];
  24.100 +  HeapRegion** _hr_curr;
  24.101  
  24.102 -  OopsInHeapRegionClosure  *_oc;
  24.103 +  OopsInHeapRegionClosure*  _oc;
  24.104    double                    _closure_app_seconds;
  24.105  
  24.106    void process_buffer () {
  24.107 @@ -146,15 +150,20 @@
  24.108             "the two lengths should be the same");
  24.109  
  24.110      double start = os::elapsedTime();
  24.111 -    HeapRegion **hr_curr = _hr_buffer;
  24.112 -    HeapRegion *hr_prev = NULL;
  24.113 -    for (oop **curr = _buffer; curr < _buffer_curr; ++curr) {
  24.114 -      HeapRegion *region = *hr_curr;
  24.115 +    HeapRegion** hr_curr = _hr_buffer;
  24.116 +    HeapRegion*  hr_prev = NULL;
  24.117 +    for (StarTask* curr = _buffer; curr < _buffer_curr; ++curr) {
  24.118 +      HeapRegion* region = *hr_curr;
  24.119        if (region != hr_prev) {
  24.120          _oc->set_region(region);
  24.121          hr_prev = region;
  24.122        }
  24.123 -      _oc->do_oop(*curr);
  24.124 +      if (curr->is_narrow()) {
  24.125 +        assert(UseCompressedOops, "Error");
  24.126 +        _oc->do_oop((narrowOop*)(*curr));
  24.127 +      } else {
  24.128 +        _oc->do_oop((oop*)(*curr));
  24.129 +      }
  24.130        ++hr_curr;
  24.131      }
  24.132      _buffer_curr = _buffer;
  24.133 @@ -163,17 +172,16 @@
  24.134    }
  24.135  
  24.136  public:
  24.137 -  virtual void do_oop(narrowOop *p) {
  24.138 -    guarantee(false, "NYI");
  24.139 -  }
  24.140 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
  24.141 +  virtual void do_oop(      oop* p) { do_oop_work(p); }
  24.142  
  24.143 -  virtual void do_oop(oop *p) {
  24.144 +  template <class T> void do_oop_work(T* p) {
  24.145      if (_buffer_curr == _buffer_top) {
  24.146        assert(_hr_curr > _hr_buffer, "_hr_curr should be consistent with _buffer_curr");
  24.147        process_buffer();
  24.148      }
  24.149 -
  24.150 -    *_buffer_curr = p;
  24.151 +    StarTask new_ref(p);
  24.152 +    *_buffer_curr = new_ref;
  24.153      ++_buffer_curr;
  24.154      *_hr_curr = _from;
  24.155      ++_hr_curr;
    25.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Mon Jul 20 08:20:00 2009 -0700
    25.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Mon Jul 27 06:15:29 2009 -0700
    25.3 @@ -452,13 +452,10 @@
    25.4    _regionStack.allocate(G1MarkRegionStackSize);
    25.5  
    25.6    // Create & start a ConcurrentMark thread.
    25.7 -  if (G1ConcMark) {
    25.8 -    _cmThread = new ConcurrentMarkThread(this);
    25.9 -    assert(cmThread() != NULL, "CM Thread should have been created");
   25.10 -    assert(cmThread()->cm() != NULL, "CM Thread should refer to this cm");
   25.11 -  } else {
   25.12 -    _cmThread = NULL;
   25.13 -  }
   25.14 +  _cmThread = new ConcurrentMarkThread(this);
   25.15 +  assert(cmThread() != NULL, "CM Thread should have been created");
   25.16 +  assert(cmThread()->cm() != NULL, "CM Thread should refer to this cm");
   25.17 +
   25.18    _g1h = G1CollectedHeap::heap();
   25.19    assert(CGC_lock != NULL, "Where's the CGC_lock?");
   25.20    assert(_markBitMap1.covers(rs), "_markBitMap1 inconsistency");
   25.21 @@ -783,18 +780,18 @@
   25.22                       bool do_barrier) : _cm(cm), _g1h(g1h),
   25.23                                          _do_barrier(do_barrier) { }
   25.24  
   25.25 -  virtual void do_oop(narrowOop* p) {
   25.26 -    guarantee(false, "NYI");
   25.27 -  }
   25.28 -
   25.29 -  virtual void do_oop(oop* p) {
   25.30 -    oop thisOop = *p;
   25.31 -    if (thisOop != NULL) {
   25.32 -      assert(thisOop->is_oop() || thisOop->mark() == NULL,
   25.33 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
   25.34 +  virtual void do_oop(      oop* p) { do_oop_work(p); }
   25.35 +
   25.36 +  template <class T> void do_oop_work(T* p) {
   25.37 +    T heap_oop = oopDesc::load_heap_oop(p);
   25.38 +    if (!oopDesc::is_null(heap_oop)) {
   25.39 +      oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
   25.40 +      assert(obj->is_oop() || obj->mark() == NULL,
   25.41               "expected an oop, possibly with mark word displaced");
   25.42 -      HeapWord* addr = (HeapWord*)thisOop;
   25.43 +      HeapWord* addr = (HeapWord*)obj;
   25.44        if (_g1h->is_in_g1_reserved(addr)) {
   25.45 -        _cm->grayRoot(thisOop);
   25.46 +        _cm->grayRoot(obj);
   25.47        }
   25.48      }
   25.49      if (_do_barrier) {
   25.50 @@ -850,16 +847,6 @@
   25.51    double start = os::elapsedTime();
   25.52    GCOverheadReporter::recordSTWStart(start);
   25.53  
   25.54 -  // If there has not been a GC[n-1] since last GC[n] cycle completed,
   25.55 -  // precede our marking with a collection of all
   25.56 -  // younger generations to keep floating garbage to a minimum.
   25.57 -  // YSR: we won't do this for now -- it's an optimization to be
   25.58 -  // done post-beta.
   25.59 -
   25.60 -  // YSR:    ignoring weak refs for now; will do at bug fixing stage
   25.61 -  // EVM:    assert(discoveredRefsAreClear());
   25.62 -
   25.63 -
   25.64    G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy();
   25.65    g1p->record_concurrent_mark_init_start();
   25.66    checkpointRootsInitialPre();
   25.67 @@ -1135,6 +1122,13 @@
   25.68      return;
   25.69    }
   25.70  
   25.71 +  if (VerifyDuringGC) {
   25.72 +    HandleMark hm;  // handle scope
   25.73 +    gclog_or_tty->print(" VerifyDuringGC:(before)");
   25.74 +    Universe::heap()->prepare_for_verify();
   25.75 +    Universe::verify(true, false, true);
   25.76 +  }
   25.77 +
   25.78    G1CollectorPolicy* g1p = g1h->g1_policy();
   25.79    g1p->record_concurrent_mark_remark_start();
   25.80  
   25.81 @@ -1159,10 +1153,12 @@
   25.82      JavaThread::satb_mark_queue_set().set_active_all_threads(false);
   25.83  
   25.84      if (VerifyDuringGC) {
   25.85 -      g1h->prepare_for_verify();
   25.86 -      g1h->verify(/* allow_dirty */      true,
   25.87 -                  /* silent */           false,
   25.88 -                  /* use_prev_marking */ false);
   25.89 +      HandleMark hm;  // handle scope
   25.90 +      gclog_or_tty->print(" VerifyDuringGC:(after)");
   25.91 +      Universe::heap()->prepare_for_verify();
   25.92 +      Universe::heap()->verify(/* allow_dirty */      true,
   25.93 +                               /* silent */           false,
   25.94 +                               /* use_prev_marking */ false);
   25.95      }
   25.96    }
   25.97  
   25.98 @@ -1658,6 +1654,15 @@
   25.99      return;
  25.100    }
  25.101  
  25.102 +  if (VerifyDuringGC) {
  25.103 +    HandleMark hm;  // handle scope
  25.104 +    gclog_or_tty->print(" VerifyDuringGC:(before)");
  25.105 +    Universe::heap()->prepare_for_verify();
  25.106 +    Universe::verify(/* allow dirty  */ true,
  25.107 +                     /* silent       */ false,
  25.108 +                     /* prev marking */ true);
  25.109 +  }
  25.110 +
  25.111    _cleanup_co_tracker.disable();
  25.112  
  25.113    G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy();
  25.114 @@ -1790,10 +1795,12 @@
  25.115    g1h->increment_total_collections();
  25.116  
  25.117    if (VerifyDuringGC) {
  25.118 -    g1h->prepare_for_verify();
  25.119 -    g1h->verify(/* allow_dirty */      true,
  25.120 -                /* silent */           false,
  25.121 -                /* use_prev_marking */ true);
  25.122 +    HandleMark hm;  // handle scope
  25.123 +    gclog_or_tty->print(" VerifyDuringGC:(after)");
  25.124 +    Universe::heap()->prepare_for_verify();
  25.125 +    Universe::verify(/* allow dirty  */ true,
  25.126 +                     /* silent       */ false,
  25.127 +                     /* prev marking */ true);
  25.128    }
  25.129  }
  25.130  
  25.131 @@ -1852,12 +1859,11 @@
  25.132      _g1(g1), _cm(cm),
  25.133      _bitMap(bitMap) {}
  25.134  
  25.135 -  void do_oop(narrowOop* p) {
  25.136 -    guarantee(false, "NYI");
  25.137 -  }
  25.138 -
  25.139 -  void do_oop(oop* p) {
  25.140 -    oop thisOop = *p;
  25.141 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
  25.142 +  virtual void do_oop(      oop* p) { do_oop_work(p); }
  25.143 +
  25.144 +  template <class T> void do_oop_work(T* p) {
  25.145 +    oop thisOop = oopDesc::load_decode_heap_oop(p);
  25.146      HeapWord* addr = (HeapWord*)thisOop;
  25.147      if (_g1->is_in_g1_reserved(addr) && _g1->is_obj_ill(thisOop)) {
  25.148        _bitMap->mark(addr);
  25.149 @@ -2016,12 +2022,11 @@
  25.150    ReachablePrinterOopClosure(CMBitMapRO* bitmap, outputStream* out) :
  25.151      _bitmap(bitmap), _g1h(G1CollectedHeap::heap()), _out(out) { }
  25.152  
  25.153 -  void do_oop(narrowOop* p) {
  25.154 -    guarantee(false, "NYI");
  25.155 -  }
  25.156 -
  25.157 -  void do_oop(oop* p) {
  25.158 -    oop         obj = *p;
  25.159 +  void do_oop(narrowOop* p) { do_oop_work(p); }
  25.160 +  void do_oop(      oop* p) { do_oop_work(p); }
  25.161 +
  25.162 +  template <class T> void do_oop_work(T* p) {
  25.163 +    oop         obj = oopDesc::load_decode_heap_oop(p);
  25.164      const char* str = NULL;
  25.165      const char* str2 = "";
  25.166  
  25.167 @@ -2163,6 +2168,7 @@
  25.168  
  25.169  
  25.170    HeapWord* objAddr = (HeapWord*) obj;
  25.171 +  assert(obj->is_oop_or_null(true /* ignore mark word */), "Error");
  25.172    if (_g1h->is_in_g1_reserved(objAddr)) {
  25.173      tmp_guarantee_CM( obj != NULL, "is_in_g1_reserved should ensure this" );
  25.174      HeapRegion* hr = _g1h->heap_region_containing(obj);
  25.175 @@ -2380,7 +2386,7 @@
  25.176      }
  25.177    }
  25.178  
  25.179 -  bool drain() {
  25.180 +  template <class T> bool drain() {
  25.181      while (_ms_ind > 0) {
  25.182        oop obj = pop();
  25.183        assert(obj != NULL, "Since index was non-zero.");
  25.184 @@ -2394,9 +2400,8 @@
  25.185          }
  25.186          // Now process this portion of this one.
  25.187          int lim = MIN2(next_arr_ind, len);
  25.188 -        assert(!UseCompressedOops, "This needs to be fixed");
  25.189          for (int j = arr_ind; j < lim; j++) {
  25.190 -          do_oop(aobj->obj_at_addr<oop>(j));
  25.191 +          do_oop(aobj->obj_at_addr<T>(j));
  25.192          }
  25.193  
  25.194        } else {
  25.195 @@ -2423,13 +2428,13 @@
  25.196      FREE_C_HEAP_ARRAY(jint, _array_ind_stack);
  25.197    }
  25.198  
  25.199 -  void do_oop(narrowOop* p) {
  25.200 -    guarantee(false, "NYI");
  25.201 -  }
  25.202 -
  25.203 -  void do_oop(oop* p) {
  25.204 -    oop obj = *p;
  25.205 -    if (obj == NULL) return;
  25.206 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
  25.207 +  virtual void do_oop(      oop* p) { do_oop_work(p); }
  25.208 +
  25.209 +  template <class T> void do_oop_work(T* p) {
  25.210 +    T heap_oop = oopDesc::load_heap_oop(p);
  25.211 +    if (oopDesc::is_null(heap_oop)) return;
  25.212 +    oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
  25.213      if (obj->is_forwarded()) {
  25.214        // If the object has already been forwarded, we have to make sure
  25.215        // that it's marked.  So follow the forwarding pointer.  Note that
  25.216 @@ -2478,7 +2483,11 @@
  25.217      oop obj = oop(addr);
  25.218      if (!obj->is_forwarded()) {
  25.219        if (!_oop_cl.push(obj)) return false;
  25.220 -      if (!_oop_cl.drain()) return false;
  25.221 +      if (UseCompressedOops) {
  25.222 +        if (!_oop_cl.drain<narrowOop>()) return false;
  25.223 +      } else {
  25.224 +        if (!_oop_cl.drain<oop>()) return false;
  25.225 +      }
  25.226      }
  25.227      // Otherwise...
  25.228      return true;
  25.229 @@ -2636,9 +2645,6 @@
  25.230  
  25.231  // abandon current marking iteration due to a Full GC
  25.232  void ConcurrentMark::abort() {
  25.233 -  // If we're not marking, nothing to do.
  25.234 -  if (!G1ConcMark) return;
  25.235 -
  25.236    // Clear all marks to force marking thread to do nothing
  25.237    _nextMarkBitMap->clearAll();
  25.238    // Empty mark stack
  25.239 @@ -2814,14 +2820,14 @@
  25.240    CMTask*            _task;
  25.241  
  25.242  public:
  25.243 -  void do_oop(narrowOop* p) {
  25.244 -    guarantee(false, "NYI");
  25.245 -  }
  25.246 -
  25.247 -  void do_oop(oop* p) {
  25.248 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
  25.249 +  virtual void do_oop(      oop* p) { do_oop_work(p); }
  25.250 +
  25.251 +  template <class T> void do_oop_work(T* p) {
  25.252      tmp_guarantee_CM( _g1h->is_in_g1_reserved((HeapWord*) p), "invariant" );
  25.253 -
  25.254 -    oop obj = *p;
  25.255 +    tmp_guarantee_CM( !_g1h->heap_region_containing((HeapWord*) p)->is_on_free_list(), "invariant" );
  25.256 +
  25.257 +    oop obj = oopDesc::load_decode_heap_oop(p);
  25.258      if (_cm->verbose_high())
  25.259        gclog_or_tty->print_cr("[%d] we're looking at location "
  25.260                               "*"PTR_FORMAT" = "PTR_FORMAT,
  25.261 @@ -2967,6 +2973,7 @@
  25.262    ++_refs_reached;
  25.263  
  25.264    HeapWord* objAddr = (HeapWord*) obj;
  25.265 +  assert(obj->is_oop_or_null(true /* ignore mark word */), "Error");
  25.266    if (_g1h->is_in_g1_reserved(objAddr)) {
  25.267      tmp_guarantee_CM( obj != NULL, "is_in_g1_reserved should ensure this" );
  25.268      HeapRegion* hr =  _g1h->heap_region_containing(obj);
  25.269 @@ -3030,6 +3037,7 @@
  25.270  void CMTask::push(oop obj) {
  25.271    HeapWord* objAddr = (HeapWord*) obj;
  25.272    tmp_guarantee_CM( _g1h->is_in_g1_reserved(objAddr), "invariant" );
  25.273 +  tmp_guarantee_CM( !_g1h->heap_region_containing(objAddr)->is_on_free_list(), "invariant" );
  25.274    tmp_guarantee_CM( !_g1h->is_obj_ill(obj), "invariant" );
  25.275    tmp_guarantee_CM( _nextMarkBitMap->isMarked(objAddr), "invariant" );
  25.276  
  25.277 @@ -3275,6 +3283,8 @@
  25.278  
  25.279        tmp_guarantee_CM( _g1h->is_in_g1_reserved((HeapWord*) obj),
  25.280                          "invariant" );
  25.281 +      tmp_guarantee_CM( !_g1h->heap_region_containing(obj)->is_on_free_list(),
  25.282 +                        "invariant" );
  25.283  
  25.284        scan_object(obj);
  25.285  
    26.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Mon Jul 20 08:20:00 2009 -0700
    26.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Mon Jul 27 06:15:29 2009 -0700
    26.3 @@ -763,6 +763,7 @@
    26.4    CMBitMap*                   _nextMarkBitMap;
    26.5    // the task queue of this task
    26.6    CMTaskQueue*                _task_queue;
    26.7 +private:
    26.8    // the task queue set---needed for stealing
    26.9    CMTaskQueueSet*             _task_queues;
   26.10    // indicates whether the task has been claimed---this is only  for
    27.1 --- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp	Mon Jul 20 08:20:00 2009 -0700
    27.2 +++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp	Mon Jul 27 06:15:29 2009 -0700
    27.3 @@ -424,7 +424,7 @@
    27.4        while (n <= next_boundary) {
    27.5          q = n;
    27.6          oop obj = oop(q);
    27.7 -        if (obj->klass() == NULL) return q;
    27.8 +        if (obj->klass_or_null() == NULL) return q;
    27.9          n += obj->size();
   27.10        }
   27.11        assert(q <= next_boundary && n > next_boundary, "Consequence of loop");
   27.12 @@ -436,7 +436,7 @@
   27.13        while (n <= next_boundary) {
   27.14          q = n;
   27.15          oop obj = oop(q);
   27.16 -        if (obj->klass() == NULL) return q;
   27.17 +        if (obj->klass_or_null() == NULL) return q;
   27.18          n += _sp->block_size(q);
   27.19        }
   27.20        assert(q <= next_boundary && n > next_boundary, "Consequence of loop");
    28.1 --- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp	Mon Jul 20 08:20:00 2009 -0700
    28.2 +++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp	Mon Jul 27 06:15:29 2009 -0700
    28.3 @@ -96,14 +96,14 @@
    28.4      while (n <= addr) {
    28.5        q = n;
    28.6        oop obj = oop(q);
    28.7 -      if (obj->klass() == NULL) return q;
    28.8 +      if (obj->klass_or_null() == NULL) return q;
    28.9        n += obj->size();
   28.10      }
   28.11    } else {
   28.12      while (n <= addr) {
   28.13        q = n;
   28.14        oop obj = oop(q);
   28.15 -      if (obj->klass() == NULL) return q;
   28.16 +      if (obj->klass_or_null() == NULL) return q;
   28.17        n += _sp->block_size(q);
   28.18      }
   28.19    }
   28.20 @@ -115,7 +115,7 @@
   28.21  inline HeapWord*
   28.22  G1BlockOffsetArray::forward_to_block_containing_addr(HeapWord* q,
   28.23                                                       const void* addr) {
   28.24 -  if (oop(q)->klass() == NULL) return q;
   28.25 +  if (oop(q)->klass_or_null() == NULL) return q;
   28.26    HeapWord* n = q + _sp->block_size(q);
   28.27    // In the normal case, where the query "addr" is a card boundary, and the
   28.28    // offset table chunks are the same size as cards, the block starting at
    29.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Mon Jul 20 08:20:00 2009 -0700
    29.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Mon Jul 27 06:15:29 2009 -0700
    29.3 @@ -902,6 +902,10 @@
    29.4                                      size_t word_size) {
    29.5    ResourceMark rm;
    29.6  
    29.7 +  if (PrintHeapAtGC) {
    29.8 +    Universe::print_heap_before_gc();
    29.9 +  }
   29.10 +
   29.11    if (full && DisableExplicitGC) {
   29.12      gclog_or_tty->print("\n\n\nDisabling Explicit GC\n\n\n");
   29.13      return;
   29.14 @@ -927,7 +931,7 @@
   29.15      g1_policy()->record_full_collection_start();
   29.16  
   29.17      gc_prologue(true);
   29.18 -    increment_total_collections();
   29.19 +    increment_total_collections(true /* full gc */);
   29.20  
   29.21      size_t g1h_prev_used = used();
   29.22      assert(used() == recalculate_used(), "Should be equal");
   29.23 @@ -1066,6 +1070,10 @@
   29.24      assert( check_young_list_empty(false, false),
   29.25              "young list should be empty at this point");
   29.26    }
   29.27 +
   29.28 +  if (PrintHeapAtGC) {
   29.29 +    Universe::print_heap_after_gc();
   29.30 +  }
   29.31  }
   29.32  
   29.33  void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) {
   29.34 @@ -1647,11 +1655,19 @@
   29.35  // Computes the sum of the storage used by the various regions.
   29.36  
   29.37  size_t G1CollectedHeap::used() const {
   29.38 -  assert(Heap_lock->owner() != NULL,
   29.39 -         "Should be owned on this thread's behalf.");
   29.40 +  // Temporarily, until 6859911 is fixed. XXX
   29.41 +  // assert(Heap_lock->owner() != NULL,
   29.42 +  //        "Should be owned on this thread's behalf.");
   29.43    size_t result = _summary_bytes_used;
   29.44 -  if (_cur_alloc_region != NULL)
   29.45 -    result += _cur_alloc_region->used();
   29.46 +  // Read only once in case it is set to NULL concurrently
   29.47 +  HeapRegion* hr = _cur_alloc_region;
   29.48 +  if (hr != NULL)
   29.49 +    result += hr->used();
   29.50 +  return result;
   29.51 +}
   29.52 +
   29.53 +size_t G1CollectedHeap::used_unlocked() const {
   29.54 +  size_t result = _summary_bytes_used;
   29.55    return result;
   29.56  }
   29.57  
   29.58 @@ -2125,13 +2141,13 @@
   29.59    VerifyLivenessOopClosure(G1CollectedHeap* _g1h) {
   29.60      g1h = _g1h;
   29.61    }
   29.62 -  void do_oop(narrowOop *p) {
   29.63 -    guarantee(false, "NYI");
   29.64 -  }
   29.65 -  void do_oop(oop *p) {
   29.66 -    oop obj = *p;
   29.67 -    assert(obj == NULL || !g1h->is_obj_dead(obj),
   29.68 -           "Dead object referenced by a not dead object");
   29.69 +  void do_oop(narrowOop *p) { do_oop_work(p); }
   29.70 +  void do_oop(      oop *p) { do_oop_work(p); }
   29.71 +
   29.72 +  template <class T> void do_oop_work(T *p) {
   29.73 +    oop obj = oopDesc::load_decode_heap_oop(p);
   29.74 +    guarantee(obj == NULL || !g1h->is_obj_dead(obj),
   29.75 +              "Dead object referenced by a not dead object");
   29.76    }
   29.77  };
   29.78  
   29.79 @@ -2198,8 +2214,10 @@
   29.80    // use_prev_marking == true  -> use "prev" marking information,
   29.81    // use_prev_marking == false -> use "next" marking information
   29.82    VerifyRegionClosure(bool allow_dirty, bool par, bool use_prev_marking)
   29.83 -    : _allow_dirty(allow_dirty), _par(par),
   29.84 +    : _allow_dirty(allow_dirty),
   29.85 +      _par(par),
   29.86        _use_prev_marking(use_prev_marking) {}
   29.87 +
   29.88    bool doHeapRegion(HeapRegion* r) {
   29.89      guarantee(_par || r->claim_value() == HeapRegion::InitialClaimValue,
   29.90                "Should be unclaimed at verify points.");
   29.91 @@ -2223,18 +2241,16 @@
   29.92    // use_prev_marking == true  -> use "prev" marking information,
   29.93    // use_prev_marking == false -> use "next" marking information
   29.94    VerifyRootsClosure(bool use_prev_marking) :
   29.95 -    _g1h(G1CollectedHeap::heap()), _failures(false),
   29.96 +    _g1h(G1CollectedHeap::heap()),
   29.97 +    _failures(false),
   29.98      _use_prev_marking(use_prev_marking) { }
   29.99  
  29.100    bool failures() { return _failures; }
  29.101  
  29.102 -  void do_oop(narrowOop* p) {
  29.103 -    guarantee(false, "NYI");
  29.104 -  }
  29.105 -
  29.106 -  void do_oop(oop* p) {
  29.107 -    oop obj = *p;
  29.108 -    if (obj != NULL) {
  29.109 +  template <class T> void do_oop_nv(T* p) {
  29.110 +    T heap_oop = oopDesc::load_heap_oop(p);
  29.111 +    if (!oopDesc::is_null(heap_oop)) {
  29.112 +      oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
  29.113        if (_g1h->is_obj_dead_cond(obj, _use_prev_marking)) {
  29.114          gclog_or_tty->print_cr("Root location "PTR_FORMAT" "
  29.115                                 "points to dead obj "PTR_FORMAT, p, (void*) obj);
  29.116 @@ -2243,6 +2259,9 @@
  29.117        }
  29.118      }
  29.119    }
  29.120 +
  29.121 +  void do_oop(oop* p)       { do_oop_nv(p); }
  29.122 +  void do_oop(narrowOop* p) { do_oop_nv(p); }
  29.123  };
  29.124  
  29.125  // This is the task used for parallel heap verification.
  29.126 @@ -2259,7 +2278,8 @@
  29.127    G1ParVerifyTask(G1CollectedHeap* g1h, bool allow_dirty,
  29.128                    bool use_prev_marking) :
  29.129      AbstractGangTask("Parallel verify task"),
  29.130 -    _g1h(g1h), _allow_dirty(allow_dirty),
  29.131 +    _g1h(g1h),
  29.132 +    _allow_dirty(allow_dirty),
  29.133      _use_prev_marking(use_prev_marking) { }
  29.134  
  29.135    void work(int worker_i) {
  29.136 @@ -2325,9 +2345,37 @@
  29.137    }
  29.138  };
  29.139  
  29.140 -void G1CollectedHeap::print() const { print_on(gclog_or_tty); }
  29.141 +void G1CollectedHeap::print() const { print_on(tty); }
  29.142  
  29.143  void G1CollectedHeap::print_on(outputStream* st) const {
  29.144 +  print_on(st, PrintHeapAtGCExtended);
  29.145 +}
  29.146 +
  29.147 +void G1CollectedHeap::print_on(outputStream* st, bool extended) const {
  29.148 +  st->print(" %-20s", "garbage-first heap");
  29.149 +  st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K",
  29.150 +            capacity()/K, used_unlocked()/K);
  29.151 +  st->print(" [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT ")",
  29.152 +            _g1_storage.low_boundary(),
  29.153 +            _g1_storage.high(),
  29.154 +            _g1_storage.high_boundary());
  29.155 +  st->cr();
  29.156 +  st->print("  region size " SIZE_FORMAT "K, ",
  29.157 +            HeapRegion::GrainBytes/K);
  29.158 +  size_t young_regions = _young_list->length();
  29.159 +  st->print(SIZE_FORMAT " young (" SIZE_FORMAT "K), ",
  29.160 +            young_regions, young_regions * HeapRegion::GrainBytes / K);
  29.161 +  size_t survivor_regions = g1_policy()->recorded_survivor_regions();
  29.162 +  st->print(SIZE_FORMAT " survivors (" SIZE_FORMAT "K)",
  29.163 +            survivor_regions, survivor_regions * HeapRegion::GrainBytes / K);
  29.164 +  st->cr();
  29.165 +  perm()->as_gen()->print_on(st);
  29.166 +  if (extended) {
  29.167 +    print_on_extended(st);
  29.168 +  }
  29.169 +}
  29.170 +
  29.171 +void G1CollectedHeap::print_on_extended(outputStream* st) const {
  29.172    PrintRegionClosure blk(st);
  29.173    _hrs->iterate(&blk);
  29.174  }
  29.175 @@ -2408,10 +2456,6 @@
  29.176  }
  29.177  
  29.178  void G1CollectedHeap::gc_prologue(bool full /* Ignored */) {
  29.179 -  if (PrintHeapAtGC){
  29.180 -    gclog_or_tty->print_cr(" {Heap before GC collections=%d:", total_collections());
  29.181 -    Universe::print();
  29.182 -  }
  29.183    assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer");
  29.184    // Call allocation profiler
  29.185    AllocationProfiler::iterate_since_last_gc();
  29.186 @@ -2425,12 +2469,6 @@
  29.187    // is set.
  29.188    COMPILER2_PRESENT(assert(DerivedPointerTable::is_empty(),
  29.189                          "derived pointer present"));
  29.190 -
  29.191 -  if (PrintHeapAtGC){
  29.192 -    gclog_or_tty->print_cr(" Heap after GC collections=%d:", total_collections());
  29.193 -    Universe::print();
  29.194 -    gclog_or_tty->print("} ");
  29.195 -  }
  29.196  }
  29.197  
  29.198  void G1CollectedHeap::do_collection_pause() {
  29.199 @@ -2453,12 +2491,10 @@
  29.200  
  29.201  void
  29.202  G1CollectedHeap::doConcurrentMark() {
  29.203 -  if (G1ConcMark) {
  29.204 -    MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
  29.205 -    if (!_cmThread->in_progress()) {
  29.206 -      _cmThread->set_started();
  29.207 -      CGC_lock->notify();
  29.208 -    }
  29.209 +  MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
  29.210 +  if (!_cmThread->in_progress()) {
  29.211 +    _cmThread->set_started();
  29.212 +    CGC_lock->notify();
  29.213    }
  29.214  }
  29.215  
  29.216 @@ -2535,9 +2571,11 @@
  29.217                            "Not enough space for young surv words summary.");
  29.218    }
  29.219    memset(_surviving_young_words, 0, array_length * sizeof(size_t));
  29.220 +#ifdef ASSERT
  29.221    for (size_t i = 0;  i < array_length; ++i) {
  29.222 -    guarantee( _surviving_young_words[i] == 0, "invariant" );
  29.223 -  }
  29.224 +    assert( _surviving_young_words[i] == 0, "memset above" );
  29.225 +  }
  29.226 +#endif // !ASSERT
  29.227  }
  29.228  
  29.229  void
  29.230 @@ -2559,241 +2597,254 @@
  29.231  
  29.232  void
  29.233  G1CollectedHeap::do_collection_pause_at_safepoint() {
  29.234 -  char verbose_str[128];
  29.235 -  sprintf(verbose_str, "GC pause ");
  29.236 -  if (g1_policy()->in_young_gc_mode()) {
  29.237 -    if (g1_policy()->full_young_gcs())
  29.238 -      strcat(verbose_str, "(young)");
  29.239 -    else
  29.240 -      strcat(verbose_str, "(partial)");
  29.241 -  }
  29.242 -  if (g1_policy()->should_initiate_conc_mark())
  29.243 -    strcat(verbose_str, " (initial-mark)");
  29.244 -
  29.245 -  GCCauseSetter x(this, GCCause::_g1_inc_collection_pause);
  29.246 -
  29.247 -  // if PrintGCDetails is on, we'll print long statistics information
  29.248 -  // in the collector policy code, so let's not print this as the output
  29.249 -  // is messy if we do.
  29.250 -  gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
  29.251 -  TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
  29.252 -  TraceTime t(verbose_str, PrintGC && !PrintGCDetails, true, gclog_or_tty);
  29.253 -
  29.254 -  ResourceMark rm;
  29.255 -  assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
  29.256 -  assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread");
  29.257 -  guarantee(!is_gc_active(), "collection is not reentrant");
  29.258 -  assert(regions_accounted_for(), "Region leakage!");
  29.259 -
  29.260 -  increment_gc_time_stamp();
  29.261 -
  29.262 -  if (g1_policy()->in_young_gc_mode()) {
  29.263 -    assert(check_young_list_well_formed(),
  29.264 -                "young list should be well formed");
  29.265 -  }
  29.266 -
  29.267 -  if (GC_locker::is_active()) {
  29.268 -    return; // GC is disabled (e.g. JNI GetXXXCritical operation)
  29.269 -  }
  29.270 -
  29.271 -  bool abandoned = false;
  29.272 -  { // Call to jvmpi::post_class_unload_events must occur outside of active GC
  29.273 -    IsGCActiveMark x;
  29.274 -
  29.275 -    gc_prologue(false);
  29.276 -    increment_total_collections();
  29.277 +  if (PrintHeapAtGC) {
  29.278 +    Universe::print_heap_before_gc();
  29.279 +  }
  29.280 +
  29.281 +  {
  29.282 +    char verbose_str[128];
  29.283 +    sprintf(verbose_str, "GC pause ");
  29.284 +    if (g1_policy()->in_young_gc_mode()) {
  29.285 +      if (g1_policy()->full_young_gcs())
  29.286 +        strcat(verbose_str, "(young)");
  29.287 +      else
  29.288 +        strcat(verbose_str, "(partial)");
  29.289 +    }
  29.290 +    if (g1_policy()->should_initiate_conc_mark())
  29.291 +      strcat(verbose_str, " (initial-mark)");
  29.292 +
  29.293 +    GCCauseSetter x(this, GCCause::_g1_inc_collection_pause);
  29.294 +
  29.295 +    // if PrintGCDetails is on, we'll print long statistics information
  29.296 +    // in the collector policy code, so let's not print this as the output
  29.297 +    // is messy if we do.
  29.298 +    gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
  29.299 +    TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
  29.300 +    TraceTime t(verbose_str, PrintGC && !PrintGCDetails, true, gclog_or_tty);
  29.301 +
  29.302 +    ResourceMark rm;
  29.303 +    assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
  29.304 +    assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread");
  29.305 +    guarantee(!is_gc_active(), "collection is not reentrant");
  29.306 +    assert(regions_accounted_for(), "Region leakage!");
  29.307 +
  29.308 +    increment_gc_time_stamp();
  29.309 +
  29.310 +    if (g1_policy()->in_young_gc_mode()) {
  29.311 +      assert(check_young_list_well_formed(),
  29.312 +             "young list should be well formed");
  29.313 +    }
  29.314 +
  29.315 +    if (GC_locker::is_active()) {
  29.316 +      return; // GC is disabled (e.g. JNI GetXXXCritical operation)
  29.317 +    }
  29.318 +
  29.319 +    bool abandoned = false;
  29.320 +    { // Call to jvmpi::post_class_unload_events must occur outside of active GC
  29.321 +      IsGCActiveMark x;
  29.322 +
  29.323 +      gc_prologue(false);
  29.324 +      increment_total_collections(false /* full gc */);
  29.325  
  29.326  #if G1_REM_SET_LOGGING
  29.327 -    gclog_or_tty->print_cr("\nJust chose CS, heap:");
  29.328 -    print();
  29.329 -#endif
  29.330 -
  29.331 -    if (VerifyBeforeGC && total_collections() >= VerifyGCStartAt) {
  29.332 -      HandleMark hm;  // Discard invalid handles created during verification
  29.333 -      prepare_for_verify();
  29.334 -      gclog_or_tty->print(" VerifyBeforeGC:");
  29.335 -      Universe::verify(false);
  29.336 -    }
  29.337 -
  29.338 -    COMPILER2_PRESENT(DerivedPointerTable::clear());
  29.339 -
  29.340 -    // We want to turn off ref discovery, if necessary, and turn it back on
  29.341 -    // on again later if we do.
  29.342 -    bool was_enabled = ref_processor()->discovery_enabled();
  29.343 -    if (was_enabled) ref_processor()->disable_discovery();
  29.344 -
  29.345 -    // Forget the current alloc region (we might even choose it to be part
  29.346 -    // of the collection set!).
  29.347 -    abandon_cur_alloc_region();
  29.348 -
  29.349 -    // The elapsed time induced by the start time below deliberately elides
  29.350 -    // the possible verification above.
  29.351 -    double start_time_sec = os::elapsedTime();
  29.352 -    GCOverheadReporter::recordSTWStart(start_time_sec);
  29.353 -    size_t start_used_bytes = used();
  29.354 -    if (!G1ConcMark) {
  29.355 -      do_sync_mark();
  29.356 -    }
  29.357 -
  29.358 -    g1_policy()->record_collection_pause_start(start_time_sec,
  29.359 -                                               start_used_bytes);
  29.360 -
  29.361 -    guarantee(_in_cset_fast_test == NULL, "invariant");
  29.362 -    guarantee(_in_cset_fast_test_base == NULL, "invariant");
  29.363 -    _in_cset_fast_test_length = max_regions();
  29.364 -    _in_cset_fast_test_base =
  29.365 -                             NEW_C_HEAP_ARRAY(bool, _in_cset_fast_test_length);
  29.366 -    memset(_in_cset_fast_test_base, false,
  29.367 -                                     _in_cset_fast_test_length * sizeof(bool));
  29.368 -    // We're biasing _in_cset_fast_test to avoid subtracting the
  29.369 -    // beginning of the heap every time we want to index; basically
  29.370 -    // it's the same with what we do with the card table.
  29.371 -    _in_cset_fast_test = _in_cset_fast_test_base -
  29.372 -              ((size_t) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes);
  29.373 -
  29.374 -#if SCAN_ONLY_VERBOSE
  29.375 -    _young_list->print();
  29.376 -#endif // SCAN_ONLY_VERBOSE
  29.377 -
  29.378 -    if (g1_policy()->should_initiate_conc_mark()) {
  29.379 -      concurrent_mark()->checkpointRootsInitialPre();
  29.380 -    }
  29.381 -    save_marks();
  29.382 -
  29.383 -    // We must do this before any possible evacuation that should propagate
  29.384 -    // marks.
  29.385 -    if (mark_in_progress()) {
  29.386 -      double start_time_sec = os::elapsedTime();
  29.387 -
  29.388 -      _cm->drainAllSATBBuffers();
  29.389 -      double finish_mark_ms = (os::elapsedTime() - start_time_sec) * 1000.0;
  29.390 -      g1_policy()->record_satb_drain_time(finish_mark_ms);
  29.391 -
  29.392 -    }
  29.393 -    // Record the number of elements currently on the mark stack, so we
  29.394 -    // only iterate over these.  (Since evacuation may add to the mark
  29.395 -    // stack, doing more exposes race conditions.)  If no mark is in
  29.396 -    // progress, this will be zero.
  29.397 -    _cm->set_oops_do_bound();
  29.398 -
  29.399 -    assert(regions_accounted_for(), "Region leakage.");
  29.400 -
  29.401 -    if (mark_in_progress())
  29.402 -      concurrent_mark()->newCSet();
  29.403 -
  29.404 -    // Now choose the CS.
  29.405 -    g1_policy()->choose_collection_set();
  29.406 -
  29.407 -    // We may abandon a pause if we find no region that will fit in the MMU
  29.408 -    // pause.
  29.409 -    bool abandoned = (g1_policy()->collection_set() == NULL);
  29.410 -
  29.411 -    // Nothing to do if we were unable to choose a collection set.
  29.412 -    if (!abandoned) {
  29.413 -#if G1_REM_SET_LOGGING
  29.414 -      gclog_or_tty->print_cr("\nAfter pause, heap:");
  29.415 +      gclog_or_tty->print_cr("\nJust chose CS, heap:");
  29.416        print();
  29.417  #endif
  29.418  
  29.419 -      setup_surviving_young_words();
  29.420 -
  29.421 -      // Set up the gc allocation regions.
  29.422 -      get_gc_alloc_regions();
  29.423 -
  29.424 -      // Actually do the work...
  29.425 -      evacuate_collection_set();
  29.426 -      free_collection_set(g1_policy()->collection_set());
  29.427 -      g1_policy()->clear_collection_set();
  29.428 -
  29.429 -      FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base);
  29.430 -      // this is more for peace of mind; we're nulling them here and
  29.431 -      // we're expecting them to be null at the beginning of the next GC
  29.432 -      _in_cset_fast_test = NULL;
  29.433 -      _in_cset_fast_test_base = NULL;
  29.434 -
  29.435 -      release_gc_alloc_regions(false /* totally */);
  29.436 -
  29.437 -      cleanup_surviving_young_words();
  29.438 -
  29.439 -      if (g1_policy()->in_young_gc_mode()) {
  29.440 -        _young_list->reset_sampled_info();
  29.441 -        assert(check_young_list_empty(true),
  29.442 -               "young list should be empty");
  29.443 +      if (VerifyBeforeGC && total_collections() >= VerifyGCStartAt) {
  29.444 +        HandleMark hm;  // Discard invalid handles created during verification
  29.445 +        prepare_for_verify();
  29.446 +        gclog_or_tty->print(" VerifyBeforeGC:");
  29.447 +        Universe::verify(false);
  29.448 +      }
  29.449 +
  29.450 +      COMPILER2_PRESENT(DerivedPointerTable::clear());
  29.451 +
  29.452 +      // We want to turn off ref discovery, if necessary, and turn it back on
  29.453 +      // on again later if we do. XXX Dubious: why is discovery disabled?
  29.454 +      bool was_enabled = ref_processor()->discovery_enabled();
  29.455 +      if (was_enabled) ref_processor()->disable_discovery();
  29.456 +
  29.457 +      // Forget the current alloc region (we might even choose it to be part
  29.458 +      // of the collection set!).
  29.459 +      abandon_cur_alloc_region();
  29.460 +
  29.461 +      // The elapsed time induced by the start time below deliberately elides
  29.462 +      // the possible verification above.
  29.463 +      double start_time_sec = os::elapsedTime();
  29.464 +      GCOverheadReporter::recordSTWStart(start_time_sec);
  29.465 +      size_t start_used_bytes = used();
  29.466 +
  29.467 +      g1_policy()->record_collection_pause_start(start_time_sec,
  29.468 +                                                 start_used_bytes);
  29.469 +
  29.470 +      guarantee(_in_cset_fast_test == NULL, "invariant");
  29.471 +      guarantee(_in_cset_fast_test_base == NULL, "invariant");
  29.472 +      _in_cset_fast_test_length = max_regions();
  29.473 +      _in_cset_fast_test_base =
  29.474 +                             NEW_C_HEAP_ARRAY(bool, _in_cset_fast_test_length);
  29.475 +      memset(_in_cset_fast_test_base, false,
  29.476 +                                     _in_cset_fast_test_length * sizeof(bool));
  29.477 +      // We're biasing _in_cset_fast_test to avoid subtracting the
  29.478 +      // beginning of the heap every time we want to index; basically
  29.479 +      // it's the same with what we do with the card table.
  29.480 +      _in_cset_fast_test = _in_cset_fast_test_base -
  29.481 +              ((size_t) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes);
  29.482  
  29.483  #if SCAN_ONLY_VERBOSE
  29.484 -        _young_list->print();
  29.485 +      _young_list->print();
  29.486  #endif // SCAN_ONLY_VERBOSE
  29.487  
  29.488 -        g1_policy()->record_survivor_regions(_young_list->survivor_length(),
  29.489 -                                             _young_list->first_survivor_region(),
  29.490 -                                             _young_list->last_survivor_region());
  29.491 -        _young_list->reset_auxilary_lists();
  29.492 +      if (g1_policy()->should_initiate_conc_mark()) {
  29.493 +        concurrent_mark()->checkpointRootsInitialPre();
  29.494        }
  29.495 -    } else {
  29.496 -      COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
  29.497 +      save_marks();
  29.498 +
  29.499 +      // We must do this before any possible evacuation that should propagate
  29.500 +      // marks.
  29.501 +      if (mark_in_progress()) {
  29.502 +        double start_time_sec = os::elapsedTime();
  29.503 +
  29.504 +        _cm->drainAllSATBBuffers();
  29.505 +        double finish_mark_ms = (os::elapsedTime() - start_time_sec) * 1000.0;
  29.506 +        g1_policy()->record_satb_drain_time(finish_mark_ms);
  29.507 +      }
  29.508 +      // Record the number of elements currently on the mark stack, so we
  29.509 +      // only iterate over these.  (Since evacuation may add to the mark
  29.510 +      // stack, doing more exposes race conditions.)  If no mark is in
  29.511 +      // progress, this will be zero.
  29.512 +      _cm->set_oops_do_bound();
  29.513 +
  29.514 +      assert(regions_accounted_for(), "Region leakage.");
  29.515 +
  29.516 +      if (mark_in_progress())
  29.517 +        concurrent_mark()->newCSet();
  29.518 +
  29.519 +      // Now choose the CS.
  29.520 +      g1_policy()->choose_collection_set();
  29.521 +
  29.522 +      // We may abandon a pause if we find no region that will fit in the MMU
  29.523 +      // pause.
  29.524 +      bool abandoned = (g1_policy()->collection_set() == NULL);
  29.525 +
  29.526 +      // Nothing to do if we were unable to choose a collection set.
  29.527 +      if (!abandoned) {
  29.528 +#if G1_REM_SET_LOGGING
  29.529 +        gclog_or_tty->print_cr("\nAfter pause, heap:");
  29.530 +        print();
  29.531 +#endif
  29.532 +
  29.533 +        setup_surviving_young_words();
  29.534 +
  29.535 +        // Set up the gc allocation regions.
  29.536 +        get_gc_alloc_regions();
  29.537 +
  29.538 +        // Actually do the work...
  29.539 +        evacuate_collection_set();
  29.540 +        free_collection_set(g1_policy()->collection_set());
  29.541 +        g1_policy()->clear_collection_set();
  29.542 +
  29.543 +        FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base);
  29.544 +        // this is more for peace of mind; we're nulling them here and
  29.545 +        // we're expecting them to be null at the beginning of the next GC
  29.546 +        _in_cset_fast_test = NULL;
  29.547 +        _in_cset_fast_test_base = NULL;
  29.548 +
  29.549 +        release_gc_alloc_regions(false /* totally */);
  29.550 +
  29.551 +        cleanup_surviving_young_words();
  29.552 +
  29.553 +        if (g1_policy()->in_young_gc_mode()) {
  29.554 +          _young_list->reset_sampled_info();
  29.555 +          assert(check_young_list_empty(true),
  29.556 +                 "young list should be empty");
  29.557 +
  29.558 +#if SCAN_ONLY_VERBOSE
  29.559 +          _young_list->print();
  29.560 +#endif // SCAN_ONLY_VERBOSE
  29.561 +
  29.562 +          g1_policy()->record_survivor_regions(_young_list->survivor_length(),
  29.563 +                                          _young_list->first_survivor_region(),
  29.564 +                                          _young_list->last_survivor_region());
  29.565 +          _young_list->reset_auxilary_lists();
  29.566 +        }
  29.567 +      } else {
  29.568 +        COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
  29.569 +      }
  29.570 +
  29.571 +      if (evacuation_failed()) {
  29.572 +        _summary_bytes_used = recalculate_used();
  29.573 +      } else {
  29.574 +        // The "used" of the the collection set have already been subtracted
  29.575 +        // when they were freed.  Add in the bytes evacuated.
  29.576 +        _summary_bytes_used += g1_policy()->bytes_in_to_space();
  29.577 +      }
  29.578 +
  29.579 +      if (g1_policy()->in_young_gc_mode() &&
  29.580 +          g1_policy()->should_initiate_conc_mark()) {
  29.581 +        concurrent_mark()->checkpointRootsInitialPost();
  29.582 +        set_marking_started();
  29.583 +        // CAUTION: after the doConcurrentMark() call below,
  29.584 +        // the concurrent marking thread(s) could be running
  29.585 +        // concurrently with us. Make sure that anything after
  29.586 +        // this point does not assume that we are the only GC thread
  29.587 +        // running. Note: of course, the actual marking work will
  29.588 +        // not start until the safepoint itself is released in
  29.589 +        // ConcurrentGCThread::safepoint_desynchronize().
  29.590 +        doConcurrentMark();
  29.591 +      }
  29.592 +
  29.593 +#if SCAN_ONLY_VERBOSE
  29.594 +      _young_list->print();
  29.595 +#endif // SCAN_ONLY_VERBOSE
  29.596 +
  29.597 +      double end_time_sec = os::elapsedTime();
  29.598 +      double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS;
  29.599 +      g1_policy()->record_pause_time_ms(pause_time_ms);
  29.600 +      GCOverheadReporter::recordSTWEnd(end_time_sec);
  29.601 +      g1_policy()->record_collection_pause_end(abandoned);
  29.602 +
  29.603 +      assert(regions_accounted_for(), "Region leakage.");
  29.604 +
  29.605 +      if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) {
  29.606 +        HandleMark hm;  // Discard invalid handles created during verification
  29.607 +        gclog_or_tty->print(" VerifyAfterGC:");
  29.608 +        prepare_for_verify();
  29.609 +        Universe::verify(false);
  29.610 +      }
  29.611 +
  29.612 +      if (was_enabled) ref_processor()->enable_discovery();
  29.613 +
  29.614 +      {
  29.615 +        size_t expand_bytes = g1_policy()->expansion_amount();
  29.616 +        if (expand_bytes > 0) {
  29.617 +          size_t bytes_before = capacity();
  29.618 +          expand(expand_bytes);
  29.619 +        }
  29.620 +      }
  29.621 +
  29.622 +      if (mark_in_progress()) {
  29.623 +        concurrent_mark()->update_g1_committed();
  29.624 +      }
  29.625 +
  29.626 +#ifdef TRACESPINNING
  29.627 +      ParallelTaskTerminator::print_termination_counts();
  29.628 +#endif
  29.629 +
  29.630 +      gc_epilogue(false);
  29.631      }
  29.632  
  29.633 -    if (evacuation_failed()) {
  29.634 -      _summary_bytes_used = recalculate_used();
  29.635 -    } else {
  29.636 -      // The "used" of the the collection set have already been subtracted
  29.637 -      // when they were freed.  Add in the bytes evacuated.
  29.638 -      _summary_bytes_used += g1_policy()->bytes_in_to_space();
  29.639 +    assert(verify_region_lists(), "Bad region lists.");
  29.640 +
  29.641 +    if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) {
  29.642 +      gclog_or_tty->print_cr("Stopping after GC #%d", ExitAfterGCNum);
  29.643 +      print_tracing_info();
  29.644 +      vm_exit(-1);
  29.645      }
  29.646 -
  29.647 -    if (g1_policy()->in_young_gc_mode() &&
  29.648 -        g1_policy()->should_initiate_conc_mark()) {
  29.649 -      concurrent_mark()->checkpointRootsInitialPost();
  29.650 -      set_marking_started();
  29.651 -      doConcurrentMark();
  29.652 -    }
  29.653 -
  29.654 -#if SCAN_ONLY_VERBOSE
  29.655 -    _young_list->print();
  29.656 -#endif // SCAN_ONLY_VERBOSE
  29.657 -
  29.658 -    double end_time_sec = os::elapsedTime();
  29.659 -    double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS;
  29.660 -    g1_policy()->record_pause_time_ms(pause_time_ms);
  29.661 -    GCOverheadReporter::recordSTWEnd(end_time_sec);
  29.662 -    g1_policy()->record_collection_pause_end(abandoned);
  29.663 -
  29.664 -    assert(regions_accounted_for(), "Region leakage.");
  29.665 -
  29.666 -    if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) {
  29.667 -      HandleMark hm;  // Discard invalid handles created during verification
  29.668 -      gclog_or_tty->print(" VerifyAfterGC:");
  29.669 -      prepare_for_verify();
  29.670 -      Universe::verify(false);
  29.671 -    }
  29.672 -
  29.673 -    if (was_enabled) ref_processor()->enable_discovery();
  29.674 -
  29.675 -    {
  29.676 -      size_t expand_bytes = g1_policy()->expansion_amount();
  29.677 -      if (expand_bytes > 0) {
  29.678 -        size_t bytes_before = capacity();
  29.679 -        expand(expand_bytes);
  29.680 -      }
  29.681 -    }
  29.682 -
  29.683 -    if (mark_in_progress()) {
  29.684 -      concurrent_mark()->update_g1_committed();
  29.685 -    }
  29.686 -
  29.687 -#ifdef TRACESPINNING
  29.688 -    ParallelTaskTerminator::print_termination_counts();
  29.689 -#endif
  29.690 -
  29.691 -    gc_epilogue(false);
  29.692 -  }
  29.693 -
  29.694 -  assert(verify_region_lists(), "Bad region lists.");
  29.695 -
  29.696 -  if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) {
  29.697 -    gclog_or_tty->print_cr("Stopping after GC #%d", ExitAfterGCNum);
  29.698 -    print_tracing_info();
  29.699 -    vm_exit(-1);
  29.700 +  }
  29.701 +
  29.702 +  if (PrintHeapAtGC) {
  29.703 +    Universe::print_heap_after_gc();
  29.704    }
  29.705  }
  29.706  
  29.707 @@ -3088,10 +3139,8 @@
  29.708    G1CollectedHeap* _g1;
  29.709  public:
  29.710    G1KeepAliveClosure(G1CollectedHeap* g1) : _g1(g1) {}
  29.711 -  void do_oop(narrowOop* p) {
  29.712 -    guarantee(false, "NYI");
  29.713 -  }
  29.714 -  void do_oop(oop* p) {
  29.715 +  void do_oop(narrowOop* p) { guarantee(false, "Not needed"); }
  29.716 +  void do_oop(      oop* p) {
  29.717      oop obj = *p;
  29.718  #ifdef G1_DEBUG
  29.719      if (PrintGC && Verbose) {
  29.720 @@ -3103,7 +3152,6 @@
  29.721      if (_g1->obj_in_cs(obj)) {
  29.722        assert( obj->is_forwarded(), "invariant" );
  29.723        *p = obj->forwardee();
  29.724 -
  29.725  #ifdef G1_DEBUG
  29.726        gclog_or_tty->print_cr("     in CSet: moved "PTR_FORMAT" -> "PTR_FORMAT,
  29.727                               (void*) obj, (void*) *p);
  29.728 @@ -3120,12 +3168,12 @@
  29.729    UpdateRSetImmediate(G1CollectedHeap* g1) :
  29.730      _g1(g1), _g1_rem_set(g1->g1_rem_set()) {}
  29.731  
  29.732 -  void do_oop(narrowOop* p) {
  29.733 -    guarantee(false, "NYI");
  29.734 -  }
  29.735 -  void do_oop(oop* p) {
  29.736 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
  29.737 +  virtual void do_oop(      oop* p) { do_oop_work(p); }
  29.738 +  template <class T> void do_oop_work(T* p) {
  29.739      assert(_from->is_in_reserved(p), "paranoia");
  29.740 -    if (*p != NULL && !_from->is_survivor()) {
  29.741 +    T heap_oop = oopDesc::load_heap_oop(p);
  29.742 +    if (!oopDesc::is_null(heap_oop) && !_from->is_survivor()) {
  29.743        _g1_rem_set->par_write_ref(_from, p, 0);
  29.744      }
  29.745    }
  29.746 @@ -3141,12 +3189,12 @@
  29.747    UpdateRSetDeferred(G1CollectedHeap* g1, DirtyCardQueue* dcq) :
  29.748      _g1(g1), _ct_bs((CardTableModRefBS*)_g1->barrier_set()), _dcq(dcq) {}
  29.749  
  29.750 -  void do_oop(narrowOop* p) {
  29.751 -    guarantee(false, "NYI");
  29.752 -  }
  29.753 -  void do_oop(oop* p) {
  29.754 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
  29.755 +  virtual void do_oop(      oop* p) { do_oop_work(p); }
  29.756 +  template <class T> void do_oop_work(T* p) {
  29.757      assert(_from->is_in_reserved(p), "paranoia");
  29.758 -    if (!_from->is_in_reserved(*p) && !_from->is_survivor()) {
  29.759 +    if (!_from->is_in_reserved(oopDesc::load_decode_heap_oop(p)) &&
  29.760 +        !_from->is_survivor()) {
  29.761        size_t card_index = _ct_bs->index_for(p);
  29.762        if (_ct_bs->mark_card_deferred(card_index)) {
  29.763          _dcq->enqueue((jbyte*)_ct_bs->byte_for_index(card_index));
  29.764 @@ -3501,614 +3549,66 @@
  29.765    fill_with_object(block, free_words);
  29.766  }
  29.767  
  29.768 -#define use_local_bitmaps         1
  29.769 -#define verify_local_bitmaps      0
  29.770 -
  29.771  #ifndef PRODUCT
  29.772 -
  29.773 -class GCLabBitMap;
  29.774 -class GCLabBitMapClosure: public BitMapClosure {
  29.775 -private:
  29.776 -  ConcurrentMark* _cm;
  29.777 -  GCLabBitMap*    _bitmap;
  29.778 -
  29.779 -public:
  29.780 -  GCLabBitMapClosure(ConcurrentMark* cm,
  29.781 -                     GCLabBitMap* bitmap) {
  29.782 -    _cm     = cm;
  29.783 -    _bitmap = bitmap;
  29.784 -  }
  29.785 -
  29.786 -  virtual bool do_bit(size_t offset);
  29.787 -};
  29.788 -
  29.789 -#endif // PRODUCT
  29.790 -
  29.791 -#define oop_buffer_length 256
  29.792 -
  29.793 -class GCLabBitMap: public BitMap {
  29.794 -private:
  29.795 -  ConcurrentMark* _cm;
  29.796 -
  29.797 -  int       _shifter;
  29.798 -  size_t    _bitmap_word_covers_words;
  29.799 -
  29.800 -  // beginning of the heap
  29.801 -  HeapWord* _heap_start;
  29.802 -
  29.803 -  // this is the actual start of the GCLab
  29.804 -  HeapWord* _real_start_word;
  29.805 -
  29.806 -  // this is the actual end of the GCLab
  29.807 -  HeapWord* _real_end_word;
  29.808 -
  29.809 -  // this is the first word, possibly located before the actual start
  29.810 -  // of the GCLab, that corresponds to the first bit of the bitmap
  29.811 -  HeapWord* _start_word;
  29.812 -
  29.813 -  // size of a GCLab in words
  29.814 -  size_t _gclab_word_size;
  29.815 -
  29.816 -  static int shifter() {
  29.817 -    return MinObjAlignment - 1;
  29.818 -  }
  29.819 -
  29.820 -  // how many heap words does a single bitmap word corresponds to?
  29.821 -  static size_t bitmap_word_covers_words() {
  29.822 -    return BitsPerWord << shifter();
  29.823 -  }
  29.824 -
  29.825 -  static size_t gclab_word_size() {
  29.826 -    return G1ParallelGCAllocBufferSize / HeapWordSize;
  29.827 -  }
  29.828 -
  29.829 -  static size_t bitmap_size_in_bits() {
  29.830 -    size_t bits_in_bitmap = gclab_word_size() >> shifter();
  29.831 -    // We are going to ensure that the beginning of a word in this
  29.832 -    // bitmap also corresponds to the beginning of a word in the
  29.833 -    // global marking bitmap. To handle the case where a GCLab
  29.834 -    // starts from the middle of the bitmap, we need to add enough
  29.835 -    // space (i.e. up to a bitmap word) to ensure that we have
  29.836 -    // enough bits in the bitmap.
  29.837 -    return bits_in_bitmap + BitsPerWord - 1;
  29.838 -  }
  29.839 -public:
  29.840 -  GCLabBitMap(HeapWord* heap_start)
  29.841 -    : BitMap(bitmap_size_in_bits()),
  29.842 -      _cm(G1CollectedHeap::heap()->concurrent_mark()),
  29.843 -      _shifter(shifter()),
  29.844 -      _bitmap_word_covers_words(bitmap_word_covers_words()),
  29.845 -      _heap_start(heap_start),
  29.846 -      _gclab_word_size(gclab_word_size()),
  29.847 -      _real_start_word(NULL),
  29.848 -      _real_end_word(NULL),
  29.849 -      _start_word(NULL)
  29.850 -  {
  29.851 -    guarantee( size_in_words() >= bitmap_size_in_words(),
  29.852 -               "just making sure");
  29.853 -  }
  29.854 -
  29.855 -  inline unsigned heapWordToOffset(HeapWord* addr) {
  29.856 -    unsigned offset = (unsigned) pointer_delta(addr, _start_word) >> _shifter;
  29.857 -    assert(offset < size(), "offset should be within bounds");
  29.858 -    return offset;
  29.859 -  }
  29.860 -
  29.861 -  inline HeapWord* offsetToHeapWord(size_t offset) {
  29.862 -    HeapWord* addr =  _start_word + (offset << _shifter);
  29.863 -    assert(_real_start_word <= addr && addr < _real_end_word, "invariant");
  29.864 -    return addr;
  29.865 -  }
  29.866 -
  29.867 -  bool fields_well_formed() {
  29.868 -    bool ret1 = (_real_start_word == NULL) &&
  29.869 -                (_real_end_word == NULL) &&
  29.870 -                (_start_word == NULL);
  29.871 -    if (ret1)
  29.872 -      return true;
  29.873 -
  29.874 -    bool ret2 = _real_start_word >= _start_word &&
  29.875 -      _start_word < _real_end_word &&
  29.876 -      (_real_start_word + _gclab_word_size) == _real_end_word &&
  29.877 -      (_start_word + _gclab_word_size + _bitmap_word_covers_words)
  29.878 -                                                              > _real_end_word;
  29.879 -    return ret2;
  29.880 -  }
  29.881 -
  29.882 -  inline bool mark(HeapWord* addr) {
  29.883 -    guarantee(use_local_bitmaps, "invariant");
  29.884 -    assert(fields_well_formed(), "invariant");
  29.885 -
  29.886 -    if (addr >= _real_start_word && addr < _real_end_word) {
  29.887 -      assert(!isMarked(addr), "should not have already been marked");
  29.888 -
  29.889 -      // first mark it on the bitmap
  29.890 -      at_put(heapWordToOffset(addr), true);
  29.891 -
  29.892 -      return true;
  29.893 -    } else {
  29.894 -      return false;
  29.895 -    }
  29.896 -  }
  29.897 -
  29.898 -  inline bool isMarked(HeapWord* addr) {
  29.899 -    guarantee(use_local_bitmaps, "invariant");
  29.900 -    assert(fields_well_formed(), "invariant");
  29.901 -
  29.902 -    return at(heapWordToOffset(addr));
  29.903 -  }
  29.904 -
  29.905 -  void set_buffer(HeapWord* start) {
  29.906 -    guarantee(use_local_bitmaps, "invariant");
  29.907 -    clear();
  29.908 -
  29.909 -    assert(start != NULL, "invariant");
  29.910 -    _real_start_word = start;
  29.911 -    _real_end_word   = start + _gclab_word_size;
  29.912 -
  29.913 -    size_t diff =
  29.914 -      pointer_delta(start, _heap_start) % _bitmap_word_covers_words;
  29.915 -    _start_word = start - diff;
  29.916 -
  29.917 -    assert(fields_well_formed(), "invariant");
  29.918 -  }
  29.919 -
  29.920 -#ifndef PRODUCT
  29.921 -  void verify() {
  29.922 -    // verify that the marks have been propagated
  29.923 -    GCLabBitMapClosure cl(_cm, this);
  29.924 -    iterate(&cl);
  29.925 -  }
  29.926 -#endif // PRODUCT
  29.927 -
  29.928 -  void retire() {
  29.929 -    guarantee(use_local_bitmaps, "invariant");
  29.930 -    assert(fields_well_formed(), "invariant");
  29.931 -
  29.932 -    if (_start_word != NULL) {
  29.933 -      CMBitMap*       mark_bitmap = _cm->nextMarkBitMap();
  29.934 -
  29.935 -      // this means that the bitmap was set up for the GCLab
  29.936 -      assert(_real_start_word != NULL && _real_end_word != NULL, "invariant");
  29.937 -
  29.938 -      mark_bitmap->mostly_disjoint_range_union(this,
  29.939 -                                0, // always start from the start of the bitmap
  29.940 -                                _start_word,
  29.941 -                                size_in_words());
  29.942 -      _cm->grayRegionIfNecessary(MemRegion(_real_start_word, _real_end_word));
  29.943 -
  29.944 -#ifndef PRODUCT
  29.945 -      if (use_local_bitmaps && verify_local_bitmaps)
  29.946 -        verify();
  29.947 -#endif // PRODUCT
  29.948 -    } else {
  29.949 -      assert(_real_start_word == NULL && _real_end_word == NULL, "invariant");
  29.950 -    }
  29.951 -  }
  29.952 -
  29.953 -  static size_t bitmap_size_in_words() {
  29.954 -    return (bitmap_size_in_bits() + BitsPerWord - 1) / BitsPerWord;
  29.955 -  }
  29.956 -};
  29.957 -
  29.958 -#ifndef PRODUCT
  29.959 -
  29.960  bool GCLabBitMapClosure::do_bit(size_t offset) {
  29.961    HeapWord* addr = _bitmap->offsetToHeapWord(offset);
  29.962    guarantee(_cm->isMarked(oop(addr)), "it should be!");
  29.963    return true;
  29.964  }
  29.965 -
  29.966  #endif // PRODUCT
  29.967  
  29.968 -class G1ParGCAllocBuffer: public ParGCAllocBuffer {
  29.969 -private:
  29.970 -  bool        _retired;
  29.971 -  bool        _during_marking;
  29.972 -  GCLabBitMap _bitmap;
  29.973 -
  29.974 -public:
  29.975 -  G1ParGCAllocBuffer() :
  29.976 -    ParGCAllocBuffer(G1ParallelGCAllocBufferSize / HeapWordSize),
  29.977 -    _during_marking(G1CollectedHeap::heap()->mark_in_progress()),
  29.978 -    _bitmap(G1CollectedHeap::heap()->reserved_region().start()),
  29.979 -    _retired(false)
  29.980 -  { }
  29.981 -
  29.982 -  inline bool mark(HeapWord* addr) {
  29.983 -    guarantee(use_local_bitmaps, "invariant");
  29.984 -    assert(_during_marking, "invariant");
  29.985 -    return _bitmap.mark(addr);
  29.986 -  }
  29.987 -
  29.988 -  inline void set_buf(HeapWord* buf) {
  29.989 -    if (use_local_bitmaps && _during_marking)
  29.990 -      _bitmap.set_buffer(buf);
  29.991 -    ParGCAllocBuffer::set_buf(buf);
  29.992 -    _retired = false;
  29.993 -  }
  29.994 -
  29.995 -  inline void retire(bool end_of_gc, bool retain) {
  29.996 -    if (_retired)
  29.997 -      return;
  29.998 -    if (use_local_bitmaps && _during_marking) {
  29.999 -      _bitmap.retire();
 29.1000 -    }
 29.1001 -    ParGCAllocBuffer::retire(end_of_gc, retain);
 29.1002 -    _retired = true;
 29.1003 -  }
 29.1004 -};
 29.1005 -
 29.1006 -
 29.1007 -class G1ParScanThreadState : public StackObj {
 29.1008 -protected:
 29.1009 -  G1CollectedHeap* _g1h;
 29.1010 -  RefToScanQueue*  _refs;
 29.1011 -  DirtyCardQueue   _dcq;
 29.1012 -  CardTableModRefBS* _ct_bs;
 29.1013 -  G1RemSet* _g1_rem;
 29.1014 -
 29.1015 -  typedef GrowableArray<oop*> OverflowQueue;
 29.1016 -  OverflowQueue* _overflowed_refs;
 29.1017 -
 29.1018 -  G1ParGCAllocBuffer _alloc_buffers[GCAllocPurposeCount];
 29.1019 -  ageTable           _age_table;
 29.1020 -
 29.1021 -  size_t           _alloc_buffer_waste;
 29.1022 -  size_t           _undo_waste;
 29.1023 -
 29.1024 -  OopsInHeapRegionClosure*      _evac_failure_cl;
 29.1025 -  G1ParScanHeapEvacClosure*     _evac_cl;
 29.1026 -  G1ParScanPartialArrayClosure* _partial_scan_cl;
 29.1027 -
 29.1028 -  int _hash_seed;
 29.1029 -  int _queue_num;
 29.1030 -
 29.1031 -  int _term_attempts;
 29.1032 +G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num)
 29.1033 +  : _g1h(g1h),
 29.1034 +    _refs(g1h->task_queue(queue_num)),
 29.1035 +    _dcq(&g1h->dirty_card_queue_set()),
 29.1036 +    _ct_bs((CardTableModRefBS*)_g1h->barrier_set()),
 29.1037 +    _g1_rem(g1h->g1_rem_set()),
 29.1038 +    _hash_seed(17), _queue_num(queue_num),
 29.1039 +    _term_attempts(0),
 29.1040 +    _age_table(false),
 29.1041  #if G1_DETAILED_STATS
 29.1042 -  int _pushes, _pops, _steals, _steal_attempts;
 29.1043 -  int _overflow_pushes;
 29.1044 +    _pushes(0), _pops(0), _steals(0),
 29.1045 +    _steal_attempts(0),  _overflow_pushes(0),
 29.1046  #endif
 29.1047 -
 29.1048 -  double _start;
 29.1049 -  double _start_strong_roots;
 29.1050 -  double _strong_roots_time;
 29.1051 -  double _start_term;
 29.1052 -  double _term_time;
 29.1053 -
 29.1054 -  // Map from young-age-index (0 == not young, 1 is youngest) to
 29.1055 -  // surviving words. base is what we get back from the malloc call
 29.1056 -  size_t* _surviving_young_words_base;
 29.1057 -  // this points into the array, as we use the first few entries for padding
 29.1058 -  size_t* _surviving_young_words;
 29.1059 -
 29.1060 -#define PADDING_ELEM_NUM (64 / sizeof(size_t))
 29.1061 -
 29.1062 -  void   add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; }
 29.1063 -
 29.1064 -  void   add_to_undo_waste(size_t waste)         { _undo_waste += waste; }
 29.1065 -
 29.1066 -  DirtyCardQueue& dirty_card_queue()             { return _dcq;  }
 29.1067 -  CardTableModRefBS* ctbs()                      { return _ct_bs; }
 29.1068 -
 29.1069 -  void immediate_rs_update(HeapRegion* from, oop* p, int tid) {
 29.1070 -    if (!from->is_survivor()) {
 29.1071 -      _g1_rem->par_write_ref(from, p, tid);
 29.1072 -    }
 29.1073 -  }
 29.1074 -
 29.1075 -  void deferred_rs_update(HeapRegion* from, oop* p, int tid) {
 29.1076 -    // If the new value of the field points to the same region or
 29.1077 -    // is the to-space, we don't need to include it in the Rset updates.
 29.1078 -    if (!from->is_in_reserved(*p) && !from->is_survivor()) {
 29.1079 -      size_t card_index = ctbs()->index_for(p);
 29.1080 -      // If the card hasn't been added to the buffer, do it.
 29.1081 -      if (ctbs()->mark_card_deferred(card_index)) {
 29.1082 -        dirty_card_queue().enqueue((jbyte*)ctbs()->byte_for_index(card_index));
 29.1083 -      }
 29.1084 -    }
 29.1085 -  }
 29.1086 -
 29.1087 -public:
 29.1088 -  G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num)
 29.1089 -    : _g1h(g1h),
 29.1090 -      _refs(g1h->task_queue(queue_num)),
 29.1091 -      _dcq(&g1h->dirty_card_queue_set()),
 29.1092 -      _ct_bs((CardTableModRefBS*)_g1h->barrier_set()),
 29.1093 -      _g1_rem(g1h->g1_rem_set()),
 29.1094 -      _hash_seed(17), _queue_num(queue_num),
 29.1095 -      _term_attempts(0),
 29.1096 -      _age_table(false),
 29.1097 -#if G1_DETAILED_STATS
 29.1098 -      _pushes(0), _pops(0), _steals(0),
 29.1099 -      _steal_attempts(0),  _overflow_pushes(0),
 29.1100 -#endif
 29.1101 -      _strong_roots_time(0), _term_time(0),
 29.1102 -      _alloc_buffer_waste(0), _undo_waste(0)
 29.1103 -  {
 29.1104 -    // we allocate G1YoungSurvRateNumRegions plus one entries, since
 29.1105 -    // we "sacrifice" entry 0 to keep track of surviving bytes for
 29.1106 -    // non-young regions (where the age is -1)
 29.1107 -    // We also add a few elements at the beginning and at the end in
 29.1108 -    // an attempt to eliminate cache contention
 29.1109 -    size_t real_length = 1 + _g1h->g1_policy()->young_cset_length();
 29.1110 -    size_t array_length = PADDING_ELEM_NUM +
 29.1111 -                          real_length +
 29.1112 -                          PADDING_ELEM_NUM;
 29.1113 -    _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length);
 29.1114 -    if (_surviving_young_words_base == NULL)
 29.1115 -      vm_exit_out_of_memory(array_length * sizeof(size_t),
 29.1116 -                            "Not enough space for young surv histo.");
 29.1117 -    _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
 29.1118 -    memset(_surviving_young_words, 0, real_length * sizeof(size_t));
 29.1119 -
 29.1120 -    _overflowed_refs = new OverflowQueue(10);
 29.1121 -
 29.1122 -    _start = os::elapsedTime();
 29.1123 -  }
 29.1124 -
 29.1125 -  ~G1ParScanThreadState() {
 29.1126 -    FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base);
 29.1127 -  }
 29.1128 -
 29.1129 -  RefToScanQueue*   refs()            { return _refs;             }
 29.1130 -  OverflowQueue*    overflowed_refs() { return _overflowed_refs;  }
 29.1131 -  ageTable*         age_table()       { return &_age_table;       }
 29.1132 -
 29.1133 -  G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) {
 29.1134 -    return &_alloc_buffers[purpose];
 29.1135 -  }
 29.1136 -
 29.1137 -  size_t alloc_buffer_waste()                    { return _alloc_buffer_waste; }
 29.1138 -  size_t undo_waste()                            { return _undo_waste; }
 29.1139 -
 29.1140 -  void push_on_queue(oop* ref) {
 29.1141 -    assert(ref != NULL, "invariant");
 29.1142 -    assert(has_partial_array_mask(ref) || _g1h->obj_in_cs(*ref), "invariant");
 29.1143 -
 29.1144 -    if (!refs()->push(ref)) {
 29.1145 -      overflowed_refs()->push(ref);
 29.1146 -      IF_G1_DETAILED_STATS(note_overflow_push());
 29.1147 -    } else {
 29.1148 -      IF_G1_DETAILED_STATS(note_push());
 29.1149 -    }
 29.1150 -  }
 29.1151 -
 29.1152 -  void pop_from_queue(oop*& ref) {
 29.1153 -    if (!refs()->pop_local(ref)) {
 29.1154 -      ref = NULL;
 29.1155 -    } else {
 29.1156 -      assert(ref != NULL, "invariant");
 29.1157 -      assert(has_partial_array_mask(ref) || _g1h->obj_in_cs(*ref),
 29.1158 -             "invariant");
 29.1159 -
 29.1160 -      IF_G1_DETAILED_STATS(note_pop());
 29.1161 -    }
 29.1162 -  }
 29.1163 -
 29.1164 -  void pop_from_overflow_queue(oop*& ref) {
 29.1165 -    ref = overflowed_refs()->pop();
 29.1166 -  }
 29.1167 -
 29.1168 -  int refs_to_scan()                             { return refs()->size();                 }
 29.1169 -  int overflowed_refs_to_scan()                  { return overflowed_refs()->length();    }
 29.1170 -
 29.1171 -  void update_rs(HeapRegion* from, oop* p, int tid) {
 29.1172 -    if (G1DeferredRSUpdate) {
 29.1173 -      deferred_rs_update(from, p, tid);
 29.1174 -    } else {
 29.1175 -      immediate_rs_update(from, p, tid);
 29.1176 -    }
 29.1177 -  }
 29.1178 -
 29.1179 -  HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz) {
 29.1180 -
 29.1181 -    HeapWord* obj = NULL;
 29.1182 -    if (word_sz * 100 <
 29.1183 -        (size_t)(G1ParallelGCAllocBufferSize / HeapWordSize) *
 29.1184 -                                                  ParallelGCBufferWastePct) {
 29.1185 -      G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose);
 29.1186 -      add_to_alloc_buffer_waste(alloc_buf->words_remaining());
 29.1187 -      alloc_buf->retire(false, false);
 29.1188 -
 29.1189 -      HeapWord* buf =
 29.1190 -        _g1h->par_allocate_during_gc(purpose, G1ParallelGCAllocBufferSize / HeapWordSize);
 29.1191 -      if (buf == NULL) return NULL; // Let caller handle allocation failure.
 29.1192 -      // Otherwise.
 29.1193 -      alloc_buf->set_buf(buf);
 29.1194 -
 29.1195 -      obj = alloc_buf->allocate(word_sz);
 29.1196 -      assert(obj != NULL, "buffer was definitely big enough...");
 29.1197 -    } else {
 29.1198 -      obj = _g1h->par_allocate_during_gc(purpose, word_sz);
 29.1199 -    }
 29.1200 -    return obj;
 29.1201 -  }
 29.1202 -
 29.1203 -  HeapWord* allocate(GCAllocPurpose purpose, size_t word_sz) {
 29.1204 -    HeapWord* obj = alloc_buffer(purpose)->allocate(word_sz);
 29.1205 -    if (obj != NULL) return obj;
 29.1206 -    return allocate_slow(purpose, word_sz);
 29.1207 -  }
 29.1208 -
 29.1209 -  void undo_allocation(GCAllocPurpose purpose, HeapWord* obj, size_t word_sz) {
 29.1210 -    if (alloc_buffer(purpose)->contains(obj)) {
 29.1211 -      guarantee(alloc_buffer(purpose)->contains(obj + word_sz - 1),
 29.1212 -                "should contain whole object");
 29.1213 -      alloc_buffer(purpose)->undo_allocation(obj, word_sz);
 29.1214 -    } else {
 29.1215 -      CollectedHeap::fill_with_object(obj, word_sz);
 29.1216 -      add_to_undo_waste(word_sz);
 29.1217 -    }
 29.1218 -  }
 29.1219 -
 29.1220 -  void set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_cl) {
 29.1221 -    _evac_failure_cl = evac_failure_cl;
 29.1222 -  }
 29.1223 -  OopsInHeapRegionClosure* evac_failure_closure() {
 29.1224 -    return _evac_failure_cl;
 29.1225 -  }
 29.1226 -
 29.1227 -  void set_evac_closure(G1ParScanHeapEvacClosure* evac_cl) {
 29.1228 -    _evac_cl = evac_cl;
 29.1229 -  }
 29.1230 -
 29.1231 -  void set_partial_scan_closure(G1ParScanPartialArrayClosure* partial_scan_cl) {
 29.1232 -    _partial_scan_cl = partial_scan_cl;
 29.1233 -  }
 29.1234 -
 29.1235 -  int* hash_seed() { return &_hash_seed; }
 29.1236 -  int  queue_num() { return _queue_num; }
 29.1237 -
 29.1238 -  int term_attempts()   { return _term_attempts; }
 29.1239 -  void note_term_attempt()  { _term_attempts++; }
 29.1240 -
 29.1241 -#if G1_DETAILED_STATS
 29.1242 -  int pushes()          { return _pushes; }
 29.1243 -  int pops()            { return _pops; }
 29.1244 -  int steals()          { return _steals; }
 29.1245 -  int steal_attempts()  { return _steal_attempts; }
 29.1246 -  int overflow_pushes() { return _overflow_pushes; }
 29.1247 -
 29.1248 -  void note_push()          { _pushes++; }
 29.1249 -  void note_pop()           { _pops++; }
 29.1250 -  void note_steal()         { _steals++; }
 29.1251 -  void note_steal_attempt() { _steal_attempts++; }
 29.1252 -  void note_overflow_push() { _overflow_pushes++; }
 29.1253 -#endif
 29.1254 -
 29.1255 -  void start_strong_roots() {
 29.1256 -    _start_strong_roots = os::elapsedTime();
 29.1257 -  }
 29.1258 -  void end_strong_roots() {
 29.1259 -    _strong_roots_time += (os::elapsedTime() - _start_strong_roots);
 29.1260 -  }
 29.1261 -  double strong_roots_time() { return _strong_roots_time; }
 29.1262 -
 29.1263 -  void start_term_time() {
 29.1264 -    note_term_attempt();
 29.1265 -    _start_term = os::elapsedTime();
 29.1266 -  }
 29.1267 -  void end_term_time() {
 29.1268 -    _term_time += (os::elapsedTime() - _start_term);
 29.1269 -  }
 29.1270 -  double term_time() { return _term_time; }
 29.1271 -
 29.1272 -  double elapsed() {
 29.1273 -    return os::elapsedTime() - _start;
 29.1274 -  }
 29.1275 -
 29.1276 -  size_t* surviving_young_words() {
 29.1277 -    // We add on to hide entry 0 which accumulates surviving words for
 29.1278 -    // age -1 regions (i.e. non-young ones)
 29.1279 -    return _surviving_young_words;
 29.1280 -  }
 29.1281 -
 29.1282 -  void retire_alloc_buffers() {
 29.1283 -    for (int ap = 0; ap < GCAllocPurposeCount; ++ap) {
 29.1284 -      size_t waste = _alloc_buffers[ap].words_remaining();
 29.1285 -      add_to_alloc_buffer_waste(waste);
 29.1286 -      _alloc_buffers[ap].retire(true, false);
 29.1287 -    }
 29.1288 -  }
 29.1289 -
 29.1290 -private:
 29.1291 -  void deal_with_reference(oop* ref_to_scan) {
 29.1292 -    if (has_partial_array_mask(ref_to_scan)) {
 29.1293 -      _partial_scan_cl->do_oop_nv(ref_to_scan);
 29.1294 -    } else {
 29.1295 -      // Note: we can use "raw" versions of "region_containing" because
 29.1296 -      // "obj_to_scan" is definitely in the heap, and is not in a
 29.1297 -      // humongous region.
 29.1298 -      HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan);
 29.1299 -      _evac_cl->set_region(r);
 29.1300 -      _evac_cl->do_oop_nv(ref_to_scan);
 29.1301 -    }
 29.1302 -  }
 29.1303 -
 29.1304 -public:
 29.1305 -  void trim_queue() {
 29.1306 -    // I've replicated the loop twice, first to drain the overflow
 29.1307 -    // queue, second to drain the task queue. This is better than
 29.1308 -    // having a single loop, which checks both conditions and, inside
 29.1309 -    // it, either pops the overflow queue or the task queue, as each
 29.1310 -    // loop is tighter. Also, the decision to drain the overflow queue
 29.1311 -    // first is not arbitrary, as the overflow queue is not visible
 29.1312 -    // to the other workers, whereas the task queue is. So, we want to
 29.1313 -    // drain the "invisible" entries first, while allowing the other
 29.1314 -    // workers to potentially steal the "visible" entries.
 29.1315 -
 29.1316 -    while (refs_to_scan() > 0 || overflowed_refs_to_scan() > 0) {
 29.1317 -      while (overflowed_refs_to_scan() > 0) {
 29.1318 -        oop *ref_to_scan = NULL;
 29.1319 -        pop_from_overflow_queue(ref_to_scan);
 29.1320 -        assert(ref_to_scan != NULL, "invariant");
 29.1321 -        // We shouldn't have pushed it on the queue if it was not
 29.1322 -        // pointing into the CSet.
 29.1323 -        assert(ref_to_scan != NULL, "sanity");
 29.1324 -        assert(has_partial_array_mask(ref_to_scan) ||
 29.1325 -                                      _g1h->obj_in_cs(*ref_to_scan), "sanity");
 29.1326 -
 29.1327 -        deal_with_reference(ref_to_scan);
 29.1328 -      }
 29.1329 -
 29.1330 -      while (refs_to_scan() > 0) {
 29.1331 -        oop *ref_to_scan = NULL;
 29.1332 -        pop_from_queue(ref_to_scan);
 29.1333 -
 29.1334 -        if (ref_to_scan != NULL) {
 29.1335 -          // We shouldn't have pushed it on the queue if it was not
 29.1336 -          // pointing into the CSet.
 29.1337 -          assert(has_partial_array_mask(ref_to_scan) ||
 29.1338 -                                      _g1h->obj_in_cs(*ref_to_scan), "sanity");
 29.1339 -
 29.1340 -          deal_with_reference(ref_to_scan);
 29.1341 -        }
 29.1342 -      }
 29.1343 -    }
 29.1344 -  }
 29.1345 -};
 29.1346 +    _strong_roots_time(0), _term_time(0),
 29.1347 +    _alloc_buffer_waste(0), _undo_waste(0)
 29.1348 +{
 29.1349 +  // we allocate G1YoungSurvRateNumRegions plus one entries, since
 29.1350 +  // we "sacrifice" entry 0 to keep track of surviving bytes for
 29.1351 +  // non-young regions (where the age is -1)
 29.1352 +  // We also add a few elements at the beginning and at the end in
 29.1353 +  // an attempt to eliminate cache contention
 29.1354 +  size_t real_length = 1 + _g1h->g1_policy()->young_cset_length();
 29.1355 +  size_t array_length = PADDING_ELEM_NUM +
 29.1356 +                        real_length +
 29.1357 +                        PADDING_ELEM_NUM;
 29.1358 +  _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length);
 29.1359 +  if (_surviving_young_words_base == NULL)
 29.1360 +    vm_exit_out_of_memory(array_length * sizeof(size_t),
 29.1361 +                          "Not enough space for young surv histo.");
 29.1362 +  _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
 29.1363 +  memset(_surviving_young_words, 0, real_length * sizeof(size_t));
 29.1364 +
 29.1365 +  _overflowed_refs = new OverflowQueue(10);
 29.1366 +
 29.1367 +  _start = os::elapsedTime();
 29.1368 +}
 29.1369  
 29.1370  G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
 29.1371    _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()),
 29.1372    _par_scan_state(par_scan_state) { }
 29.1373  
 29.1374 -// This closure is applied to the fields of the objects that have just been copied.
 29.1375 -// Should probably be made inline and moved in g1OopClosures.inline.hpp.
 29.1376 -void G1ParScanClosure::do_oop_nv(oop* p) {
 29.1377 -  oop obj = *p;
 29.1378 -
 29.1379 -  if (obj != NULL) {
 29.1380 -    if (_g1->in_cset_fast_test(obj)) {
 29.1381 -      // We're not going to even bother checking whether the object is
 29.1382 -      // already forwarded or not, as this usually causes an immediate
 29.1383 -      // stall. We'll try to prefetch the object (for write, given that
 29.1384 -      // we might need to install the forwarding reference) and we'll
 29.1385 -      // get back to it when pop it from the queue
 29.1386 -      Prefetch::write(obj->mark_addr(), 0);
 29.1387 -      Prefetch::read(obj->mark_addr(), (HeapWordSize*2));
 29.1388 -
 29.1389 -      // slightly paranoid test; I'm trying to catch potential
 29.1390 -      // problems before we go into push_on_queue to know where the
 29.1391 -      // problem is coming from
 29.1392 -      assert(obj == *p, "the value of *p should not have changed");
 29.1393 -      _par_scan_state->push_on_queue(p);
 29.1394 -    } else {
 29.1395 -      _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num());
 29.1396 -    }
 29.1397 -  }
 29.1398 -}
 29.1399 -
 29.1400 -void G1ParCopyHelper::mark_forwardee(oop* p) {
 29.1401 +template <class T> void G1ParCopyHelper::mark_forwardee(T* p) {
 29.1402    // This is called _after_ do_oop_work has been called, hence after
 29.1403    // the object has been relocated to its new location and *p points
 29.1404    // to its new location.
 29.1405  
 29.1406 -  oop thisOop = *p;
 29.1407 -  if (thisOop != NULL) {
 29.1408 -    assert((_g1->evacuation_failed()) || (!_g1->obj_in_cs(thisOop)),
 29.1409 +  T heap_oop = oopDesc::load_heap_oop(p);
 29.1410 +  if (!oopDesc::is_null(heap_oop)) {
 29.1411 +    oop obj = oopDesc::decode_heap_oop(heap_oop);
 29.1412 +    assert((_g1->evacuation_failed()) || (!_g1->obj_in_cs(obj)),
 29.1413             "shouldn't still be in the CSet if evacuation didn't fail.");
 29.1414 -    HeapWord* addr = (HeapWord*)thisOop;
 29.1415 +    HeapWord* addr = (HeapWord*)obj;
 29.1416      if (_g1->is_in_g1_reserved(addr))
 29.1417        _cm->grayRoot(oop(addr));
 29.1418    }
 29.1419 @@ -4191,7 +3691,8 @@
 29.1420  
 29.1421      if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) {
 29.1422        arrayOop(old)->set_length(0);
 29.1423 -      _par_scan_state->push_on_queue(set_partial_array_mask(old));
 29.1424 +      oop* old_p = set_partial_array_mask(old);
 29.1425 +      _par_scan_state->push_on_queue(old_p);
 29.1426      } else {
 29.1427        // No point in using the slower heap_region_containing() method,
 29.1428        // given that we know obj is in the heap.
 29.1429 @@ -4205,11 +3706,11 @@
 29.1430    return obj;
 29.1431  }
 29.1432  
 29.1433 -template<bool do_gen_barrier, G1Barrier barrier,
 29.1434 -         bool do_mark_forwardee, bool skip_cset_test>
 29.1435 -void G1ParCopyClosure<do_gen_barrier, barrier,
 29.1436 -                      do_mark_forwardee, skip_cset_test>::do_oop_work(oop* p) {
 29.1437 -  oop obj = *p;
 29.1438 +template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee, bool skip_cset_test>
 29.1439 +template <class T>
 29.1440 +void G1ParCopyClosure <do_gen_barrier, barrier, do_mark_forwardee, skip_cset_test>
 29.1441 +::do_oop_work(T* p) {
 29.1442 +  oop obj = oopDesc::load_decode_heap_oop(p);
 29.1443    assert(barrier != G1BarrierRS || obj != NULL,
 29.1444           "Precondition: G1BarrierRS implies obj is nonNull");
 29.1445  
 29.1446 @@ -4226,9 +3727,10 @@
 29.1447                             "into CS.", p, (void*) obj);
 29.1448  #endif
 29.1449      if (obj->is_forwarded()) {
 29.1450 -      *p = obj->forwardee();
 29.1451 +      oopDesc::encode_store_heap_oop(p, obj->forwardee());
 29.1452      } else {
 29.1453 -      *p = copy_to_survivor_space(obj);
 29.1454 +      oop copy_oop = copy_to_survivor_space(obj);
 29.1455 +      oopDesc::encode_store_heap_oop(p, copy_oop);
 29.1456      }
 29.1457      // When scanning the RS, we only care about objs in CS.
 29.1458      if (barrier == G1BarrierRS) {
 29.1459 @@ -4247,21 +3749,9 @@
 29.1460  }
 29.1461  
 29.1462  template void G1ParCopyClosure<false, G1BarrierEvac, false, true>::do_oop_work(oop* p);
 29.1463 -
 29.1464 -template<class T> void G1ParScanPartialArrayClosure::process_array_chunk(
 29.1465 -  oop obj, int start, int end) {
 29.1466 -  // process our set of indices (include header in first chunk)
 29.1467 -  assert(start < end, "invariant");
 29.1468 -  T* const base      = (T*)objArrayOop(obj)->base();
 29.1469 -  T* const start_addr = (start == 0) ? (T*) obj : base + start;
 29.1470 -  T* const end_addr   = base + end;
 29.1471 -  MemRegion mr((HeapWord*)start_addr, (HeapWord*)end_addr);
 29.1472 -  _scanner.set_region(_g1->heap_region_containing(obj));
 29.1473 -  obj->oop_iterate(&_scanner, mr);
 29.1474 -}
 29.1475 -
 29.1476 -void G1ParScanPartialArrayClosure::do_oop_nv(oop* p) {
 29.1477 -  assert(!UseCompressedOops, "Needs to be fixed to work with compressed oops");
 29.1478 +template void G1ParCopyClosure<false, G1BarrierEvac, false, true>::do_oop_work(narrowOop* p);
 29.1479 +
 29.1480 +template <class T> void G1ParScanPartialArrayClosure::do_oop_nv(T* p) {
 29.1481    assert(has_partial_array_mask(p), "invariant");
 29.1482    oop old = clear_partial_array_mask(p);
 29.1483    assert(old->is_objArray(), "must be obj array");
 29.1484 @@ -4281,19 +3771,19 @@
 29.1485      end = start + ParGCArrayScanChunk;
 29.1486      arrayOop(old)->set_length(end);
 29.1487      // Push remainder.
 29.1488 -    _par_scan_state->push_on_queue(set_partial_array_mask(old));
 29.1489 +    oop* old_p = set_partial_array_mask(old);
 29.1490 +    assert(arrayOop(old)->length() < obj->length(), "Empty push?");
 29.1491 +    _par_scan_state->push_on_queue(old_p);
 29.1492    } else {
 29.1493      // Restore length so that the heap remains parsable in
 29.1494      // case of evacuation failure.
 29.1495      arrayOop(old)->set_length(end);
 29.1496    }
 29.1497 -
 29.1498 +  _scanner.set_region(_g1->heap_region_containing_raw(obj));
 29.1499    // process our set of indices (include header in first chunk)
 29.1500 -  process_array_chunk<oop>(obj, start, end);
 29.1501 +  obj->oop_iterate_range(&_scanner, start, end);
 29.1502  }
 29.1503  
 29.1504 -int G1ScanAndBalanceClosure::_nq = 0;
 29.1505 -
 29.1506  class G1ParEvacuateFollowersClosure : public VoidClosure {
 29.1507  protected:
 29.1508    G1CollectedHeap*              _g1h;
 29.1509 @@ -4316,21 +3806,28 @@
 29.1510    void do_void() {
 29.1511      G1ParScanThreadState* pss = par_scan_state();
 29.1512      while (true) {
 29.1513 -      oop* ref_to_scan;
 29.1514        pss->trim_queue();
 29.1515        IF_G1_DETAILED_STATS(pss->note_steal_attempt());
 29.1516 -      if (queues()->steal(pss->queue_num(),
 29.1517 -                          pss->hash_seed(),
 29.1518 -                          ref_to_scan)) {
 29.1519 +
 29.1520 +      StarTask stolen_task;
 29.1521 +      if (queues()->steal(pss->queue_num(), pss->hash_seed(), stolen_task)) {
 29.1522          IF_G1_DETAILED_STATS(pss->note_steal());
 29.1523  
 29.1524          // slightly paranoid tests; I'm trying to catch potential
 29.1525          // problems before we go into push_on_queue to know where the
 29.1526          // problem is coming from
 29.1527 -        assert(ref_to_scan != NULL, "invariant");
 29.1528 -        assert(has_partial_array_mask(ref_to_scan) ||
 29.1529 -                                   _g1h->obj_in_cs(*ref_to_scan), "invariant");
 29.1530 -        pss->push_on_queue(ref_to_scan);
 29.1531 +        assert((oop*)stolen_task != NULL, "Error");
 29.1532 +        if (stolen_task.is_narrow()) {
 29.1533 +          assert(UseCompressedOops, "Error");
 29.1534 +          narrowOop* p = (narrowOop*) stolen_task;
 29.1535 +          assert(has_partial_array_mask(p) ||
 29.1536 +                 _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "Error");
 29.1537 +          pss->push_on_queue(p);
 29.1538 +        } else {
 29.1539 +          oop* p = (oop*) stolen_task;
 29.1540 +          assert(has_partial_array_mask(p) || _g1h->obj_in_cs(*p), "Error");
 29.1541 +          pss->push_on_queue(p);
 29.1542 +        }
 29.1543          continue;
 29.1544        }
 29.1545        pss->start_term_time();
 29.1546 @@ -4347,6 +3844,7 @@
 29.1547    G1CollectedHeap*       _g1h;
 29.1548    RefToScanQueueSet      *_queues;
 29.1549    ParallelTaskTerminator _terminator;
 29.1550 +  int _n_workers;
 29.1551  
 29.1552    Mutex _stats_lock;
 29.1553    Mutex* stats_lock() { return &_stats_lock; }
 29.1554 @@ -4362,7 +3860,8 @@
 29.1555        _g1h(g1h),
 29.1556        _queues(task_queues),
 29.1557        _terminator(workers, _queues),
 29.1558 -      _stats_lock(Mutex::leaf, "parallel G1 stats lock", true)
 29.1559 +      _stats_lock(Mutex::leaf, "parallel G1 stats lock", true),
 29.1560 +      _n_workers(workers)
 29.1561    {}
 29.1562  
 29.1563    RefToScanQueueSet* queues() { return _queues; }
 29.1564 @@ -4372,6 +3871,7 @@
 29.1565    }
 29.1566  
 29.1567    void work(int i) {
 29.1568 +    if (i >= _n_workers) return;  // no work needed this round
 29.1569      ResourceMark rm;
 29.1570      HandleMark   hm;
 29.1571  
 29.1572 @@ -4469,23 +3969,6 @@
 29.1573  
 29.1574  // *** Common G1 Evacuation Stuff
 29.1575  
 29.1576 -class G1CountClosure: public OopsInHeapRegionClosure {
 29.1577 -public:
 29.1578 -  int n;
 29.1579 -  G1CountClosure() : n(0) {}
 29.1580 -  void do_oop(narrowOop* p) {
 29.1581 -    guarantee(false, "NYI");
 29.1582 -  }
 29.1583 -  void do_oop(oop* p) {
 29.1584 -    oop obj = *p;
 29.1585 -    assert(obj != NULL && G1CollectedHeap::heap()->obj_in_cs(obj),
 29.1586 -           "Rem set closure called on non-rem-set pointer.");
 29.1587 -    n++;
 29.1588 -  }
 29.1589 -};
 29.1590 -
 29.1591 -static G1CountClosure count_closure;
 29.1592 -
 29.1593  void
 29.1594  G1CollectedHeap::
 29.1595  g1_process_strong_roots(bool collecting_perm_gen,
 29.1596 @@ -5357,7 +4840,7 @@
 29.1597    assert(_free_region_list == NULL, "Postcondition of loop.");
 29.1598    if (_free_region_list_size != 0) {
 29.1599      gclog_or_tty->print_cr("Size is %d.", _free_region_list_size);
 29.1600 -    print();
 29.1601 +    print_on(gclog_or_tty, true /* extended */);
 29.1602    }
 29.1603    assert(_free_region_list_size == 0, "Postconditions of loop.");
 29.1604  }
 29.1605 @@ -5535,8 +5018,3 @@
 29.1606  void G1CollectedHeap::g1_unimplemented() {
 29.1607    // Unimplemented();
 29.1608  }
 29.1609 -
 29.1610 -
 29.1611 -// Local Variables: ***
 29.1612 -// c-indentation-style: gnu ***
 29.1613 -// End: ***
    30.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Mon Jul 20 08:20:00 2009 -0700
    30.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Mon Jul 27 06:15:29 2009 -0700
    30.3 @@ -56,8 +56,8 @@
    30.4  #  define IF_G1_DETAILED_STATS(code)
    30.5  #endif
    30.6  
    30.7 -typedef GenericTaskQueue<oop*>    RefToScanQueue;
    30.8 -typedef GenericTaskQueueSet<oop*> RefToScanQueueSet;
    30.9 +typedef GenericTaskQueue<StarTask>    RefToScanQueue;
   30.10 +typedef GenericTaskQueueSet<StarTask> RefToScanQueueSet;
   30.11  
   30.12  typedef int RegionIdx_t;   // needs to hold [ 0..max_regions() )
   30.13  typedef int CardIdx_t;     // needs to hold [ 0..CardsPerRegion )
   30.14 @@ -700,6 +700,9 @@
   30.15    size_t g1_reserved_obj_bytes() { return _g1_reserved.byte_size(); }
   30.16    virtual size_t capacity() const;
   30.17    virtual size_t used() const;
   30.18 +  // This should be called when we're not holding the heap lock. The
   30.19 +  // result might be a bit inaccurate.
   30.20 +  size_t used_unlocked() const;
   30.21    size_t recalculate_used() const;
   30.22  #ifndef PRODUCT
   30.23    size_t recalculate_used_regions() const;
   30.24 @@ -1061,8 +1064,14 @@
   30.25  
   30.26    // Override; it uses the "prev" marking information
   30.27    virtual void verify(bool allow_dirty, bool silent);
   30.28 +  // Default behavior by calling print(tty);
   30.29    virtual void print() const;
   30.30 +  // This calls print_on(st, PrintHeapAtGCExtended).
   30.31    virtual void print_on(outputStream* st) const;
   30.32 +  // If extended is true, it will print out information for all
   30.33 +  // regions in the heap by calling print_on_extended(st).
   30.34 +  virtual void print_on(outputStream* st, bool extended) const;
   30.35 +  virtual void print_on_extended(outputStream* st) const;
   30.36  
   30.37    virtual void print_gc_threads_on(outputStream* st) const;
   30.38    virtual void gc_threads_do(ThreadClosure* tc) const;
   30.39 @@ -1265,6 +1274,552 @@
   30.40  
   30.41  };
   30.42  
   30.43 -// Local Variables: ***
   30.44 -// c-indentation-style: gnu ***
   30.45 -// End: ***
   30.46 +#define use_local_bitmaps         1
   30.47 +#define verify_local_bitmaps      0
   30.48 +#define oop_buffer_length       256
   30.49 +
   30.50 +#ifndef PRODUCT
   30.51 +class GCLabBitMap;
   30.52 +class GCLabBitMapClosure: public BitMapClosure {
   30.53 +private:
   30.54 +  ConcurrentMark* _cm;
   30.55 +  GCLabBitMap*    _bitmap;
   30.56 +
   30.57 +public:
   30.58 +  GCLabBitMapClosure(ConcurrentMark* cm,
   30.59 +                     GCLabBitMap* bitmap) {
   30.60 +    _cm     = cm;
   30.61 +    _bitmap = bitmap;
   30.62 +  }
   30.63 +
   30.64 +  virtual bool do_bit(size_t offset);
   30.65 +};
   30.66 +#endif // !PRODUCT
   30.67 +
   30.68 +class GCLabBitMap: public BitMap {
   30.69 +private:
   30.70 +  ConcurrentMark* _cm;
   30.71 +
   30.72 +  int       _shifter;
   30.73 +  size_t    _bitmap_word_covers_words;
   30.74 +
   30.75 +  // beginning of the heap
   30.76 +  HeapWord* _heap_start;
   30.77 +
   30.78 +  // this is the actual start of the GCLab
   30.79 +  HeapWord* _real_start_word;
   30.80 +
   30.81 +  // this is the actual end of the GCLab
   30.82 +  HeapWord* _real_end_word;
   30.83 +
   30.84 +  // this is the first word, possibly located before the actual start
   30.85 +  // of the GCLab, that corresponds to the first bit of the bitmap
   30.86 +  HeapWord* _start_word;
   30.87 +
   30.88 +  // size of a GCLab in words
   30.89 +  size_t _gclab_word_size;
   30.90 +
   30.91 +  static int shifter() {
   30.92 +    return MinObjAlignment - 1;
   30.93 +  }
   30.94 +
   30.95 +  // how many heap words does a single bitmap word corresponds to?
   30.96 +  static size_t bitmap_word_covers_words() {
   30.97 +    return BitsPerWord << shifter();
   30.98 +  }
   30.99 +
  30.100 +  static size_t gclab_word_size() {
  30.101 +    return G1ParallelGCAllocBufferSize / HeapWordSize;
  30.102 +  }
  30.103 +
  30.104 +  static size_t bitmap_size_in_bits() {
  30.105 +    size_t bits_in_bitmap = gclab_word_size() >> shifter();
  30.106 +    // We are going to ensure that the beginning of a word in this
  30.107 +    // bitmap also corresponds to the beginning of a word in the
  30.108 +    // global marking bitmap. To handle the case where a GCLab
  30.109 +    // starts from the middle of the bitmap, we need to add enough
  30.110 +    // space (i.e. up to a bitmap word) to ensure that we have
  30.111 +    // enough bits in the bitmap.
  30.112 +    return bits_in_bitmap + BitsPerWord - 1;
  30.113 +  }
  30.114 +public:
  30.115 +  GCLabBitMap(HeapWord* heap_start)
  30.116 +    : BitMap(bitmap_size_in_bits()),
  30.117 +      _cm(G1CollectedHeap::heap()->concurrent_mark()),
  30.118 +      _shifter(shifter()),
  30.119 +      _bitmap_word_covers_words(bitmap_word_covers_words()),
  30.120 +      _heap_start(heap_start),
  30.121 +      _gclab_word_size(gclab_word_size()),
  30.122 +      _real_start_word(NULL),
  30.123 +      _real_end_word(NULL),
  30.124 +      _start_word(NULL)
  30.125 +  {
  30.126 +    guarantee( size_in_words() >= bitmap_size_in_words(),
  30.127 +               "just making sure");
  30.128 +  }
  30.129 +
  30.130 +  inline unsigned heapWordToOffset(HeapWord* addr) {
  30.131 +    unsigned offset = (unsigned) pointer_delta(addr, _start_word) >> _shifter;
  30.132 +    assert(offset < size(), "offset should be within bounds");
  30.133 +    return offset;
  30.134 +  }
  30.135 +
  30.136 +  inline HeapWord* offsetToHeapWord(size_t offset) {
  30.137 +    HeapWord* addr =  _start_word + (offset << _shifter);
  30.138 +    assert(_real_start_word <= addr && addr < _real_end_word, "invariant");
  30.139 +    return addr;
  30.140 +  }
  30.141 +
  30.142 +  bool fields_well_formed() {
  30.143 +    bool ret1 = (_real_start_word == NULL) &&
  30.144 +                (_real_end_word == NULL) &&
  30.145 +                (_start_word == NULL);
  30.146 +    if (ret1)
  30.147 +      return true;
  30.148 +
  30.149 +    bool ret2 = _real_start_word >= _start_word &&
  30.150 +      _start_word < _real_end_word &&
  30.151 +      (_real_start_word + _gclab_word_size) == _real_end_word &&
  30.152 +      (_start_word + _gclab_word_size + _bitmap_word_covers_words)
  30.153 +                                                              > _real_end_word;
  30.154 +    return ret2;
  30.155 +  }
  30.156 +
  30.157 +  inline bool mark(HeapWord* addr) {
  30.158 +    guarantee(use_local_bitmaps, "invariant");
  30.159 +    assert(fields_well_formed(), "invariant");
  30.160 +
  30.161 +    if (addr >= _real_start_word && addr < _real_end_word) {
  30.162 +      assert(!isMarked(addr), "should not have already been marked");
  30.163 +
  30.164 +      // first mark it on the bitmap
  30.165 +      at_put(heapWordToOffset(addr), true);
  30.166 +
  30.167 +      return true;
  30.168 +    } else {
  30.169 +      return false;
  30.170 +    }
  30.171 +  }
  30.172 +
  30.173 +  inline bool isMarked(HeapWord* addr) {
  30.174 +    guarantee(use_local_bitmaps, "invariant");
  30.175 +    assert(fields_well_formed(), "invariant");
  30.176 +
  30.177 +    return at(heapWordToOffset(addr));
  30.178 +  }
  30.179 +
  30.180 +  void set_buffer(HeapWord* start) {
  30.181 +    guarantee(use_local_bitmaps, "invariant");
  30.182 +    clear();
  30.183 +
  30.184 +    assert(start != NULL, "invariant");
  30.185 +    _real_start_word = start;
  30.186 +    _real_end_word   = start + _gclab_word_size;
  30.187 +
  30.188 +    size_t diff =
  30.189 +      pointer_delta(start, _heap_start) % _bitmap_word_covers_words;
  30.190 +    _start_word = start - diff;
  30.191 +
  30.192 +    assert(fields_well_formed(), "invariant");
  30.193 +  }
  30.194 +
  30.195 +#ifndef PRODUCT
  30.196 +  void verify() {
  30.197 +    // verify that the marks have been propagated
  30.198 +    GCLabBitMapClosure cl(_cm, this);
  30.199 +    iterate(&cl);
  30.200 +  }
  30.201 +#endif // PRODUCT
  30.202 +
  30.203 +  void retire() {
  30.204 +    guarantee(use_local_bitmaps, "invariant");
  30.205 +    assert(fields_well_formed(), "invariant");
  30.206 +
  30.207 +    if (_start_word != NULL) {
  30.208 +      CMBitMap*       mark_bitmap = _cm->nextMarkBitMap();
  30.209 +
  30.210 +      // this means that the bitmap was set up for the GCLab
  30.211 +      assert(_real_start_word != NULL && _real_end_word != NULL, "invariant");
  30.212 +
  30.213 +      mark_bitmap->mostly_disjoint_range_union(this,
  30.214 +                                0, // always start from the start of the bitmap
  30.215 +                                _start_word,
  30.216 +                                size_in_words());
  30.217 +      _cm->grayRegionIfNecessary(MemRegion(_real_start_word, _real_end_word));
  30.218 +
  30.219 +#ifndef PRODUCT
  30.220 +      if (use_local_bitmaps && verify_local_bitmaps)
  30.221 +        verify();
  30.222 +#endif // PRODUCT
  30.223 +    } else {
  30.224 +      assert(_real_start_word == NULL && _real_end_word == NULL, "invariant");
  30.225 +    }
  30.226 +  }
  30.227 +
  30.228 +  static size_t bitmap_size_in_words() {
  30.229 +    return (bitmap_size_in_bits() + BitsPerWord - 1) / BitsPerWord;
  30.230 +  }
  30.231 +};
  30.232 +
  30.233 +class G1ParGCAllocBuffer: public ParGCAllocBuffer {
  30.234 +private:
  30.235 +  bool        _retired;
  30.236 +  bool        _during_marking;
  30.237 +  GCLabBitMap _bitmap;
  30.238 +
  30.239 +public:
  30.240 +  G1ParGCAllocBuffer() :
  30.241 +    ParGCAllocBuffer(G1ParallelGCAllocBufferSize / HeapWordSize),
  30.242 +    _during_marking(G1CollectedHeap::heap()->mark_in_progress()),
  30.243 +    _bitmap(G1CollectedHeap::heap()->reserved_region().start()),
  30.244 +    _retired(false)
  30.245 +  { }
  30.246 +
  30.247 +  inline bool mark(HeapWord* addr) {
  30.248 +    guarantee(use_local_bitmaps, "invariant");
  30.249 +    assert(_during_marking, "invariant");
  30.250 +    return _bitmap.mark(addr);
  30.251 +  }
  30.252 +
  30.253 +  inline void set_buf(HeapWord* buf) {
  30.254 +    if (use_local_bitmaps && _during_marking)
  30.255 +      _bitmap.set_buffer(buf);
  30.256 +    ParGCAllocBuffer::set_buf(buf);
  30.257 +    _retired = false;
  30.258 +  }
  30.259 +
  30.260 +  inline void retire(bool end_of_gc, bool retain) {
  30.261 +    if (_retired)
  30.262 +      return;
  30.263 +    if (use_local_bitmaps && _during_marking) {
  30.264 +      _bitmap.retire();
  30.265 +    }
  30.266 +    ParGCAllocBuffer::retire(end_of_gc, retain);
  30.267 +    _retired = true;
  30.268 +  }
  30.269 +};
  30.270 +
  30.271 +class G1ParScanThreadState : public StackObj {
  30.272 +protected:
  30.273 +  G1CollectedHeap* _g1h;
  30.274 +  RefToScanQueue*  _refs;
  30.275 +  DirtyCardQueue   _dcq;
  30.276 +  CardTableModRefBS* _ct_bs;
  30.277 +  G1RemSet* _g1_rem;
  30.278 +
  30.279 +  typedef GrowableArray<StarTask> OverflowQueue;
  30.280 +  OverflowQueue* _overflowed_refs;
  30.281 +
  30.282 +  G1ParGCAllocBuffer _alloc_buffers[GCAllocPurposeCount];
  30.283 +  ageTable           _age_table;
  30.284 +
  30.285 +  size_t           _alloc_buffer_waste;
  30.286 +  size_t           _undo_waste;
  30.287 +
  30.288 +  OopsInHeapRegionClosure*      _evac_failure_cl;
  30.289 +  G1ParScanHeapEvacClosure*     _evac_cl;
  30.290 +  G1ParScanPartialArrayClosure* _partial_scan_cl;
  30.291 +
  30.292 +  int _hash_seed;
  30.293 +  int _queue_num;
  30.294 +
  30.295 +  int _term_attempts;
  30.296 +#if G1_DETAILED_STATS
  30.297 +  int _pushes, _pops, _steals, _steal_attempts;
  30.298 +  int _overflow_pushes;
  30.299 +#endif
  30.300 +
  30.301 +  double _start;
  30.302 +  double _start_strong_roots;
  30.303 +  double _strong_roots_time;
  30.304 +  double _start_term;
  30.305 +  double _term_time;
  30.306 +
  30.307 +  // Map from young-age-index (0 == not young, 1 is youngest) to
  30.308 +  // surviving words. base is what we get back from the malloc call
  30.309 +  size_t* _surviving_young_words_base;
  30.310 +  // this points into the array, as we use the first few entries for padding
  30.311 +  size_t* _surviving_young_words;
  30.312 +
  30.313 +#define PADDING_ELEM_NUM (64 / sizeof(size_t))
  30.314 +
  30.315 +  void   add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; }
  30.316 +
  30.317 +  void   add_to_undo_waste(size_t waste)         { _undo_waste += waste; }
  30.318 +
  30.319 +  DirtyCardQueue& dirty_card_queue()             { return _dcq;  }
  30.320 +  CardTableModRefBS* ctbs()                      { return _ct_bs; }
  30.321 +
  30.322 +  template <class T> void immediate_rs_update(HeapRegion* from, T* p, int tid) {
  30.323 +    if (!from->is_survivor()) {
  30.324 +      _g1_rem->par_write_ref(from, p, tid);
  30.325 +    }
  30.326 +  }
  30.327 +
  30.328 +  template <class T> void deferred_rs_update(HeapRegion* from, T* p, int tid) {
  30.329 +    // If the new value of the field points to the same region or
  30.330 +    // is the to-space, we don't need to include it in the Rset updates.
  30.331 +    if (!from->is_in_reserved(oopDesc::load_decode_heap_oop(p)) && !from->is_survivor()) {
  30.332 +      size_t card_index = ctbs()->index_for(p);
  30.333 +      // If the card hasn't been added to the buffer, do it.
  30.334 +      if (ctbs()->mark_card_deferred(card_index)) {
  30.335 +        dirty_card_queue().enqueue((jbyte*)ctbs()->byte_for_index(card_index));
  30.336 +      }
  30.337 +    }
  30.338 +  }
  30.339 +
  30.340 +public:
  30.341 +  G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num);
  30.342 +
  30.343 +  ~G1ParScanThreadState() {
  30.344 +    FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base);
  30.345 +  }
  30.346 +
  30.347 +  RefToScanQueue*   refs()            { return _refs;             }
  30.348 +  OverflowQueue*    overflowed_refs() { return _overflowed_refs;  }
  30.349 +  ageTable*         age_table()       { return &_age_table;       }
  30.350 +
  30.351 +  G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) {
  30.352 +    return &_alloc_buffers[purpose];
  30.353 +  }
  30.354 +
  30.355 +  size_t alloc_buffer_waste()                    { return _alloc_buffer_waste; }
  30.356 +  size_t undo_waste()                            { return _undo_waste; }
  30.357 +
  30.358 +  template <class T> void push_on_queue(T* ref) {
  30.359 +    assert(ref != NULL, "invariant");
  30.360 +    assert(has_partial_array_mask(ref) ||
  30.361 +           _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(ref)), "invariant");
  30.362 +#ifdef ASSERT
  30.363 +    if (has_partial_array_mask(ref)) {
  30.364 +      oop p = clear_partial_array_mask(ref);
  30.365 +      // Verify that we point into the CS
  30.366 +      assert(_g1h->obj_in_cs(p), "Should be in CS");
  30.367 +    }
  30.368 +#endif
  30.369 +    if (!refs()->push(ref)) {
  30.370 +      overflowed_refs()->push(ref);
  30.371 +      IF_G1_DETAILED_STATS(note_overflow_push());
  30.372 +    } else {
  30.373 +      IF_G1_DETAILED_STATS(note_push());
  30.374 +    }
  30.375 +  }
  30.376 +
  30.377 +  void pop_from_queue(StarTask& ref) {
  30.378 +    if (refs()->pop_local(ref)) {
  30.379 +      assert((oop*)ref != NULL, "pop_local() returned true");
  30.380 +      assert(UseCompressedOops || !ref.is_narrow(), "Error");
  30.381 +      assert(has_partial_array_mask((oop*)ref) ||
  30.382 +             _g1h->obj_in_cs(ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)ref)
  30.383 +                                             : oopDesc::load_decode_heap_oop((oop*)ref)),
  30.384 +             "invariant");
  30.385 +      IF_G1_DETAILED_STATS(note_pop());
  30.386 +    } else {
  30.387 +      StarTask null_task;
  30.388 +      ref = null_task;
  30.389 +    }
  30.390 +  }
  30.391 +
  30.392 +  void pop_from_overflow_queue(StarTask& ref) {
  30.393 +    StarTask new_ref = overflowed_refs()->pop();
  30.394 +    assert((oop*)new_ref != NULL, "pop() from a local non-empty stack");
  30.395 +    assert(UseCompressedOops || !new_ref.is_narrow(), "Error");
  30.396 +    assert(has_partial_array_mask((oop*)new_ref) ||
  30.397 +           _g1h->obj_in_cs(new_ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)new_ref)
  30.398 +                                               : oopDesc::load_decode_heap_oop((oop*)new_ref)),
  30.399 +             "invariant");
  30.400 +    ref = new_ref;
  30.401 +  }
  30.402 +
  30.403 +  int refs_to_scan()                             { return refs()->size();                 }
  30.404 +  int overflowed_refs_to_scan()                  { return overflowed_refs()->length();    }
  30.405 +
  30.406 +  template <class T> void update_rs(HeapRegion* from, T* p, int tid) {
  30.407 +    if (G1DeferredRSUpdate) {
  30.408 +      deferred_rs_update(from, p, tid);
  30.409 +    } else {
  30.410 +      immediate_rs_update(from, p, tid);
  30.411 +    }
  30.412 +  }
  30.413 +
  30.414 +  HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz) {
  30.415 +
  30.416 +    HeapWord* obj = NULL;
  30.417 +    if (word_sz * 100 <
  30.418 +        (size_t)(G1ParallelGCAllocBufferSize / HeapWordSize) *
  30.419 +                                                  ParallelGCBufferWastePct) {
  30.420 +      G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose);
  30.421 +      add_to_alloc_buffer_waste(alloc_buf->words_remaining());
  30.422 +      alloc_buf->retire(false, false);
  30.423 +
  30.424 +      HeapWord* buf =
  30.425 +        _g1h->par_allocate_during_gc(purpose, G1ParallelGCAllocBufferSize / HeapWordSize);
  30.426 +      if (buf == NULL) return NULL; // Let caller handle allocation failure.
  30.427 +      // Otherwise.
  30.428 +      alloc_buf->set_buf(buf);
  30.429 +
  30.430 +      obj = alloc_buf->allocate(word_sz);
  30.431 +      assert(obj != NULL, "buffer was definitely big enough...");
  30.432 +    } else {
  30.433 +      obj = _g1h->par_allocate_during_gc(purpose, word_sz);
  30.434 +    }
  30.435 +    return obj;
  30.436 +  }
  30.437 +
  30.438 +  HeapWord* allocate(GCAllocPurpose purpose, size_t word_sz) {
  30.439 +    HeapWord* obj = alloc_buffer(purpose)->allocate(word_sz);
  30.440 +    if (obj != NULL) return obj;
  30.441 +    return allocate_slow(purpose, word_sz);
  30.442 +  }
  30.443 +
  30.444 +  void undo_allocation(GCAllocPurpose purpose, HeapWord* obj, size_t word_sz) {
  30.445 +    if (alloc_buffer(purpose)->contains(obj)) {
  30.446 +      assert(alloc_buffer(purpose)->contains(obj + word_sz - 1),
  30.447 +             "should contain whole object");
  30.448 +      alloc_buffer(purpose)->undo_allocation(obj, word_sz);
  30.449 +    } else {
  30.450 +      CollectedHeap::fill_with_object(obj, word_sz);
  30.451 +      add_to_undo_waste(word_sz);
  30.452 +    }
  30.453 +  }
  30.454 +
  30.455 +  void set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_cl) {
  30.456 +    _evac_failure_cl = evac_failure_cl;
  30.457 +  }
  30.458 +  OopsInHeapRegionClosure* evac_failure_closure() {
  30.459 +    return _evac_failure_cl;
  30.460 +  }
  30.461 +
  30.462 +  void set_evac_closure(G1ParScanHeapEvacClosure* evac_cl) {
  30.463 +    _evac_cl = evac_cl;
  30.464 +  }
  30.465 +
  30.466 +  void set_partial_scan_closure(G1ParScanPartialArrayClosure* partial_scan_cl) {
  30.467 +    _partial_scan_cl = partial_scan_cl;
  30.468 +  }
  30.469 +
  30.470 +  int* hash_seed() { return &_hash_seed; }
  30.471 +  int  queue_num() { return _queue_num; }
  30.472 +
  30.473 +  int term_attempts()   { return _term_attempts; }
  30.474 +  void note_term_attempt()  { _term_attempts++; }
  30.475 +
  30.476 +#if G1_DETAILED_STATS
  30.477 +  int pushes()          { return _pushes; }
  30.478 +  int pops()            { return _pops; }
  30.479 +  int steals()          { return _steals; }
  30.480 +  int steal_attempts()  { return _steal_attempts; }
  30.481 +  int overflow_pushes() { return _overflow_pushes; }
  30.482 +
  30.483 +  void note_push()          { _pushes++; }
  30.484 +  void note_pop()           { _pops++; }
  30.485 +  void note_steal()         { _steals++; }
  30.486 +  void note_steal_attempt() { _steal_attempts++; }
  30.487 +  void note_overflow_push() { _overflow_pushes++; }
  30.488 +#endif
  30.489 +
  30.490 +  void start_strong_roots() {
  30.491 +    _start_strong_roots = os::elapsedTime();
  30.492 +  }
  30.493 +  void end_strong_roots() {
  30.494 +    _strong_roots_time += (os::elapsedTime() - _start_strong_roots);
  30.495 +  }
  30.496 +  double strong_roots_time() { return _strong_roots_time; }
  30.497 +
  30.498 +  void start_term_time() {
  30.499 +    note_term_attempt();
  30.500 +    _start_term = os::elapsedTime();
  30.501 +  }
  30.502 +  void end_term_time() {
  30.503 +    _term_time += (os::elapsedTime() - _start_term);
  30.504 +  }
  30.505 +  double term_time() { return _term_time; }
  30.506 +
  30.507 +  double elapsed() {
  30.508 +    return os::elapsedTime() - _start;
  30.509 +  }
  30.510 +
  30.511 +  size_t* surviving_young_words() {
  30.512 +    // We add on to hide entry 0 which accumulates surviving words for
  30.513 +    // age -1 regions (i.e. non-young ones)
  30.514 +    return _surviving_young_words;
  30.515 +  }
  30.516 +
  30.517 +  void retire_alloc_buffers() {
  30.518 +    for (int ap = 0; ap < GCAllocPurposeCount; ++ap) {
  30.519 +      size_t waste = _alloc_buffers[ap].words_remaining();
  30.520 +      add_to_alloc_buffer_waste(waste);
  30.521 +      _alloc_buffers[ap].retire(true, false);
  30.522 +    }
  30.523 +  }
  30.524 +
  30.525 +private:
  30.526 +  template <class T> void deal_with_reference(T* ref_to_scan) {
  30.527 +    if (has_partial_array_mask(ref_to_scan)) {
  30.528 +      _partial_scan_cl->do_oop_nv(ref_to_scan);
  30.529 +    } else {
  30.530 +      // Note: we can use "raw" versions of "region_containing" because
  30.531 +      // "obj_to_scan" is definitely in the heap, and is not in a
  30.532 +      // humongous region.
  30.533 +      HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan);
  30.534 +      _evac_cl->set_region(r);
  30.535 +      _evac_cl->do_oop_nv(ref_to_scan);
  30.536 +    }
  30.537 +  }
  30.538 +
  30.539 +public:
  30.540 +  void trim_queue() {
  30.541 +    // I've replicated the loop twice, first to drain the overflow
  30.542 +    // queue, second to drain the task queue. This is better than
  30.543 +    // having a single loop, which checks both conditions and, inside
  30.544 +    // it, either pops the overflow queue or the task queue, as each
  30.545 +    // loop is tighter. Also, the decision to drain the overflow queue
  30.546 +    // first is not arbitrary, as the overflow queue is not visible
  30.547 +    // to the other workers, whereas the task queue is. So, we want to
  30.548 +    // drain the "invisible" entries first, while allowing the other
  30.549 +    // workers to potentially steal the "visible" entries.
  30.550 +
  30.551 +    while (refs_to_scan() > 0 || overflowed_refs_to_scan() > 0) {
  30.552 +      while (overflowed_refs_to_scan() > 0) {
  30.553 +        StarTask ref_to_scan;
  30.554 +        assert((oop*)ref_to_scan == NULL, "Constructed above");
  30.555 +        pop_from_overflow_queue(ref_to_scan);
  30.556 +        // We shouldn't have pushed it on the queue if it was not
  30.557 +        // pointing into the CSet.
  30.558 +        assert((oop*)ref_to_scan != NULL, "Follows from inner loop invariant");
  30.559 +        if (ref_to_scan.is_narrow()) {
  30.560 +          assert(UseCompressedOops, "Error");
  30.561 +          narrowOop* p = (narrowOop*)ref_to_scan;
  30.562 +          assert(!has_partial_array_mask(p) &&
  30.563 +                 _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity");
  30.564 +          deal_with_reference(p);
  30.565 +        } else {
  30.566 +          oop* p = (oop*)ref_to_scan;
  30.567 +          assert((has_partial_array_mask(p) && _g1h->obj_in_cs(clear_partial_array_mask(p))) ||
  30.568 +                 _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity");
  30.569 +          deal_with_reference(p);
  30.570 +        }
  30.571 +      }
  30.572 +
  30.573 +      while (refs_to_scan() > 0) {
  30.574 +        StarTask ref_to_scan;
  30.575 +        assert((oop*)ref_to_scan == NULL, "Constructed above");
  30.576 +        pop_from_queue(ref_to_scan);
  30.577 +        if ((oop*)ref_to_scan != NULL) {
  30.578 +          if (ref_to_scan.is_narrow()) {
  30.579 +            assert(UseCompressedOops, "Error");
  30.580 +            narrowOop* p = (narrowOop*)ref_to_scan;
  30.581 +            assert(!has_partial_array_mask(p) &&
  30.582 +                   _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity");
  30.583 +            deal_with_reference(p);
  30.584 +          } else {
  30.585 +            oop* p = (oop*)ref_to_scan;
  30.586 +            assert((has_partial_array_mask(p) && _g1h->obj_in_cs(clear_partial_array_mask(p))) ||
  30.587 +                  _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity");
  30.588 +            deal_with_reference(p);
  30.589 +          }
  30.590 +        }
  30.591 +      }
  30.592 +    }
  30.593 +  }
  30.594 +};
    31.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Mon Jul 20 08:20:00 2009 -0700
    31.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Mon Jul 27 06:15:29 2009 -0700
    31.3 @@ -293,10 +293,6 @@
    31.4    if (G1SteadyStateUsed < 50) {
    31.5      vm_exit_during_initialization("G1SteadyStateUsed must be at least 50%.");
    31.6    }
    31.7 -  if (UseConcMarkSweepGC) {
    31.8 -    vm_exit_during_initialization("-XX:+UseG1GC is incompatible with "
    31.9 -                                  "-XX:+UseConcMarkSweepGC.");
   31.10 -  }
   31.11  
   31.12    initialize_gc_policy_counters();
   31.13  
    32.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Mon Jul 20 08:20:00 2009 -0700
    32.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Mon Jul 27 06:15:29 2009 -0700
    32.3 @@ -1097,6 +1097,10 @@
    32.4      _recorded_survivor_tail    = tail;
    32.5    }
    32.6  
    32.7 +  size_t recorded_survivor_regions() {
    32.8 +    return _recorded_survivor_regions;
    32.9 +  }
   32.10 +
   32.11    void record_thread_age_table(ageTable* age_table)
   32.12    {
   32.13      _survivors_age_table.merge_par(age_table);
    33.1 --- a/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Mon Jul 20 08:20:00 2009 -0700
    33.2 +++ b/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Mon Jul 27 06:15:29 2009 -0700
    33.3 @@ -42,18 +42,6 @@
    33.4    virtual void set_region(HeapRegion* from) { _from = from; }
    33.5  };
    33.6  
    33.7 -
    33.8 -class G1ScanAndBalanceClosure : public OopClosure {
    33.9 -  G1CollectedHeap* _g1;
   33.10 -  static int _nq;
   33.11 -public:
   33.12 -  G1ScanAndBalanceClosure(G1CollectedHeap* g1) : _g1(g1) { }
   33.13 -  inline  void do_oop_nv(oop* p);
   33.14 -  inline  void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); }
   33.15 -  virtual void do_oop(oop* p);
   33.16 -  virtual void do_oop(narrowOop* p)    { guarantee(false, "NYI"); }
   33.17 -};
   33.18 -
   33.19  class G1ParClosureSuper : public OopsInHeapRegionClosure {
   33.20  protected:
   33.21    G1CollectedHeap* _g1;
   33.22 @@ -69,34 +57,32 @@
   33.23  public:
   33.24    G1ParScanClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
   33.25      G1ParClosureSuper(g1, par_scan_state) { }
   33.26 -  void do_oop_nv(oop* p);   // should be made inline
   33.27 -  inline  void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); }
   33.28 +  template <class T> void do_oop_nv(T* p);
   33.29    virtual void do_oop(oop* p)          { do_oop_nv(p); }
   33.30    virtual void do_oop(narrowOop* p)    { do_oop_nv(p); }
   33.31  };
   33.32  
   33.33 -#define G1_PARTIAL_ARRAY_MASK 1
   33.34 +#define G1_PARTIAL_ARRAY_MASK 0x2
   33.35  
   33.36 -inline bool has_partial_array_mask(oop* ref) {
   33.37 -  return (intptr_t) ref & G1_PARTIAL_ARRAY_MASK;
   33.38 +template <class T> inline bool has_partial_array_mask(T* ref) {
   33.39 +  return ((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) == G1_PARTIAL_ARRAY_MASK;
   33.40  }
   33.41  
   33.42 -inline oop* set_partial_array_mask(oop obj) {
   33.43 -  return (oop*) ((intptr_t) obj | G1_PARTIAL_ARRAY_MASK);
   33.44 +template <class T> inline T* set_partial_array_mask(T obj) {
   33.45 +  assert(((uintptr_t)obj & G1_PARTIAL_ARRAY_MASK) == 0, "Information loss!");
   33.46 +  return (T*) ((uintptr_t)obj | G1_PARTIAL_ARRAY_MASK);
   33.47  }
   33.48  
   33.49 -inline oop clear_partial_array_mask(oop* ref) {
   33.50 -  return oop((intptr_t) ref & ~G1_PARTIAL_ARRAY_MASK);
   33.51 +template <class T> inline oop clear_partial_array_mask(T* ref) {
   33.52 +  return oop((intptr_t)ref & ~G1_PARTIAL_ARRAY_MASK);
   33.53  }
   33.54  
   33.55  class G1ParScanPartialArrayClosure : public G1ParClosureSuper {
   33.56    G1ParScanClosure _scanner;
   33.57 -  template <class T> void process_array_chunk(oop obj, int start, int end);
   33.58  public:
   33.59    G1ParScanPartialArrayClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
   33.60      G1ParClosureSuper(g1, par_scan_state), _scanner(g1, par_scan_state) { }
   33.61 -  void do_oop_nv(oop* p);
   33.62 -  void do_oop_nv(narrowOop* p)      { guarantee(false, "NYI"); }
   33.63 +  template <class T> void do_oop_nv(T* p);
   33.64    virtual void do_oop(oop* p)       { do_oop_nv(p); }
   33.65    virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
   33.66  };
   33.67 @@ -105,7 +91,7 @@
   33.68  class G1ParCopyHelper : public G1ParClosureSuper {
   33.69    G1ParScanClosure *_scanner;
   33.70  protected:
   33.71 -  void mark_forwardee(oop* p);
   33.72 +  template <class T> void mark_forwardee(T* p);
   33.73    oop copy_to_survivor_space(oop obj);
   33.74  public:
   33.75    G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state,
   33.76 @@ -117,36 +103,35 @@
   33.77           bool do_mark_forwardee, bool skip_cset_test>
   33.78  class G1ParCopyClosure : public G1ParCopyHelper {
   33.79    G1ParScanClosure _scanner;
   33.80 -  void do_oop_work(oop* p);
   33.81 -  void do_oop_work(narrowOop* p) { guarantee(false, "NYI"); }
   33.82 +  template <class T> void do_oop_work(T* p);
   33.83  public:
   33.84    G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
   33.85      _scanner(g1, par_scan_state), G1ParCopyHelper(g1, par_scan_state, &_scanner) { }
   33.86 -  inline void do_oop_nv(oop* p) {
   33.87 +  template <class T> void do_oop_nv(T* p) {
   33.88      do_oop_work(p);
   33.89      if (do_mark_forwardee)
   33.90        mark_forwardee(p);
   33.91    }
   33.92 -  inline void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); }
   33.93    virtual void do_oop(oop* p)       { do_oop_nv(p); }
   33.94    virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
   33.95  };
   33.96  
   33.97  typedef G1ParCopyClosure<false, G1BarrierNone, false, false> G1ParScanExtRootClosure;
   33.98  typedef G1ParCopyClosure<true,  G1BarrierNone, false, false> G1ParScanPermClosure;
   33.99 +typedef G1ParCopyClosure<false, G1BarrierRS,   false, false> G1ParScanHeapRSClosure;
  33.100  typedef G1ParCopyClosure<false, G1BarrierNone, true,  false> G1ParScanAndMarkExtRootClosure;
  33.101  typedef G1ParCopyClosure<true,  G1BarrierNone, true,  false> G1ParScanAndMarkPermClosure;
  33.102 -typedef G1ParCopyClosure<false, G1BarrierRS,   false, false> G1ParScanHeapRSClosure;
  33.103  typedef G1ParCopyClosure<false, G1BarrierRS,   true,  false> G1ParScanAndMarkHeapRSClosure;
  33.104  // This is the only case when we set skip_cset_test. Basically, this
  33.105  // closure is (should?) only be called directly while we're draining
  33.106  // the overflow and task queues. In that case we know that the
  33.107  // reference in question points into the collection set, otherwise we
  33.108 -// would not have pushed it on the queue.
  33.109 -typedef G1ParCopyClosure<false, G1BarrierEvac, false, true> G1ParScanHeapEvacClosure;
  33.110 +// would not have pushed it on the queue. The following is defined in
  33.111 +// g1_specialized_oop_closures.hpp.
  33.112 +// typedef G1ParCopyClosure<false, G1BarrierEvac, false, true> G1ParScanHeapEvacClosure;
  33.113  // We need a separate closure to handle references during evacuation
  33.114 -// failure processing, as it cannot asume that the reference already
  33.115 - // points to the collection set (like G1ParScanHeapEvacClosure does).
  33.116 +// failure processing, as we cannot asume that the reference already
  33.117 +// points into the collection set (like G1ParScanHeapEvacClosure does).
  33.118  typedef G1ParCopyClosure<false, G1BarrierEvac, false, false> G1ParScanHeapEvacFailureClosure;
  33.119  
  33.120  class FilterIntoCSClosure: public OopClosure {
  33.121 @@ -158,10 +143,9 @@
  33.122                          G1CollectedHeap* g1, OopClosure* oc) :
  33.123      _dcto_cl(dcto_cl), _g1(g1), _oc(oc)
  33.124    {}
  33.125 -  inline void do_oop_nv(oop* p);
  33.126 -  inline void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); }
  33.127 -  virtual void do_oop(oop* p);
  33.128 -  virtual void do_oop(narrowOop* p)   { guarantee(false, "NYI"); }
  33.129 +  template <class T> void do_oop_nv(T* p);
  33.130 +  virtual void do_oop(oop* p)        { do_oop_nv(p); }
  33.131 +  virtual void do_oop(narrowOop* p)  { do_oop_nv(p); }
  33.132    bool apply_to_weak_ref_discovered_field() { return true; }
  33.133    bool do_header() { return false; }
  33.134  };
  33.135 @@ -174,10 +158,9 @@
  33.136                                       OopsInHeapRegionClosure* oc) :
  33.137      _g1(g1), _oc(oc)
  33.138    {}
  33.139 -  inline  void do_oop_nv(oop* p);
  33.140 -  inline  void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); }
  33.141 -  virtual void do_oop(oop* p);
  33.142 -  virtual void do_oop(narrowOop* p)    { guarantee(false, "NYI"); }
  33.143 +  template <class T> void do_oop_nv(T* p);
  33.144 +  virtual void do_oop(oop* p) { do_oop_nv(p); }
  33.145 +  virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
  33.146    bool apply_to_weak_ref_discovered_field() { return true; }
  33.147    bool do_header() { return false; }
  33.148    void set_region(HeapRegion* from) {
  33.149 @@ -195,10 +178,9 @@
  33.150                                              ConcurrentMark* cm)
  33.151    : _g1(g1), _oc(oc), _cm(cm) { }
  33.152  
  33.153 -  inline  void do_oop_nv(oop* p);
  33.154 -  inline  void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); }
  33.155 -  virtual void do_oop(oop* p);
  33.156 -  virtual void do_oop(narrowOop* p)    { guarantee(false, "NYI"); }
  33.157 +  template <class T> void do_oop_nv(T* p);
  33.158 +  virtual void do_oop(oop* p) { do_oop_nv(p); }
  33.159 +  virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
  33.160    bool apply_to_weak_ref_discovered_field() { return true; }
  33.161    bool do_header() { return false; }
  33.162    void set_region(HeapRegion* from) {
  33.163 @@ -213,10 +195,9 @@
  33.164    int _out_of_region;
  33.165  public:
  33.166    FilterOutOfRegionClosure(HeapRegion* r, OopClosure* oc);
  33.167 -  inline  void do_oop_nv(oop* p);
  33.168 -  inline  void do_oop_nv(narrowOop* p) { guarantee(false, "NYI"); }
  33.169 -  virtual void do_oop(oop* p);
  33.170 -  virtual void do_oop(narrowOop* p)   { guarantee(false, "NYI"); }
  33.171 +  template <class T> void do_oop_nv(T* p);
  33.172 +  virtual void do_oop(oop* p) { do_oop_nv(p); }
  33.173 +  virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
  33.174    bool apply_to_weak_ref_discovered_field() { return true; }
  33.175    bool do_header() { return false; }
  33.176    int out_of_region() { return _out_of_region; }
    34.1 --- a/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp	Mon Jul 20 08:20:00 2009 -0700
    34.2 +++ b/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp	Mon Jul 27 06:15:29 2009 -0700
    34.3 @@ -31,9 +31,10 @@
    34.4  // perf-critical inner loop.
    34.5  #define FILTERINTOCSCLOSURE_DOHISTOGRAMCOUNT 0
    34.6  
    34.7 -inline void FilterIntoCSClosure::do_oop_nv(oop* p) {
    34.8 -  oop obj = *p;
    34.9 -  if (obj != NULL && _g1->obj_in_cs(obj)) {
   34.10 +template <class T> inline void FilterIntoCSClosure::do_oop_nv(T* p) {
   34.11 +  T heap_oop = oopDesc::load_heap_oop(p);
   34.12 +  if (!oopDesc::is_null(heap_oop) &&
   34.13 +      _g1->obj_in_cs(oopDesc::decode_heap_oop_not_null(heap_oop))) {
   34.14      _oc->do_oop(p);
   34.15  #if FILTERINTOCSCLOSURE_DOHISTOGRAMCOUNT
   34.16      _dcto_cl->incr_count();
   34.17 @@ -41,44 +42,32 @@
   34.18    }
   34.19  }
   34.20  
   34.21 -inline void FilterIntoCSClosure::do_oop(oop* p)
   34.22 -{
   34.23 -  do_oop_nv(p);
   34.24 -}
   34.25 -
   34.26  #define FILTEROUTOFREGIONCLOSURE_DOHISTOGRAMCOUNT 0
   34.27  
   34.28 -inline void FilterOutOfRegionClosure::do_oop_nv(oop* p) {
   34.29 -  oop obj = *p;
   34.30 -  HeapWord* obj_hw = (HeapWord*)obj;
   34.31 -  if (obj_hw != NULL && (obj_hw < _r_bottom || obj_hw >= _r_end)) {
   34.32 -    _oc->do_oop(p);
   34.33 +template <class T> inline void FilterOutOfRegionClosure::do_oop_nv(T* p) {
   34.34 +  T heap_oop = oopDesc::load_heap_oop(p);
   34.35 +  if (!oopDesc::is_null(heap_oop)) {
   34.36 +    HeapWord* obj_hw = (HeapWord*)oopDesc::decode_heap_oop_not_null(heap_oop);
   34.37 +    if (obj_hw < _r_bottom || obj_hw >= _r_end) {
   34.38 +      _oc->do_oop(p);
   34.39  #if FILTEROUTOFREGIONCLOSURE_DOHISTOGRAMCOUNT
   34.40 -    _out_of_region++;
   34.41 +      _out_of_region++;
   34.42  #endif
   34.43 +    }
   34.44    }
   34.45  }
   34.46  
   34.47 -inline void FilterOutOfRegionClosure::do_oop(oop* p)
   34.48 -{
   34.49 -  do_oop_nv(p);
   34.50 -}
   34.51 -
   34.52 -inline void FilterInHeapRegionAndIntoCSClosure::do_oop_nv(oop* p) {
   34.53 -  oop obj = *p;
   34.54 -  if (obj != NULL && _g1->obj_in_cs(obj))
   34.55 +template <class T> inline void FilterInHeapRegionAndIntoCSClosure::do_oop_nv(T* p) {
   34.56 +  T heap_oop = oopDesc::load_heap_oop(p);
   34.57 +  if (!oopDesc::is_null(heap_oop) &&
   34.58 +      _g1->obj_in_cs(oopDesc::decode_heap_oop_not_null(heap_oop)))
   34.59      _oc->do_oop(p);
   34.60  }
   34.61  
   34.62 -inline void FilterInHeapRegionAndIntoCSClosure::do_oop(oop* p)
   34.63 -{
   34.64 -  do_oop_nv(p);
   34.65 -}
   34.66 -
   34.67 -
   34.68 -inline void FilterAndMarkInHeapRegionAndIntoCSClosure::do_oop_nv(oop* p) {
   34.69 -  oop obj = *p;
   34.70 -  if (obj != NULL) {
   34.71 +template <class T> inline void FilterAndMarkInHeapRegionAndIntoCSClosure::do_oop_nv(T* p) {
   34.72 +  T heap_oop = oopDesc::load_heap_oop(p);
   34.73 +  if (!oopDesc::is_null(heap_oop)) {
   34.74 +    oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
   34.75      HeapRegion* hr = _g1->heap_region_containing((HeapWord*) obj);
   34.76      if (hr != NULL) {
   34.77        if (hr->in_collection_set())
   34.78 @@ -89,24 +78,29 @@
   34.79    }
   34.80  }
   34.81  
   34.82 -inline void FilterAndMarkInHeapRegionAndIntoCSClosure::do_oop(oop* p)
   34.83 -{
   34.84 -  do_oop_nv(p);
   34.85 +// This closure is applied to the fields of the objects that have just been copied.
   34.86 +template <class T> inline void G1ParScanClosure::do_oop_nv(T* p) {
   34.87 +  T heap_oop = oopDesc::load_heap_oop(p);
   34.88 +
   34.89 +  if (!oopDesc::is_null(heap_oop)) {
   34.90 +    oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
   34.91 +    if (_g1->in_cset_fast_test(obj)) {
   34.92 +      // We're not going to even bother checking whether the object is
   34.93 +      // already forwarded or not, as this usually causes an immediate
   34.94 +      // stall. We'll try to prefetch the object (for write, given that
   34.95 +      // we might need to install the forwarding reference) and we'll
   34.96 +      // get back to it when pop it from the queue
   34.97 +      Prefetch::write(obj->mark_addr(), 0);
   34.98 +      Prefetch::read(obj->mark_addr(), (HeapWordSize*2));
   34.99 +
  34.100 +      // slightly paranoid test; I'm trying to catch potential
  34.101 +      // problems before we go into push_on_queue to know where the
  34.102 +      // problem is coming from
  34.103 +      assert(obj == oopDesc::load_decode_heap_oop(p),
  34.104 +             "p should still be pointing to obj");
  34.105 +      _par_scan_state->push_on_queue(p);
  34.106 +    } else {
  34.107 +      _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num());
  34.108 +    }
  34.109 +  }
  34.110  }
  34.111 -
  34.112 -inline void G1ScanAndBalanceClosure::do_oop_nv(oop* p) {
  34.113 -  RefToScanQueue* q;
  34.114 -  if (ParallelGCThreads > 0) {
  34.115 -    // Deal the work out equally.
  34.116 -    _nq = (_nq + 1) % ParallelGCThreads;
  34.117 -    q = _g1->task_queue(_nq);
  34.118 -  } else {
  34.119 -    q = _g1->task_queue(0);
  34.120 -  }
  34.121 -  bool nooverflow = q->push(p);
  34.122 -  guarantee(nooverflow, "Overflow during poplularity region processing");
  34.123 -}
  34.124 -
  34.125 -inline void G1ScanAndBalanceClosure::do_oop(oop* p) {
  34.126 -  do_oop_nv(p);
  34.127 -}
    35.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Mon Jul 20 08:20:00 2009 -0700
    35.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Mon Jul 27 06:15:29 2009 -0700
    35.3 @@ -65,11 +65,10 @@
    35.4    void set_region(HeapRegion* from) {
    35.5      _blk->set_region(from);
    35.6    }
    35.7 -  virtual void do_oop(narrowOop* p) {
    35.8 -    guarantee(false, "NYI");
    35.9 -  }
   35.10 -  virtual void do_oop(oop* p) {
   35.11 -    oop obj = *p;
   35.12 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
   35.13 +  virtual void do_oop(      oop* p) { do_oop_work(p); }
   35.14 +  template <class T> void do_oop_work(T* p) {
   35.15 +    oop obj = oopDesc::load_decode_heap_oop(p);
   35.16      if (_g1->obj_in_cs(obj)) _blk->do_oop(p);
   35.17    }
   35.18    bool apply_to_weak_ref_discovered_field() { return true; }
   35.19 @@ -110,11 +109,10 @@
   35.20  public:
   35.21    VerifyRSCleanCardOopClosure(G1CollectedHeap* g1) : _g1(g1) {}
   35.22  
   35.23 -  virtual void do_oop(narrowOop* p) {
   35.24 -    guarantee(false, "NYI");
   35.25 -  }
   35.26 -  virtual void do_oop(oop* p) {
   35.27 -    oop obj = *p;
   35.28 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
   35.29 +  virtual void do_oop(      oop* p) { do_oop_work(p); }
   35.30 +  template <class T> void do_oop_work(T* p) {
   35.31 +    oop obj = oopDesc::load_decode_heap_oop(p);
   35.32      HeapRegion* to = _g1->heap_region_containing(obj);
   35.33      guarantee(to == NULL || !to->in_collection_set(),
   35.34                "Missed a rem set member.");
   35.35 @@ -129,9 +127,9 @@
   35.36  {
   35.37    _seq_task = new SubTasksDone(NumSeqTasks);
   35.38    guarantee(n_workers() > 0, "There should be some workers");
   35.39 -  _new_refs = NEW_C_HEAP_ARRAY(GrowableArray<oop*>*, n_workers());
   35.40 +  _new_refs = NEW_C_HEAP_ARRAY(GrowableArray<OopOrNarrowOopStar>*, n_workers());
   35.41    for (uint i = 0; i < n_workers(); i++) {
   35.42 -    _new_refs[i] = new (ResourceObj::C_HEAP) GrowableArray<oop*>(8192,true);
   35.43 +    _new_refs[i] = new (ResourceObj::C_HEAP) GrowableArray<OopOrNarrowOopStar>(8192,true);
   35.44    }
   35.45  }
   35.46  
   35.47 @@ -140,7 +138,7 @@
   35.48    for (uint i = 0; i < n_workers(); i++) {
   35.49      delete _new_refs[i];
   35.50    }
   35.51 -  FREE_C_HEAP_ARRAY(GrowableArray<oop*>*, _new_refs);
   35.52 +  FREE_C_HEAP_ARRAY(GrowableArray<OopOrNarrowOopStar>*, _new_refs);
   35.53  }
   35.54  
   35.55  void CountNonCleanMemRegionClosure::do_MemRegion(MemRegion mr) {
   35.56 @@ -428,15 +426,15 @@
   35.57    }
   35.58  };
   35.59  
   35.60 -void
   35.61 -HRInto_G1RemSet::scanNewRefsRS(OopsInHeapRegionClosure* oc,
   35.62 -                                             int worker_i) {
   35.63 +template <class T> void
   35.64 +HRInto_G1RemSet::scanNewRefsRS_work(OopsInHeapRegionClosure* oc,
   35.65 +                                    int worker_i) {
   35.66    double scan_new_refs_start_sec = os::elapsedTime();
   35.67    G1CollectedHeap* g1h = G1CollectedHeap::heap();
   35.68    CardTableModRefBS* ct_bs = (CardTableModRefBS*) (g1h->barrier_set());
   35.69    for (int i = 0; i < _new_refs[worker_i]->length(); i++) {
   35.70 -    oop* p = _new_refs[worker_i]->at(i);
   35.71 -    oop obj = *p;
   35.72 +    T* p = (T*) _new_refs[worker_i]->at(i);
   35.73 +    oop obj = oopDesc::load_decode_heap_oop(p);
   35.74      // *p was in the collection set when p was pushed on "_new_refs", but
   35.75      // another thread may have processed this location from an RS, so it
   35.76      // might not point into the CS any longer.  If so, it's obviously been
   35.77 @@ -549,11 +547,10 @@
   35.78    G1CollectedHeap* _g1;
   35.79  public:
   35.80    UpdateRSetOopsIntoCSImmediate(G1CollectedHeap* g1) : _g1(g1) { }
   35.81 -  virtual void do_oop(narrowOop* p) {
   35.82 -    guarantee(false, "NYI");
   35.83 -  }
   35.84 -  virtual void do_oop(oop* p) {
   35.85 -    HeapRegion* to = _g1->heap_region_containing(*p);
   35.86 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
   35.87 +  virtual void do_oop(      oop* p) { do_oop_work(p); }
   35.88 +  template <class T> void do_oop_work(T* p) {
   35.89 +    HeapRegion* to = _g1->heap_region_containing(oopDesc::load_decode_heap_oop(p));
   35.90      if (to->in_collection_set()) {
   35.91        to->rem_set()->add_reference(p, 0);
   35.92      }
   35.93 @@ -567,11 +564,10 @@
   35.94  public:
   35.95    UpdateRSetOopsIntoCSDeferred(G1CollectedHeap* g1, DirtyCardQueue* dcq) :
   35.96      _g1(g1), _ct_bs((CardTableModRefBS*)_g1->barrier_set()), _dcq(dcq) { }
   35.97 -  virtual void do_oop(narrowOop* p) {
   35.98 -    guarantee(false, "NYI");
   35.99 -  }
  35.100 -  virtual void do_oop(oop* p) {
  35.101 -    oop obj = *p;
  35.102 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
  35.103 +  virtual void do_oop(      oop* p) { do_oop_work(p); }
  35.104 +  template <class T> void do_oop_work(T* p) {
  35.105 +    oop obj = oopDesc::load_decode_heap_oop(p);
  35.106      if (_g1->obj_in_cs(obj)) {
  35.107        size_t card_index = _ct_bs->index_for(p);
  35.108        if (_ct_bs->mark_card_deferred(card_index)) {
  35.109 @@ -581,10 +577,10 @@
  35.110    }
  35.111  };
  35.112  
  35.113 -void HRInto_G1RemSet::new_refs_iterate(OopClosure* cl) {
  35.114 +template <class T> void HRInto_G1RemSet::new_refs_iterate_work(OopClosure* cl) {
  35.115    for (size_t i = 0; i < n_workers(); i++) {
  35.116      for (int j = 0; j < _new_refs[i]->length(); j++) {
  35.117 -      oop* p = _new_refs[i]->at(j);
  35.118 +      T* p = (T*) _new_refs[i]->at(j);
  35.119        cl->do_oop(p);
  35.120      }
  35.121    }
    36.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.hpp	Mon Jul 20 08:20:00 2009 -0700
    36.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.hpp	Mon Jul 27 06:15:29 2009 -0700
    36.3 @@ -62,10 +62,12 @@
    36.4    // If "this" is of the given subtype, return "this", else "NULL".
    36.5    virtual HRInto_G1RemSet* as_HRInto_G1RemSet() { return NULL; }
    36.6  
    36.7 -  // Record, if necessary, the fact that *p (where "p" is in region "from")
    36.8 -  // has changed to its new value.
    36.9 +  // Record, if necessary, the fact that *p (where "p" is in region "from",
   36.10 +  // and is, a fortiori, required to be non-NULL) has changed to its new value.
   36.11    virtual void write_ref(HeapRegion* from, oop* p) = 0;
   36.12 +  virtual void write_ref(HeapRegion* from, narrowOop* p) = 0;
   36.13    virtual void par_write_ref(HeapRegion* from, oop* p, int tid) = 0;
   36.14 +  virtual void par_write_ref(HeapRegion* from, narrowOop* p, int tid) = 0;
   36.15  
   36.16    // Requires "region_bm" and "card_bm" to be bitmaps with 1 bit per region
   36.17    // or card, respectively, such that a region or card with a corresponding
   36.18 @@ -105,7 +107,9 @@
   36.19  
   36.20    // Nothing is necessary in the version below.
   36.21    void write_ref(HeapRegion* from, oop* p) {}
   36.22 +  void write_ref(HeapRegion* from, narrowOop* p) {}
   36.23    void par_write_ref(HeapRegion* from, oop* p, int tid) {}
   36.24 +  void par_write_ref(HeapRegion* from, narrowOop* p, int tid) {}
   36.25  
   36.26    void scrub(BitMap* region_bm, BitMap* card_bm) {}
   36.27    void scrub_par(BitMap* region_bm, BitMap* card_bm,
   36.28 @@ -143,8 +147,19 @@
   36.29    // their references into the collection summarized in "_new_refs".
   36.30    bool _par_traversal_in_progress;
   36.31    void set_par_traversal(bool b) { _par_traversal_in_progress = b; }
   36.32 -  GrowableArray<oop*>** _new_refs;
   36.33 -  void new_refs_iterate(OopClosure* cl);
   36.34 +  GrowableArray<OopOrNarrowOopStar>** _new_refs;
   36.35 +  template <class T> void new_refs_iterate_work(OopClosure* cl);
   36.36 +  void new_refs_iterate(OopClosure* cl) {
   36.37 +    if (UseCompressedOops) {
   36.38 +      new_refs_iterate_work<narrowOop>(cl);
   36.39 +    } else {
   36.40 +      new_refs_iterate_work<oop>(cl);
   36.41 +    }
   36.42 +  }
   36.43 +
   36.44 +protected:
   36.45 +  template <class T> void write_ref_nv(HeapRegion* from, T* p);
   36.46 +  template <class T> void par_write_ref_nv(HeapRegion* from, T* p, int tid);
   36.47  
   36.48  public:
   36.49    // This is called to reset dual hash tables after the gc pause
   36.50 @@ -161,7 +176,14 @@
   36.51    void prepare_for_oops_into_collection_set_do();
   36.52    void cleanup_after_oops_into_collection_set_do();
   36.53    void scanRS(OopsInHeapRegionClosure* oc, int worker_i);
   36.54 -  void scanNewRefsRS(OopsInHeapRegionClosure* oc, int worker_i);
   36.55 +  template <class T> void scanNewRefsRS_work(OopsInHeapRegionClosure* oc, int worker_i);
   36.56 +  void scanNewRefsRS(OopsInHeapRegionClosure* oc, int worker_i) {
   36.57 +    if (UseCompressedOops) {
   36.58 +      scanNewRefsRS_work<narrowOop>(oc, worker_i);
   36.59 +    } else {
   36.60 +      scanNewRefsRS_work<oop>(oc, worker_i);
   36.61 +    }
   36.62 +  }
   36.63    void updateRS(int worker_i);
   36.64    HeapRegion* calculateStartRegion(int i);
   36.65  
   36.66 @@ -172,12 +194,22 @@
   36.67  
   36.68    // Record, if necessary, the fact that *p (where "p" is in region "from",
   36.69    // which is required to be non-NULL) has changed to a new non-NULL value.
   36.70 -  inline void write_ref(HeapRegion* from, oop* p);
   36.71 -  // The "_nv" version is the same; it exists just so that it is not virtual.
   36.72 -  inline void write_ref_nv(HeapRegion* from, oop* p);
   36.73 +  // [Below the virtual version calls a non-virtual protected
   36.74 +  // workhorse that is templatified for narrow vs wide oop.]
   36.75 +  inline void write_ref(HeapRegion* from, oop* p) {
   36.76 +    write_ref_nv(from, p);
   36.77 +  }
   36.78 +  inline void write_ref(HeapRegion* from, narrowOop* p) {
   36.79 +    write_ref_nv(from, p);
   36.80 +  }
   36.81 +  inline void par_write_ref(HeapRegion* from, oop* p, int tid) {
   36.82 +    par_write_ref_nv(from, p, tid);
   36.83 +  }
   36.84 +  inline void par_write_ref(HeapRegion* from, narrowOop* p, int tid) {
   36.85 +    par_write_ref_nv(from, p, tid);
   36.86 +  }
   36.87  
   36.88 -  inline bool self_forwarded(oop obj);
   36.89 -  inline void par_write_ref(HeapRegion* from, oop* p, int tid);
   36.90 +  bool self_forwarded(oop obj);
   36.91  
   36.92    void scrub(BitMap* region_bm, BitMap* card_bm);
   36.93    void scrub_par(BitMap* region_bm, BitMap* card_bm,
   36.94 @@ -208,6 +240,9 @@
   36.95    HeapRegion* _from;
   36.96    HRInto_G1RemSet* _rs;
   36.97    int _worker_i;
   36.98 +
   36.99 +  template <class T> void do_oop_work(T* p);
  36.100 +
  36.101  public:
  36.102    UpdateRSOopClosure(HRInto_G1RemSet* rs, int worker_i = 0) :
  36.103      _from(NULL), _rs(rs), _worker_i(worker_i) {
  36.104 @@ -219,11 +254,10 @@
  36.105      _from = from;
  36.106    }
  36.107  
  36.108 -  virtual void do_oop(narrowOop* p);
  36.109 -  virtual void do_oop(oop* p);
  36.110 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
  36.111 +  virtual void do_oop(oop* p)       { do_oop_work(p); }
  36.112  
  36.113    // Override: this closure is idempotent.
  36.114    //  bool idempotent() { return true; }
  36.115    bool apply_to_weak_ref_discovered_field() { return true; }
  36.116  };
  36.117 -
    37.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp	Mon Jul 20 08:20:00 2009 -0700
    37.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp	Mon Jul 27 06:15:29 2009 -0700
    37.3 @@ -30,12 +30,8 @@
    37.4    }
    37.5  }
    37.6  
    37.7 -inline void HRInto_G1RemSet::write_ref_nv(HeapRegion* from, oop* p) {
    37.8 -  par_write_ref(from, p, 0);
    37.9 -}
   37.10 -
   37.11 -inline void HRInto_G1RemSet::write_ref(HeapRegion* from, oop* p) {
   37.12 -  write_ref_nv(from, p);
   37.13 +template <class T> inline void HRInto_G1RemSet::write_ref_nv(HeapRegion* from, T* p) {
   37.14 +  par_write_ref_nv(from, p, 0);
   37.15  }
   37.16  
   37.17  inline bool HRInto_G1RemSet::self_forwarded(oop obj) {
   37.18 @@ -43,8 +39,8 @@
   37.19    return result;
   37.20  }
   37.21  
   37.22 -inline void HRInto_G1RemSet::par_write_ref(HeapRegion* from, oop* p, int tid) {
   37.23 -  oop obj = *p;
   37.24 +template <class T> inline void HRInto_G1RemSet::par_write_ref_nv(HeapRegion* from, T* p, int tid) {
   37.25 +  oop obj = oopDesc::load_decode_heap_oop(p);
   37.26  #ifdef ASSERT
   37.27    // can't do because of races
   37.28    // assert(obj == NULL || obj->is_oop(), "expected an oop");
   37.29 @@ -71,7 +67,7 @@
   37.30      // false during the evacuation failure handing.
   37.31      if (_par_traversal_in_progress &&
   37.32          to->in_collection_set() && !self_forwarded(obj)) {
   37.33 -      _new_refs[tid]->push(p);
   37.34 +      _new_refs[tid]->push((void*)p);
   37.35        // Deferred updates to the Cset are either discarded (in the normal case),
   37.36        // or processed (if an evacuation failure occurs) at the end
   37.37        // of the collection.
   37.38 @@ -89,11 +85,7 @@
   37.39    }
   37.40  }
   37.41  
   37.42 -inline void UpdateRSOopClosure::do_oop(narrowOop* p) {
   37.43 -  guarantee(false, "NYI");
   37.44 -}
   37.45 -
   37.46 -inline void UpdateRSOopClosure::do_oop(oop* p) {
   37.47 +template <class T> inline void UpdateRSOopClosure::do_oop_work(T* p) {
   37.48    assert(_from != NULL, "from region must be non-NULL");
   37.49    _rs->par_write_ref(_from, p, _worker_i);
   37.50  }
    38.1 --- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp	Mon Jul 20 08:20:00 2009 -0700
    38.2 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp	Mon Jul 27 06:15:29 2009 -0700
    38.3 @@ -34,6 +34,7 @@
    38.4  
    38.5  
    38.6  void G1SATBCardTableModRefBS::enqueue(oop pre_val) {
    38.7 +  assert(pre_val->is_oop_or_null(true), "Error");
    38.8    if (!JavaThread::satb_mark_queue_set().active()) return;
    38.9    Thread* thr = Thread::current();
   38.10    if (thr->is_Java_thread()) {
   38.11 @@ -46,32 +47,31 @@
   38.12  }
   38.13  
   38.14  // When we know the current java thread:
   38.15 -void
   38.16 -G1SATBCardTableModRefBS::write_ref_field_pre_static(void* field,
   38.17 -                                                    oop newVal,
   38.18 +template <class T> void
   38.19 +G1SATBCardTableModRefBS::write_ref_field_pre_static(T* field,
   38.20 +                                                    oop new_val,
   38.21                                                      JavaThread* jt) {
   38.22    if (!JavaThread::satb_mark_queue_set().active()) return;
   38.23 -  assert(!UseCompressedOops, "Else will need to modify this to deal with narrowOop");
   38.24 -  oop preVal = *(oop*)field;
   38.25 -  if (preVal != NULL) {
   38.26 -    jt->satb_mark_queue().enqueue(preVal);
   38.27 +  T heap_oop = oopDesc::load_heap_oop(field);
   38.28 +  if (!oopDesc::is_null(heap_oop)) {
   38.29 +    oop pre_val = oopDesc::decode_heap_oop_not_null(heap_oop);
   38.30 +    assert(pre_val->is_oop(true /* ignore mark word */), "Error");
   38.31 +    jt->satb_mark_queue().enqueue(pre_val);
   38.32    }
   38.33  }
   38.34  
   38.35 -void
   38.36 -G1SATBCardTableModRefBS::write_ref_array_pre(MemRegion mr) {
   38.37 +template <class T> void
   38.38 +G1SATBCardTableModRefBS::write_ref_array_pre_work(T* dst, int count) {
   38.39    if (!JavaThread::satb_mark_queue_set().active()) return;
   38.40 -  assert(!UseCompressedOops, "Else will need to modify this to deal with narrowOop");
   38.41 -  oop* elem_ptr = (oop*)mr.start();
   38.42 -  while ((HeapWord*)elem_ptr < mr.end()) {
   38.43 -    oop elem = *elem_ptr;
   38.44 -    if (elem != NULL) enqueue(elem);
   38.45 -    elem_ptr++;
   38.46 +  T* elem_ptr = dst;
   38.47 +  for (int i = 0; i < count; i++, elem_ptr++) {
   38.48 +    T heap_oop = oopDesc::load_heap_oop(elem_ptr);
   38.49 +    if (!oopDesc::is_null(heap_oop)) {
   38.50 +      enqueue(oopDesc::decode_heap_oop_not_null(heap_oop));
   38.51 +    }
   38.52    }
   38.53  }
   38.54  
   38.55 -
   38.56 -
   38.57  G1SATBCardTableLoggingModRefBS::
   38.58  G1SATBCardTableLoggingModRefBS(MemRegion whole_heap,
   38.59                                 int max_covered_regions) :
    39.1 --- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp	Mon Jul 20 08:20:00 2009 -0700
    39.2 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp	Mon Jul 27 06:15:29 2009 -0700
    39.3 @@ -47,31 +47,41 @@
    39.4  
    39.5    // This notes that we don't need to access any BarrierSet data
    39.6    // structures, so this can be called from a static context.
    39.7 -  static void write_ref_field_pre_static(void* field, oop newVal) {
    39.8 -    assert(!UseCompressedOops, "Else needs to be templatized");
    39.9 -    oop preVal = *((oop*)field);
   39.10 -    if (preVal != NULL) {
   39.11 -      enqueue(preVal);
   39.12 +  template <class T> static void write_ref_field_pre_static(T* field, oop newVal) {
   39.13 +    T heap_oop = oopDesc::load_heap_oop(field);
   39.14 +    if (!oopDesc::is_null(heap_oop)) {
   39.15 +      enqueue(oopDesc::decode_heap_oop(heap_oop));
   39.16      }
   39.17    }
   39.18  
   39.19    // When we know the current java thread:
   39.20 -  static void write_ref_field_pre_static(void* field, oop newVal,
   39.21 -                                         JavaThread* jt);
   39.22 +  template <class T> static void write_ref_field_pre_static(T* field, oop newVal,
   39.23 +                                                            JavaThread* jt);
   39.24  
   39.25    // We export this to make it available in cases where the static
   39.26    // type of the barrier set is known.  Note that it is non-virtual.
   39.27 -  inline void inline_write_ref_field_pre(void* field, oop newVal) {
   39.28 +  template <class T> inline void inline_write_ref_field_pre(T* field, oop newVal) {
   39.29      write_ref_field_pre_static(field, newVal);
   39.30    }
   39.31  
   39.32 -  // This is the more general virtual version.
   39.33 -  void write_ref_field_pre_work(void* field, oop new_val) {
   39.34 +  // These are the more general virtual versions.
   39.35 +  virtual void write_ref_field_pre_work(oop* field, oop new_val) {
   39.36      inline_write_ref_field_pre(field, new_val);
   39.37    }
   39.38 +  virtual void write_ref_field_pre_work(narrowOop* field, oop new_val) {
   39.39 +    inline_write_ref_field_pre(field, new_val);
   39.40 +  }
   39.41 +  virtual void write_ref_field_pre_work(void* field, oop new_val) {
   39.42 +    guarantee(false, "Not needed");
   39.43 +  }
   39.44  
   39.45 -  virtual void write_ref_array_pre(MemRegion mr);
   39.46 -
   39.47 +  template <class T> void write_ref_array_pre_work(T* dst, int count);
   39.48 +  virtual void write_ref_array_pre(oop* dst, int count) {
   39.49 +    write_ref_array_pre_work(dst, count);
   39.50 +  }
   39.51 +  virtual void write_ref_array_pre(narrowOop* dst, int count) {
   39.52 +    write_ref_array_pre_work(dst, count);
   39.53 +  }
   39.54  };
   39.55  
   39.56  // Adds card-table logging to the post-barrier.
    40.1 --- a/src/share/vm/gc_implementation/g1/g1_globals.hpp	Mon Jul 20 08:20:00 2009 -0700
    40.2 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp	Mon Jul 27 06:15:29 2009 -0700
    40.3 @@ -80,9 +80,6 @@
    40.4    develop(bool, G1TraceConcurrentRefinement, false,                         \
    40.5            "Trace G1 concurrent refinement")                                 \
    40.6                                                                              \
    40.7 -  develop(bool, G1ConcMark, true,                                           \
    40.8 -          "If true, run concurrent marking for G1")                         \
    40.9 -                                                                            \
   40.10    product(intx, G1MarkStackSize, 2 * 1024 * 1024,                           \
   40.11            "Size of the mark stack for concurrent marking.")                 \
   40.12                                                                              \
    41.1 --- a/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp	Mon Jul 20 08:20:00 2009 -0700
    41.2 +++ b/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp	Mon Jul 27 06:15:29 2009 -0700
    41.3 @@ -37,14 +37,12 @@
    41.4  class G1ParCopyClosure;
    41.5  class G1ParScanClosure;
    41.6  
    41.7 -typedef G1ParCopyClosure<false, G1BarrierEvac, false, true>
    41.8 -                                                      G1ParScanHeapEvacClosure;
    41.9 +typedef G1ParCopyClosure<false, G1BarrierEvac, false, true> G1ParScanHeapEvacClosure;
   41.10  
   41.11  class FilterIntoCSClosure;
   41.12  class FilterOutOfRegionClosure;
   41.13  class FilterInHeapRegionAndIntoCSClosure;
   41.14  class FilterAndMarkInHeapRegionAndIntoCSClosure;
   41.15 -class G1ScanAndBalanceClosure;
   41.16  
   41.17  #ifdef FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES
   41.18  #error "FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES already defined."
   41.19 @@ -56,8 +54,7 @@
   41.20        f(FilterIntoCSClosure,_nv)                        \
   41.21        f(FilterOutOfRegionClosure,_nv)                   \
   41.22        f(FilterInHeapRegionAndIntoCSClosure,_nv)         \
   41.23 -      f(FilterAndMarkInHeapRegionAndIntoCSClosure,_nv)  \
   41.24 -      f(G1ScanAndBalanceClosure,_nv)
   41.25 +      f(FilterAndMarkInHeapRegionAndIntoCSClosure,_nv)
   41.26  
   41.27  #ifdef FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES
   41.28  #error "FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES already defined."
    42.1 --- a/src/share/vm/gc_implementation/g1/heapRegion.cpp	Mon Jul 20 08:20:00 2009 -0700
    42.2 +++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp	Mon Jul 27 06:15:29 2009 -0700
    42.3 @@ -66,16 +66,16 @@
    42.4    bool failures() { return _failures; }
    42.5    int n_failures() { return _n_failures; }
    42.6  
    42.7 -  virtual void do_oop(narrowOop* p) {
    42.8 -    guarantee(false, "NYI");
    42.9 -  }
   42.10 +  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
   42.11 +  virtual void do_oop(      oop* p) { do_oop_work(p); }
   42.12  
   42.13 -  void do_oop(oop* p) {
   42.14 +  template <class T> void do_oop_work(T* p) {
   42.15      assert(_containing_obj != NULL, "Precondition");
   42.16      assert(!_g1h->is_obj_dead_cond(_containing_obj, _use_prev_marking),
   42.17             "Precondition");
   42.18 -    oop obj = *p;
   42.19 -    if (obj != NULL) {
   42.20 +    T heap_oop = oopDesc::load_heap_oop(p);
   42.21 +    if (!oopDesc::is_null(heap_oop)) {
   42.22 +      oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
   42.23        bool failed = false;
   42.24        if (!_g1h->is_in_closed_subset(obj) ||
   42.25            _g1h->is_obj_dead_cond(obj, _use_prev_marking)) {
   42.26 @@ -106,8 +106,8 @@
   42.27        }
   42.28  
   42.29        if (!_g1h->full_collection()) {
   42.30 -        HeapRegion* from = _g1h->heap_region_containing(p);
   42.31 -        HeapRegion* to   = _g1h->heap_region_containing(*p);
   42.32 +        HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
   42.33 +        HeapRegion* to   = _g1h->heap_region_containing(obj);
   42.34          if (from != NULL && to != NULL &&
   42.35              from != to &&
   42.36              !to->isHumongous()) {
   42.37 @@ -534,13 +534,13 @@
   42.38    // Otherwise, find the obj that extends onto mr.start().
   42.39  
   42.40    assert(cur <= mr.start()
   42.41 -         && (oop(cur)->klass() == NULL ||
   42.42 +         && (oop(cur)->klass_or_null() == NULL ||
   42.43               cur + oop(cur)->size() > mr.start()),
   42.44           "postcondition of block_start");
   42.45    oop obj;
   42.46    while (cur < mr.end()) {
   42.47      obj = oop(cur);
   42.48 -    if (obj->klass() == NULL) {
   42.49 +    if (obj->klass_or_null() == NULL) {
   42.50        // Ran into an unparseable point.
   42.51        return cur;
   42.52      } else if (!g1h->is_obj_dead(obj)) {
   42.53 @@ -577,7 +577,7 @@
   42.54    assert(cur <= mr.start(), "Postcondition");
   42.55  
   42.56    while (cur <= mr.start()) {
   42.57 -    if (oop(cur)->klass() == NULL) {
   42.58 +    if (oop(cur)->klass_or_null() == NULL) {
   42.59        // Ran into an unparseable point.
   42.60        return cur;
   42.61      }
   42.62 @@ -591,7 +591,7 @@
   42.63    obj = oop(cur);
   42.64    // If we finish this loop...
   42.65    assert(cur <= mr.start()
   42.66 -         && obj->klass() != NULL
   42.67 +         && obj->klass_or_null() != NULL
   42.68           && cur + obj->size() > mr.start(),
   42.69           "Loop postcondition");
   42.70    if (!g1h->is_obj_dead(obj)) {
   42.71 @@ -601,7 +601,7 @@
   42.72    HeapWord* next;
   42.73    while (cur < mr.end()) {
   42.74      obj = oop(cur);
   42.75 -    if (obj->klass() == NULL) {
   42.76 +    if (obj->klass_or_null() == NULL) {
   42.77        // Ran into an unparseable point.
   42.78        return cur;
   42.79      };
   42.80 @@ -703,7 +703,7 @@
   42.81    }
   42.82    if (vl_cl.failures()) {
   42.83      gclog_or_tty->print_cr("Heap:");
   42.84 -    G1CollectedHeap::heap()->print();
   42.85 +    G1CollectedHeap::heap()->print_on(gclog_or_tty, true /* extended */);
   42.86      gclog_or_tty->print_cr("");
   42.87    }
   42.88    if (VerifyDuringGC &&
   42.89 @@ -781,8 +781,13 @@
   42.90      // will pick up the right saved_mark_word() as the high water mark
   42.91      // of the region. Either way, the behaviour will be correct.
   42.92      ContiguousSpace::set_saved_mark();
   42.93 +    OrderAccess::storestore();
   42.94      _gc_time_stamp = curr_gc_time_stamp;
   42.95 -    OrderAccess::fence();
   42.96 +    // The following fence is to force a flush of the writes above, but
   42.97 +    // is strictly not needed because when an allocating worker thread
   42.98 +    // calls set_saved_mark() it does so under the ParGCRareEvent_lock;
   42.99 +    // when the lock is released, the write will be flushed.
  42.100 +    // OrderAccess::fence();
  42.101    }
  42.102  }
  42.103  
    43.1 --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Mon Jul 20 08:20:00 2009 -0700
    43.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Mon Jul 27 06:15:29 2009 -0700
    43.3 @@ -126,7 +126,7 @@
    43.4      }
    43.5    }
    43.6  
    43.7 -  void add_reference_work(oop* from, bool par) {
    43.8 +  void add_reference_work(OopOrNarrowOopStar from, bool par) {
    43.9      // Must make this robust in case "from" is not in "_hr", because of
   43.10      // concurrency.
   43.11  
   43.12 @@ -173,11 +173,11 @@
   43.13      _bm.clear();
   43.14    }
   43.15  
   43.16 -  void add_reference(oop* from) {
   43.17 +  void add_reference(OopOrNarrowOopStar from) {
   43.18      add_reference_work(from, /*parallel*/ true);
   43.19    }
   43.20  
   43.21 -  void seq_add_reference(oop* from) {
   43.22 +  void seq_add_reference(OopOrNarrowOopStar from) {
   43.23      add_reference_work(from, /*parallel*/ false);
   43.24    }
   43.25  
   43.26 @@ -220,7 +220,7 @@
   43.27    }
   43.28  
   43.29    // Requires "from" to be in "hr()".
   43.30 -  bool contains_reference(oop* from) const {
   43.31 +  bool contains_reference(OopOrNarrowOopStar from) const {
   43.32      assert(hr()->is_in_reserved(from), "Precondition.");
   43.33      size_t card_ind = pointer_delta(from, hr()->bottom(),
   43.34                                      CardTableModRefBS::card_size);
   43.35 @@ -394,7 +394,7 @@
   43.36    void set_next(PosParPRT* nxt) { _next = nxt; }
   43.37    PosParPRT** next_addr() { return &_next; }
   43.38  
   43.39 -  void add_reference(oop* from, int tid) {
   43.40 +  void add_reference(OopOrNarrowOopStar from, int tid) {
   43.41      // Expand if necessary.
   43.42      PerRegionTable** pt = par_tables();
   43.43      if (par_tables() == NULL && tid > 0 && hr()->is_gc_alloc_region()) {
   43.44 @@ -447,7 +447,7 @@
   43.45      return res;
   43.46    }
   43.47  
   43.48 -  bool contains_reference(oop* from) const {
   43.49 +  bool contains_reference(OopOrNarrowOopStar from) const {
   43.50      if (PerRegionTable::contains_reference(from)) return true;
   43.51      if (_par_tables != NULL) {
   43.52        for (int i = 0; i < HeapRegionRemSet::num_par_rem_sets()-1; i++) {
   43.53 @@ -564,12 +564,15 @@
   43.54  }
   43.55  #endif
   43.56  
   43.57 -void OtherRegionsTable::add_reference(oop* from, int tid) {
   43.58 +void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, int tid) {
   43.59    size_t cur_hrs_ind = hr()->hrs_index();
   43.60  
   43.61  #if HRRS_VERBOSE
   43.62    gclog_or_tty->print_cr("ORT::add_reference_work(" PTR_FORMAT "->" PTR_FORMAT ").",
   43.63 -                                                  from, *from);
   43.64 +                                                  from,
   43.65 +                                                  UseCompressedOops
   43.66 +                                                  ? oopDesc::load_decode_heap_oop((narrowOop*)from)
   43.67 +                                                  : oopDesc::load_decode_heap_oop((oop*)from));
   43.68  #endif
   43.69  
   43.70    int from_card = (int)(uintptr_t(from) >> CardTableModRefBS::card_shift);
   43.71 @@ -1021,13 +1024,13 @@
   43.72    }
   43.73  }
   43.74  
   43.75 -bool OtherRegionsTable::contains_reference(oop* from) const {
   43.76 +bool OtherRegionsTable::contains_reference(OopOrNarrowOopStar from) const {
   43.77    // Cast away const in this case.
   43.78    MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag);
   43.79    return contains_reference_locked(from);
   43.80  }
   43.81  
   43.82 -bool OtherRegionsTable::contains_reference_locked(oop* from) const {
   43.83 +bool OtherRegionsTable::contains_reference_locked(OopOrNarrowOopStar from) const {
   43.84    HeapRegion* hr = _g1h->heap_region_containing_raw(from);
   43.85    if (hr == NULL) return false;
   43.86    RegionIdx_t hr_ind = (RegionIdx_t) hr->hrs_index();
   43.87 @@ -1288,24 +1291,24 @@
   43.88  
   43.89  
   43.90  
   43.91 -oop**        HeapRegionRemSet::_recorded_oops = NULL;
   43.92 -HeapWord**   HeapRegionRemSet::_recorded_cards = NULL;
   43.93 -HeapRegion** HeapRegionRemSet::_recorded_regions = NULL;
   43.94 -int          HeapRegionRemSet::_n_recorded = 0;
   43.95 +OopOrNarrowOopStar* HeapRegionRemSet::_recorded_oops = NULL;
   43.96 +HeapWord**          HeapRegionRemSet::_recorded_cards = NULL;
   43.97 +HeapRegion**        HeapRegionRemSet::_recorded_regions = NULL;
   43.98 +int                 HeapRegionRemSet::_n_recorded = 0;
   43.99  
  43.100  HeapRegionRemSet::Event* HeapRegionRemSet::_recorded_events = NULL;
  43.101  int*         HeapRegionRemSet::_recorded_event_index = NULL;
  43.102  int          HeapRegionRemSet::_n_recorded_events = 0;
  43.103  
  43.104 -void HeapRegionRemSet::record(HeapRegion* hr, oop* f) {
  43.105 +void HeapRegionRemSet::record(HeapRegion* hr, OopOrNarrowOopStar f) {
  43.106    if (_recorded_oops == NULL) {
  43.107      assert(_n_recorded == 0
  43.108             && _recorded_cards == NULL
  43.109             && _recorded_regions == NULL,
  43.110             "Inv");
  43.111 -    _recorded_oops = NEW_C_HEAP_ARRAY(oop*, MaxRecorded);
  43.112 -    _recorded_cards = NEW_C_HEAP_ARRAY(HeapWord*, MaxRecorded);
  43.113 -    _recorded_regions = NEW_C_HEAP_ARRAY(HeapRegion*, MaxRecorded);
  43.114 +    _recorded_oops    = NEW_C_HEAP_ARRAY(OopOrNarrowOopStar, MaxRecorded);
  43.115 +    _recorded_cards   = NEW_C_HEAP_ARRAY(HeapWord*,          MaxRecorded);
  43.116 +    _recorded_regions = NEW_C_HEAP_ARRAY(HeapRegion*,        MaxRecorded);
  43.117    }
  43.118    if (_n_recorded == MaxRecorded) {
  43.119      gclog_or_tty->print_cr("Filled up 'recorded' (%d).", MaxRecorded);
  43.120 @@ -1408,21 +1411,21 @@
  43.121    HeapRegionRemSet* hrrs = hr0->rem_set();
  43.122  
  43.123    // Make three references from region 0x101...
  43.124 -  hrrs->add_reference((oop*)hr1_start);
  43.125 -  hrrs->add_reference((oop*)hr1_mid);
  43.126 -  hrrs->add_reference((oop*)hr1_last);
  43.127 +  hrrs->add_reference((OopOrNarrowOopStar)hr1_start);
  43.128 +  hrrs->add_reference((OopOrNarrowOopStar)hr1_mid);
  43.129 +  hrrs->add_reference((OopOrNarrowOopStar)hr1_last);
  43.130  
  43.131 -  hrrs->add_reference((oop*)hr2_start);
  43.132 -  hrrs->add_reference((oop*)hr2_mid);
  43.133 -  hrrs->add_reference((oop*)hr2_last);
  43.134 +  hrrs->add_reference((OopOrNarrowOopStar)hr2_start);
  43.135 +  hrrs->add_reference((OopOrNarrowOopStar)hr2_mid);
  43.136 +  hrrs->add_reference((OopOrNarrowOopStar)hr2_last);
  43.137  
  43.138 -  hrrs->add_reference((oop*)hr3_start);
  43.139 -  hrrs->add_reference((oop*)hr3_mid);
  43.140 -  hrrs->add_reference((oop*)hr3_last);
  43.141 +  hrrs->add_reference((OopOrNarrowOopStar)hr3_start);
  43.142 +  hrrs->add_reference((OopOrNarrowOopStar)hr3_mid);
  43.143 +  hrrs->add_reference((OopOrNarrowOopStar)hr3_last);
  43.144  
  43.145    // Now cause a coarsening.
  43.146 -  hrrs->add_reference((oop*)hr4->bottom());
  43.147 -  hrrs->add_reference((oop*)hr5->bottom());
  43.148 +  hrrs->add_reference((OopOrNarrowOopStar)hr4->bottom());
  43.149 +  hrrs->add_reference((OopOrNarrowOopStar)hr5->bottom());
  43.150  
  43.151    // Now, does iteration yield these three?
  43.152    HeapRegionRemSetIterator iter;
    44.1 --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Mon Jul 20 08:20:00 2009 -0700
    44.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Mon Jul 27 06:15:29 2009 -0700
    44.3 @@ -116,9 +116,9 @@
    44.4  
    44.5    // For now.  Could "expand" some tables in the future, so that this made
    44.6    // sense.
    44.7 -  void add_reference(oop* from, int tid);
    44.8 +  void add_reference(OopOrNarrowOopStar from, int tid);
    44.9  
   44.10 -  void add_reference(oop* from) {
   44.11 +  void add_reference(OopOrNarrowOopStar from) {
   44.12      return add_reference(from, 0);
   44.13    }
   44.14  
   44.15 @@ -140,8 +140,8 @@
   44.16    static size_t static_mem_size();
   44.17    static size_t fl_mem_size();
   44.18  
   44.19 -  bool contains_reference(oop* from) const;
   44.20 -  bool contains_reference_locked(oop* from) const;
   44.21 +  bool contains_reference(OopOrNarrowOopStar from) const;
   44.22 +  bool contains_reference_locked(OopOrNarrowOopStar from) const;
   44.23  
   44.24    void clear();
   44.25  
   44.26 @@ -192,10 +192,10 @@
   44.27    // Unused unless G1RecordHRRSOops is true.
   44.28  
   44.29    static const int MaxRecorded = 1000000;
   44.30 -  static oop**        _recorded_oops;
   44.31 -  static HeapWord**   _recorded_cards;
   44.32 -  static HeapRegion** _recorded_regions;
   44.33 -  static int          _n_recorded;
   44.34 +  static OopOrNarrowOopStar* _recorded_oops;
   44.35 +  static HeapWord**          _recorded_cards;
   44.36 +  static HeapRegion**        _recorded_regions;
   44.37 +  static int                 _n_recorded;
   44.38  
   44.39    static const int MaxRecordedEvents = 1000;
   44.40    static Event*       _recorded_events;
   44.41 @@ -231,13 +231,13 @@
   44.42  
   44.43    /* Used in the sequential case.  Returns "true" iff this addition causes
   44.44       the size limit to be reached. */
   44.45 -  void add_reference(oop* from) {
   44.46 +  void add_reference(OopOrNarrowOopStar from) {
   44.47      _other_regions.add_reference(from);
   44.48    }
   44.49  
   44.50    /* Used in the parallel case.  Returns "true" iff this addition causes
   44.51       the size limit to be reached. */
   44.52 -  void add_reference(oop* from, int tid) {
   44.53 +  void add_reference(OopOrNarrowOopStar from, int tid) {
   44.54      _other_regions.add_reference(from, tid);
   44.55    }
   44.56  
   44.57 @@ -301,7 +301,7 @@
   44.58      return OtherRegionsTable::fl_mem_size();
   44.59    }
   44.60  
   44.61 -  bool contains_reference(oop* from) const {
   44.62 +  bool contains_reference(OopOrNarrowOopStar from) const {
   44.63      return _other_regions.contains_reference(from);
   44.64    }
   44.65    void print() const;
   44.66 @@ -329,7 +329,7 @@
   44.67    }
   44.68  #endif
   44.69  
   44.70 -  static void record(HeapRegion* hr, oop* f);
   44.71 +  static void record(HeapRegion* hr, OopOrNarrowOopStar f);
   44.72    static void print_recorded();
   44.73    static void record_event(Event evnt);
   44.74  
    45.1 --- a/src/share/vm/gc_implementation/g1/satbQueue.cpp	Mon Jul 20 08:20:00 2009 -0700
    45.2 +++ b/src/share/vm/gc_implementation/g1/satbQueue.cpp	Mon Jul 27 06:15:29 2009 -0700
    45.3 @@ -43,6 +43,18 @@
    45.4      }
    45.5    }
    45.6  }
    45.7 +
    45.8 +#ifdef ASSERT
    45.9 +void ObjPtrQueue::verify_oops_in_buffer() {
   45.10 +  if (_buf == NULL) return;
   45.11 +  for (size_t i = _index; i < _sz; i += oopSize) {
   45.12 +    oop obj = (oop)_buf[byte_index_to_index((int)i)];
   45.13 +    assert(obj != NULL && obj->is_oop(true /* ignore mark word */),
   45.14 +           "Not an oop");
   45.15 +  }
   45.16 +}
   45.17 +#endif
   45.18 +
   45.19  #ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away
   45.20  #pragma warning( disable:4355 ) // 'this' : used in base member initializer list
   45.21  #endif // _MSC_VER
   45.22 @@ -66,6 +78,7 @@
   45.23  
   45.24  
   45.25  void SATBMarkQueueSet::handle_zero_index_for_thread(JavaThread* t) {
   45.26 +  DEBUG_ONLY(t->satb_mark_queue().verify_oops_in_buffer();)
   45.27    t->satb_mark_queue().handle_zero_index();
   45.28  }
   45.29  
   45.30 @@ -143,7 +156,7 @@
   45.31      }
   45.32      _completed_buffers_tail = NULL;
   45.33      _n_completed_buffers = 0;
   45.34 -    debug_only(assert_completed_buffer_list_len_correct_locked());
   45.35 +    DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked());
   45.36    }
   45.37    while (buffers_to_delete != NULL) {
   45.38      CompletedBufferNode* nd = buffers_to_delete;
    46.1 --- a/src/share/vm/gc_implementation/g1/satbQueue.hpp	Mon Jul 20 08:20:00 2009 -0700
    46.2 +++ b/src/share/vm/gc_implementation/g1/satbQueue.hpp	Mon Jul 27 06:15:29 2009 -0700
    46.3 @@ -39,6 +39,7 @@
    46.4    static void apply_closure_to_buffer(ObjectClosure* cl,
    46.5                                        void** buf, size_t index, size_t sz);
    46.6  
    46.7 +  void verify_oops_in_buffer() NOT_DEBUG_RETURN;
    46.8  };
    46.9  
   46.10  
    47.1 --- a/src/share/vm/gc_implementation/includeDB_gc_g1	Mon Jul 20 08:20:00 2009 -0700
    47.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_g1	Mon Jul 27 06:15:29 2009 -0700
    47.3 @@ -27,6 +27,7 @@
    47.4  bufferingOopClosure.hpp			genOopClosures.hpp
    47.5  bufferingOopClosure.hpp			generation.hpp
    47.6  bufferingOopClosure.hpp			os.hpp
    47.7 +bufferingOopClosure.hpp			taskqueue.hpp
    47.8  
    47.9  cardTableRS.cpp				concurrentMark.hpp
   47.10  cardTableRS.cpp				g1SATBCardTableModRefBS.hpp
   47.11 @@ -139,7 +140,7 @@
   47.12  g1CollectedHeap.cpp                     g1CollectedHeap.inline.hpp
   47.13  g1CollectedHeap.cpp                     g1CollectorPolicy.hpp
   47.14  g1CollectedHeap.cpp                     g1MarkSweep.hpp
   47.15 -g1CollectedHeap.cpp                     g1RemSet.hpp
   47.16 +g1CollectedHeap.cpp                     g1RemSet.inline.hpp
   47.17  g1CollectedHeap.cpp                     g1OopClosures.inline.hpp
   47.18  g1CollectedHeap.cpp                     genOopClosures.inline.hpp
   47.19  g1CollectedHeap.cpp                     gcLocker.inline.hpp
   47.20 @@ -151,13 +152,14 @@
   47.21  g1CollectedHeap.cpp                     isGCActiveMark.hpp
   47.22  g1CollectedHeap.cpp			oop.inline.hpp
   47.23  g1CollectedHeap.cpp			oop.pcgc.inline.hpp
   47.24 -g1CollectedHeap.cpp			parGCAllocBuffer.hpp
   47.25  g1CollectedHeap.cpp                     vm_operations_g1.hpp
   47.26  g1CollectedHeap.cpp                     vmThread.hpp
   47.27  
   47.28  g1CollectedHeap.hpp                     barrierSet.hpp
   47.29 +g1CollectedHeap.hpp                     g1RemSet.hpp
   47.30  g1CollectedHeap.hpp                     heapRegion.hpp
   47.31  g1CollectedHeap.hpp                     memRegion.hpp
   47.32 +g1CollectedHeap.hpp			parGCAllocBuffer.hpp
   47.33  g1CollectedHeap.hpp                     sharedHeap.hpp
   47.34  
   47.35  g1CollectedHeap.inline.hpp              concurrentMark.hpp
   47.36 @@ -245,6 +247,7 @@
   47.37  g1RemSet.cpp				iterator.hpp
   47.38  g1RemSet.cpp				oop.inline.hpp
   47.39  
   47.40 +g1RemSet.inline.hpp			oop.inline.hpp
   47.41  g1RemSet.inline.hpp			g1RemSet.hpp
   47.42  g1RemSet.inline.hpp			heapRegionRemSet.hpp
   47.43  
   47.44 @@ -255,6 +258,7 @@
   47.45  g1SATBCardTableModRefBS.cpp		thread_<os_family>.inline.hpp
   47.46  g1SATBCardTableModRefBS.cpp		satbQueue.hpp
   47.47  
   47.48 +g1SATBCardTableModRefBS.hpp		oop.inline.hpp
   47.49  g1SATBCardTableModRefBS.hpp		cardTableModRefBS.hpp
   47.50  g1SATBCardTableModRefBS.hpp		memRegion.hpp
   47.51  
    48.1 --- a/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp	Mon Jul 20 08:20:00 2009 -0700
    48.2 +++ b/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp	Mon Jul 27 06:15:29 2009 -0700
    48.3 @@ -31,9 +31,10 @@
    48.4                                                          bool clear,
    48.5                                                          int n_threads) {
    48.6    if (n_threads > 0) {
    48.7 -    assert(n_threads == (int)ParallelGCThreads, "# worker threads != # requested!");
    48.8 -
    48.9 -      // Make sure the LNC array is valid for the space.
   48.10 +    assert((n_threads == 1 && ParallelGCThreads == 0) ||
   48.11 +           n_threads <= (int)ParallelGCThreads,
   48.12 +           "# worker threads != # requested!");
   48.13 +    // Make sure the LNC array is valid for the space.
   48.14      jbyte**   lowest_non_clean;
   48.15      uintptr_t lowest_non_clean_base_chunk_index;
   48.16      size_t    lowest_non_clean_chunk_size;
    49.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Mon Jul 20 08:20:00 2009 -0700
    49.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Mon Jul 27 06:15:29 2009 -0700
    49.3 @@ -885,7 +885,7 @@
    49.4  }
    49.5  
    49.6  
    49.7 -void ParallelScavengeHeap::verify(bool allow_dirty, bool silent) {
    49.8 +void ParallelScavengeHeap::verify(bool allow_dirty, bool silent, bool option /* ignored */) {
    49.9    // Why do we need the total_collections()-filter below?
   49.10    if (total_collections() > 0) {
   49.11      if (!silent) {
    50.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Mon Jul 20 08:20:00 2009 -0700
    50.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Mon Jul 27 06:15:29 2009 -0700
    50.3 @@ -217,7 +217,7 @@
    50.4    virtual void gc_threads_do(ThreadClosure* tc) const;
    50.5    virtual void print_tracing_info() const;
    50.6  
    50.7 -  void verify(bool allow_dirty, bool silent);
    50.8 +  void verify(bool allow_dirty, bool silent, bool /* option */);
    50.9  
   50.10    void print_heap_change(size_t prev_used);
   50.11  
    51.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp	Mon Jul 20 08:20:00 2009 -0700
    51.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp	Mon Jul 27 06:15:29 2009 -0700
    51.3 @@ -117,6 +117,7 @@
    51.4      process_array_chunk(old);
    51.5    } else {
    51.6      if (p.is_narrow()) {
    51.7 +      assert(UseCompressedOops, "Error");
    51.8        PSScavenge::copy_and_push_safe_barrier(this, (narrowOop*)p);
    51.9      } else {
   51.10        PSScavenge::copy_and_push_safe_barrier(this, (oop*)p);
    52.1 --- a/src/share/vm/gc_interface/collectedHeap.hpp	Mon Jul 20 08:20:00 2009 -0700
    52.2 +++ b/src/share/vm/gc_interface/collectedHeap.hpp	Mon Jul 27 06:15:29 2009 -0700
    52.3 @@ -533,7 +533,7 @@
    52.4    virtual void print_tracing_info() const = 0;
    52.5  
    52.6    // Heap verification
    52.7 -  virtual void verify(bool allow_dirty, bool silent) = 0;
    52.8 +  virtual void verify(bool allow_dirty, bool silent, bool option) = 0;
    52.9  
   52.10    // Non product verification and debugging.
   52.11  #ifndef PRODUCT
    53.1 --- a/src/share/vm/includeDB_core	Mon Jul 20 08:20:00 2009 -0700
    53.2 +++ b/src/share/vm/includeDB_core	Mon Jul 27 06:15:29 2009 -0700
    53.3 @@ -554,7 +554,6 @@
    53.4  ciEnv.cpp                               linkResolver.hpp
    53.5  ciEnv.cpp                               methodDataOop.hpp
    53.6  ciEnv.cpp                               objArrayKlass.hpp
    53.7 -ciEnv.cpp                               oop.hpp
    53.8  ciEnv.cpp                               oop.inline.hpp
    53.9  ciEnv.cpp                               oop.inline2.hpp
   53.10  ciEnv.cpp                               oopFactory.hpp
   53.11 @@ -785,7 +784,6 @@
   53.12  ciSignature.cpp                         allocation.inline.hpp
   53.13  ciSignature.cpp                         ciSignature.hpp
   53.14  ciSignature.cpp                         ciUtilities.hpp
   53.15 -ciSignature.cpp                         oop.hpp
   53.16  ciSignature.cpp                         oop.inline.hpp
   53.17  ciSignature.cpp                         signature.hpp
   53.18  
   53.19 @@ -950,7 +948,6 @@
   53.20  classify.cpp                            classify.hpp
   53.21  classify.cpp                            systemDictionary.hpp
   53.22  
   53.23 -classify.hpp                            oop.hpp
   53.24  classify.hpp                            oop.inline.hpp
   53.25  
   53.26  codeBlob.cpp                            allocation.inline.hpp
   53.27 @@ -1185,7 +1182,6 @@
   53.28  compilerOracle.cpp                      jniHandles.hpp
   53.29  compilerOracle.cpp                      klass.hpp
   53.30  compilerOracle.cpp                      methodOop.hpp
   53.31 -compilerOracle.cpp                      oop.hpp
   53.32  compilerOracle.cpp                      oop.inline.hpp
   53.33  compilerOracle.cpp                      oopFactory.hpp
   53.34  compilerOracle.cpp                      resourceArea.hpp
   53.35 @@ -1629,7 +1625,6 @@
   53.36  frame.cpp                               methodOop.hpp
   53.37  frame.cpp                               monitorChunk.hpp
   53.38  frame.cpp                               nativeInst_<arch>.hpp
   53.39 -frame.cpp                               oop.hpp
   53.40  frame.cpp                               oop.inline.hpp
   53.41  frame.cpp                               oop.inline2.hpp
   53.42  frame.cpp                               oopMapCache.hpp
   53.43 @@ -1797,7 +1792,6 @@
   53.44  generation.cpp                          generation.hpp
   53.45  generation.cpp                          generation.inline.hpp
   53.46  generation.cpp                          java.hpp
   53.47 -generation.cpp                          oop.hpp
   53.48  generation.cpp                          oop.inline.hpp
   53.49  generation.cpp                          spaceDecorator.hpp
   53.50  generation.cpp                          space.inline.hpp
   53.51 @@ -2270,7 +2264,6 @@
   53.52  java.cpp                                memprofiler.hpp
   53.53  java.cpp                                methodOop.hpp
   53.54  java.cpp                                objArrayOop.hpp
   53.55 -java.cpp                                oop.hpp
   53.56  java.cpp                                oop.inline.hpp
   53.57  java.cpp                                oopFactory.hpp
   53.58  java.cpp                                sharedRuntime.hpp
   53.59 @@ -2947,7 +2940,7 @@
   53.60  nativeInst_<arch>.cpp                   assembler_<arch>.inline.hpp
   53.61  nativeInst_<arch>.cpp                   handles.hpp
   53.62  nativeInst_<arch>.cpp                   nativeInst_<arch>.hpp
   53.63 -nativeInst_<arch>.cpp                   oop.hpp
   53.64 +nativeInst_<arch>.cpp                   oop.inline.hpp
   53.65  nativeInst_<arch>.cpp                   ostream.hpp
   53.66  nativeInst_<arch>.cpp                   resourceArea.hpp
   53.67  nativeInst_<arch>.cpp                   sharedRuntime.hpp
   53.68 @@ -3842,7 +3835,7 @@
   53.69  stackValue.cpp                          debugInfo.hpp
   53.70  stackValue.cpp                          frame.inline.hpp
   53.71  stackValue.cpp                          handles.inline.hpp
   53.72 -stackValue.cpp                          oop.hpp
   53.73 +stackValue.cpp                          oop.inline.hpp
   53.74  stackValue.cpp                          stackValue.hpp
   53.75  
   53.76  stackValue.hpp                          handles.hpp
   53.77 @@ -4329,7 +4322,6 @@
   53.78  unhandledOops.cpp                       collectedHeap.hpp
   53.79  unhandledOops.cpp                       gcLocker.inline.hpp
   53.80  unhandledOops.cpp                       globalDefinitions.hpp
   53.81 -unhandledOops.cpp                       oop.hpp
   53.82  unhandledOops.cpp                       oop.inline.hpp
   53.83  unhandledOops.cpp                       thread.hpp
   53.84  unhandledOops.cpp                       unhandledOops.hpp
   53.85 @@ -4465,7 +4457,6 @@
   53.86  vframe.cpp                              nmethod.hpp
   53.87  vframe.cpp                              objectMonitor.hpp
   53.88  vframe.cpp                              objectMonitor.inline.hpp
   53.89 -vframe.cpp                              oop.hpp
   53.90  vframe.cpp                              oop.inline.hpp
   53.91  vframe.cpp                              oopMapCache.hpp
   53.92  vframe.cpp                              pcDesc.hpp
   53.93 @@ -4577,7 +4568,6 @@
   53.94  vmThread.cpp                            interfaceSupport.hpp
   53.95  vmThread.cpp                            methodOop.hpp
   53.96  vmThread.cpp                            mutexLocker.hpp
   53.97 -vmThread.cpp                            oop.hpp
   53.98  vmThread.cpp                            oop.inline.hpp
   53.99  vmThread.cpp                            os.hpp
  53.100  vmThread.cpp                            resourceArea.hpp
    54.1 --- a/src/share/vm/includeDB_features	Mon Jul 20 08:20:00 2009 -0700
    54.2 +++ b/src/share/vm/includeDB_features	Mon Jul 27 06:15:29 2009 -0700
    54.3 @@ -47,7 +47,7 @@
    54.4  dump.cpp                                javaClasses.hpp
    54.5  dump.cpp                                loaderConstraints.hpp
    54.6  dump.cpp                                methodDataOop.hpp
    54.7 -dump.cpp                                oop.hpp
    54.8 +dump.cpp                                oop.inline.hpp
    54.9  dump.cpp                                oopFactory.hpp
   54.10  dump.cpp                                resourceArea.hpp
   54.11  dump.cpp                                signature.hpp
   54.12 @@ -237,7 +237,7 @@
   54.13  serialize.cpp                           compiledICHolderOop.hpp
   54.14  serialize.cpp                           methodDataOop.hpp
   54.15  serialize.cpp                           objArrayOop.hpp
   54.16 -serialize.cpp                           oop.hpp
   54.17 +serialize.cpp                           oop.inline.hpp
   54.18  serialize.cpp                           symbolTable.hpp
   54.19  serialize.cpp                           systemDictionary.hpp
   54.20  
   54.21 @@ -295,7 +295,7 @@
   54.22  vmStructs.cpp                           objArrayKlass.hpp
   54.23  vmStructs.cpp                           objArrayKlassKlass.hpp
   54.24  vmStructs.cpp                           objArrayOop.hpp
   54.25 -vmStructs.cpp                           oop.hpp
   54.26 +vmStructs.cpp                           oop.inline.hpp
   54.27  vmStructs.cpp                           oopMap.hpp
   54.28  vmStructs.cpp                           pcDesc.hpp
   54.29  vmStructs.cpp                           perfMemory.hpp
    55.1 --- a/src/share/vm/interpreter/rewriter.cpp	Mon Jul 20 08:20:00 2009 -0700
    55.2 +++ b/src/share/vm/interpreter/rewriter.cpp	Mon Jul 27 06:15:29 2009 -0700
    55.3 @@ -273,6 +273,7 @@
    55.4    compute_index_maps();
    55.5  
    55.6    if (RegisterFinalizersAtInit && _klass->name() == vmSymbols::java_lang_Object()) {
    55.7 +    bool did_rewrite = false;
    55.8      int i = _methods->length();
    55.9      while (i-- > 0) {
   55.10        methodOop method = (methodOop)_methods->obj_at(i);
   55.11 @@ -281,9 +282,11 @@
   55.12          // object for finalization if needed.
   55.13          methodHandle m(THREAD, method);
   55.14          rewrite_Object_init(m, CHECK);
   55.15 +        did_rewrite = true;
   55.16          break;
   55.17        }
   55.18      }
   55.19 +    assert(did_rewrite, "must find Object::<init> to rewrite it");
   55.20    }
   55.21  
   55.22    // rewrite methods, in two passes
    56.1 --- a/src/share/vm/memory/barrierSet.cpp	Mon Jul 20 08:20:00 2009 -0700
    56.2 +++ b/src/share/vm/memory/barrierSet.cpp	Mon Jul 27 06:15:29 2009 -0700
    56.3 @@ -25,12 +25,27 @@
    56.4  # include "incls/_precompiled.incl"
    56.5  # include "incls/_barrierSet.cpp.incl"
    56.6  
    56.7 -// count is in HeapWord's
    56.8 +// count is number of array elements being written
    56.9  void BarrierSet::static_write_ref_array_pre(HeapWord* start, size_t count) {
   56.10 -   Universe::heap()->barrier_set()->write_ref_array_pre(MemRegion(start, start + count));
   56.11 +  assert(count <= (size_t)max_intx, "count too large");
   56.12 +#if 0
   56.13 +  warning("Pre: \t" INTPTR_FORMAT "[" SIZE_FORMAT "]\t",
   56.14 +                   start,            count);
   56.15 +#endif
   56.16 +  if (UseCompressedOops) {
   56.17 +    Universe::heap()->barrier_set()->write_ref_array_pre((narrowOop*)start, (int)count);
   56.18 +  } else {
   56.19 +    Universe::heap()->barrier_set()->write_ref_array_pre(      (oop*)start, (int)count);
   56.20 +  }
   56.21  }
   56.22  
   56.23 -// count is in HeapWord's
   56.24 +// count is number of array elements being written
   56.25  void BarrierSet::static_write_ref_array_post(HeapWord* start, size_t count) {
   56.26 -   Universe::heap()->barrier_set()->write_ref_array_work(MemRegion(start, start + count));
   56.27 +  assert(count <= (size_t)max_intx, "count too large");
   56.28 +  HeapWord* end = start + objArrayOopDesc::array_size((int)count);
   56.29 +#if 0
   56.30 +  warning("Post:\t" INTPTR_FORMAT "[" SIZE_FORMAT "] : [" INTPTR_FORMAT","INTPTR_FORMAT")\t",
   56.31 +                   start,            count,              start,          end);
   56.32 +#endif
   56.33 +  Universe::heap()->barrier_set()->write_ref_array_work(MemRegion(start, end));
   56.34  }
    57.1 --- a/src/share/vm/memory/barrierSet.hpp	Mon Jul 20 08:20:00 2009 -0700
    57.2 +++ b/src/share/vm/memory/barrierSet.hpp	Mon Jul 27 06:15:29 2009 -0700
    57.3 @@ -81,9 +81,13 @@
    57.4    // barrier types.  Semantically, it should be thought of as a call to the
    57.5    // virtual "_work" function below, which must implement the barrier.)
    57.6    // First the pre-write versions...
    57.7 -  inline void write_ref_field_pre(void* field, oop new_val);
    57.8 +  template <class T> inline void write_ref_field_pre(T* field, oop new_val);
    57.9 +private:
   57.10 +  // Keep this private so as to catch violations at build time.
   57.11 +  virtual void write_ref_field_pre_work(     void* field, oop new_val) { guarantee(false, "Not needed"); };
   57.12  protected:
   57.13 -  virtual void write_ref_field_pre_work(void* field, oop new_val) {};
   57.14 +  virtual void write_ref_field_pre_work(      oop* field, oop new_val) {};
   57.15 +  virtual void write_ref_field_pre_work(narrowOop* field, oop new_val) {};
   57.16  public:
   57.17  
   57.18    // ...then the post-write version.
   57.19 @@ -117,12 +121,17 @@
   57.20    virtual void read_ref_array(MemRegion mr) = 0;
   57.21    virtual void read_prim_array(MemRegion mr) = 0;
   57.22  
   57.23 -  virtual void write_ref_array_pre(MemRegion mr) {}
   57.24 +  virtual void write_ref_array_pre(      oop* dst, int length) {}
   57.25 +  virtual void write_ref_array_pre(narrowOop* dst, int length) {}
   57.26    inline void write_ref_array(MemRegion mr);
   57.27  
   57.28    // Static versions, suitable for calling from generated code.
   57.29    static void static_write_ref_array_pre(HeapWord* start, size_t count);
   57.30    static void static_write_ref_array_post(HeapWord* start, size_t count);
   57.31 +  // Narrow oop versions of the above; count is # of array elements being written,
   57.32 +  // starting with "start", which is HeapWord-aligned.
   57.33 +  static void static_write_ref_array_pre_narrow(HeapWord* start, size_t count);
   57.34 +  static void static_write_ref_array_post_narrow(HeapWord* start, size_t count);
   57.35  
   57.36  protected:
   57.37    virtual void write_ref_array_work(MemRegion mr) = 0;
    58.1 --- a/src/share/vm/memory/barrierSet.inline.hpp	Mon Jul 20 08:20:00 2009 -0700
    58.2 +++ b/src/share/vm/memory/barrierSet.inline.hpp	Mon Jul 27 06:15:29 2009 -0700
    58.3 @@ -23,10 +23,10 @@
    58.4   */
    58.5  
    58.6  // Inline functions of BarrierSet, which de-virtualize certain
    58.7 -// performance-critical calls when when the barrier is the most common
    58.8 +// performance-critical calls when the barrier is the most common
    58.9  // card-table kind.
   58.10  
   58.11 -void BarrierSet::write_ref_field_pre(void* field, oop new_val) {
   58.12 +template <class T> void BarrierSet::write_ref_field_pre(T* field, oop new_val) {
   58.13    if (kind() == CardTableModRef) {
   58.14      ((CardTableModRefBS*)this)->inline_write_ref_field_pre(field, new_val);
   58.15    } else {
    59.1 --- a/src/share/vm/memory/cardTableModRefBS.hpp	Mon Jul 20 08:20:00 2009 -0700
    59.2 +++ b/src/share/vm/memory/cardTableModRefBS.hpp	Mon Jul 27 06:15:29 2009 -0700
    59.3 @@ -287,7 +287,7 @@
    59.4    // these functions here for performance.
    59.5  protected:
    59.6    void write_ref_field_work(oop obj, size_t offset, oop newVal);
    59.7 -  void write_ref_field_work(void* field, oop newVal);
    59.8 +  virtual void write_ref_field_work(void* field, oop newVal);
    59.9  public:
   59.10  
   59.11    bool has_write_ref_array_opt() { return true; }
   59.12 @@ -317,10 +317,10 @@
   59.13  
   59.14    // *** Card-table-barrier-specific things.
   59.15  
   59.16 -  inline void inline_write_ref_field_pre(void* field, oop newVal) {}
   59.17 +  template <class T> inline void inline_write_ref_field_pre(T* field, oop newVal) {}
   59.18  
   59.19 -  inline void inline_write_ref_field(void* field, oop newVal) {
   59.20 -    jbyte* byte = byte_for(field);
   59.21 +  template <class T> inline void inline_write_ref_field(T* field, oop newVal) {
   59.22 +    jbyte* byte = byte_for((void*)field);
   59.23      *byte = dirty_card;
   59.24    }
   59.25  
    60.1 --- a/src/share/vm/memory/genCollectedHeap.cpp	Mon Jul 20 08:20:00 2009 -0700
    60.2 +++ b/src/share/vm/memory/genCollectedHeap.cpp	Mon Jul 27 06:15:29 2009 -0700
    60.3 @@ -1194,7 +1194,7 @@
    60.4    return _gens[level]->gc_stats();
    60.5  }
    60.6  
    60.7 -void GenCollectedHeap::verify(bool allow_dirty, bool silent) {
    60.8 +void GenCollectedHeap::verify(bool allow_dirty, bool silent, bool option /* ignored */) {
    60.9    if (!silent) {
   60.10      gclog_or_tty->print("permgen ");
   60.11    }
    61.1 --- a/src/share/vm/memory/genCollectedHeap.hpp	Mon Jul 20 08:20:00 2009 -0700
    61.2 +++ b/src/share/vm/memory/genCollectedHeap.hpp	Mon Jul 27 06:15:29 2009 -0700
    61.3 @@ -325,7 +325,7 @@
    61.4    void prepare_for_verify();
    61.5  
    61.6    // Override.
    61.7 -  void verify(bool allow_dirty, bool silent);
    61.8 +  void verify(bool allow_dirty, bool silent, bool /* option */);
    61.9  
   61.10    // Override.
   61.11    void print() const;
    62.1 --- a/src/share/vm/memory/genOopClosures.hpp	Mon Jul 20 08:20:00 2009 -0700
    62.2 +++ b/src/share/vm/memory/genOopClosures.hpp	Mon Jul 27 06:15:29 2009 -0700
    62.3 @@ -57,7 +57,7 @@
    62.4    template <class T> void do_barrier(T* p);
    62.5  
    62.6    // Version for use by closures that may be called in parallel code.
    62.7 -  void par_do_barrier(oop* p);
    62.8 +  template <class T> void par_do_barrier(T* p);
    62.9  
   62.10   public:
   62.11    OopsInGenClosure() : OopClosure(NULL),
    63.1 --- a/src/share/vm/memory/genOopClosures.inline.hpp	Mon Jul 20 08:20:00 2009 -0700
    63.2 +++ b/src/share/vm/memory/genOopClosures.inline.hpp	Mon Jul 27 06:15:29 2009 -0700
    63.3 @@ -40,18 +40,20 @@
    63.4  
    63.5  template <class T> inline void OopsInGenClosure::do_barrier(T* p) {
    63.6    assert(generation()->is_in_reserved(p), "expected ref in generation");
    63.7 -  assert(!oopDesc::is_null(*p), "expected non-null object");
    63.8 -  oop obj = oopDesc::load_decode_heap_oop_not_null(p);
    63.9 +  T heap_oop = oopDesc::load_heap_oop(p);
   63.10 +  assert(!oopDesc::is_null(heap_oop), "expected non-null oop");
   63.11 +  oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
   63.12    // If p points to a younger generation, mark the card.
   63.13    if ((HeapWord*)obj < _gen_boundary) {
   63.14      _rs->inline_write_ref_field_gc(p, obj);
   63.15    }
   63.16  }
   63.17  
   63.18 -inline void OopsInGenClosure::par_do_barrier(oop* p) {
   63.19 +template <class T> inline void OopsInGenClosure::par_do_barrier(T* p) {
   63.20    assert(generation()->is_in_reserved(p), "expected ref in generation");
   63.21 -  oop obj = *p;
   63.22 -  assert(obj != NULL, "expected non-null object");
   63.23 +  T heap_oop = oopDesc::load_heap_oop(p);
   63.24 +  assert(!oopDesc::is_null(heap_oop), "expected non-null oop");
   63.25 +  oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
   63.26    // If p points to a younger generation, mark the card.
   63.27    if ((HeapWord*)obj < gen_boundary()) {
   63.28      rs()->write_ref_field_gc_par(p, obj);
    64.1 --- a/src/share/vm/memory/referenceProcessor.cpp	Mon Jul 20 08:20:00 2009 -0700
    64.2 +++ b/src/share/vm/memory/referenceProcessor.cpp	Mon Jul 27 06:15:29 2009 -0700
    64.3 @@ -1013,12 +1013,19 @@
    64.4    // discovered_addr.
    64.5    oop current_head = refs_list.head();
    64.6  
    64.7 -  // Note: In the case of G1, this pre-barrier is strictly
    64.8 +  // Note: In the case of G1, this specific pre-barrier is strictly
    64.9    // not necessary because the only case we are interested in
   64.10 -  // here is when *discovered_addr is NULL, so this will expand to
   64.11 -  // nothing. As a result, I am just manually eliding this out for G1.
   64.12 +  // here is when *discovered_addr is NULL (see the CAS further below),
   64.13 +  // so this will expand to nothing. As a result, we have manually
   64.14 +  // elided this out for G1, but left in the test for some future
   64.15 +  // collector that might have need for a pre-barrier here.
   64.16    if (_discovered_list_needs_barrier && !UseG1GC) {
   64.17 -    _bs->write_ref_field_pre((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR");
   64.18 +    if (UseCompressedOops) {
   64.19 +      _bs->write_ref_field_pre((narrowOop*)discovered_addr, current_head);
   64.20 +    } else {
   64.21 +      _bs->write_ref_field_pre((oop*)discovered_addr, current_head);
   64.22 +    }
   64.23 +    guarantee(false, "Need to check non-G1 collector");
   64.24    }
   64.25    oop retest = oopDesc::atomic_compare_exchange_oop(current_head, discovered_addr,
   64.26                                                      NULL);
   64.27 @@ -1029,9 +1036,8 @@
   64.28      refs_list.set_head(obj);
   64.29      refs_list.inc_length(1);
   64.30      if (_discovered_list_needs_barrier) {
   64.31 -      _bs->write_ref_field((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR");
   64.32 +      _bs->write_ref_field((void*)discovered_addr, current_head);
   64.33      }
   64.34 -
   64.35    } else {
   64.36      // If retest was non NULL, another thread beat us to it:
   64.37      // The reference has already been discovered...
   64.38 @@ -1177,11 +1183,16 @@
   64.39      // pre-value, we can safely elide the pre-barrier here for the case of G1.
   64.40      assert(discovered == NULL, "control point invariant");
   64.41      if (_discovered_list_needs_barrier && !UseG1GC) { // safe to elide for G1
   64.42 -      _bs->write_ref_field_pre((oop*)discovered_addr, current_head);
   64.43 +      if (UseCompressedOops) {
   64.44 +        _bs->write_ref_field_pre((narrowOop*)discovered_addr, current_head);
   64.45 +      } else {
   64.46 +        _bs->write_ref_field_pre((oop*)discovered_addr, current_head);
   64.47 +      }
   64.48 +      guarantee(false, "Need to check non-G1 collector");
   64.49      }
   64.50      oop_store_raw(discovered_addr, current_head);
   64.51      if (_discovered_list_needs_barrier) {
   64.52 -      _bs->write_ref_field((oop*)discovered_addr, current_head);
   64.53 +      _bs->write_ref_field((void*)discovered_addr, current_head);
   64.54      }
   64.55      list->set_head(obj);
   64.56      list->inc_length(1);
    65.1 --- a/src/share/vm/memory/space.hpp	Mon Jul 20 08:20:00 2009 -0700
    65.2 +++ b/src/share/vm/memory/space.hpp	Mon Jul 27 06:15:29 2009 -0700
    65.3 @@ -106,6 +106,7 @@
    65.4    virtual void set_end(HeapWord* value)    { _end = value; }
    65.5  
    65.6    virtual HeapWord* saved_mark_word() const  { return _saved_mark_word; }
    65.7 +
    65.8    void set_saved_mark_word(HeapWord* p) { _saved_mark_word = p; }
    65.9  
   65.10    MemRegionClosure* preconsumptionDirtyCardClosure() const {
    66.1 --- a/src/share/vm/memory/universe.cpp	Mon Jul 20 08:20:00 2009 -0700
    66.2 +++ b/src/share/vm/memory/universe.cpp	Mon Jul 27 06:15:29 2009 -0700
    66.3 @@ -1170,7 +1170,7 @@
    66.4    st->print_cr("}");
    66.5  }
    66.6  
    66.7 -void Universe::verify(bool allow_dirty, bool silent) {
    66.8 +void Universe::verify(bool allow_dirty, bool silent, bool option) {
    66.9    if (SharedSkipVerify) {
   66.10      return;
   66.11    }
   66.12 @@ -1194,7 +1194,7 @@
   66.13    if (!silent) gclog_or_tty->print("[Verifying ");
   66.14    if (!silent) gclog_or_tty->print("threads ");
   66.15    Threads::verify();
   66.16 -  heap()->verify(allow_dirty, silent);
   66.17 +  heap()->verify(allow_dirty, silent, option);
   66.18  
   66.19    if (!silent) gclog_or_tty->print("syms ");
   66.20    SymbolTable::verify();
    67.1 --- a/src/share/vm/memory/universe.hpp	Mon Jul 20 08:20:00 2009 -0700
    67.2 +++ b/src/share/vm/memory/universe.hpp	Mon Jul 27 06:15:29 2009 -0700
    67.3 @@ -343,6 +343,7 @@
    67.4    // For UseCompressedOops
    67.5    static address* narrow_oop_base_addr()              { return &_narrow_oop._base; }
    67.6    static address  narrow_oop_base()                   { return  _narrow_oop._base; }
    67.7 +  static bool  is_narrow_oop_base(void* addr)         { return (narrow_oop_base() == (address)addr); }
    67.8    static int      narrow_oop_shift()                  { return  _narrow_oop._shift; }
    67.9    static void     set_narrow_oop_base(address base)   { _narrow_oop._base  = base; }
   67.10    static void     set_narrow_oop_shift(int shift)     { _narrow_oop._shift = shift; }
   67.11 @@ -398,7 +399,7 @@
   67.12  
   67.13    // Debugging
   67.14    static bool verify_in_progress() { return _verify_in_progress; }
   67.15 -  static void verify(bool allow_dirty = true, bool silent = false);
   67.16 +  static void verify(bool allow_dirty = true, bool silent = false, bool option = true);
   67.17    static int  verify_count()                  { return _verify_count; }
   67.18    static void print();
   67.19    static void print_on(outputStream* st);
    68.1 --- a/src/share/vm/oops/instanceRefKlass.cpp	Mon Jul 20 08:20:00 2009 -0700
    68.2 +++ b/src/share/vm/oops/instanceRefKlass.cpp	Mon Jul 27 06:15:29 2009 -0700
    68.3 @@ -28,13 +28,14 @@
    68.4  template <class T>
    68.5  static void specialized_oop_follow_contents(instanceRefKlass* ref, oop obj) {
    68.6    T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
    68.7 -  oop referent = oopDesc::load_decode_heap_oop(referent_addr);
    68.8 +  T heap_oop = oopDesc::load_heap_oop(referent_addr);
    68.9    debug_only(
   68.10      if(TraceReferenceGC && PrintGCDetails) {
   68.11        gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, obj);
   68.12      }
   68.13    )
   68.14 -  if (referent != NULL) {
   68.15 +  if (!oopDesc::is_null(heap_oop)) {
   68.16 +    oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);
   68.17      if (!referent->is_gc_marked() &&
   68.18          MarkSweep::ref_processor()->
   68.19            discover_reference(obj, ref->reference_type())) {
   68.20 @@ -81,13 +82,14 @@
   68.21                                              ParCompactionManager* cm,
   68.22                                              oop obj) {
   68.23    T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
   68.24 -  oop referent = oopDesc::load_decode_heap_oop(referent_addr);
   68.25 +  T heap_oop = oopDesc::load_heap_oop(referent_addr);
   68.26    debug_only(
   68.27      if(TraceReferenceGC && PrintGCDetails) {
   68.28        gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, obj);
   68.29      }
   68.30    )
   68.31 -  if (referent != NULL) {
   68.32 +  if (!oopDesc::is_null(heap_oop)) {
   68.33 +    oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);
   68.34      if (PSParallelCompact::mark_bitmap()->is_unmarked(referent) &&
   68.35          PSParallelCompact::ref_processor()->
   68.36            discover_reference(obj, ref->reference_type())) {
   68.37 @@ -182,9 +184,10 @@
   68.38    }                                                                             \
   68.39                                                                                  \
   68.40    T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);           \
   68.41 -  oop referent = oopDesc::load_decode_heap_oop(referent_addr);                  \
   68.42 -  if (referent != NULL && contains(referent_addr)) {                            \
   68.43 +  T heap_oop = oopDesc::load_heap_oop(referent_addr);                           \
   68.44 +  if (!oopDesc::is_null(heap_oop) && contains(referent_addr)) {                 \
   68.45      ReferenceProcessor* rp = closure->_ref_processor;                           \
   68.46 +    oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);                 \
   68.47      if (!referent->is_gc_marked() && (rp != NULL) &&                            \
   68.48          rp->discover_reference(obj, reference_type())) {                        \
   68.49        return size;                                                              \
    69.1 --- a/src/share/vm/oops/methodKlass.cpp	Mon Jul 20 08:20:00 2009 -0700
    69.2 +++ b/src/share/vm/oops/methodKlass.cpp	Mon Jul 27 06:15:29 2009 -0700
    69.3 @@ -68,7 +68,7 @@
    69.4    m->set_constants(NULL);
    69.5    m->set_max_stack(0);
    69.6    m->set_max_locals(0);
    69.7 -  m->clear_intrinsic_id_cache();
    69.8 +  m->set_intrinsic_id(vmIntrinsics::_none);
    69.9    m->set_method_data(NULL);
   69.10    m->set_interpreter_throwout_count(0);
   69.11    m->set_vtable_index(methodOopDesc::garbage_vtable_index);
    70.1 --- a/src/share/vm/oops/methodOop.cpp	Mon Jul 20 08:20:00 2009 -0700
    70.2 +++ b/src/share/vm/oops/methodOop.cpp	Mon Jul 27 06:15:29 2009 -0700
    70.3 @@ -962,26 +962,39 @@
    70.4    return newm;
    70.5  }
    70.6  
    70.7 -vmIntrinsics::ID methodOopDesc::compute_intrinsic_id() const {
    70.8 -  assert(vmIntrinsics::_none == 0, "correct coding of default case");
    70.9 -  const uintptr_t max_cache_uint = right_n_bits((int)(sizeof(_intrinsic_id_cache) * BitsPerByte));
   70.10 -  assert((uintptr_t)vmIntrinsics::ID_LIMIT <= max_cache_uint, "else fix cache size");
   70.11 +vmSymbols::SID methodOopDesc::klass_id_for_intrinsics(klassOop holder) {
   70.12    // if loader is not the default loader (i.e., != NULL), we can't know the intrinsics
   70.13    // because we are not loading from core libraries
   70.14 -  if (instanceKlass::cast(method_holder())->class_loader() != NULL) return vmIntrinsics::_none;
   70.15 +  if (instanceKlass::cast(holder)->class_loader() != NULL)
   70.16 +    return vmSymbols::NO_SID;   // regardless of name, no intrinsics here
   70.17  
   70.18    // see if the klass name is well-known:
   70.19 -  symbolOop klass_name    = instanceKlass::cast(method_holder())->name();
   70.20 -  vmSymbols::SID klass_id = vmSymbols::find_sid(klass_name);
   70.21 -  if (klass_id == vmSymbols::NO_SID)  return vmIntrinsics::_none;
   70.22 +  symbolOop klass_name = instanceKlass::cast(holder)->name();
   70.23 +  return vmSymbols::find_sid(klass_name);
   70.24 +}
   70.25 +
   70.26 +void methodOopDesc::init_intrinsic_id() {
   70.27 +  assert(_intrinsic_id == vmIntrinsics::_none, "do this just once");
   70.28 +  const uintptr_t max_id_uint = right_n_bits((int)(sizeof(_intrinsic_id) * BitsPerByte));
   70.29 +  assert((uintptr_t)vmIntrinsics::ID_LIMIT <= max_id_uint, "else fix size");
   70.30 +
   70.31 +  // the klass name is well-known:
   70.32 +  vmSymbols::SID klass_id = klass_id_for_intrinsics(method_holder());
   70.33 +  assert(klass_id != vmSymbols::NO_SID, "caller responsibility");
   70.34  
   70.35    // ditto for method and signature:
   70.36    vmSymbols::SID  name_id = vmSymbols::find_sid(name());
   70.37 -  if (name_id  == vmSymbols::NO_SID)  return vmIntrinsics::_none;
   70.38 +  if (name_id  == vmSymbols::NO_SID)  return;
   70.39    vmSymbols::SID   sig_id = vmSymbols::find_sid(signature());
   70.40 -  if (sig_id   == vmSymbols::NO_SID)  return vmIntrinsics::_none;
   70.41 +  if (sig_id   == vmSymbols::NO_SID)  return;
   70.42    jshort flags = access_flags().as_short();
   70.43  
   70.44 +  vmIntrinsics::ID id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags);
   70.45 +  if (id != vmIntrinsics::_none) {
   70.46 +    set_intrinsic_id(id);
   70.47 +    return;
   70.48 +  }
   70.49 +
   70.50    // A few slightly irregular cases:
   70.51    switch (klass_id) {
   70.52    case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_StrictMath):
   70.53 @@ -992,15 +1005,18 @@
   70.54      case vmSymbols::VM_SYMBOL_ENUM_NAME(sqrt_name):
   70.55        // pretend it is the corresponding method in the non-strict class:
   70.56        klass_id = vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_Math);
   70.57 +      id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags);
   70.58        break;
   70.59      }
   70.60    }
   70.61  
   70.62 -  // return intrinsic id if any
   70.63 -  return vmIntrinsics::find_id(klass_id, name_id, sig_id, flags);
   70.64 +  if (id != vmIntrinsics::_none) {
   70.65 +    // Set up its iid.  It is an alias method.
   70.66 +    set_intrinsic_id(id);
   70.67 +    return;
   70.68 +  }
   70.69  }
   70.70  
   70.71 -
   70.72  // These two methods are static since a GC may move the methodOopDesc
   70.73  bool methodOopDesc::load_signature_classes(methodHandle m, TRAPS) {
   70.74    bool sig_is_loaded = true;
    71.1 --- a/src/share/vm/oops/methodOop.hpp	Mon Jul 20 08:20:00 2009 -0700
    71.2 +++ b/src/share/vm/oops/methodOop.hpp	Mon Jul 27 06:15:29 2009 -0700
    71.3 @@ -104,7 +104,7 @@
    71.4    u2                _max_stack;                  // Maximum number of entries on the expression stack
    71.5    u2                _max_locals;                 // Number of local variables used by this method
    71.6    u2                _size_of_parameters;         // size of the parameter block (receiver + arguments) in words
    71.7 -  u1                _intrinsic_id_cache;         // Cache for intrinsic_id; 0 or 1+vmInt::ID
    71.8 +  u1                _intrinsic_id;               // vmSymbols::intrinsic_id (0 == _none)
    71.9    u1                _highest_tier_compile;       // Highest compile level this method has ever seen.
   71.10    u2                _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
   71.11    u2                _number_of_breakpoints;      // fullspeed debugging support
   71.12 @@ -224,8 +224,6 @@
   71.13    int highest_tier_compile()                     { return _highest_tier_compile;}
   71.14    void set_highest_tier_compile(int level)      { _highest_tier_compile = level;}
   71.15  
   71.16 -  void clear_intrinsic_id_cache() { _intrinsic_id_cache = 0; }
   71.17 -
   71.18    // Count of times method was exited via exception while interpreting
   71.19    void interpreter_throwout_increment() {
   71.20      if (_interpreter_throwout_count < 65534) {
   71.21 @@ -571,18 +569,12 @@
   71.22    void set_cached_itable_index(int index)           { instanceKlass::cast(method_holder())->set_cached_itable_index(method_idnum(), index); }
   71.23  
   71.24    // Support for inlining of intrinsic methods
   71.25 -  vmIntrinsics::ID intrinsic_id() const { // returns zero if not an intrinsic
   71.26 -    const u1& cache = _intrinsic_id_cache;
   71.27 -    if (cache != 0) {
   71.28 -      return (vmIntrinsics::ID)(cache - 1);
   71.29 -    } else {
   71.30 -      vmIntrinsics::ID id = compute_intrinsic_id();
   71.31 -      *(u1*)&cache = ((u1) id) + 1;   // force the cache to be non-const
   71.32 -      vmIntrinsics::verify_method(id, (methodOop) this);
   71.33 -      assert((vmIntrinsics::ID)(cache - 1) == id, "proper conversion");
   71.34 -      return id;
   71.35 -    }
   71.36 -  }
   71.37 +  vmIntrinsics::ID intrinsic_id() const          { return (vmIntrinsics::ID) _intrinsic_id;           }
   71.38 +  void     set_intrinsic_id(vmIntrinsics::ID id) {                           _intrinsic_id = (u1) id; }
   71.39 +
   71.40 +  // Helper routines for intrinsic_id() and vmIntrinsics::method().
   71.41 +  void init_intrinsic_id();     // updates from _none if a match
   71.42 +  static vmSymbols::SID klass_id_for_intrinsics(klassOop holder);
   71.43  
   71.44    // On-stack replacement support
   71.45    bool has_osr_nmethod()                         { return instanceKlass::cast(method_holder())->lookup_osr_nmethod(this, InvocationEntryBci) != NULL; }
   71.46 @@ -635,9 +627,6 @@
   71.47    void set_size_of_parameters(int size)          { _size_of_parameters = size; }
   71.48   private:
   71.49  
   71.50 -  // Helper routine for intrinsic_id().
   71.51 -  vmIntrinsics::ID compute_intrinsic_id() const;
   71.52 -
   71.53    // Inlined elements
   71.54    address* native_function_addr() const          { assert(is_native(), "must be native"); return (address*) (this+1); }
   71.55    address* signature_handler_addr() const        { return native_function_addr() + 1; }
    72.1 --- a/src/share/vm/oops/objArrayKlass.cpp	Mon Jul 20 08:20:00 2009 -0700
    72.2 +++ b/src/share/vm/oops/objArrayKlass.cpp	Mon Jul 27 06:15:29 2009 -0700
    72.3 @@ -84,8 +84,6 @@
    72.4  template <class T> void objArrayKlass::do_copy(arrayOop s, T* src,
    72.5                                 arrayOop d, T* dst, int length, TRAPS) {
    72.6  
    72.7 -  const size_t word_len = objArrayOopDesc::array_size(length);
    72.8 -
    72.9    BarrierSet* bs = Universe::heap()->barrier_set();
   72.10    // For performance reasons, we assume we are that the write barrier we
   72.11    // are using has optimized modes for arrays of references.  At least one
   72.12 @@ -93,11 +91,10 @@
   72.13    assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
   72.14    assert(bs->has_write_ref_array_pre_opt(), "For pre-barrier as well.");
   72.15  
   72.16 -  MemRegion dst_mr = MemRegion((HeapWord*)dst, word_len);
   72.17    if (s == d) {
   72.18      // since source and destination are equal we do not need conversion checks.
   72.19      assert(length > 0, "sanity check");
   72.20 -    bs->write_ref_array_pre(dst_mr);
   72.21 +    bs->write_ref_array_pre(dst, length);
   72.22      Copy::conjoint_oops_atomic(src, dst, length);
   72.23    } else {
   72.24      // We have to make sure all elements conform to the destination array
   72.25 @@ -105,7 +102,7 @@
   72.26      klassOop stype = objArrayKlass::cast(s->klass())->element_klass();
   72.27      if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) {
   72.28        // elements are guaranteed to be subtypes, so no check necessary
   72.29 -      bs->write_ref_array_pre(dst_mr);
   72.30 +      bs->write_ref_array_pre(dst, length);
   72.31        Copy::conjoint_oops_atomic(src, dst, length);
   72.32      } else {
   72.33        // slow case: need individual subtype checks
   72.34 @@ -137,6 +134,7 @@
   72.35        }
   72.36      }
   72.37    }
   72.38 +  const size_t word_len = objArrayOopDesc::array_size(length);
   72.39    bs->write_ref_array(MemRegion((HeapWord*)dst, word_len));
   72.40  }
   72.41  
    73.1 --- a/src/share/vm/oops/oop.inline.hpp	Mon Jul 20 08:20:00 2009 -0700
    73.2 +++ b/src/share/vm/oops/oop.inline.hpp	Mon Jul 27 06:15:29 2009 -0700
    73.3 @@ -148,12 +148,14 @@
    73.4  
    73.5  inline narrowOop oopDesc::encode_heap_oop_not_null(oop v) {
    73.6    assert(!is_null(v), "oop value can never be zero");
    73.7 +  assert(Universe::heap()->is_in_reserved(v), "Address not in heap");
    73.8    address base = Universe::narrow_oop_base();
    73.9    int    shift = Universe::narrow_oop_shift();
   73.10    uint64_t  pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1));
   73.11    assert(OopEncodingHeapMax > pd, "change encoding max if new encoding");
   73.12    uint64_t result = pd >> shift;
   73.13    assert((result & CONST64(0xffffffff00000000)) == 0, "narrow oop overflow");
   73.14 +  assert(decode_heap_oop(result) == v, "reversibility");
   73.15    return (narrowOop)result;
   73.16  }
   73.17  
   73.18 @@ -449,7 +451,7 @@
   73.19    oopDesc::bs()->write_ref_field(p, v);
   73.20  }
   73.21  
   73.22 -inline void update_barrier_set_pre(void* p, oop v) {
   73.23 +template <class T> inline void update_barrier_set_pre(T* p, oop v) {
   73.24    oopDesc::bs()->write_ref_field_pre(p, v);
   73.25  }
   73.26  
   73.27 @@ -459,15 +461,15 @@
   73.28    } else {
   73.29      update_barrier_set_pre(p, v);
   73.30      oopDesc::encode_store_heap_oop(p, v);
   73.31 -    update_barrier_set(p, v);
   73.32 +    update_barrier_set((void*)p, v);  // cast away type
   73.33    }
   73.34  }
   73.35  
   73.36  template <class T> inline void oop_store(volatile T* p, oop v) {
   73.37 -  update_barrier_set_pre((void*)p, v);
   73.38 +  update_barrier_set_pre((T*)p, v);   // cast away volatile
   73.39    // Used by release_obj_field_put, so use release_store_ptr.
   73.40    oopDesc::release_encode_store_heap_oop(p, v);
   73.41 -  update_barrier_set((void*)p, v);
   73.42 +  update_barrier_set((void*)p, v);    // cast away type
   73.43  }
   73.44  
   73.45  template <class T> inline void oop_store_without_check(T* p, oop v) {
    74.1 --- a/src/share/vm/oops/oopsHierarchy.hpp	Mon Jul 20 08:20:00 2009 -0700
    74.2 +++ b/src/share/vm/oops/oopsHierarchy.hpp	Mon Jul 27 06:15:29 2009 -0700
    74.3 @@ -29,6 +29,7 @@
    74.4  typedef juint narrowOop; // Offset instead of address for an oop within a java object
    74.5  typedef class klassOopDesc* wideKlassOop; // to keep SA happy and unhandled oop
    74.6                                            // detector happy.
    74.7 +typedef void* OopOrNarrowOopStar;
    74.8  
    74.9  #ifndef CHECK_UNHANDLED_OOPS
   74.10  
    75.1 --- a/src/share/vm/opto/block.cpp	Mon Jul 20 08:20:00 2009 -0700
    75.2 +++ b/src/share/vm/opto/block.cpp	Mon Jul 27 06:15:29 2009 -0700
    75.3 @@ -910,7 +910,16 @@
    75.4                !(b->head()->is_Loop() && n->is_Phi()) &&
    75.5                // See (+++) comment in reg_split.cpp
    75.6                !(n->jvms() != NULL && n->jvms()->is_monitor_use(k)) ) {
    75.7 -            assert( b->find_node(def) < j, "uses must follow definitions" );
    75.8 +            bool is_loop = false;
    75.9 +            if (n->is_Phi()) {
   75.10 +              for( uint l = 1; l < def->req(); l++ ) {
   75.11 +                if (n == def->in(l)) {
   75.12 +                  is_loop = true;
   75.13 +                  break; // Some kind of loop
   75.14 +                }
   75.15 +              }
   75.16 +            }
   75.17 +            assert( is_loop || b->find_node(def) < j, "uses must follow definitions" );
   75.18            }
   75.19            if( def->is_SafePointScalarObject() ) {
   75.20              assert(_bbs[def->_idx] == b, "SafePointScalarObject Node should be at the same block as its SafePoint node");
    76.1 --- a/src/share/vm/opto/compile.cpp	Mon Jul 20 08:20:00 2009 -0700
    76.2 +++ b/src/share/vm/opto/compile.cpp	Mon Jul 27 06:15:29 2009 -0700
    76.3 @@ -101,7 +101,8 @@
    76.4      }
    76.5    }
    76.6    // Lazily create intrinsics for intrinsic IDs well-known in the runtime.
    76.7 -  if (m->intrinsic_id() != vmIntrinsics::_none) {
    76.8 +  if (m->intrinsic_id() != vmIntrinsics::_none &&
    76.9 +      m->intrinsic_id() <= vmIntrinsics::LAST_COMPILER_INLINE) {
   76.10      CallGenerator* cg = make_vm_intrinsic(m, is_virtual);
   76.11      if (cg != NULL) {
   76.12        // Save it for next time:
   76.13 @@ -440,6 +441,8 @@
   76.14                    _orig_pc_slot_offset_in_bytes(0),
   76.15                    _node_bundling_limit(0),
   76.16                    _node_bundling_base(NULL),
   76.17 +                  _java_calls(0),
   76.18 +                  _inner_loops(0),
   76.19  #ifndef PRODUCT
   76.20                    _trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")),
   76.21                    _printer(IdealGraphPrinter::printer()),
   76.22 @@ -710,6 +713,8 @@
   76.23      _code_buffer("Compile::Fill_buffer"),
   76.24      _node_bundling_limit(0),
   76.25      _node_bundling_base(NULL),
   76.26 +    _java_calls(0),
   76.27 +    _inner_loops(0),
   76.28  #ifndef PRODUCT
   76.29      _trace_opto_output(TraceOptoOutput),
   76.30      _printer(NULL),
   76.31 @@ -1850,22 +1855,26 @@
   76.32    int  _float_count;            // count float ops requiring 24-bit precision
   76.33    int  _double_count;           // count double ops requiring more precision
   76.34    int  _java_call_count;        // count non-inlined 'java' calls
   76.35 +  int  _inner_loop_count;       // count loops which need alignment
   76.36    VectorSet _visited;           // Visitation flags
   76.37    Node_List _tests;             // Set of IfNodes & PCTableNodes
   76.38  
   76.39    Final_Reshape_Counts() :
   76.40 -    _call_count(0), _float_count(0), _double_count(0), _java_call_count(0),
   76.41 +    _call_count(0), _float_count(0), _double_count(0),
   76.42 +    _java_call_count(0), _inner_loop_count(0),
   76.43      _visited( Thread::current()->resource_area() ) { }
   76.44  
   76.45    void inc_call_count  () { _call_count  ++; }
   76.46    void inc_float_count () { _float_count ++; }
   76.47    void inc_double_count() { _double_count++; }
   76.48    void inc_java_call_count() { _java_call_count++; }
   76.49 +  void inc_inner_loop_count() { _inner_loop_count++; }
   76.50  
   76.51    int  get_call_count  () const { return _call_count  ; }
   76.52    int  get_float_count () const { return _float_count ; }
   76.53    int  get_double_count() const { return _double_count; }
   76.54    int  get_java_call_count() const { return _java_call_count; }
   76.55 +  int  get_inner_loop_count() const { return _inner_loop_count; }
   76.56  };
   76.57  
   76.58  static bool oop_offset_is_sane(const TypeInstPtr* tp) {
   76.59 @@ -1877,7 +1886,7 @@
   76.60  
   76.61  //------------------------------final_graph_reshaping_impl----------------------
   76.62  // Implement items 1-5 from final_graph_reshaping below.
   76.63 -static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) {
   76.64 +static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
   76.65  
   76.66    if ( n->outcnt() == 0 ) return; // dead node
   76.67    uint nop = n->Opcode();
   76.68 @@ -1919,13 +1928,13 @@
   76.69    case Op_CmpF:
   76.70    case Op_CmpF3:
   76.71    // case Op_ConvL2F: // longs are split into 32-bit halves
   76.72 -    fpu.inc_float_count();
   76.73 +    frc.inc_float_count();
   76.74      break;
   76.75  
   76.76    case Op_ConvF2D:
   76.77    case Op_ConvD2F:
   76.78 -    fpu.inc_float_count();
   76.79 -    fpu.inc_double_count();
   76.80 +    frc.inc_float_count();
   76.81 +    frc.inc_double_count();
   76.82      break;
   76.83  
   76.84    // Count all double operations that may use FPU
   76.85 @@ -1942,7 +1951,7 @@
   76.86    case Op_ConD:
   76.87    case Op_CmpD:
   76.88    case Op_CmpD3:
   76.89 -    fpu.inc_double_count();
   76.90 +    frc.inc_double_count();
   76.91      break;
   76.92    case Op_Opaque1:              // Remove Opaque Nodes before matching
   76.93    case Op_Opaque2:              // Remove Opaque Nodes before matching
   76.94 @@ -1951,7 +1960,7 @@
   76.95    case Op_CallStaticJava:
   76.96    case Op_CallJava:
   76.97    case Op_CallDynamicJava:
   76.98 -    fpu.inc_java_call_count(); // Count java call site;
   76.99 +    frc.inc_java_call_count(); // Count java call site;
  76.100    case Op_CallRuntime:
  76.101    case Op_CallLeaf:
  76.102    case Op_CallLeafNoFP: {
  76.103 @@ -1962,7 +1971,7 @@
  76.104      // uncommon_trap, _complete_monitor_locking, _complete_monitor_unlocking,
  76.105      // _new_Java, _new_typeArray, _new_objArray, _rethrow_Java, ...
  76.106      if( !call->is_CallStaticJava() || !call->as_CallStaticJava()->_name ) {
  76.107 -      fpu.inc_call_count();   // Count the call site
  76.108 +      frc.inc_call_count();   // Count the call site
  76.109      } else {                  // See if uncommon argument is shared
  76.110        Node *n = call->in(TypeFunc::Parms);
  76.111        int nop = n->Opcode();
  76.112 @@ -1983,11 +1992,11 @@
  76.113    case Op_StoreD:
  76.114    case Op_LoadD:
  76.115    case Op_LoadD_unaligned:
  76.116 -    fpu.inc_double_count();
  76.117 +    frc.inc_double_count();
  76.118      goto handle_mem;
  76.119    case Op_StoreF:
  76.120    case Op_LoadF:
  76.121 -    fpu.inc_float_count();
  76.122 +    frc.inc_float_count();
  76.123      goto handle_mem;
  76.124  
  76.125    case Op_StoreB:
  76.126 @@ -2324,6 +2333,12 @@
  76.127        n->subsume_by(btp);
  76.128      }
  76.129      break;
  76.130 +  case Op_Loop:
  76.131 +  case Op_CountedLoop:
  76.132 +    if (n->as_Loop()->is_inner_loop()) {
  76.133 +      frc.inc_inner_loop_count();
  76.134 +    }
  76.135 +    break;
  76.136    default:
  76.137      assert( !n->is_Call(), "" );
  76.138      assert( !n->is_Mem(), "" );
  76.139 @@ -2332,17 +2347,17 @@
  76.140  
  76.141    // Collect CFG split points
  76.142    if (n->is_MultiBranch())
  76.143 -    fpu._tests.push(n);
  76.144 +    frc._tests.push(n);
  76.145  }
  76.146  
  76.147  //------------------------------final_graph_reshaping_walk---------------------
  76.148  // Replacing Opaque nodes with their input in final_graph_reshaping_impl(),
  76.149  // requires that the walk visits a node's inputs before visiting the node.
  76.150 -static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Reshape_Counts &fpu ) {
  76.151 +static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Reshape_Counts &frc ) {
  76.152    ResourceArea *area = Thread::current()->resource_area();
  76.153    Unique_Node_List sfpt(area);
  76.154  
  76.155 -  fpu._visited.set(root->_idx); // first, mark node as visited
  76.156 +  frc._visited.set(root->_idx); // first, mark node as visited
  76.157    uint cnt = root->req();
  76.158    Node *n = root;
  76.159    uint  i = 0;
  76.160 @@ -2351,7 +2366,7 @@
  76.161        // Place all non-visited non-null inputs onto stack
  76.162        Node* m = n->in(i);
  76.163        ++i;
  76.164 -      if (m != NULL && !fpu._visited.test_set(m->_idx)) {
  76.165 +      if (m != NULL && !frc._visited.test_set(m->_idx)) {
  76.166          if (m->is_SafePoint() && m->as_SafePoint()->jvms() != NULL)
  76.167            sfpt.push(m);
  76.168          cnt = m->req();
  76.169 @@ -2361,7 +2376,7 @@
  76.170        }
  76.171      } else {
  76.172        // Now do post-visit work
  76.173 -      final_graph_reshaping_impl( n, fpu );
  76.174 +      final_graph_reshaping_impl( n, frc );
  76.175        if (nstack.is_empty())
  76.176          break;             // finished
  76.177        n = nstack.node();   // Get node from stack
  76.178 @@ -2442,16 +2457,16 @@
  76.179      return true;
  76.180    }
  76.181  
  76.182 -  Final_Reshape_Counts fpu;
  76.183 +  Final_Reshape_Counts frc;
  76.184  
  76.185    // Visit everybody reachable!
  76.186    // Allocate stack of size C->unique()/2 to avoid frequent realloc
  76.187    Node_Stack nstack(unique() >> 1);
  76.188 -  final_graph_reshaping_walk(nstack, root(), fpu);
  76.189 +  final_graph_reshaping_walk(nstack, root(), frc);
  76.190  
  76.191    // Check for unreachable (from below) code (i.e., infinite loops).
  76.192 -  for( uint i = 0; i < fpu._tests.size(); i++ ) {
  76.193 -    MultiBranchNode *n = fpu._tests[i]->as_MultiBranch();
  76.194 +  for( uint i = 0; i < frc._tests.size(); i++ ) {
  76.195 +    MultiBranchNode *n = frc._tests[i]->as_MultiBranch();
  76.196      // Get number of CFG targets.
  76.197      // Note that PCTables include exception targets after calls.
  76.198      uint required_outcnt = n->required_outcnt();
  76.199 @@ -2497,7 +2512,7 @@
  76.200      // Check that I actually visited all kids.  Unreached kids
  76.201      // must be infinite loops.
  76.202      for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++)
  76.203 -      if (!fpu._visited.test(n->fast_out(j)->_idx)) {
  76.204 +      if (!frc._visited.test(n->fast_out(j)->_idx)) {
  76.205          record_method_not_compilable("infinite loop");
  76.206          return true;            // Found unvisited kid; must be unreach
  76.207        }
  76.208 @@ -2506,13 +2521,14 @@
  76.209    // If original bytecodes contained a mixture of floats and doubles
  76.210    // check if the optimizer has made it homogenous, item (3).
  76.211    if( Use24BitFPMode && Use24BitFP &&
  76.212 -      fpu.get_float_count() > 32 &&
  76.213 -      fpu.get_double_count() == 0 &&
  76.214 -      (10 * fpu.get_call_count() < fpu.get_float_count()) ) {
  76.215 +      frc.get_float_count() > 32 &&
  76.216 +      frc.get_double_count() == 0 &&
  76.217 +      (10 * frc.get_call_count() < frc.get_float_count()) ) {
  76.218      set_24_bit_selection_and_mode( false,  true );
  76.219    }
  76.220  
  76.221 -  set_has_java_calls(fpu.get_java_call_count() > 0);
  76.222 +  set_java_calls(frc.get_java_call_count());
  76.223 +  set_inner_loops(frc.get_inner_loop_count());
  76.224  
  76.225    // No infinite loops, no reason to bail out.
  76.226    return false;
    77.1 --- a/src/share/vm/opto/compile.hpp	Mon Jul 20 08:20:00 2009 -0700
    77.2 +++ b/src/share/vm/opto/compile.hpp	Mon Jul 27 06:15:29 2009 -0700
    77.3 @@ -223,7 +223,8 @@
    77.4    PhaseCFG*             _cfg;                   // Results of CFG finding
    77.5    bool                  _select_24_bit_instr;   // We selected an instruction with a 24-bit result
    77.6    bool                  _in_24_bit_fp_mode;     // We are emitting instructions with 24-bit results
    77.7 -  bool                  _has_java_calls;        // True if the method has java calls
    77.8 +  int                   _java_calls;            // Number of java calls in the method
    77.9 +  int                   _inner_loops;           // Number of inner loops in the method
   77.10    Matcher*              _matcher;               // Engine to map ideal to machine instructions
   77.11    PhaseRegAlloc*        _regalloc;              // Results of register allocation.
   77.12    int                   _frame_slots;           // Size of total frame in stack slots
   77.13 @@ -505,7 +506,9 @@
   77.14    PhaseCFG*         cfg()                       { return _cfg; }
   77.15    bool              select_24_bit_instr() const { return _select_24_bit_instr; }
   77.16    bool              in_24_bit_fp_mode() const   { return _in_24_bit_fp_mode; }
   77.17 -  bool              has_java_calls() const      { return _has_java_calls; }
   77.18 +  bool              has_java_calls() const      { return _java_calls > 0; }
   77.19 +  int               java_calls() const          { return _java_calls; }
   77.20 +  int               inner_loops() const         { return _inner_loops; }
   77.21    Matcher*          matcher()                   { return _matcher; }
   77.22    PhaseRegAlloc*    regalloc()                  { return _regalloc; }
   77.23    int               frame_slots() const         { return _frame_slots; }
   77.24 @@ -532,7 +535,8 @@
   77.25      _in_24_bit_fp_mode   = mode;
   77.26    }
   77.27  
   77.28 -  void set_has_java_calls(bool z) { _has_java_calls = z; }
   77.29 +  void  set_java_calls(int z) { _java_calls  = z; }
   77.30 +  void set_inner_loops(int z) { _inner_loops = z; }
   77.31  
   77.32    // Instruction bits passed off to the VM
   77.33    int               code_size()                 { return _method_size; }
    78.1 --- a/src/share/vm/opto/library_call.cpp	Mon Jul 20 08:20:00 2009 -0700
    78.2 +++ b/src/share/vm/opto/library_call.cpp	Mon Jul 27 06:15:29 2009 -0700
    78.3 @@ -310,11 +310,6 @@
    78.4      if (!InlineAtomicLong)  return NULL;
    78.5      break;
    78.6  
    78.7 -  case vmIntrinsics::_Object_init:
    78.8 -  case vmIntrinsics::_invoke:
    78.9 -    // We do not intrinsify these; they are marked for other purposes.
   78.10 -    return NULL;
   78.11 -
   78.12    case vmIntrinsics::_getCallerClass:
   78.13      if (!UseNewReflection)  return NULL;
   78.14      if (!InlineReflectionGetCallerClass)  return NULL;
   78.15 @@ -327,6 +322,8 @@
   78.16      break;
   78.17  
   78.18   default:
   78.19 +    assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility");
   78.20 +    assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?");
   78.21      break;
   78.22    }
   78.23  
   78.24 @@ -394,18 +391,11 @@
   78.25    }
   78.26  
   78.27    if (PrintIntrinsics) {
   78.28 -    switch (intrinsic_id()) {
   78.29 -    case vmIntrinsics::_invoke:
   78.30 -    case vmIntrinsics::_Object_init:
   78.31 -      // We do not expect to inline these, so do not produce any noise about them.
   78.32 -      break;
   78.33 -    default:
   78.34 -      tty->print("Did not inline intrinsic %s%s at bci:%d in",
   78.35 -                 vmIntrinsics::name_at(intrinsic_id()),
   78.36 -                 (is_virtual() ? " (virtual)" : ""), kit.bci());
   78.37 -      kit.caller()->print_short_name(tty);
   78.38 -      tty->print_cr(" (%d bytes)", kit.caller()->code_size());
   78.39 -    }
   78.40 +    tty->print("Did not inline intrinsic %s%s at bci:%d in",
   78.41 +               vmIntrinsics::name_at(intrinsic_id()),
   78.42 +               (is_virtual() ? " (virtual)" : ""), kit.bci());
   78.43 +    kit.caller()->print_short_name(tty);
   78.44 +    tty->print_cr(" (%d bytes)", kit.caller()->code_size());
   78.45    }
   78.46    C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed);
   78.47    return NULL;
    79.1 --- a/src/share/vm/opto/output.cpp	Mon Jul 20 08:20:00 2009 -0700
    79.2 +++ b/src/share/vm/opto/output.cpp	Mon Jul 27 06:15:29 2009 -0700
    79.3 @@ -50,6 +50,13 @@
    79.4    init_scratch_buffer_blob();
    79.5    if (failing())  return; // Out of memory
    79.6  
    79.7 +  // The number of new nodes (mostly MachNop) is proportional to
    79.8 +  // the number of java calls and inner loops which are aligned.
    79.9 +  if ( C->check_node_count((NodeLimitFudgeFactor + C->java_calls()*3 +
   79.10 +                            C->inner_loops()*(OptoLoopAlignment-1)),
   79.11 +                           "out of nodes before code generation" ) ) {
   79.12 +    return;
   79.13 +  }
   79.14    // Make sure I can find the Start Node
   79.15    Block_Array& bbs = _cfg->_bbs;
   79.16    Block *entry = _cfg->_blocks[1];
   79.17 @@ -1105,7 +1112,7 @@
   79.18    uint *call_returns = NEW_RESOURCE_ARRAY(uint, _cfg->_num_blocks+1);
   79.19  
   79.20    uint  return_offset = 0;
   79.21 -  MachNode *nop = new (this) MachNopNode();
   79.22 +  int nop_size = (new (this) MachNopNode())->size(_regalloc);
   79.23  
   79.24    int previous_offset = 0;
   79.25    int current_offset  = 0;
   79.26 @@ -1188,7 +1195,6 @@
   79.27          }
   79.28  
   79.29          // align the instruction if necessary
   79.30 -        int nop_size = nop->size(_regalloc);
   79.31          int padding = mach->compute_padding(current_offset);
   79.32          // Make sure safepoint node for polling is distinct from a call's
   79.33          // return by adding a nop if needed.
   79.34 @@ -1372,7 +1378,6 @@
   79.35  
   79.36      // If the next block is the top of a loop, pad this block out to align
   79.37      // the loop top a little. Helps prevent pipe stalls at loop back branches.
   79.38 -    int nop_size = (new (this) MachNopNode())->size(_regalloc);
   79.39      if( i<_cfg->_num_blocks-1 ) {
   79.40        Block *nb = _cfg->_blocks[i+1];
   79.41        uint padding = nb->alignment_padding(current_offset);
    80.1 --- a/src/share/vm/prims/unsafe.cpp	Mon Jul 20 08:20:00 2009 -0700
    80.2 +++ b/src/share/vm/prims/unsafe.cpp	Mon Jul 27 06:15:29 2009 -0700
    80.3 @@ -1048,7 +1048,11 @@
    80.4    oop e = JNIHandles::resolve(e_h);
    80.5    oop p = JNIHandles::resolve(obj);
    80.6    HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);
    80.7 -  update_barrier_set_pre((void*)addr, e);
    80.8 +  if (UseCompressedOops) {
    80.9 +    update_barrier_set_pre((narrowOop*)addr, e);
   80.10 +  } else {
   80.11 +    update_barrier_set_pre((oop*)addr, e);
   80.12 +  }
   80.13    oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e);
   80.14    jboolean success  = (res == e);
   80.15    if (success)
    81.1 --- a/src/share/vm/runtime/arguments.cpp	Mon Jul 20 08:20:00 2009 -0700
    81.2 +++ b/src/share/vm/runtime/arguments.cpp	Mon Jul 27 06:15:29 2009 -0700
    81.3 @@ -1202,18 +1202,13 @@
    81.4    }
    81.5  
    81.6  #ifdef _LP64
    81.7 -  // Compressed Headers do not work with CMS, which uses a bit in the klass
    81.8 -  // field offset to determine free list chunk markers.
    81.9    // Check that UseCompressedOops can be set with the max heap size allocated
   81.10    // by ergonomics.
   81.11    if (MaxHeapSize <= max_heap_for_compressed_oops()) {
   81.12 -    if (FLAG_IS_DEFAULT(UseCompressedOops) && !UseG1GC) {
   81.13 +    if (FLAG_IS_DEFAULT(UseCompressedOops)) {
   81.14        // Turn off until bug is fixed.
   81.15        // the following line to return it to default status.
   81.16        // FLAG_SET_ERGO(bool, UseCompressedOops, true);
   81.17 -    } else if (UseCompressedOops && UseG1GC) {
   81.18 -      warning(" UseCompressedOops does not currently work with UseG1GC; switching off UseCompressedOops. ");
   81.19 -      FLAG_SET_DEFAULT(UseCompressedOops, false);
   81.20      }
   81.21  #ifdef _WIN64
   81.22      if (UseLargePages && UseCompressedOops) {
   81.23 @@ -1454,6 +1449,7 @@
   81.24    if (UseSerialGC)                       i++;
   81.25    if (UseConcMarkSweepGC || UseParNewGC) i++;
   81.26    if (UseParallelGC || UseParallelOldGC) i++;
   81.27 +  if (UseG1GC)                           i++;
   81.28    if (i > 1) {
   81.29      jio_fprintf(defaultStream::error_stream(),
   81.30                  "Conflicting collector combinations in option list; "
   81.31 @@ -2603,22 +2599,6 @@
   81.32      return result;
   81.33    }
   81.34  
   81.35 -  // These are hacks until G1 is fully supported and tested
   81.36 -  // but lets you force -XX:+UseG1GC in PRT and get it where it (mostly) works
   81.37 -  if (UseG1GC) {
   81.38 -    if (UseConcMarkSweepGC || UseParNewGC || UseParallelGC || UseParallelOldGC || UseSerialGC) {
   81.39 -#ifndef PRODUCT
   81.40 -      tty->print_cr("-XX:+UseG1GC is incompatible with other collectors, using UseG1GC");
   81.41 -#endif // PRODUCT
   81.42 -      UseConcMarkSweepGC = false;
   81.43 -      UseParNewGC        = false;
   81.44 -      UseParallelGC      = false;
   81.45 -      UseParallelOldGC   = false;
   81.46 -      UseSerialGC        = false;
   81.47 -    }
   81.48 -    no_shared_spaces();
   81.49 -  }
   81.50 -
   81.51  #ifndef PRODUCT
   81.52    if (TraceBytecodesAt != 0) {
   81.53      TraceBytecodes = true;
   81.54 @@ -2676,10 +2656,7 @@
   81.55    } else if (UseParNewGC) {
   81.56      // Set some flags for ParNew
   81.57      set_parnew_gc_flags();
   81.58 -  }
   81.59 -  // Temporary; make the "if" an "else-if" before
   81.60 -  // we integrate G1. XXX
   81.61 -  if (UseG1GC) {
   81.62 +  } else if (UseG1GC) {
   81.63      // Set some flags for garbage-first, if needed.
   81.64      set_g1_gc_flags();
   81.65    }
    82.1 --- a/src/share/vm/runtime/atomic.hpp	Mon Jul 20 08:20:00 2009 -0700
    82.2 +++ b/src/share/vm/runtime/atomic.hpp	Mon Jul 27 06:15:29 2009 -0700
    82.3 @@ -39,6 +39,8 @@
    82.4    static void store_ptr(intptr_t store_value, volatile intptr_t* dest);
    82.5    static void store_ptr(void*    store_value, volatile void*     dest);
    82.6  
    82.7 +  static jlong load(volatile jlong* src);
    82.8 +
    82.9    // Atomically add to a location, return updated value
   82.10    static jint     add    (jint     add_value, volatile jint*     dest);
   82.11    static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest);
    83.1 --- a/src/share/vm/runtime/globals.hpp	Mon Jul 20 08:20:00 2009 -0700
    83.2 +++ b/src/share/vm/runtime/globals.hpp	Mon Jul 27 06:15:29 2009 -0700
    83.3 @@ -1994,6 +1994,10 @@
    83.4    product_rw(bool, PrintHeapAtGC, false,                                    \
    83.5            "Print heap layout before and after each GC")                     \
    83.6                                                                              \
    83.7 +  product_rw(bool, PrintHeapAtGCExtended, false,                            \
    83.8 +          "Prints extended information about the layout of the heap "       \
    83.9 +          "when -XX:+PrintHeapAtGC is set")                                 \
   83.10 +                                                                            \
   83.11    product(bool, PrintHeapAtSIGBREAK, true,                                  \
   83.12            "Print heap layout in response to SIGBREAK")                      \
   83.13                                                                              \
    84.1 --- a/src/share/vm/runtime/safepoint.cpp	Mon Jul 20 08:20:00 2009 -0700
    84.2 +++ b/src/share/vm/runtime/safepoint.cpp	Mon Jul 27 06:15:29 2009 -0700
    84.3 @@ -49,7 +49,7 @@
    84.4      // In the future we should investigate whether CMS can use the
    84.5      // more-general mechanism below.  DLD (01/05).
    84.6      ConcurrentMarkSweepThread::synchronize(false);
    84.7 -  } else {
    84.8 +  } else if (UseG1GC) {
    84.9      ConcurrentGCThread::safepoint_synchronize();
   84.10    }
   84.11  #endif // SERIALGC
   84.12 @@ -400,7 +400,7 @@
   84.13    // If there are any concurrent GC threads resume them.
   84.14    if (UseConcMarkSweepGC) {
   84.15      ConcurrentMarkSweepThread::desynchronize(false);
   84.16 -  } else {
   84.17 +  } else if (UseG1GC) {
   84.18      ConcurrentGCThread::safepoint_desynchronize();
   84.19    }
   84.20  #endif // SERIALGC
    85.1 --- a/src/share/vm/runtime/sharedRuntime.cpp	Mon Jul 20 08:20:00 2009 -0700
    85.2 +++ b/src/share/vm/runtime/sharedRuntime.cpp	Mon Jul 27 06:15:29 2009 -0700
    85.3 @@ -119,6 +119,7 @@
    85.4      assert(false, "should be optimized out");
    85.5      return;
    85.6    }
    85.7 +  assert(orig->is_oop(true /* ignore mark word */), "Error");
    85.8    // store the original value that was in the field reference
    85.9    thread->satb_mark_queue().enqueue(orig);
   85.10  JRT_END
    86.1 --- a/src/share/vm/runtime/stackValue.cpp	Mon Jul 20 08:20:00 2009 -0700
    86.2 +++ b/src/share/vm/runtime/stackValue.cpp	Mon Jul 27 06:15:29 2009 -0700
    86.3 @@ -104,7 +104,17 @@
    86.4      }
    86.5  #endif
    86.6      case Location::oop: {
    86.7 -      Handle h(*(oop *)value_addr); // Wrap a handle around the oop
    86.8 +      oop val = *(oop *)value_addr;
    86.9 +#ifdef _LP64
   86.10 +      if (Universe::is_narrow_oop_base(val)) {
   86.11 +         // Compiled code may produce decoded oop = narrow_oop_base
   86.12 +         // when a narrow oop implicit null check is used.
   86.13 +         // The narrow_oop_base could be NULL or be the address
   86.14 +         // of the page below heap. Use NULL value for both cases.
   86.15 +         val = (oop)NULL;
   86.16 +      }
   86.17 +#endif
   86.18 +      Handle h(val); // Wrap a handle around the oop
   86.19        return new StackValue(h);
   86.20      }
   86.21      case Location::addr: {
    87.1 --- a/src/share/vm/utilities/taskqueue.cpp	Mon Jul 20 08:20:00 2009 -0700
    87.2 +++ b/src/share/vm/utilities/taskqueue.cpp	Mon Jul 27 06:15:29 2009 -0700
    87.3 @@ -64,15 +64,18 @@
    87.4  }
    87.5  
    87.6  void ParallelTaskTerminator::yield() {
    87.7 +  assert(_offered_termination <= _n_threads, "Invariant");
    87.8    os::yield();
    87.9  }
   87.10  
   87.11  void ParallelTaskTerminator::sleep(uint millis) {
   87.12 +  assert(_offered_termination <= _n_threads, "Invariant");
   87.13    os::sleep(Thread::current(), millis, false);
   87.14  }
   87.15  
   87.16  bool
   87.17  ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) {
   87.18 +  assert(_offered_termination < _n_threads, "Invariant");
   87.19    Atomic::inc(&_offered_termination);
   87.20  
   87.21    uint yield_count = 0;
   87.22 @@ -96,6 +99,7 @@
   87.23    // Loop waiting for all threads to offer termination or
   87.24    // more work.
   87.25    while (true) {
   87.26 +    assert(_offered_termination <= _n_threads, "Invariant");
   87.27      // Are all threads offering termination?
   87.28      if (_offered_termination == _n_threads) {
   87.29        return true;
   87.30 @@ -151,6 +155,7 @@
   87.31        if (peek_in_queue_set() ||
   87.32            (terminator != NULL && terminator->should_exit_termination())) {
   87.33          Atomic::dec(&_offered_termination);
   87.34 +        assert(_offered_termination < _n_threads, "Invariant");
   87.35          return false;
   87.36        }
   87.37      }
    88.1 --- a/src/share/vm/utilities/taskqueue.hpp	Mon Jul 20 08:20:00 2009 -0700
    88.2 +++ b/src/share/vm/utilities/taskqueue.hpp	Mon Jul 27 06:15:29 2009 -0700
    88.3 @@ -560,8 +560,14 @@
    88.4  class StarTask {
    88.5    void*  _holder;        // either union oop* or narrowOop*
    88.6   public:
    88.7 -  StarTask(narrowOop *p) { _holder = (void *)((uintptr_t)p | COMPRESSED_OOP_MASK); }
    88.8 -  StarTask(oop *p)       { _holder = (void*)p; }
    88.9 +  StarTask(narrowOop* p) {
   88.10 +    assert(((uintptr_t)p & COMPRESSED_OOP_MASK) == 0, "Information loss!");
   88.11 +    _holder = (void *)((uintptr_t)p | COMPRESSED_OOP_MASK);
   88.12 +  }
   88.13 +  StarTask(oop* p)       {
   88.14 +    assert(((uintptr_t)p & COMPRESSED_OOP_MASK) == 0, "Information loss!");
   88.15 +    _holder = (void*)p;
   88.16 +  }
   88.17    StarTask()             { _holder = NULL; }
   88.18    operator oop*()        { return (oop*)_holder; }
   88.19    operator narrowOop*()  {
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/test/compiler/6826736/Test.java	Mon Jul 27 06:15:29 2009 -0700
    89.3 @@ -0,0 +1,75 @@
    89.4 +/*
    89.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    89.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    89.7 + *
    89.8 + * This code is free software; you can redistribute it and/or modify it
    89.9 + * under the terms of the GNU General Public License version 2 only, as
   89.10 + * published by the Free Software Foundation.
   89.11 + *
   89.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   89.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   89.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   89.15 + * version 2 for more details (a copy is included in the LICENSE file that
   89.16 + * accompanied this code).
   89.17 + *
   89.18 + * You should have received a copy of the GNU General Public License version
   89.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   89.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   89.21 + *
   89.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   89.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   89.24 + * have any questions.
   89.25 + *
   89.26 + */
   89.27 +
   89.28 +/**
   89.29 + * @test
   89.30 + * @bug 6826736
   89.31 + * @summary CMS: core dump with -XX:+UseCompressedOops
   89.32 + *
   89.33 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:+ScavengeALot -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g -XX:CompileThreshold=100 -XX:CompileOnly=Test.test -XX:-BlockLayoutRotateLoops -XX:LoopUnrollLimit=0 Test
   89.34 + */
   89.35 +
   89.36 +public class Test {
   89.37 +    int[] arr;
   89.38 +    int[] arr2;
   89.39 +    int test(int r) {
   89.40 +        for (int i = 0; i < 100; i++) {
   89.41 +            for (int j = i; j < 100; j++) {
   89.42 +               int a = 0;
   89.43 +               for (long k = 0; k < 100; k++) {
   89.44 +                  a += k;
   89.45 +               }
   89.46 +               if (arr != null)
   89.47 +                   a = arr[j];
   89.48 +               r += a;
   89.49 +            }
   89.50 +        }
   89.51 +        return r;
   89.52 +    }
   89.53 +
   89.54 +    public static void main(String[] args) {
   89.55 +        int r = 0;
   89.56 +        Test t = new Test();
   89.57 +        for (int i = 0; i < 100; i++) {
   89.58 +            t.arr = new int[100];
   89.59 +            r = t.test(r);
   89.60 +        }
   89.61 +        System.out.println("Warmup 1 is done.");
   89.62 +        for (int i = 0; i < 100; i++) {
   89.63 +            t.arr = null;
   89.64 +            r = t.test(r);
   89.65 +        }
   89.66 +        System.out.println("Warmup 2 is done.");
   89.67 +        for (int i = 0; i < 100; i++) {
   89.68 +            t.arr = new int[100];
   89.69 +            r = t.test(r);
   89.70 +        }
   89.71 +        System.out.println("Warmup is done.");
   89.72 +        for (int i = 0; i < 100; i++) {
   89.73 +            t.arr = new int[1000000];
   89.74 +            t.arr = null;
   89.75 +            r = t.test(r);
   89.76 +        }
   89.77 +    }
   89.78 +}
    90.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.2 +++ b/test/compiler/6857159/Test6857159.java	Mon Jul 27 06:15:29 2009 -0700
    90.3 @@ -0,0 +1,68 @@
    90.4 +/*
    90.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    90.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    90.7 + *
    90.8 + * This code is free software; you can redistribute it and/or modify it
    90.9 + * under the terms of the GNU General Public License version 2 only, as
   90.10 + * published by the Free Software Foundation.
   90.11 + *
   90.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   90.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   90.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   90.15 + * version 2 for more details (a copy is included in the LICENSE file that
   90.16 + * accompanied this code).
   90.17 + *
   90.18 + * You should have received a copy of the GNU General Public License version
   90.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   90.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   90.21 + *
   90.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   90.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   90.24 + * have any questions.
   90.25 + *
   90.26 + */
   90.27 +
   90.28 +/**
   90.29 + * @test
   90.30 + * @bug 6857159
   90.31 + * @summary local schedule failed with checkcast of Thread.currentThread()
   90.32 + *
   90.33 + * @run shell Test6857159.sh
   90.34 + */
   90.35 +
   90.36 +public class Test6857159 extends Thread {
   90.37 +    static class ct0 extends Test6857159 {
   90.38 +        public void message() {
   90.39 +            // System.out.println("message");
   90.40 +        }
   90.41 +
   90.42 +        public void run() {
   90.43 +             message();
   90.44 +             ct0 ct = (ct0) Thread.currentThread();
   90.45 +             ct.message();
   90.46 +        }
   90.47 +    }
   90.48 +    static class ct1 extends ct0 {
   90.49 +        public void message() {
   90.50 +            // System.out.println("message");
   90.51 +        }
   90.52 +    }
   90.53 +    static class ct2 extends ct0 {
   90.54 +        public void message() {
   90.55 +            // System.out.println("message");
   90.56 +        }
   90.57 +    }
   90.58 +
   90.59 +    public static void main(String[] args) throws Exception {
   90.60 +        for (int i = 0; i < 100000; i++) {
   90.61 +            Thread t = null;
   90.62 +            switch (i % 3) {
   90.63 +              case 0: t = new ct0(); break;
   90.64 +              case 1: t = new ct1(); break;
   90.65 +              case 2: t = new ct2(); break;
   90.66 +            }
   90.67 +            t.start();
   90.68 +            t.join();
   90.69 +        }
   90.70 +    }
   90.71 +}
    91.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.2 +++ b/test/compiler/6857159/Test6857159.sh	Mon Jul 27 06:15:29 2009 -0700
    91.3 @@ -0,0 +1,65 @@
    91.4 +#!/bin/sh
    91.5 +# 
    91.6 +# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    91.7 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    91.8 +# 
    91.9 +# This code is free software; you can redistribute it and/or modify it
   91.10 +# under the terms of the GNU General Public License version 2 only, as
   91.11 +# published by the Free Software Foundation.
   91.12 +# 
   91.13 +# This code is distributed in the hope that it will be useful, but WITHOUT
   91.14 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   91.15 +# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   91.16 +# version 2 for more details (a copy is included in the LICENSE file that
   91.17 +# accompanied this code).
   91.18 +# 
   91.19 +# You should have received a copy of the GNU General Public License version
   91.20 +# 2 along with this work; if not, write to the Free Software Foundation,
   91.21 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   91.22 +# 
   91.23 +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   91.24 +# CA 95054 USA or visit www.sun.com if you need additional information or
   91.25 +# have any questions.
   91.26 +# 
   91.27 +# 
   91.28 +
   91.29 +if [ "${TESTSRC}" = "" ]
   91.30 +then
   91.31 +  echo "TESTSRC not set.  Test cannot execute.  Failed."
   91.32 +  exit 1
   91.33 +fi
   91.34 +echo "TESTSRC=${TESTSRC}"
   91.35 +if [ "${TESTJAVA}" = "" ]
   91.36 +then
   91.37 +  echo "TESTJAVA not set.  Test cannot execute.  Failed."
   91.38 +  exit 1
   91.39 +fi
   91.40 +echo "TESTJAVA=${TESTJAVA}"
   91.41 +if [ "${TESTCLASSES}" = "" ]
   91.42 +then
   91.43 +  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
   91.44 +  exit 1
   91.45 +fi
   91.46 +echo "TESTCLASSES=${TESTCLASSES}"
   91.47 +echo "CLASSPATH=${CLASSPATH}"
   91.48 +
   91.49 +set -x
   91.50 +
   91.51 +cp ${TESTSRC}/Test6857159.java .
   91.52 +cp ${TESTSRC}/Test6857159.sh .
   91.53 +
   91.54 +${TESTJAVA}/bin/javac -d . Test6857159.java
   91.55 +
   91.56 +${TESTJAVA}/bin/java  ${TESTVMOPTS} -Xbatch -XX:+PrintCompilation -XX:CompileOnly=Test6857159\$ct.run Test6857159 > test.out 2>&1
   91.57 +
   91.58 +grep "COMPILE SKIPPED" test.out
   91.59 +
   91.60 +result=$?
   91.61 +if [ $result -eq 1 ]
   91.62 +then
   91.63 +  echo "Passed"
   91.64 +  exit 0
   91.65 +else
   91.66 +  echo "Failed"
   91.67 +  exit 1
   91.68 +fi
    92.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.2 +++ b/test/compiler/6863420/Test.java	Mon Jul 27 06:15:29 2009 -0700
    92.3 @@ -0,0 +1,91 @@
    92.4 +/*
    92.5 + * Copyright 2009 D.E. Shaw.  All Rights Reserved.
    92.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    92.7 + *
    92.8 + * This code is free software; you can redistribute it and/or modify it
    92.9 + * under the terms of the GNU General Public License version 2 only, as
   92.10 + * published by the Free Software Foundation.
   92.11 + *
   92.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   92.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   92.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   92.15 + * version 2 for more details (a copy is included in the LICENSE file that
   92.16 + * accompanied this code).
   92.17 + *
   92.18 + * You should have received a copy of the GNU General Public License version
   92.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   92.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   92.21 + *
   92.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   92.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   92.24 + * have any questions.
   92.25 + *
   92.26 + */
   92.27 +
   92.28 +/**
   92.29 + * @test
   92.30 + * @bug 6863420
   92.31 + * @summary os::javaTimeNanos() go backward on Solaris x86
   92.32 + *
   92.33 + * @run main/othervm Test
   92.34 + */
   92.35 +
   92.36 +public class Test {
   92.37 +    static long value = 0;
   92.38 +    static boolean got_backward_time = false;
   92.39 +
   92.40 +    public static void main(String args[]) {
   92.41 +        final int count = 100000;
   92.42 +
   92.43 +        for (int numThreads = 1; numThreads <= 32; numThreads++) {
   92.44 +            final int numRuns = 1;
   92.45 +            for (int t=1; t <= numRuns; t++) {
   92.46 +                final int curRun = t;
   92.47 +
   92.48 +                System.out.println("Spawning " + numThreads + " threads");
   92.49 +                final Thread threads[] = new Thread[numThreads];
   92.50 +                for (int i = 0; i < threads.length; i++) {
   92.51 +                    Runnable thread =
   92.52 +                        new Runnable() {
   92.53 +                            public void run() {
   92.54 +                                for (long l = 0; l < 100000; l++) {
   92.55 +                                    final long start = System.nanoTime();
   92.56 +                                    if (value == 12345678) {
   92.57 +                                        System.out.println("Wow!");
   92.58 +                                    }
   92.59 +                                    final long end = System.nanoTime();
   92.60 +                                    final long time = end - start;
   92.61 +                                    value += time;
   92.62 +                                    if (time < 0) {
   92.63 +                                        System.out.println(
   92.64 +                                            "Backwards: " +
   92.65 +                                            "start=" + start + " " +
   92.66 +                                            "end=" + end + " " +
   92.67 +                                            "time= " + time
   92.68 +                                        );
   92.69 +                                        got_backward_time = true;
   92.70 +                                    }
   92.71 +                                }
   92.72 +                            }
   92.73 +                        };
   92.74 +                    threads[i] = new Thread(thread, "Thread" + i);
   92.75 +                }
   92.76 +                for (int i = 0; i < threads.length; i++) {
   92.77 +                    threads[i].start();
   92.78 +                }
   92.79 +                for (int i = 0; i < threads.length; i++) {
   92.80 +                    try {
   92.81 +                        threads[i].join();
   92.82 +                    }
   92.83 +                    catch (InterruptedException e) {
   92.84 +                        continue;
   92.85 +                    }
   92.86 +                }
   92.87 +            }
   92.88 +        }
   92.89 +
   92.90 +        if (got_backward_time) {
   92.91 +            System.exit(97);
   92.92 +        }
   92.93 +    }
   92.94 +}

mercurial