Merge remote-tracking branch 'mfoliveira/ppc64el-v2'
authorZoltan Varga <vargaz@gmail.com>
Sun, 30 Nov 2014 01:48:38 +0000 (02:48 +0100)
committerZoltan Varga <vargaz@gmail.com>
Sun, 30 Nov 2014 01:48:38 +0000 (02:48 +0100)
This is a merge of:

https://github.com/mono/mono/pull/1409

1  2 
mono/metadata/sgen-marksweep.c
mono/mini/aot-compiler.c
mono/mini/exceptions-ppc.c
mono/mini/mini-gc.c
mono/mini/mini-ppc.h
mono/mini/mini.c

index d60f8d045672488a00a5ac8ee66fd19583c3995d,1dfaf23d5e500d64f2b89963ad3e894d389a012b..88664226b9abdcec1108362a26abe1f9a24b2525
  #include "metadata/gc-internal.h"
  #include "metadata/sgen-pointer-queue.h"
  #include "metadata/sgen-pinning.h"
 +#include "metadata/sgen-workers.h"
  
  #define SGEN_HAVE_CONCURRENT_MARK
  
- #define MS_BLOCK_SIZE_SHIFT   14      /* INT FASTENABLE */
- #define MS_BLOCK_SIZE         (1 << MS_BLOCK_SIZE_SHIFT)
+ #if defined(ARCH_MIN_MS_BLOCK_SIZE) && defined(ARCH_MIN_MS_BLOCK_SIZE_SHIFT)
+ #define MS_BLOCK_SIZE ARCH_MIN_MS_BLOCK_SIZE
+ #define MS_BLOCK_SIZE_SHIFT   ARCH_MIN_MS_BLOCK_SIZE_SHIFT
+ #else
 -#define MS_BLOCK_SIZE (16*1024)
 -#define MS_BLOCK_SIZE_SHIFT   14
++#define MS_BLOCK_SIZE_SHIFT     14      /* INT FASTENABLE */
++#define MS_BLOCK_SIZE           (1 << MS_BLOCK_SIZE_SHIFT)
+ #endif
  #define MAJOR_SECTION_SIZE    MS_BLOCK_SIZE
  #define CARDS_PER_BLOCK (MS_BLOCK_SIZE / CARD_SIZE_IN_BYTES)
  
   * of a block is the MSBlockHeader, then opional padding, then come
   * the objects, so this must be >= sizeof (MSBlockHeader).
   */
 -#define MS_BLOCK_SKIP 16
 +#define MS_BLOCK_SKIP ((sizeof (MSBlockHeader) + 15) & ~15)
  
  #define MS_BLOCK_FREE (MS_BLOCK_SIZE - MS_BLOCK_SKIP)
  
  #define MS_NUM_MARK_WORDS     ((MS_BLOCK_SIZE / SGEN_ALLOC_ALIGN + sizeof (mword) * 8 - 1) / (sizeof (mword) * 8))
  
 -#if SGEN_MAX_SMALL_OBJ_SIZE > MS_BLOCK_FREE / 2
 -#error MAX_SMALL_OBJ_SIZE must be at most MS_BLOCK_FREE / 2
 -#endif
 -
  typedef struct _MSBlockInfo MSBlockInfo;
  struct _MSBlockInfo {
        int obj_size;
@@@ -77,6 -85,7 +82,6 @@@
        unsigned int has_pinned : 1;    /* means cannot evacuate */
        unsigned int is_to_space : 1;
        unsigned int swept : 1;
 -      char *block;
        void **free_list;
        MSBlockInfo *next_free;
        size_t pin_queue_first_entry;
        mword mark_words [MS_NUM_MARK_WORDS];
  };
  
 -#define MS_BLOCK_FOR_BLOCK_INFO(b)    ((b)->block)
 +#define MS_BLOCK_FOR_BLOCK_INFO(b)    ((char*)(b))
  
  #define MS_BLOCK_OBJ(b,i)             (MS_BLOCK_FOR_BLOCK_INFO(b) + MS_BLOCK_SKIP + (b)->obj_size * (i))
  #define MS_BLOCK_OBJ_FOR_SIZE(b,i,obj_size)           (MS_BLOCK_FOR_BLOCK_INFO(b) + MS_BLOCK_SKIP + (obj_size) * (i))
  #define MS_BLOCK_DATA_FOR_OBJ(o)      ((char*)((mword)(o) & ~(mword)(MS_BLOCK_SIZE - 1)))
  
  typedef struct {
 -      MSBlockInfo *info;
 +      MSBlockInfo info;
  } MSBlockHeader;
  
 -#define MS_BLOCK_FOR_OBJ(o)           (((MSBlockHeader*)MS_BLOCK_DATA_FOR_OBJ ((o)))->info)
 +#define MS_BLOCK_FOR_OBJ(o)           (&((MSBlockHeader*)MS_BLOCK_DATA_FOR_OBJ ((o)))->info)
  
  /* object index will always be small */
  #define MS_BLOCK_OBJ_INDEX(o,b)       ((int)(((char*)(o) - (MS_BLOCK_FOR_BLOCK_INFO(b) + MS_BLOCK_SKIP)) / (b)->obj_size))
  
  #define MS_MARK_BIT(bl,w,b)   ((bl)->mark_words [(w)] & (ONE_P << (b)))
  #define MS_SET_MARK_BIT(bl,w,b)       ((bl)->mark_words [(w)] |= (ONE_P << (b)))
 -#define MS_PAR_SET_MARK_BIT(was_marked,bl,w,b)        do {                    \
 -              mword __old = (bl)->mark_words [(w)];                   \
 -              mword __bitmask = ONE_P << (b);                         \
 -              if (__old & __bitmask) {                                \
 -                      was_marked = TRUE;                              \
 -                      break;                                          \
 -              }                                                       \
 -              if (SGEN_CAS_PTR ((gpointer*)&(bl)->mark_words [(w)],   \
 -                                              (gpointer)(__old | __bitmask), \
 -                                              (gpointer)__old) ==     \
 -                              (gpointer)__old) {                      \
 -                      was_marked = FALSE;                             \
 -                      break;                                          \
 -              }                                                       \
 -      } while (1)
  
  #define MS_OBJ_ALLOCED(o,b)   (*(void**)(o) && (*(char**)(o) < MS_BLOCK_FOR_BLOCK_INFO (b) || *(char**)(o) >= MS_BLOCK_FOR_BLOCK_INFO (b) + MS_BLOCK_SIZE))
  
 -#define MS_BLOCK_OBJ_SIZE_FACTOR      (sqrt (2.0))
 +#define MS_BLOCK_OBJ_SIZE_FACTOR      (pow (2.0, 1.0 / 3))
  
  /*
   * This way we can lookup block object size indexes for sizes up to
@@@ -172,41 -196,25 +177,41 @@@ static size_t num_major_sections = 0
  /* one free block list for each block object size */
  static MSBlockInfo **free_block_lists [MS_BLOCK_TYPE_MAX];
  
 -static long long stat_major_blocks_alloced = 0;
 -static long long stat_major_blocks_freed = 0;
 -static long long stat_major_blocks_lazy_swept = 0;
 -static long long stat_major_objects_evacuated = 0;
 +static guint64 stat_major_blocks_alloced = 0;
 +static guint64 stat_major_blocks_freed = 0;
 +static guint64 stat_major_blocks_lazy_swept = 0;
 +static guint64 stat_major_objects_evacuated = 0;
  
  #if SIZEOF_VOID_P != 8
 -static long long stat_major_blocks_freed_ideal = 0;
 -static long long stat_major_blocks_freed_less_ideal = 0;
 -static long long stat_major_blocks_freed_individual = 0;
 -static long long stat_major_blocks_alloced_less_ideal = 0;
 +static guint64 stat_major_blocks_freed_ideal = 0;
 +static guint64 stat_major_blocks_freed_less_ideal = 0;
 +static guint64 stat_major_blocks_freed_individual = 0;
 +static guint64 stat_major_blocks_alloced_less_ideal = 0;
  #endif
  
  #ifdef SGEN_COUNT_NUMBER_OF_MAJOR_OBJECTS_MARKED
 -static long long num_major_objects_marked = 0;
 +static guint64 num_major_objects_marked = 0;
  #define INC_NUM_MAJOR_OBJECTS_MARKED()        (++num_major_objects_marked)
  #else
  #define INC_NUM_MAJOR_OBJECTS_MARKED()
  #endif
  
 +#ifdef SGEN_HEAVY_BINARY_PROTOCOL
 +static mono_mutex_t scanned_objects_list_lock;
 +static SgenPointerQueue scanned_objects_list;
 +
 +static void
 +add_scanned_object (void *ptr)
 +{
 +      if (!binary_protocol_is_enabled ())
 +              return;
 +
 +      mono_mutex_lock (&scanned_objects_list_lock);
 +      sgen_pointer_queue_add (&scanned_objects_list, ptr);
 +      mono_mutex_unlock (&scanned_objects_list_lock);
 +}
 +#endif
 +
  static void
  sweep_block (MSBlockInfo *block, gboolean during_major_collection);
  
