src/cpu/sparc/vm/args.cc

Thu, 07 Apr 2011 09:53:20 -0700

author
johnc
date
Thu, 07 Apr 2011 09:53:20 -0700
changeset 2781
e1162778c1c8
parent 1907
c18cbe5936b8
child 6876
710a3c8b516e
permissions
-rw-r--r--

7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes

     1 /*
     2  * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *  
    23  */
    25 #include <stdio.h>
    26 #include <string.h>
    28 static const int R_O0_num = 1000;
    29 static const int R_I0_num = 2000;
    30 static const int R_F0_num = 3000;
    31 static const int R_F1_num = R_F0_num + 1;
    32 static const int R_F2_num = R_F0_num + 2;
    33 static const int STACK_num= 4000;
    35 static bool LP64 = false;
    36 static bool LONGS_IN_ONE_ENTRY = false;
    38 static const int Op_RegI = 'I';
    39 static const int Op_RegP = 'P';
    40 static const int Op_RegF = 'F';
    41 static const int Op_RegD = 'D';
    42 static const int Op_RegL = 'L';
    43 static const int SPARC_ARGS_IN_REGS_NUM=6;
    45 static void print_reg( int reg ) {
    46   if( reg == 0 )
    47     printf("__");               // halve's
    48   else if( reg >= STACK_num && reg < STACK_num+100 )
    49     printf("S%d_",reg - STACK_num);
    50   else if( reg >= R_F0_num && reg < R_F0_num+100 )
    51     printf("F%d_",reg - R_F0_num);
    52   else if( reg >= R_O0_num && reg < R_O0_num+100 ) {
    53     if( LONGS_IN_ONE_ENTRY ) {
    54       reg -= R_O0_num;
    55       printf("O%d",reg>>1);
    56       printf(reg&1 ? "H" : "L");
    57     } else
    58       printf("O%d_",reg - R_O0_num);
    59   } else
    60     printf("Wretched: %d\n", reg);
    61 }
    63 static void print_convention( int *sig, const char *s, int length ) {
    64   // Print it out
    65   for( int i = 0; i < length; i++) {
    66     if( sig[i] == 0 ) continue; // do not print 'halves'
    67     print_reg( sig[i] & 0xFFFF );
    68     int reg = sig[i] >> 16;
    69     if( reg ) {
    70       printf(":");
    71       print_reg( reg );
    72     } else {
    73       printf("    ");
    74     }
    75     printf("  ");
    76   }
    77   printf("\n");
    78 }
    80 static int INT_SCALE( int x ) {
    81   return LONGS_IN_ONE_ENTRY ? (x<<1) : x;
    82 }
    84 static void java_convention( int *sig, const char *s, int length ) {
    85   if( LP64 && !LONGS_IN_ONE_ENTRY ) {
    86     printf("LP64 and 2-reg longs not supported\n");
    87     return;
    88   }
    89   for( int i = 0; i < length; i++ )
    90     sig[i] = s[i];              // Reset sig array
    91   bool is_outgoing = true;
    93   int int_base = (is_outgoing ? R_O0_num : R_I0_num);
    95   // Convention is to pack the first 6 int/oop args into the first 6
    96   // registers (I0-I5), extras spill to the stack.  Then pack the first
    97   // 32 float args into F0-F31, extras spill to the stack.  Then pad
    98   // all register sets to align.  Then put longs and doubles into the
    99   // same registers as they fit, else spill to the stack.
   100   int int_reg_max = SPARC_ARGS_IN_REGS_NUM;
   101   int flt_reg_max = 32;
   103   // Count int/oop and float args.  See how many stack slots we'll need
   104   // and where the longs & doubles will go.
   105   int int_reg_cnt   = 0;
   106   int flt_reg_cnt   = 0;
   107   int stk_reg_pairs = 0;
   108   for( int i = 0; i < length; i++) {
   109     switch( sig[i] ) {
   110     case Op_RegL:               // Longs-in-1-reg compete with int args
   111       if( LONGS_IN_ONE_ENTRY ) { 
   112         if( int_reg_cnt < int_reg_max ) int_reg_cnt++;
   113       }
   114       break;
   115     case Op_RegP:
   116       if( int_reg_cnt < int_reg_max ) int_reg_cnt++;
   117       else if( !LP64 )                stk_reg_pairs++;
   118       break;
   119     case Op_RegI:
   120       if( int_reg_cnt < int_reg_max ) int_reg_cnt++;
   121       else                            stk_reg_pairs++;
   122       break;
   123     case Op_RegF:
   124       if( flt_reg_cnt < flt_reg_max ) flt_reg_cnt++;
   125       else                            stk_reg_pairs++;
   126       break;
   127     }
   128   }
   130   // This is where the longs/doubles start on the stack.
   131   stk_reg_pairs = (stk_reg_pairs+1) & ~1; // Round
   133   int int_reg_pairs = (int_reg_cnt+1) & ~1; // 32-bit 2-reg longs only
   134   int flt_reg_pairs = (flt_reg_cnt+1) & ~1;
   136   int stk_reg = 0;
   137   int int_reg = 0;
   138   int flt_reg = 0;
   140   // Now do the signature layout
   141   for( int i = 0; i < length; i++) {
   142     int tmp = sig[i];
   143     if( tmp == Op_RegP )
   144       tmp = LP64 ? Op_RegL : Op_RegI;   // Treat ptrs and ints or long accordingly
   145     switch( tmp ) {
   146     case Op_RegI:
   147 //  case Op_RegP: 
   148       if( int_reg < int_reg_max) tmp = INT_SCALE(int_reg++) + int_base;
   149       else                       tmp = STACK_num + stk_reg++;
   150       sig[i] = tmp;
   151       break;
   153     case Op_RegL: 
   154       if( sig[i] != Op_RegP && sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; }
   155 //  case Op_RegP: 
   156       if( LONGS_IN_ONE_ENTRY ) {
   157         if( int_reg < int_reg_max ) {
   158           tmp = INT_SCALE(int_reg++) + int_base;
   159         } else {
   160           tmp = STACK_num + stk_reg_pairs;
   161           stk_reg_pairs += 2;
   162         }
   163       } else {
   164         if( int_reg_pairs < int_reg_max ) {
   165           tmp = int_reg_pairs + int_base;
   166           int_reg_pairs += 2;
   167         } else {
   168           tmp = STACK_num + stk_reg_pairs;
   169           stk_reg_pairs += 2;
   170         }
   171       }
   172       sig[i] = tmp | (tmp+1)<<16; // Smear to pair
   173       break;
   175     case Op_RegF: 
   176       sig[i] = (flt_reg < flt_reg_max) ? (R_F0_num + flt_reg++) : STACK_num + stk_reg++;
   177       break;
   178     case Op_RegD: 
   179       if( sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; }
   180       if( flt_reg_pairs < flt_reg_max ) {
   181         tmp = R_F0_num + flt_reg_pairs;
   182         flt_reg_pairs += 2;
   183       } else {
   184         tmp = STACK_num + stk_reg_pairs;
   185         stk_reg_pairs += 2;
   186       }
   187       sig[i] = tmp | (tmp+1)<<16; // Smear to pair
   188       break;
   189     case 'h': sig[i] = 0; break;
   190     default:
   191       printf("Bad character: %c\n", sig[i] );
   192       return;
   193     }
   194   }
   196   printf("java ");
   197   printf(LP64 ? "LP64 " : "LP32 ");
   198   printf(LONGS_IN_ONE_ENTRY ? "long1: " : "long2: ");
   199   print_convention(sig,s,length);
   200 }
   202 static int int_stk_helper( int i ) {
   203   if( i < 6 ) return R_O0_num + (LONGS_IN_ONE_ENTRY ? i<<1 : i);
   204   else        return STACK_num + (LP64              ? i<<1 : i);
   205 }
   207 static void native_convention( int *sig, const char *s, int length ) {
   208   if( LP64 && !LONGS_IN_ONE_ENTRY ) {
   209     printf("LP64 and 2-reg longs not supported\n");
   210     return;
   211   }
   212   for( int i = 0; i < length; i++ )
   213     sig[i] = s[i];              // Reset sig array
   215   // The native convention is V8 if !LP64, which means the V8 convention is
   216   // used both with and without LONGS_IN_ONE_ENTRY, an unfortunate split.  The
   217   // same actual machine registers are used, but they are named differently in
   218   // the LONGS_IN_ONE_ENTRY mode.  The LP64 convention is the V9 convention
   219   // which is slightly more sane.
   221   if( LP64 ) {
   222     // V9 convention: All things "as-if" on double-wide stack slots.
   223     // Hoist any int/ptr/long's in the first 6 to int regs.
   224     // Hoist any flt/dbl's in the first 16 dbl regs.
   225     int j = 0;                  // Count of actual args, not HALVES
   226     for( int i=0; i<length; i++, j++ ) {
   227       int tmp;
   228       switch( sig[i] ) {
   229       case Op_RegI:
   230         sig[i] = int_stk_helper( j );
   231         break;
   232       case Op_RegL:
   233         if( sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; }
   234       case Op_RegP:
   235         tmp = int_stk_helper( j );
   236         sig[i] = tmp | ((tmp+1) << 16); // Smear to pair
   237         break;
   238       case Op_RegF:                 // V9ism: floats go in ODD registers
   239         sig[i] = ((j < 16) ? R_F1_num : (STACK_num + 1)) + (j<<1);
   240         break;
   241       case Op_RegD:                 // V9ism: doubles go in EVEN/ODD regs
   242         tmp    = ((j < 16) ? R_F0_num : STACK_num) + (j<<1);
   243         sig[i] = tmp | ((tmp+1) << 16); // Smear to pair
   244         break;
   245       case 'h': sig[i] = 0; j--; break; // Do not count HALVES
   246       default:
   247         printf("Bad character: %c\n", sig[i] );
   248         return;
   249       }
   250     }
   252   } else {
   253     // V8 convention: first 6 things in O-regs, rest on stack.
   254     // Alignment is willy-nilly.
   255     for( int i=0; i<length; i++ ) {
   256       int tmp;
   257       switch( sig[i] ) {
   258       case Op_RegI:
   259       case Op_RegP:
   260       case Op_RegF:
   261         sig[i] = int_stk_helper( i );
   262         break;
   263       case Op_RegL:
   264       case Op_RegD:
   265         if( sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; }
   266         tmp = int_stk_helper( i );
   267         sig[i] = tmp | (int_stk_helper( i+1 ) << 16);
   268         break;
   269       case 'h': sig[i] = 0; break;
   270       default:
   271         printf("Bad character: %c\n", sig[i] );
   272         return;
   273       }
   274     }
   275   }
   277   printf("natv ");
   278   printf(LP64 ? "LP64 " : "LP32 ");
   279   printf(LONGS_IN_ONE_ENTRY ? "long1: " : "long2: ");
   280   print_convention(sig,s,length);
   281 }
   283 int main( int argc, char **argv ) {
   285   if( argc != 2 ) {
   286     printf("Usage: args IPFLhDh... (Java argument string)\n");
   287     printf("Returns argument layout\n");
   288     return -1;
   289   }
   291   const char *s = argv[1];
   292   int length = strlen(s);
   293   int sig[1000];
   295   LP64 = false; LONGS_IN_ONE_ENTRY = false;
   296   java_convention( sig, s, length );
   297   LP64 = false; LONGS_IN_ONE_ENTRY = true;
   298   java_convention( sig, s, length );
   299   LP64 = true ; LONGS_IN_ONE_ENTRY = true;
   300   java_convention( sig, s, length );
   302   LP64 = false; LONGS_IN_ONE_ENTRY = false;
   303   native_convention( sig, s, length );
   304   LP64 = false; LONGS_IN_ONE_ENTRY = true;
   305   native_convention( sig, s, length );
   306   LP64 = true ; LONGS_IN_ONE_ENTRY = true;
   307   native_convention( sig, s, length );
   308 }

mercurial