@@@ -411,6 -419,7 +416,6 @@@ ms_alloc_block (int size_index, gboolea
        int size = block_obj_sizes [size_index];
        int count = MS_BLOCK_FREE / size;
        MSBlockInfo *info;
 -      MSBlockHeader *header;
        MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, has_references);
        char *obj_start;
        int i;
        if (!sgen_memgov_try_alloc_space (MS_BLOCK_SIZE, SPACE_MAJOR))
                return FALSE;
  
 -      info = sgen_alloc_internal (INTERNAL_MEM_MS_BLOCK_INFO);
 +      info = (MSBlockInfo*)ms_get_empty_block ();
  
        SGEN_ASSERT (9, count >= 2, "block with %d objects, it must hold at least 2", count);
  
         */
        info->is_to_space = (sgen_get_current_collection_generation () == GENERATION_OLD);
        info->swept = 1;
 -      info->block = ms_get_empty_block ();
 -
 -      header = (MSBlockHeader*) info->block;
 -      header->info = info;
  #ifdef SGEN_HAVE_CONCURRENT_MARK
        info->cardtable_mod_union = NULL;
  #endif
@@@ -606,6 -619,8 +611,6 @@@ major_alloc_degraded (MonoVTable *vtabl
        return obj;
  }
  
 -#define MAJOR_OBJ_IS_IN_TO_SPACE(obj) FALSE
 -
  /*
   * obj is some object.  If it's not in the major heap (i.e. if it's in
   * the nursery or LOS), return FALSE.  Otherwise return whether it's
@@@ -825,9 -840,9 +830,9 @@@ major_dump_heap (FILE *heap_dump_file
  #define MS_MARK_OBJECT_AND_ENQUEUE_CHECKED(obj,desc,block,queue) do { \
                int __word, __bit;                                      \
                MS_CALC_MARK_BIT (__word, __bit, (obj));                \
 -              if (!MS_MARK_BIT ((block), __word, __bit) && MS_OBJ_ALLOCED ((obj), (block))) { \
 +              if (!MS_MARK_BIT ((block), __word, __bit) && MS_OBJ_ALLOCED ((obj), (block))) { \
                        MS_SET_MARK_BIT ((block), __word, __bit);       \
 -                      if ((block)->has_references)                    \
 +                      if (sgen_gc_descr_has_references (desc))                        \
                                GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc)); \
                        binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((MonoObject*)(obj))); \
                        INC_NUM_MAJOR_OBJECTS_MARKED ();                \
  #define MS_MARK_OBJECT_AND_ENQUEUE(obj,desc,block,queue) do {         \
                int __word, __bit;                                      \
                MS_CALC_MARK_BIT (__word, __bit, (obj));                \
 -              SGEN_ASSERT (9, MS_OBJ_ALLOCED ((obj), (block)), "object %p not allocated", obj);       \
 +              SGEN_ASSERT (9, MS_OBJ_ALLOCED ((obj), (block)), "object %p not allocated", obj); \
                if (!MS_MARK_BIT ((block), __word, __bit)) {            \
                        MS_SET_MARK_BIT ((block), __word, __bit);       \
 -                      if ((block)->has_references)                    \
 -                              GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc)); \
 -                      binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((MonoObject*)(obj))); \
 -                      INC_NUM_MAJOR_OBJECTS_MARKED ();                \
 -              }                                                       \
 -      } while (0)
 -#define MS_PAR_MARK_OBJECT_AND_ENQUEUE(obj,desc,block,queue) do {     \
 -              int __word, __bit;                                      \
 -              gboolean __was_marked;                                  \
 -              SGEN_ASSERT (9, MS_OBJ_ALLOCED ((obj), (block)), "object %p not allocated", obj);       \
 -              MS_CALC_MARK_BIT (__word, __bit, (obj));                \
 -              MS_PAR_SET_MARK_BIT (__was_marked, (block), __word, __bit); \
 -              if (!__was_marked) {                                    \
 -                      if ((block)->has_references)                    \
 +                      if (sgen_gc_descr_has_references (desc))                        \
                                GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc)); \
                        binary_protocol_mark ((obj), (gpointer)LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((MonoObject*)(obj))); \
                        INC_NUM_MAJOR_OBJECTS_MARKED ();                \
@@@ -865,11 -893,8 +870,11 @@@ pin_major_object (char *obj, SgenGrayQu
  
  #ifdef SGEN_HAVE_CONCURRENT_MARK
  static void
 -major_copy_or_mark_object_concurrent (void **ptr, void *obj, SgenGrayQueue *queue)
 +major_copy_or_mark_object_with_evacuation_concurrent (void **ptr, void *obj, SgenGrayQueue *queue)
  {
 +      SGEN_ASSERT (9, sgen_concurrent_collection_in_progress (), "Why are we scanning concurrently when there's no concurrent collection on?");
 +      SGEN_ASSERT (9, !sgen_workers_are_working () || sgen_is_worker_thread (mono_native_thread_id_get ()), "We must not scan from two threads at the same time!");
 +
        g_assert (!SGEN_OBJECT_IS_FORWARDED (obj));
  
        if (!sgen_ptr_in_nursery (obj)) {
  }
  #endif
  
 -static void
 -major_copy_or_mark_object (void **ptr, void *obj, SgenGrayQueue *queue)
 +static long long
 +major_get_and_reset_num_major_objects_marked (void)
  {
 -      MSBlockInfo *block;
 -
 -      HEAVY_STAT (++stat_copy_object_called_major);
 -
 -      SGEN_ASSERT (9, obj, "null object from pointer %p", ptr);
 -      SGEN_ASSERT (9, current_collection_generation == GENERATION_OLD, "old gen parallel allocator called from a %d collection", current_collection_generation);
 +#ifdef SGEN_COUNT_NUMBER_OF_MAJOR_OBJECTS_MARKED
 +      long long num = num_major_objects_marked;
 +      num_major_objects_marked = 0;
 +      return num;
 +#else
 +      return 0;
 +#endif
 +}
  
 -      if (sgen_ptr_in_nursery (obj)) {
 -              int word, bit;
 -              char *forwarded, *old_obj;
 +#ifdef HEAVY_STATISTICS
 +static guint64 stat_optimized_copy;
 +static guint64 stat_optimized_copy_nursery;
 +static guint64 stat_optimized_copy_nursery_forwarded;
 +static guint64 stat_optimized_copy_nursery_pinned;
 +static guint64 stat_optimized_copy_major;
 +static guint64 stat_optimized_copy_major_small_fast;
 +static guint64 stat_optimized_copy_major_small_slow;
 +static guint64 stat_optimized_copy_major_large;
 +static guint64 stat_optimized_copy_major_forwarded;
 +static guint64 stat_optimized_copy_major_small_evacuate;
 +static guint64 stat_optimized_major_scan;
 +static guint64 stat_optimized_major_scan_no_refs;
 +
 +static guint64 stat_drain_prefetch_fills;
 +static guint64 stat_drain_prefetch_fill_failures;
 +static guint64 stat_drain_loops;
 +#endif
  
 -              if ((forwarded = SGEN_OBJECT_IS_FORWARDED (obj))) {
 -                      *ptr = forwarded;
 -                      return;
 -              }
 -              if (SGEN_OBJECT_IS_PINNED (obj))
 -                      return;
 +static void major_scan_object_with_evacuation (char *start, mword desc, SgenGrayQueue *queue);
  
 -              /* An object in the nursery To Space has already been copied and grayed. Nothing to do. */
 -              if (sgen_nursery_is_to_space (obj))
 -                      return;
 +#define COPY_OR_MARK_FUNCTION_NAME    major_copy_or_mark_object_no_evacuation
 +#define SCAN_OBJECT_FUNCTION_NAME     major_scan_object_no_evacuation
 +#define DRAIN_GRAY_STACK_FUNCTION_NAME        drain_gray_stack_no_evacuation
 +#include "sgen-marksweep-drain-gray-stack.h"
  
 -              HEAVY_STAT (++stat_objects_copied_major);
 -
 -      do_copy_object:
 -              old_obj = obj;
 -              obj = copy_object_no_checks (obj, queue);
 -              if (G_UNLIKELY (old_obj == obj)) {
 -                      /*If we fail to evacuate an object we just stop doing it for a given block size as all other will surely fail too.*/
 -                      if (!sgen_ptr_in_nursery (obj)) {
 -                              int size_index;
 -                              block = MS_BLOCK_FOR_OBJ (obj);
 -                              size_index = block->obj_size_index;
 -                              evacuate_block_obj_sizes [size_index] = FALSE;
 -                              MS_MARK_OBJECT_AND_ENQUEUE (obj, sgen_obj_get_descriptor (obj), block, queue);
 -                      }
 -                      return;
 -              }
 -              *ptr = obj;
 -
 -              /*
 -               * FIXME: See comment for copy_object_no_checks().  If
 -               * we have that, we can let the allocation function
 -               * give us the block info, too, and we won't have to
 -               * re-fetch it.
 -               *
 -               * FIXME (2): We should rework this to avoid all those nursery checks.
 -               */
 -              /*
 -               * For the split nursery allocator the object might
 -               * still be in the nursery despite having being
 -               * promoted, in which case we can't mark it.
 -               */
 -              if (!sgen_ptr_in_nursery (obj)) {
 -                      block = MS_BLOCK_FOR_OBJ (obj);
 -                      MS_CALC_MARK_BIT (word, bit, obj);
 -                      SGEN_ASSERT (9, !MS_MARK_BIT (block, word, bit), "object %p already marked", obj);
 -                      MS_SET_MARK_BIT (block, word, bit);
 -                      binary_protocol_mark (obj, (gpointer)LOAD_VTABLE (obj), sgen_safe_object_get_size ((MonoObject*)obj));
 -              }
 -      } else {
 -              char *forwarded;
 -              mword objsize;
 +#define COPY_OR_MARK_WITH_EVACUATION
 +#define COPY_OR_MARK_FUNCTION_NAME    major_copy_or_mark_object_with_evacuation
 +#define SCAN_OBJECT_FUNCTION_NAME     major_scan_object_with_evacuation
 +#define DRAIN_GRAY_STACK_FUNCTION_NAME        drain_gray_stack_with_evacuation
 +#include "sgen-marksweep-drain-gray-stack.h"
  
 -              /*
 -               * If we have don't have a fixed heap we cannot know
 -               * whether an object is in the LOS or in the small
 -               * object major heap without checking its size.  To do
 -               * that, however, we need to know that we actually
 -               * have a valid object, not a forwarding pointer, so
 -               * we have to do this check first.
 -               */
 -              if ((forwarded = SGEN_OBJECT_IS_FORWARDED (obj))) {
 -                      *ptr = forwarded;
 -                      return;
 +static gboolean
 +drain_gray_stack (ScanCopyContext ctx)
 +{
 +      gboolean evacuation = FALSE;
 +      int i;
 +      for (i = 0; i < num_block_obj_sizes; ++i) {
 +              if (evacuate_block_obj_sizes [i]) {
 +                      evacuation = TRUE;
 +                      break;
                }
 +      }
  
 -              objsize = SGEN_ALIGN_UP (sgen_safe_object_get_size ((MonoObject*)obj));
 -
 -              if (objsize <= SGEN_MAX_SMALL_OBJ_SIZE) {
 -                      int size_index;
 -                      gboolean evacuate;
 -
 -                      block = MS_BLOCK_FOR_OBJ (obj);
 -                      size_index = block->obj_size_index;
 -                      evacuate = evacuate_block_obj_sizes [size_index];
 -
 -                      if (evacuate && !block->has_pinned) {
 -                              g_assert (!SGEN_OBJECT_IS_PINNED (obj));
 -                              if (block->is_to_space)
 -                                      return;
 -                              HEAVY_STAT (++stat_major_objects_evacuated);
 -                              goto do_copy_object;
 -                      } else {
 -                              MS_MARK_OBJECT_AND_ENQUEUE (obj, sgen_obj_get_descriptor (obj), block, queue);
 -                      }
 -              } else {
 -                      if (sgen_los_object_is_pinned (obj))
 -                              return;
 -                      binary_protocol_pin (obj, (gpointer)SGEN_LOAD_VTABLE (obj), sgen_safe_object_get_size ((MonoObject*)obj));
 +      if (evacuation)
 +              return drain_gray_stack_with_evacuation (ctx);
 +      else
 +              return drain_gray_stack_no_evacuation (ctx);
 +}
  
 -#ifdef ENABLE_DTRACE
 -                      if (G_UNLIKELY (MONO_GC_OBJ_PINNED_ENABLED ())) {
 -                              MonoVTable *vt = (MonoVTable*)SGEN_LOAD_VTABLE (obj);
 -                              MONO_GC_OBJ_PINNED ((mword)obj, sgen_safe_object_get_size (obj), vt->klass->name_space, vt->klass->name, GENERATION_OLD);
 -                      }
 +#ifdef SGEN_HAVE_CONCURRENT_MARK
 +#include "sgen-marksweep-scan-object-concurrent.h"
  #endif
  
 -                      sgen_los_pin_object (obj);
 -                      if (SGEN_OBJECT_HAS_REFERENCES (obj))
 -                              GRAY_OBJECT_ENQUEUE (queue, obj, sgen_obj_get_descriptor (obj));
 -              }
 -      }
 -}
 -
  static void
  major_copy_or_mark_object_canonical (void **ptr, SgenGrayQueue *queue)
  {
 -      major_copy_or_mark_object (ptr, *ptr, queue);
 +      major_copy_or_mark_object_with_evacuation (ptr, *ptr, queue);
  }
  
  #ifdef SGEN_HAVE_CONCURRENT_MARK
  static void
  major_copy_or_mark_object_concurrent_canonical (void **ptr, SgenGrayQueue *queue)
  {
 -      major_copy_or_mark_object_concurrent (ptr, *ptr, queue);
 -}
 -#endif
 -
 -static long long
 -major_get_and_reset_num_major_objects_marked (void)
 -{
 -#ifdef SGEN_COUNT_NUMBER_OF_MAJOR_OBJECTS_MARKED
 -      long long num = num_major_objects_marked;
 -      num_major_objects_marked = 0;
 -      return num;
 -#else
 -      return 0;
 -#endif
 +      major_copy_or_mark_object_with_evacuation_concurrent (ptr, *ptr, queue);
  }
 -
 -#include "sgen-major-scan-object.h"
 -
 -#ifdef SGEN_HAVE_CONCURRENT_MARK
 -#define SCAN_FOR_CONCURRENT_MARK
 -#include "sgen-major-scan-object.h"
 -#undef SCAN_FOR_CONCURRENT_MARK
  #endif
  
  static void
@@@ -1197,7 -1294,8 +1202,7 @@@ ms_sweep (void
                        DELETE_BLOCK_IN_FOREACH ();
  
                        binary_protocol_empty (MS_BLOCK_OBJ (block, 0), (char*)MS_BLOCK_OBJ (block, count) - (char*)MS_BLOCK_OBJ (block, 0));
 -                      ms_free_block (block->block);
 -                      sgen_free_internal (block, INTERNAL_MEM_MS_BLOCK_INFO);
 +                      ms_free_block (block);
  
                        --num_major_sections;
                }
@@@ -1361,18 -1459,8 +1366,18 @@@ major_start_major_collection (void
  }
  
  static void
 -major_finish_major_collection (void)
 +major_finish_major_collection (ScannedObjectCounts *counts)
  {
 +#ifdef SGEN_HEAVY_BINARY_PROTOCOL
 +      if (binary_protocol_is_enabled ()) {
 +              counts->num_scanned_objects = scanned_objects_list.next_slot;
 +
 +              sgen_pointer_queue_sort_uniq (&scanned_objects_list);
 +              counts->num_unique_scanned_objects = scanned_objects_list.next_slot;
 +
 +              sgen_pointer_queue_clear (&scanned_objects_list);
 +      }
 +#endif
  }
  
  #if SIZEOF_VOID_P != 8
@@@ -1642,10 -1730,10 +1647,10 @@@ major_iterate_live_block_ranges (sgen_c
  }
  
  #ifdef HEAVY_STATISTICS
 -extern long long marked_cards;
 -extern long long scanned_cards;
 -extern long long scanned_objects;
 -extern long long remarked_cards;
 +extern guint64 marked_cards;
 +extern guint64 scanned_cards;
 +extern guint64 scanned_objects;
 +extern guint64 remarked_cards;
  #endif
  
  #define CARD_WORDS_PER_BLOCK (CARDS_PER_BLOCK / SIZEOF_VOID_P)
@@@ -1755,8 -1843,6 +1760,8 @@@ major_scan_card_table (gboolean mod_uni
                        end = block_start + MS_BLOCK_SIZE;
                        base = sgen_card_table_align_pointer (obj);
  
 +                      cards += MS_BLOCK_SKIP >> CARD_BITS;
 +
                        while (obj < end) {
                                size_t card_offset;
  
                        }
                        card_data_end = card_data + CARDS_PER_BLOCK;
  
 +                      card_data += MS_BLOCK_SKIP >> CARD_BITS;
 +
                        for (card_data = initial_skip_card (card_data); card_data < card_data_end; ++card_data) { //card_data = skip_card (card_data + 1, card_data_end)) {
                                size_t index;
                                size_t idx = card_data - card_base;
@@@ -1963,15 -2047,15 +1968,15 @@@ sgen_marksweep_init_internal (SgenMajor
        for (i = 0; i < MS_NUM_FAST_BLOCK_OBJ_SIZE_INDEXES * 8; ++i)
                g_assert (MS_BLOCK_OBJ_SIZE_INDEX (i) == ms_find_block_obj_size_index (i));
  
 -      mono_counters_register ("# major blocks allocated", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_major_blocks_alloced);
 -      mono_counters_register ("# major blocks freed", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_major_blocks_freed);
 -      mono_counters_register ("# major blocks lazy swept", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_major_blocks_lazy_swept);
 -      mono_counters_register ("# major objects evacuated", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_major_objects_evacuated);
 +      mono_counters_register ("# major blocks allocated", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_alloced);
 +      mono_counters_register ("# major blocks freed", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed);
 +      mono_counters_register ("# major blocks lazy swept", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_lazy_swept);
 +      mono_counters_register ("# major objects evacuated", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_objects_evacuated);
  #if SIZEOF_VOID_P != 8
 -      mono_counters_register ("# major blocks freed ideally", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_major_blocks_freed_ideal);
 -      mono_counters_register ("# major blocks freed less ideally", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_major_blocks_freed_less_ideal);
 -      mono_counters_register ("# major blocks freed individually", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_major_blocks_freed_individual);
 -      mono_counters_register ("# major blocks allocated less ideally", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_major_blocks_alloced_less_ideal);
 +      mono_counters_register ("# major blocks freed ideally", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed_ideal);
 +      mono_counters_register ("# major blocks freed less ideally", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed_less_ideal);
 +      mono_counters_register ("# major blocks freed individually", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed_individual);
 +      mono_counters_register ("# major blocks allocated less ideally", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_alloced_less_ideal);
  #endif
  
        collector->section_size = MAJOR_SECTION_SIZE;
        collector->count_cards = major_count_cards;
  
        collector->major_ops.copy_or_mark_object = major_copy_or_mark_object_canonical;
 -      collector->major_ops.scan_object = major_scan_object;
 +      collector->major_ops.scan_object = major_scan_object_with_evacuation;
  #ifdef SGEN_HAVE_CONCURRENT_MARK
        if (is_concurrent) {
                collector->major_concurrent_ops.copy_or_mark_object = major_copy_or_mark_object_concurrent_canonical;
 -              collector->major_concurrent_ops.scan_object = major_scan_object_concurrent;
 +              collector->major_concurrent_ops.scan_object = major_scan_object_no_mark_concurrent;
                collector->major_concurrent_ops.scan_vtype = major_scan_vtype_concurrent;
        }
  #endif
  
 +#if !defined (FIXED_HEAP) && !defined (SGEN_PARALLEL_MARK)
 +      /* FIXME: this will not work with evacuation or the split nursery. */
 +      if (!is_concurrent)
 +              collector->drain_gray_stack = drain_gray_stack;
 +
 +#ifdef HEAVY_STATISTICS
 +      mono_counters_register ("Optimized copy", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy);
 +      mono_counters_register ("Optimized copy nursery", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_nursery);
 +      mono_counters_register ("Optimized copy nursery forwarded", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_nursery_forwarded);
 +      mono_counters_register ("Optimized copy nursery pinned", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_nursery_pinned);
 +      mono_counters_register ("Optimized copy major", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major);
 +      mono_counters_register ("Optimized copy major small fast", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_small_fast);
 +      mono_counters_register ("Optimized copy major small slow", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_small_slow);
 +      mono_counters_register ("Optimized copy major large", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_large);
 +      mono_counters_register ("Optimized major scan", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_major_scan);
 +      mono_counters_register ("Optimized major scan no refs", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_major_scan_no_refs);
 +
 +      mono_counters_register ("Gray stack drain loops", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_drain_loops);
 +      mono_counters_register ("Gray stack prefetch fills", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_drain_prefetch_fills);
 +      mono_counters_register ("Gray stack prefetch failures", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_drain_prefetch_fill_failures);
 +#endif
 +#endif
 +
 +#ifdef SGEN_HEAVY_BINARY_PROTOCOL
 +      mono_mutex_init (&scanned_objects_list_lock);
 +#endif
 +
 +      SGEN_ASSERT (0, SGEN_MAX_SMALL_OBJ_SIZE <= MS_BLOCK_FREE / 2, "MAX_SMALL_OBJ_SIZE must be at most MS_BLOCK_FREE / 2");
 +
        /*cardtable requires major pages to be 8 cards aligned*/
        g_assert ((MS_BLOCK_SIZE % (8 * CARD_SIZE_IN_BYTES)) == 0);
  }
diff --combined mono/mini/aot-compiler.c
index 73e99aa6fda271772ca7bc0b0c76d4b262805bc4,2689b1e9e4fec1b359c6315ac2fc4d9cc04745e6..bc9c01f401fc9f688c25190250d77ad4a934f8cd
  #define TV_GETTIME(tv) tv = mono_100ns_ticks ()
  #define TV_ELAPSED(start,end) (((end) - (start)) / 10)
  
 -#ifdef TARGET_WIN32
 -#define SHARED_EXT ".dll"
 -#elif defined(__ppc__) && defined(TARGET_MACH)
 -#define SHARED_EXT ".dylib"
 -#elif defined(TARGET_MACH) && defined(TARGET_X86) && !defined(__native_client_codegen__)
 -#define SHARED_EXT ".dylib"
 -#elif defined(TARGET_MACH) && defined(TARGET_AMD64) && !defined(__native_client_codegen__)
 -#define SHARED_EXT ".dylib"
 -#else
 -#define SHARED_EXT ".so"
 -#endif
 -
  #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
  #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
  #define ROUND_DOWN(VALUE,SIZE)        ((VALUE) & ~((SIZE) - 1))
@@@ -1922,14 -1934,14 +1922,14 @@@ arch_emit_imt_thunk (MonoAotCompile *ac
        code = buf;
  
        /* Load the mscorlib got address */
-       ppc_ldptr (code, ppc_r11, sizeof (gpointer), ppc_r30);
+       ppc_ldptr (code, ppc_r12, sizeof (gpointer), ppc_r30);
        /* Load the parameter from the GOT */
        ppc_load (code, ppc_r0, offset * sizeof (gpointer));
-       ppc_ldptr_indexed (code, ppc_r11, ppc_r11, ppc_r0);
+       ppc_ldptr_indexed (code, ppc_r12, ppc_r12, ppc_r0);
  
        /* Load and check key */
        labels [1] = code;
-       ppc_ldptr (code, ppc_r0, 0, ppc_r11);
+       ppc_ldptr (code, ppc_r0, 0, ppc_r12);
        ppc_cmp (code, 0, sizeof (gpointer) == 8 ? 1 : 0, ppc_r0, MONO_ARCH_IMT_REG);
        labels [2] = code;
        ppc_bc (code, PPC_BR_TRUE, PPC_BR_EQ, 0);
        ppc_bc (code, PPC_BR_TRUE, PPC_BR_EQ, 0);
  
        /* Loop footer */
-       ppc_addi (code, ppc_r11, ppc_r11, 2 * sizeof (gpointer));
+       ppc_addi (code, ppc_r12, ppc_r12, 2 * sizeof (gpointer));
        labels [4] = code;
        ppc_b (code, 0);
        mono_ppc_patch (labels [4], labels [1]);
  
        /* Match */
        mono_ppc_patch (labels [2], code);
-       ppc_ldptr (code, ppc_r11, sizeof (gpointer), ppc_r11);
-       /* r11 now contains the value of the vtable slot */
+       ppc_ldptr (code, ppc_r12, sizeof (gpointer), ppc_r12);
+       /* r12 now contains the value of the vtable slot */
        /* this is not a function descriptor on ppc64 */
-       ppc_ldptr (code, ppc_r11, 0, ppc_r11);
-       ppc_mtctr (code, ppc_r11);
+       ppc_ldptr (code, ppc_r12, 0, ppc_r12);
+       ppc_mtctr (code, ppc_r12);
        ppc_bcctr (code, PPC_BR_ALWAYS, 0);
  
        /* Fail */
@@@ -4860,14 -4872,13 +4860,14 @@@ get_debug_sym (MonoMethod *method, cons
        char *name1, *name2, *cached;
        int i, j, len, count;
  
 +      name1 = mono_method_full_name (method, TRUE);
 +
  #ifdef TARGET_MACH
        // This is so that we don't accidentally create a local symbol (which starts with 'L')
 -      if (!prefix || !*prefix)
 +      if ((!prefix || !*prefix) && name1 [0] == 'L')
                prefix = "_";
  #endif
  
 -      name1 = mono_method_full_name (method, TRUE);
        len = strlen (name1);
        name2 = malloc (strlen (prefix) + len + 16);
        memcpy (name2, prefix, strlen (prefix));
@@@ -5374,15 -5385,6 +5374,15 @@@ emit_exception_debug_info (MonoAotCompi
                encode_value (table->num_holes, p, &p);
        }
  
 +      if (jinfo->has_arch_eh_info) {
 +              /*
 +               * In AOT mode, the code length is calculated from the address of the previous method,
 +               * which could include alignment padding, so calculating the start of the epilog as
 +               * code_len - epilog_size is correct any more. Save the real code len as a workaround.
 +               */
 +              encode_value (jinfo->code_size, p, &p);
 +      }
 +
        /* Exception table */
        if (cfg->compile_llvm) {
                /*
@@@ -7100,7 -7102,7 +7100,7 @@@ emit_llvm_file (MonoAotCompile *acfg
  
  
        tempbc = g_strdup_printf ("%s.bc", acfg->tmpbasename);
 -      mono_llvm_emit_aot_module (tempbc, acfg->final_got_size);
 +      mono_llvm_emit_aot_module (tempbc, g_path_get_basename (acfg->image->name), acfg->final_got_size);
        g_free (tempbc);
  
        /*
@@@ -8638,7 -8640,7 +8638,7 @@@ compile_asm (MonoAotCompile *acfg
        if (acfg->aot_opts.outfile)
                outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
        else
 -              outfile_name = g_strdup_printf ("%s%s", acfg->image->name, SHARED_EXT);
 +              outfile_name = g_strdup_printf ("%s%s", acfg->image->name, MONO_SOLIB_EXT);
  
        tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
  
  
        g_free (command);
  
 -      /*com = g_strdup_printf ("strip --strip-unneeded %s%s", acfg->image->name, SHARED_EXT);
 +      /*com = g_strdup_printf ("strip --strip-unneeded %s%s", acfg->image->name, MONO_SOLIB_EXT);
        printf ("Stripping the binary: %s\n", com);
        system (com);
        g_free (com);*/
@@@ -9009,7 -9011,7 +9009,7 @@@ mono_compile_assembly (MonoAssembly *as
                if (acfg->aot_opts.outfile)
                        outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
                else
 -                      outfile_name = g_strdup_printf ("%s%s", acfg->image->name, SHARED_EXT);
 +                      outfile_name = g_strdup_printf ("%s%s", acfg->image->name, MONO_SOLIB_EXT);
  
                /* 
                 * Can't use g_file_open_tmp () as it will be deleted at exit, and
index 8ba3bf083d831c19cd13bb1354962a19b8b394da,d9ae91e05aeb77a29aa799443ee78131fbfdeaa1..2697bc0895bb37584f4bec26111aa6df869129ad
@@@ -381,18 -381,18 +381,18 @@@ mono_arch_get_throw_exception_generic (
  
                if (aot) {
                        code = mono_arch_emit_load_aotconst (start, code, &ji, MONO_PATCH_INFO_IMAGE, mono_defaults.corlib);
-                       ppc_mr (code, ppc_r3, ppc_r11);
+                       ppc_mr (code, ppc_r3, ppc_r12);
                        code = mono_arch_emit_load_aotconst (start, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_exception_from_token");
  #ifdef PPC_USES_FUNCTION_DESCRIPTOR
-                       ppc_ldptr (code, ppc_r2, sizeof (gpointer), ppc_r11);
-                       ppc_ldptr (code, ppc_r11, 0, ppc_r11);
+                       ppc_ldptr (code, ppc_r2, sizeof (gpointer), ppc_r12);
+                       ppc_ldptr (code, ppc_r12, 0, ppc_r12);
  #endif
-                       ppc_mtctr (code, ppc_r11);
+                       ppc_mtctr (code, ppc_r12);
                        ppc_bcctrl (code, PPC_BR_ALWAYS, 0);
                } else {
                        ppc_load (code, ppc_r3, (gulong)mono_defaults.corlib);
-                       ppc_load_func (code, ppc_r0, mono_exception_from_token);
-                       ppc_mtctr (code, ppc_r0);
+                       ppc_load_func (code, PPC_CALL_REG, mono_exception_from_token);
+                       ppc_mtctr (code, PPC_CALL_REG);
                        ppc_bcctrl (code, PPC_BR_ALWAYS, 0);
                }
        }
                code = mono_arch_emit_load_got_addr (start, code, NULL, &ji);
                code = mono_arch_emit_load_aotconst (start, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_ppc_throw_exception");
  #ifdef PPC_USES_FUNCTION_DESCRIPTOR
-               ppc_ldptr (code, ppc_r2, sizeof (gpointer), ppc_r11);
-               ppc_ldptr (code, ppc_r11, 0, ppc_r11);
+               ppc_ldptr (code, ppc_r2, sizeof (gpointer), ppc_r12);
+               ppc_ldptr (code, ppc_r12, 0, ppc_r12);
  #endif
-               ppc_mtctr (code, ppc_r11);
+               ppc_mtctr (code, ppc_r12);
                ppc_bcctrl (code, PPC_BR_ALWAYS, 0);
        } else {
-               ppc_load_func (code, ppc_r0, mono_ppc_throw_exception);
-               ppc_mtctr (code, ppc_r0);
+               ppc_load_func (code, PPC_CALL_REG, mono_ppc_throw_exception);
+               ppc_mtctr (code, PPC_CALL_REG);
                ppc_bcctrl (code, PPC_BR_ALWAYS, 0);
        }
        /* we should never reach this breakpoint */
@@@ -594,6 -594,39 +594,6 @@@ mono_arch_find_jit_info (MonoDomain *do
        return FALSE;
  }
  
 -/*
 - * This is the function called from the signal handler
 - */
 -void
 -mono_arch_sigctx_to_monoctx (void *ctx, MonoContext *mctx)
 -{
 -#ifdef MONO_CROSS_COMPILE
 -      g_assert_not_reached ();
 -#else
 -      os_ucontext *uc = ctx;
 -
 -      mctx->sc_ir = UCONTEXT_REG_NIP(uc);
 -      mctx->sc_sp = UCONTEXT_REG_Rn(uc, 1);
 -      memcpy (&mctx->regs, &UCONTEXT_REG_Rn(uc, 13), sizeof (mgreg_t) * MONO_SAVED_GREGS);
 -      memcpy (&mctx->fregs, &UCONTEXT_REG_FPRn(uc, 14), sizeof (double) * MONO_SAVED_FREGS);
 -#endif
 -}
 -
 -void
 -mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *ctx)
 -{
 -#ifdef MONO_CROSS_COMPILE
 -      g_assert_not_reached ();
 -#else
 -      os_ucontext *uc = ctx;
 -
 -      UCONTEXT_REG_NIP(uc) = mctx->sc_ir;
 -      UCONTEXT_REG_Rn(uc, 1) = mctx->sc_sp;
 -      memcpy (&UCONTEXT_REG_Rn(uc, 13), &mctx->regs, sizeof (mgreg_t) * MONO_SAVED_GREGS);
 -      memcpy (&UCONTEXT_REG_FPRn(uc, 14), &mctx->fregs, sizeof (double) * MONO_SAVED_FREGS);
 -#endif
 -}
 -
  gpointer
  mono_arch_ip_from_context (void *sigctx)
  {
@@@ -626,7 -659,7 +626,7 @@@ altstack_handle_and_restore (void *sigc
  {
        MonoContext mctx;
  
 -      mono_arch_sigctx_to_monoctx (sigctx, &mctx);
 +      mono_sigctx_to_monoctx (sigctx, &mctx);
        mono_handle_exception (&mctx, obj);
        mono_restore_context (&mctx);
  }
@@@ -749,7 -782,7 +749,7 @@@ mono_arch_handle_exception (void *ctx, 
        void *uc = sigctx;
  
        /* Pass the ctx parameter in TLS */
 -      mono_arch_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
 +      mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
        /* The others in registers */
        UCONTEXT_REG_Rn (sigctx, PPC_FIRST_ARG_REG) = (gsize)obj;
  
        MonoContext mctx;
        gboolean result;
  
 -      mono_arch_sigctx_to_monoctx (ctx, &mctx);
 +      mono_sigctx_to_monoctx (ctx, &mctx);
  
        result = mono_handle_exception (&mctx, obj);
        /* restore the context so that returning from the signal handler will invoke
         * the catch clause 
         */
 -      mono_arch_monoctx_to_sigctx (&mctx, ctx);
 +      mono_monoctx_to_sigctx (&mctx, ctx);
        return result;
  #endif
  }
diff --combined mono/mini/mini-gc.c
index 93bcd7d1a2efceb8ece1addc184566dbd2602fb5,d0004b6c34511d7a19b34ecfda45136f6fa454af..fddca9c6c346e7be93d95e0a204e6a679a28b2e7
@@@ -12,8 -12,8 +12,8 @@@
  #include "mini-gc.h"
  #include <mono/metadata/gc-internal.h>
  
 -//#if 0
 -#if defined(MONO_ARCH_GC_MAPS_SUPPORTED)
 +#if 0
 +//#if defined(MONO_ARCH_GC_MAPS_SUPPORTED)
  
  #include <mono/metadata/sgen-conf.h>
  #include <mono/metadata/gc-internal.h>
@@@ -436,6 -436,13 +436,13 @@@ static int callee_saved_regs [] = { ARM
  static int callee_saved_regs [] = { };
  #elif defined(TARGET_S390X)
  static int callee_saved_regs [] = { s390_r6, s390_r7, s390_r8, s390_r9, s390_r10, s390_r11, s390_r12, s390_r13, s390_r14 };
+ #elif defined(TARGET_POWERPC64) && _CALL_ELF == 2
+ static int callee_saved_regs [] = {
+   ppc_r13, ppc_r14, ppc_r15, ppc_r16,
+   ppc_r17, ppc_r18, ppc_r19, ppc_r20,
+   ppc_r21, ppc_r22, ppc_r23, ppc_r24,
+   ppc_r25, ppc_r26, ppc_r27, ppc_r28,
+   ppc_r29, ppc_r30, ppc_r31 };
  #elif defined(TARGET_POWERPC)
  static int callee_saved_regs [] = { ppc_r6, ppc_r7, ppc_r8, ppc_r9, ppc_r10, ppc_r11, ppc_r12, ppc_r13, ppc_r14 };
  #endif
@@@ -609,7 -616,7 +616,7 @@@ thread_suspend_func (gpointer user_data
                tls->unwind_state.unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
                if (sigctx) {
  #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
 -                      mono_arch_sigctx_to_monoctx (sigctx, &tls->unwind_state.ctx);
 +                      mono_sigctx_to_monoctx (sigctx, &tls->unwind_state.ctx);
                        tls->unwind_state.valid = TRUE;
  #else
                        tls->unwind_state.valid = FALSE;
diff --combined mono/mini/mini-ppc.h
index 671672c682a2c67936c5b3f16790e9e7df6e6e77,7131aad0e14519330b8fae30cc48fa1b3455f279..2a9af123de4d3d816136fb52c5d504b2e09c7517
@@@ -68,7 -68,13 +68,13 @@@ typedef struct MonoCompileArch 
  #ifdef __mono_ppc64__
  #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
  #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
+ /* ELFv2 ABI doesn't use function descriptors.  */
+ #if _CALL_ELF == 2
+ #undef PPC_USES_FUNCTION_DESCRIPTOR
+ #else
  #define PPC_USES_FUNCTION_DESCRIPTOR
+ #endif
  
  #ifndef __mono_ilp32__
  #define MONO_ARCH_HAVE_TLS_GET 1
  
  #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
  #define MONO_ARCH_EMULATE_FREM 1
 -#define MONO_ARCH_BIGMUL_INTRINS 1
  #define MONO_ARCH_GC_MAPS_SUPPORTED 1
  
  /* Parameters used by the register allocator */
- #define MONO_ARCH_CALLEE_REGS ((0xff << ppc_r3) | (1 << ppc_r11) | (1 << ppc_r12))
+ #define MONO_ARCH_CALLEE_REGS ((0xff << ppc_r3) | (1 << ppc_r12) | (1 << ppc_r11))
  #define MONO_ARCH_CALLEE_SAVED_REGS (0xfffff << ppc_r13) /* ppc_13 - ppc_31 */
  
  #if defined(__APPLE__) || defined(__mono_ppc64__)
  #define PPC_MINIMAL_PARAM_AREA_SIZE 64
  #define PPC_LAST_FPARG_REG ppc_f13
  #define PPC_PASS_STRUCTS_BY_VALUE 1
 -#define PPC_SMALL_RET_STRUCT_IN_REG 0
  #define PPC_THREAD_PTR_REG ppc_r13
  #else
  #define PPC_RET_ADDR_OFFSET 4
  #define PPC_MINIMAL_PARAM_AREA_SIZE 0
  #define PPC_LAST_FPARG_REG ppc_f8
  #define PPC_PASS_STRUCTS_BY_VALUE 0
 -#define PPC_SMALL_RET_STRUCT_IN_REG 1
  #define PPC_THREAD_PTR_REG ppc_r2
  #endif
  #define PPC_FIRST_ARG_REG ppc_r3
  #define PPC_FIRST_FPARG_REG ppc_f1
  #endif
  
+ #define PPC_CALL_REG ppc_r12
  #if defined(HAVE_WORKING_SIGALTSTACK) && !defined(__APPLE__)
  #define MONO_ARCH_SIGSEGV_ON_ALTSTACK 1
  #define MONO_ARCH_SIGNAL_STACK_SIZE (12 * 1024)
  #endif /* HAVE_WORKING_SIGALTSTACK */
  
  #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
- #define MONO_ARCH_IMT_REG ppc_r12
+ #define MONO_ARCH_IMT_REG ppc_r11
  
- #define MONO_ARCH_VTABLE_REG  ppc_r12
+ #define MONO_ARCH_VTABLE_REG  ppc_r11
  #define MONO_ARCH_RGCTX_REG   MONO_ARCH_IMT_REG
  
  #define MONO_ARCH_NO_IOV_CHECK 1
  #define MONO_ARCH_HAVE_OP_TAIL_CALL 1
  
  #define PPC_NUM_REG_ARGS (PPC_LAST_ARG_REG-PPC_FIRST_ARG_REG+1)
 -#define PPC_NUM_REG_FPARGS (PPC_LAST_FPARG_REG-PPC_FIRST_FPARG_REG+1)
  
  #ifdef MONO_CROSS_COMPILE
  
diff --combined mono/mini/mini.c
index 268cb4bc51d19ef1159c7a244a3b35d79e0e0e2a,eed5fc02235e98c045fe4ae764be473ae81b00bb..b642073e91ff5d3f86b0febabd82fbe90d58a08f
@@@ -53,7 -53,6 +53,7 @@@
  #include <mono/utils/mono-math.h>
  #include <mono/utils/mono-compiler.h>
  #include <mono/utils/mono-counters.h>
 +#include <mono/utils/mono-error-internals.h>
  #include <mono/utils/mono-logger-internal.h>
  #include <mono/utils/mono-mmap.h>
  #include <mono/utils/mono-path.h>
@@@ -711,11 -710,10 +711,11 @@@ G_GNUC_UNUSED gboolea
  mono_debug_count (void)
  {
        static int count = 0;
 -      count ++;
        static gboolean inited;
        static const char *value;
  
 +      count ++;
 +
        if (!inited) {
                value = g_getenv ("COUNT");
                inited = TRUE;
@@@ -4125,8 -4123,6 +4125,8 @@@ mono_codegen (MonoCompile *cfg
  
        cfg->code_len = code - cfg->native_code;
        cfg->prolog_end = cfg->code_len;
 +      cfg->cfa_reg = cfg->cur_cfa_reg;
 +      cfg->cfa_offset = cfg->cur_cfa_offset;
  
        mono_debug_open_method (cfg);
  
                if (bb == cfg->bb_exit) {
                        cfg->epilog_begin = cfg->code_len;
                        mono_arch_emit_epilog (cfg);
 +                      cfg->epilog_end = cfg->code_len;
                }
        }
  
@@@ -4650,7 -4645,7 +4650,7 @@@ create_jit_info (MonoCompile *cfg, Mono
  
                        info = mono_jit_info_get_arch_eh_info (jinfo);
                        g_assert (info);
 -                      info->epilog_size = cfg->code_size - cfg->epilog_begin;
 +                      info->epilog_size = cfg->code_len - cfg->epilog_begin;
                }
                jinfo->unwind_info = unwind_desc;
                g_free (unwind_info);
@@@ -5012,7 -5007,6 +5012,7 @@@ mini_method_compile (MonoMethod *method
  
        if (cfg->gen_seq_points)
                cfg->seq_points = g_ptr_array_new ();
 +      mono_error_init (&cfg->error);
  
        if (cfg->compile_aot && !try_generic_shared && (method->is_generic || method->klass->generic_container || method_is_gshared)) {
                cfg->exception_type = MONO_EXCEPTION_GENERIC_SHARING_FAILED;
        */
  
  //#define DEBUGSSA "logic_run"
 -#define DEBUGSSA_CLASS "Tests"
 +//#define DEBUGSSA_CLASS "Tests"
  #ifdef DEBUGSSA
  
        if (!cfg->disable_ssa) {
@@@ -6103,10 -6097,6 +6103,10 @@@ mono_jit_compile_method_inner (MonoMeth
        case MONO_EXCEPTION_OUT_OF_MEMORY:
                ex = mono_domain_get ()->out_of_memory_ex;
                break;
 +      case MONO_EXCEPTION_MONO_ERROR:
 +              g_assert (!mono_error_ok (&cfg->error));
 +              ex = mono_error_convert_to_exception (&cfg->error);
 +              break;
        default:
                g_assert_not_reached ();
        }
@@@ -6845,7 -6835,7 +6845,7 @@@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_s
        if (fault_addr == NULL) {
                MonoContext mctx;
  
 -              mono_arch_sigctx_to_monoctx (ctx, &mctx);
 +              mono_sigctx_to_monoctx (ctx, &mctx);
  
                fault_addr = MONO_CONTEXT_GET_SP (&mctx);
        }
@@@ -7094,10 -7084,9 +7094,9 @@@ mini_get_debug_options (void
  static gpointer
  mini_create_ftnptr (MonoDomain *domain, gpointer addr)
  {
- #if !defined(__ia64__) && !defined(__ppc64__) && !defined(__powerpc64__)
+ #if !defined(__ia64__) && (!defined(__ppc64__) && !defined(__powerpc64__) || _CALL_ELF == 2)
        return addr;
  #else
        gpointer* desc = NULL;
  
        if ((desc = g_hash_table_lookup (domain->ftnptrs_hash, addr)))
  static gpointer
  mini_get_addr_from_ftnptr (gpointer descr)
  {
- #if defined(__ia64__) || defined(__ppc64__) || defined(__powerpc64__)
+ #if defined(__ia64__) || ((defined(__ppc64__) || defined(__powerpc64__)) && _CALL_ELF != 2)
        return *(gpointer*)descr;
  #else
        return descr;