diff -Naur ruby-1.9.3-p547.original/common.mk ruby-1.9.3-p547.htm/common.mk
--- ruby-1.9.3-p547.original/common.mk	2014-05-14 17:38:00.000000000 +0900
+++ ruby-1.9.3-p547.htm/common.mk	2014-09-12 06:37:35.905002000 +0900
@@ -94,6 +94,7 @@
 		vm_dump.$(OBJEXT) \
 		thread.$(OBJEXT) \
 		cont.$(OBJEXT) \
+		htm_util.$(OBJEXT) \
 		$(BUILTIN_ENCOBJS) \
 		$(BUILTIN_TRANSOBJS) \
 		$(MISSING)
@@ -592,7 +593,7 @@
 ID_H_INCLUDES      = {$(VPATH)}id.h {$(VPATH)}vm_opts.h
 VM_CORE_H_INCLUDES = {$(VPATH)}vm_core.h {$(VPATH)}thread_$(THREAD_MODEL).h \
 		     {$(VPATH)}node.h {$(VPATH)}method.h {$(VPATH)}ruby_atomic.h \
-		     $(ID_H_INCLUDES)
+		     $(ID_H_INCLUDES) {$(VPATH)}htm_util.h
 
 array.$(OBJEXT): {$(VPATH)}array.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
   $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h
@@ -718,6 +719,7 @@
 cont.$(OBJEXT): {$(VPATH)}cont.c $(RUBY_H_INCLUDES) \
   $(VM_CORE_H_INCLUDES) {$(VPATH)}gc.h {$(VPATH)}eval_intern.h \
   {$(VPATH)}debug.h {$(VPATH)}internal.h
+htm_util.$(OBJEXT): {$(VPATH)}htm_util.c {$(VPATH)}htm_util.h
 time.$(OBJEXT): {$(VPATH)}time.c $(RUBY_H_INCLUDES) \
   $(ENCODING_H_INCLUDES) {$(VPATH)}timev.h {$(VPATH)}internal.h
 util.$(OBJEXT): {$(VPATH)}util.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
diff -Naur ruby-1.9.3-p547.original/compile.c ruby-1.9.3-p547.htm/compile.c
--- ruby-1.9.3-p547.original/compile.c	2013-01-11 17:13:17.000000000 +0900
+++ ruby-1.9.3-p547.htm/compile.c	2014-09-12 06:37:35.905002000 +0900
@@ -6,6 +6,7 @@
   created at: 04/01/01 03:42:15 JST
 
   Copyright (C) 2004-2007 Koichi Sasada
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
@@ -1571,6 +1572,14 @@
     iseq->insn_info_table = insn_info_table;
     iseq->insn_info_size = k;
     iseq->stack_max = stack_max;
+#ifdef HTM_GVL
+    iseq->htm_counters = ALLOC_N(int64_t, pos);
+    MEMZERO(iseq->htm_counters, int64_t, pos);
+#ifdef HTM_GVL_INSN_STATS
+    iseq->htm_insn_stats_counters = ALLOC_N(htm_insn_stats_t, pos);
+    MEMZERO(iseq->htm_insn_stats_counters, htm_insn_stats_t, pos);
+#endif
+#endif
 
     return COMPILE_OK;
 }
diff -Naur ruby-1.9.3-p547.original/configure ruby-1.9.3-p547.htm/configure
--- ruby-1.9.3-p547.original/configure	2014-05-16 23:38:31.000000000 +0900
+++ ruby-1.9.3-p547.htm/configure	2014-09-17 13:08:43.858664003 +0900
@@ -830,6 +830,7 @@
 enable_largefile
 enable_win95
 enable_pthread
+enable_htm_gvl
 with_setjmp_type
 enable_setreuid
 with_valgrind
@@ -1494,6 +1495,7 @@
   --disable-largefile     omit support for large files
   --enable-win95          enable Windows 95 series support
   --enable-pthread        obsolete, and ignored
+  --enable-htm-gvl        use hardware transactional memory for GVL
   --enable-setreuid       use setreuid()/setregid() according to need even if
                           obsolete
   --enable-rpath          embed run path into extension libraries. enabled by
@@ -10427,6 +10429,23 @@
 fi
 
 
+# Check whether --enable-htm-gvl was given.
+if test "${enable_htm_gvl+set}" = set; then :
+  enableval=$enable_htm_gvl; use_htm_gvl=$enableval
+fi
+
+if test "$use_htm_gvl" = yes; then
+     # RUBY_APPEND_OPTION(XCFLAGS, -DHTM_GVL)
+	case " ${XCFLAGS-} " in #(
+  *' -DHTM_GVL '*) :
+     ;; #(
+  '  ') :
+     XCFLAGS="-DHTM_GVL" ;; #(
+  *) :
+     XCFLAGS="$XCFLAGS -DHTM_GVL" ;;
+esac
+fi
+
 case "$target_os" in #(
   *bsd*|dragonfly*) :
      ;; #(
diff -Naur ruby-1.9.3-p547.original/configure.in ruby-1.9.3-p547.htm/configure.in
--- ruby-1.9.3-p547.original/configure.in	2014-02-14 20:52:53.000000000 +0900
+++ ruby-1.9.3-p547.htm/configure.in	2014-09-12 06:37:35.905002000 +0900
@@ -991,6 +991,13 @@
 AC_ARG_ENABLE(pthread,
        AS_HELP_STRING([--enable-pthread], [obsolete, and ignored]))
 
+AC_ARG_ENABLE(htm-gvl,
+       AS_HELP_STRING([--enable-htm-gvl], [use hardware transactional memory for GVL]),
+       [use_htm_gvl=$enableval])
+if test "$use_htm_gvl" = yes; then
+     RUBY_APPEND_OPTION(XCFLAGS, -DHTM_GVL)
+fi
+
 dnl Checks for libraries.
 AS_CASE(["$target_os"],[*bsd*|dragonfly*],[],[ac_cv_func_daemon=no])
 
diff -Naur ruby-1.9.3-p547.original/cont.c ruby-1.9.3-p547.htm/cont.c
--- ruby-1.9.3-p547.original/cont.c	2012-02-16 07:34:48.000000000 +0900
+++ ruby-1.9.3-p547.htm/cont.c	2014-09-12 06:37:35.905002000 +0900
@@ -6,12 +6,13 @@
   created at: Thu May 23 09:03:43 2007
 
   Copyright (C) 2007 Koichi Sasada
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
 #include "ruby/ruby.h"
-#include "internal.h"
 #include "vm_core.h"
+#include "internal.h"
 #include "gc.h"
 #include "eval_intern.h"
 
@@ -138,7 +139,14 @@
     if (ptr) {
 	rb_context_t *cont = ptr;
 	rb_gc_mark(cont->value);
+#ifdef HTM_GVL
+	cont->saved_thread.gc_safe_point_reached = 1;
+#endif
+#ifdef ALIGN_RB_THREAD_T
+	rb_thread_mark_aligned(&cont->saved_thread, 0);
+#else
 	rb_thread_mark(&cont->saved_thread);
+#endif
 	rb_gc_mark(cont->saved_thread.self);
 
 	if (cont->vm_stack) {
diff -Naur ruby-1.9.3-p547.original/enc/Makefile.in ruby-1.9.3-p547.htm/enc/Makefile.in
--- ruby-1.9.3-p547.original/enc/Makefile.in	2011-07-31 22:59:04.000000000 +0900
+++ ruby-1.9.3-p547.htm/enc/Makefile.in	2014-09-12 06:37:35.905002000 +0900
@@ -48,9 +48,13 @@
 LDSHARED = @LDSHARED@
 ldflags  = $(LDFLAGS)
 dldflags = @DLDFLAGS@
+extdldflags = @EXTDLDFLAGS@
 archflag = @ARCH_FLAG@
-DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
+DLDFLAGS = $(ldflags) $(dldflags) $(extdldflags) $(archflag)
 RUBY     = $(MINIRUBY)
+TARGET_NAME_ = $(@F) # BSD make seems unable to deal with @F with substitution
+TARGET_NAME = $(TARGET_NAME_:.@DLEXT@=)
+TARGET_ENTRY = @EXPORT_PREFIX@Init_$(TARGET_NAME)
 
 WORKDIRS = @WORKDIRS@
 
diff -Naur ruby-1.9.3-p547.original/ext/dbm/extconf.rb ruby-1.9.3-p547.htm/ext/dbm/extconf.rb
--- ruby-1.9.3-p547.original/ext/dbm/extconf.rb	2012-02-17 10:16:19.000000000 +0900
+++ ruby-1.9.3-p547.htm/ext/dbm/extconf.rb	2014-09-12 06:37:35.905002000 +0900
@@ -90,16 +90,16 @@
     decltype && try_link(<<"SRC", opt, &b) or
 #{headers}
 /*top*/
-#{MAIN_DOES_NOTHING}
 extern int t(void);
 int t(void) { #{decltype["volatile p"]}; p = (#{decltype[]})#{func}; return 0; }
+#{MAIN_DOES_NOTHING "t"}
 SRC
     call && try_link(<<"SRC", opt, &b)
 #{headers}
 /*top*/
-#{MAIN_DOES_NOTHING}
 extern int t(void);
 int t(void) { #{call}; return 0; }
+#{MAIN_DOES_NOTHING "t"}
 SRC
   end
 
@@ -108,9 +108,9 @@
     try_compile(<<"SRC", opt, &b)
 #{headers}
 /*top*/
-#{MAIN_DOES_NOTHING}
 extern int t(void);
 int t(void) { const volatile void *volatile p; p = &(&#{var})[0]; return 0; }
+#{MAIN_DOES_NOTHING "t"}
 SRC
   end
 
diff -Naur ruby-1.9.3-p547.original/gc.c ruby-1.9.3-p547.htm/gc.c
--- ruby-1.9.3-p547.original/gc.c	2014-01-30 20:04:17.000000000 +0900
+++ ruby-1.9.3-p547.htm/gc.c	2014-09-12 06:37:35.905002000 +0900
@@ -8,6 +8,7 @@
   Copyright (C) 1993-2007 Yukihiro Matsumoto
   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
   Copyright (C) 2000  Information-technology Promotion Agency, Japan
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
@@ -87,6 +88,7 @@
     unsigned int initial_heap_min_slots;
     unsigned int initial_free_min;
     int gc_stress;
+    int do_not_shrink_heap;
 } ruby_gc_params_t;
 
 ruby_gc_params_t initial_params = {
@@ -96,6 +98,7 @@
 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
     FALSE,
 #endif
+    FALSE,
 };
 
 #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory]
@@ -424,6 +427,7 @@
 #define initial_malloc_limit	initial_params.initial_malloc_limit
 #define initial_heap_min_slots	initial_params.initial_heap_min_slots
 #define initial_free_min	initial_params.initial_free_min
+#define do_not_shrink_heap	initial_params.do_not_shrink_heap
 
 static void rb_objspace_call_finalizer(rb_objspace_t *objspace);
 
@@ -447,6 +451,7 @@
 rb_gc_set_params(void)
 {
     char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr;
+    char *no_shrink_heap_ptr;
 
     if (rb_safe_level() > 0) return;
 
@@ -482,6 +487,11 @@
 	    initial_free_min = free_min_i;
 	}
     }
+
+    no_shrink_heap_ptr = getenv("RUBY_DO_NOT_SHRINK_HEAP");
+    if (no_shrink_heap_ptr) {
+	do_not_shrink_heap = TRUE;
+    }
 }
 
 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
@@ -1184,11 +1194,39 @@
     return during_gc;
 }
 
+#ifdef USE_THREAD_LOCAL_HEAP
+static inline void
+fill_thread_local_heap(rb_thread_t *th, rb_objspace_t *objspace)
+{
+#define NUM_TLH_OBJECTS 256
+    int tlh_count;
+    void *old_tlh_free_list;
+    RVALUE *current_free_list;
+    RVALUE *prev_free_list;
+
+    old_tlh_free_list = th->tlh_free_list;
+    current_free_list = freelist;
+    prev_free_list = NULL;
+    for (tlh_count = 0; tlh_count < NUM_TLH_OBJECTS; tlh_count++) {
+	if (! current_free_list)
+	    break;
+	prev_free_list = current_free_list;
+	current_free_list = current_free_list->as.free.next;
+    }
+    th->tlh_free_list = (void *)freelist;
+    freelist = current_free_list;
+    prev_free_list->as.free.next = old_tlh_free_list;
+}
+#endif
+
 #define RANY(o) ((RVALUE*)(o))
 
 VALUE
 rb_newobj(void)
 {
+#ifdef USE_THREAD_LOCAL_HEAP
+    rb_thread_t *th = GET_THREAD();
+#endif
     rb_objspace_t *objspace = &rb_objspace;
     VALUE obj;
 
@@ -1205,6 +1243,20 @@
 	}
     }
 
+#ifdef USE_THREAD_LOCAL_HEAP
+    if (! th->tlh_free_list) {
+	if (UNLIKELY(!freelist)) {
+	    if (!gc_lazy_sweep(objspace)) {
+		during_gc = 0;
+		rb_memerror();
+	    }
+	}
+
+	fill_thread_local_heap(th, objspace);
+    }
+    obj = (VALUE)th->tlh_free_list;
+    th->tlh_free_list = ((RVALUE *)th->tlh_free_list)->as.free.next;
+#else
     if (UNLIKELY(!freelist)) {
 	if (!gc_lazy_sweep(objspace)) {
 	    during_gc = 0;
@@ -1214,6 +1266,7 @@
 
     obj = (VALUE)freelist;
     freelist = freelist->as.free.next;
+#endif /* USE_THREAD_LOCAL_HEAP */
 
     MEMZERO((void*)obj, RVALUE, 1);
 #ifdef GC_DEBUG
@@ -2161,7 +2214,8 @@
         p++;
     }
     if (final_num + free_num == sweep_slot->limit &&
-        objspace->heap.free_num > objspace->heap.do_heap_free) {
+        objspace->heap.free_num > objspace->heap.do_heap_free
+	&& ! do_not_shrink_heap) {
         RVALUE *pp;
 
         for (pp = deferred_final_list; pp != final; pp = pp->as.free.next) {
@@ -2539,6 +2593,18 @@
 #endif
 }
 
+#ifdef USE_THREAD_LOCAL_HEAP
+static int
+thread_free_tlh(st_data_t key, st_data_t val, st_data_t data)
+{
+    rb_thread_t *th;
+    GetThreadPtr((VALUE)key, th);
+    th->tlh_free_list = NULL;
+
+    return ST_CONTINUE;
+}
+#endif
+
 static void
 gc_marks(rb_objspace_t *objspace)
 {
@@ -2548,6 +2614,9 @@
 
     objspace->heap.live_num = 0;
     objspace->count++;
+#ifdef USE_THREAD_LOCAL_HEAP
+    st_foreach(GET_THREAD()->vm->living_threads, thread_free_tlh, (st_index_t)0);
+#endif
 
 
     SET_STACK_END;
diff -Naur ruby-1.9.3-p547.original/htm_ia32_stat.h ruby-1.9.3-p547.htm/htm_ia32_stat.h
--- ruby-1.9.3-p547.original/htm_ia32_stat.h	1970-01-01 09:00:00.000000000 +0900
+++ ruby-1.9.3-p547.htm/htm_ia32_stat.h	2014-09-17 11:58:21.318459000 +0900
@@ -0,0 +1,8 @@
+/*  Copyright (c) IBM Corp. 2014. */
+HTM_IA32_STAT(XABORT)
+HTM_IA32_STAT(TRANSIENT)
+HTM_IA32_STAT(MEMADDR_CONFLICT)
+HTM_IA32_STAT(BUFFER_OVERFLOW)
+HTM_IA32_STAT(HIT_DEBUG_BREAKPOINT)
+HTM_IA32_STAT(DURING_NESTED_TRANSACTION)
+HTM_IA32_STAT(OTHER)
diff -Naur ruby-1.9.3-p547.original/htm_ppc_stat.h ruby-1.9.3-p547.htm/htm_ppc_stat.h
--- ruby-1.9.3-p547.original/htm_ppc_stat.h	1970-01-01 09:00:00.000000000 +0900
+++ ruby-1.9.3-p547.htm/htm_ppc_stat.h	2014-09-17 11:58:21.318459000 +0900
@@ -0,0 +1,14 @@
+/*  Copyright (c) IBM Corp. 2014. */
+/* See 5.4.2 */
+HTM_PPC_STAT(Failure_Persistent)
+HTM_PPC_STAT(Disallowed)
+HTM_PPC_STAT(Nesting_Overflow)
+HTM_PPC_STAT(Footprint_Overflow)
+HTM_PPC_STAT(Self_Induced_Conflict)
+HTM_PPC_STAT(Non_Transactional_Conflict)
+HTM_PPC_STAT(Transaction_Conflict)
+HTM_PPC_STAT(Translation_Invalidation_Conflict)
+HTM_PPC_STAT(Implementation_Specific)
+HTM_PPC_STAT(Instruction_Fetch_Conflict)
+HTM_PPC_STAT(Tabort_Treclaim)
+HTM_PPC_STAT(Other)
diff -Naur ruby-1.9.3-p547.original/htm_util.c ruby-1.9.3-p547.htm/htm_util.c
--- ruby-1.9.3-p547.original/htm_util.c	1970-01-01 09:00:00.000000000 +0900
+++ ruby-1.9.3-p547.htm/htm_util.c	2014-09-17 07:43:11.923270000 +0900
@@ -0,0 +1,229 @@
+/*  Copyright (c) IBM Corp. 2014. */
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include "htm_util.h"
+
+#if defined(__370__)
+
+static int tbegin_impl(void *diag);
+#if 1
+/* lghi gpr3,0; tbegin 0(gpr1),FF00; brc 0x8,$+16; lghi gpr3,2; brc 0x6,$+8; lghi gpr3,3 */
+#pragma mc_func tbegin_impl {"A7390000" "E5601000FF00" "A7840008" "A7390002" "A7640004" "A7390003"}
+#else
+/* lghi gpr3,0; tbegin 0(gpr1),FF00; brc 0x8,$+24; lghi gpr3,1; brc 0x4,$+16; lghi gpr3,2; brc 0x2,$+8; lghi gpr3,3 */
+#pragma mc_func tbegin_impl {"A7390000" "E5601000FF00" "A784000C" "A7390001" "A7440008" "A7390002" "A7240004" "A7390003"}
+#endif
+
+static int tbegin_fp_impl(void *diag);
+#if 1
+#pragma mc_func tbegin_fp_impl {"A7390000" "E5601000FF04" "A7840008" "A7390002" "A7640004" "A7390003"}
+#else
+#pragma mc_func tbegin_fp_impl {"A7390000" "E5601000FF04" "A784000C" "A7390001" "A7440008" "A7390002" "A7240004" "A7390003"}
+#endif
+
+static void tend_impl(void *diag);
+#pragma mc_func tend_impl {"B2F81000"}  /* tend 0(gpr1) */
+
+static void tabort_impl(int code);
+#pragma mc_func tabort_impl {"B2FC1000"}  /* tabort 0(gpr1) */
+
+static void tabort_no_abend_in_no_tx_impl(int code);
+/* tbegin 0(gpr0),FF00; brc 0x7,$+8; tabort 0(gpr1) */
+#pragma mc_func tabort_no_abend_in_no_tx_impl {"E5600000FF00" "A7740004" "B2FC1000"}
+
+static void non_tx_store_impl(int64_t *addr, int64_t data);
+#pragma mc_func non_tx_store_impl { "E32010000025" }  /* ntstg gpr2,0(gpr1) */
+
+static uint64_t
+get_transaction_nesting_depth_impl();
+#pragma mc_func get_transaction_nesting_depth_impl { "B2EC0030" }  /* ETNDG gpr3 */
+
+/* std fpr8,0(gpr1); ...; std fpr15,56(gpr1) */
+static void save_preserved_fpr_impl(uint64_t *addr);
+#pragma mc_func save_preserved_fpr_impl {"60801000" "60901008" "60A01010" "60B01018" "60C01020" "60D01028" "60E01030" "60F01038"}
+
+/* ld fpr8,0(gpr1); ...; ld fpr15,56(gpr1) */
+static void restore_preserved_fpr_impl(uint64_t *addr);
+#pragma mc_func restore_preserved_fpr_impl {"68801000" "68901008" "68A01010" "68B01018" "68C01020" "68D01028" "68E01030" "68F01038"}
+
+int
+tbegin(TransactionDiagnosticInfo *diag)
+{
+  /*return tbegin_impl(diag);*/
+  return tbegin_fp_impl(diag);
+}
+
+#if defined(__370__) && __COMPILER_VER__ >= 0x410d0000
+/* Macro-expanded to intrinsic */
+#else
+void
+tend(void)
+{
+  TransactionDiagnosticInfo *diag = NULL;
+  tend_impl(diag);
+}
+#endif
+
+void
+tabort(uint64_t code)
+{
+  tabort_impl(code);
+}
+
+void
+tabort_no_abend_in_no_tx(uint64_t code)
+{
+  tabort_no_abend_in_no_tx_impl(code);
+}
+
+#if defined(__370__) && __COMPILER_VER__ >= 0x410d0000
+/* Macro-expanded to intrinsic */
+#else
+void
+non_tx_store(int64_t *addr, int64_t data)
+{
+  /* addr must be 8-byte aligned */
+  non_tx_store_impl(addr, data);
+}
+#endif
+
+#if defined(__370__) && __COMPILER_VER__ >= 0x410d0000
+/* Macro-expanded to intrinsic */
+#else
+int
+get_transaction_nesting_depth(void)
+{
+  uint64_t ret;
+
+  ret = get_transaction_nesting_depth_impl();
+  return ret & 0xFFFF;
+}
+#endif
+
+void
+save_preserved_fpr(uint64_t *addr)
+{
+  save_preserved_fpr_impl(addr);
+}
+
+void
+restore_preserved_fpr(uint64_t *addr)
+{
+  restore_preserved_fpr_impl(addr);
+}
+
+#elif defined(__x86_64__)  /* __370__ */
+
+/* Everything is in htm_util.h */
+
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+
+/* Everything is in htm_util.h */
+
+#else /* __370__ , __x86_64, __PPC__ */
+
+#error
+
+#endif  /* __370__ -> __x86_64 -> __PPC__ */
+
+void
+countHTMFailures(TransactionDiagnosticInfo *diag, uint64_t *counters)
+{
+#if defined(__370__)
+  uint64_t abortCode = diag->transactionAbortCode;
+  if (diag->format != 1) {
+    counters[0]++;
+  } else if (abortCode <= 2) {
+    counters[abortCode]++;
+    /* No such abort code as 3  */
+  } else if (abortCode <= 16) {
+    counters[abortCode - 1]++;
+  } else if (abortCode == 255) {
+    counters[16]++;
+  } else {
+    counters[17]++;
+  }
+#elif defined(__x86_64__)
+  uint64_t abortCode = diag->transactionAbortCode;
+  counters[0] += (abortCode & XABORT_EXPLICIT) ? 1 : 0;
+  counters[1] += (abortCode & XABORT_RETRY) ? 1 : 0;
+  counters[2] += (abortCode & XABORT_CONFLICT) ? 1 : 0;
+  counters[3] += (abortCode & XABORT_CAPACITY) ? 1 : 0;
+  counters[4] += (abortCode & XABORT_DEBUG) ? 1 : 0;
+  counters[5] += (abortCode & XABORT_NESTED) ? 1 : 0;
+  counters[6] += (abortCode & (XABORT_EXPLICIT | XABORT_RETRY | XABORT_CONFLICT | XABORT_CONFLICT | XABORT_DEBUG | XABORT_NESTED)) ? 0 : 1;  /* Other */
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+  uint64_t texasr = diag->transactionAbortCode;
+#define PPC_BFIELD(x) ((0x1ULL)<<(63-x))
+  counters[ 0] += (texasr & PPC_BFIELD( 7))? 1 : 0;
+  counters[ 1] += (texasr & PPC_BFIELD( 8))? 1 : 0;
+  counters[ 2] += (texasr & PPC_BFIELD( 9))? 1 : 0;
+  counters[ 3] += (texasr & PPC_BFIELD(10))? 1 : 0;
+  counters[ 4] += (texasr & PPC_BFIELD(11))? 1 : 0;
+  counters[ 5] += (texasr & PPC_BFIELD(12))? 1 : 0;
+  counters[ 6] += (texasr & PPC_BFIELD(13))? 1 : 0;
+  counters[ 7] += (texasr & PPC_BFIELD(14))? 1 : 0;
+  counters[ 8] += (texasr & PPC_BFIELD(15))? 1 : 0;
+  counters[ 9] += (texasr & PPC_BFIELD(16))? 1 : 0;
+  counters[10] += (texasr & PPC_BFIELD(31))? 1 : 0;
+  counters[11] += (texasr & (PPC_BFIELD(7) | PPC_BFIELD(8) | PPC_BFIELD(9) | PPC_BFIELD(10) | PPC_BFIELD(11) | PPC_BFIELD(12) | PPC_BFIELD(13) | PPC_BFIELD(14) | PPC_BFIELD(15) | PPC_BFIELD(16) | PPC_BFIELD(31))) ? 0 : 1;  /* Other */
+#else
+#error
+#endif
+}
+
+const char *
+getHTMFailureName(int id)
+{
+  const char *reason_strings[] = {
+#if defined(__370__)
+    "TDB_not_set",
+    "Restart_interruption",
+    "External_interruption",
+    "Program_interruption",
+    "Machine-check_interruption",
+    "I/O_interruption",
+    "Fetch_overflow",
+    "Store_overflow",
+    "Fetch_conflict",
+    "Store_conflict",
+    "Restricted_instruction",
+    "Program-interruption_condition",
+    "Nesting_depth_exceeded",
+    "Cache_fetch-related",
+    "Cache_store-related",
+    "Cache_other",
+    "Undetermined_condition",
+    "TABORT_instruction"
+#elif defined(__x86_64__)
+    "XABORT",
+    "TRANSIENT",
+    "MEMADDR_CONFLICT",
+    "BUFFER_OVERFLOW",
+    "HIT_DEBUG_BREAKPOINT",
+    "DURING_NESTED_TRANSACTION",
+    "OTHER"
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+    "Failure_Persistent",
+    "Disallowed",
+    "Nesting_Overflow",
+    "Footprint_Overflow",
+    "Self_Induced_Conflict",
+    "Non_Tx_Conflict",
+    "Tx_Conflict",
+    "Translation_Invalidation",
+    "Implementation_Specific",
+    "Instruction_Fetch_Conflict",
+    "Tabort_Treclaim",
+    "Other"
+#else
+#error
+#endif
+  };
+
+  if (id < 0 || NUM_HTM_FAILURE_REASONS <= id) {
+    return NULL;
+  }
+  return reason_strings[id];
+}
diff -Naur ruby-1.9.3-p547.original/htm_util.h ruby-1.9.3-p547.htm/htm_util.h
--- ruby-1.9.3-p547.original/htm_util.h	1970-01-01 09:00:00.000000000 +0900
+++ ruby-1.9.3-p547.htm/htm_util.h	2014-09-17 07:43:11.923270000 +0900
@@ -0,0 +1,193 @@
+/*  Copyright (c) IBM Corp. 2014. */
+#ifndef _HTM_UTIL_H
+#define _HTM_UTIL_H
+
+#include <stdint.h>
+#if defined(__370__) && __COMPILER_VER__ >= 0x410d0000
+#include <builtins.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+#if defined(__370__)
+  uint8_t format;
+  uint8_t flags;
+  uint16_t reserved0;
+  uint16_t reserved1;
+  uint16_t transactionNestingDepth;
+  uint64_t transactionAbortCode;
+  uint64_t conflictToken;
+  uint64_t abortedTransactionInstructionAddress;
+  uint8_t EAID;
+  uint8_t DXC;
+  uint16_t reserved2;
+  uint32_t programInterruptionIdentification;
+  uint64_t translationExceptionIdentification;
+  uint64_t breakingEventAddress;
+  uint64_t reserved3[8];
+  uint32_t reserved4;
+  uint16_t reserved5;
+  uint8_t reserved6;
+  uint8_t LSUAbortCode;
+  uint64_t generalRegisters[16];
+#elif defined(__x86_64)
+  uint64_t transactionAbortCode;
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+  uint64_t transactionAbortCode;
+  uint64_t abortedTransactionInstructionAddress;
+#endif
+} TransactionDiagnosticInfo;
+
+/*
+  int tbegin(TransactionDiagnosticInfo *diag);
+  Returns 0 for success
+          1 for inderminate
+          2 for transient abort
+	  3 for persistent abort
+ */
+
+#if defined(__370__)
+
+int tbegin(TransactionDiagnosticInfo *diag);
+#if __COMPILER_VER__ >= 0x410d0000
+#define tend() __TM_end()
+#else
+void tend();
+#endif
+void tabort(uint64_t code);
+void tabort_no_abend_in_no_tx(uint64_t code);
+#if __COMPILER_VER__ >= 0x410d0000
+/* addr must be 8-byte aligned */
+#define non_tx_store(addr, data) __TM_non_transactional_store((addr), (long long)data)
+#else
+void non_tx_store(int64_t *addr, int64_t data);
+#endif
+#if __COMPILER_VER__ >= 0x410d0000
+#define get_transaction_nesting_depth() __TM_nesting_depth(NULL)
+#else
+int get_transaction_nesting_depth();
+#endif
+void save_preserved_fpr(uint64_t *addr);
+void restore_preserved_fpr(uint64_t *addr);
+
+#define NUM_HTM_FAILURE_REASONS 18
+
+#elif defined(__x86_64)
+
+#define XABORT_EXPLICIT	0x01
+#define XABORT_RETRY	0x02
+#define XABORT_CONFLICT	0x04
+#define XABORT_CAPACITY	0x08
+#define XABORT_DEBUG	0x10
+#define XABORT_NESTED	0x20
+
+static inline int tbegin(TransactionDiagnosticInfo *diag)
+{
+  unsigned int xbegin_result;
+
+  xbegin_result = 0xffffffff;
+  asm volatile("mov %0, %%eax;"
+	       ".byte 0xc7; .byte 0xf8; .int 0x00000000;" /* xbegin */
+	       "mov %%eax, %0"
+	       : "+r"(xbegin_result)
+	       :
+	       : "%eax");
+  if (xbegin_result == 0xffffffff)
+    return 0;
+  else {
+    diag->transactionAbortCode = xbegin_result;
+    if (xbegin_result & XABORT_RETRY)
+      return 2;
+    return 3;
+  }
+}
+
+#define tend() do {							\
+    asm volatile(".byte 0x0f; .byte 0x01; .byte 0xd5" :: ); /* xend */	\
+  } while (0)
+
+#define tabort(code) do {						\
+    /* xabort's argument must be an 8-bit immediate */\
+    asm volatile(".byte 0xc6; .byte 0xf8; .byte %P0" :: "i"(code & 0xff)); /* xabort */ \
+  } while (0)
+
+#define NUM_HTM_FAILURE_REASONS 7
+
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+
+static inline int tbegin(TransactionDiagnosticInfo *diag)
+{
+  uint32_t tbegin_status;
+
+  asm volatile(".long 0x7c00051d;"
+	       "mfcr %0"
+	       :"=r"(tbegin_status): : "cr0");	// tbegin. 0
+  if (! (tbegin_status & 0x20000000U))
+    return 0;
+  else {
+#ifdef _ARCH_PPC64
+    uint64_t texasr;
+    uint64_t tfiar;
+
+    asm volatile("mfspr %0,130;"
+		 "mfspr %1,129"
+		 :"=r"(texasr), "=r"(tfiar): );
+    diag->transactionAbortCode = texasr;
+#else
+    uint32_t texasr;
+    uint32_t texasru;
+    uint32_t tfiar;
+
+    asm volatile("mfspr %0,130;"
+		 "mfspr %1,131;"
+		 "mfspr %2,129"
+		 :"=r"(texasr), "=r"(texasru), "=r"(tfiar): );
+    diag->transactionAbortCode = (uint64_t)texasru << 32 | (uint64_t)texasr;
+#endif
+    diag->abortedTransactionInstructionAddress = (uint64_t)tfiar & ~0x3ULL;
+    if (texasr & 0x0100000000000000ULL)
+      return 3;
+    return 2;
+  }
+}
+
+/* tend. 0 */
+#define tend() do {				\
+    asm volatile(".long 0x7c00055d":::"cr0" );	\
+  } while (0)
+
+static inline void tabort(uint64_t code)
+{
+  uint64_t int_code = code << 56;
+  asm volatile("mr 3,%0;"
+	       ".long 0x7c03071d": : "r" (int_code) : "r3", "cr0"); // tabort. 3
+  //asm(".long 0x7c00071d":::"cr0" ); // tabort. 0
+}
+
+#define tsuspend() do {				\
+    asm volatile (".long 0x7C0005DD");		\
+  } while (0)
+
+#define tresume() do {				\
+    asm volatile (".long 0x7C2005DD");		\
+  } while (0)
+
+#define NUM_HTM_FAILURE_REASONS 12
+
+#else
+
+#error
+
+#endif
+
+void countHTMFailures(TransactionDiagnosticInfo *diag, uint64_t *counters);
+const char *getHTMFailureName(int id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HTM_UTIL_H */
diff -Naur ruby-1.9.3-p547.original/include/ruby/ruby.h ruby-1.9.3-p547.htm/include/ruby/ruby.h
--- ruby-1.9.3-p547.original/include/ruby/ruby.h	2013-06-26 17:11:48.000000000 +0900
+++ ruby-1.9.3-p547.htm/include/ruby/ruby.h	2014-09-12 06:37:35.905002000 +0900
@@ -8,6 +8,7 @@
   Copyright (C) 1993-2008 Yukihiro Matsumoto
   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
   Copyright (C) 2000  Information-technology Promotion Agency, Japan
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
@@ -832,6 +833,34 @@
     TypedData_Wrap_Struct((klass),(data_type),(sval))\
 )
 
+/* We should #ifdef ALIGN_RB_THREAD_T,
+   but this file does not include vm_core.h. */
+#if defined(__370__)
+#define TypedData_Make_Struct_Cache_Line_Aligned(klass, type, data_type, sval) (\
+    (sval) = ALLOC_With_Cache_Line_Padding(type),\
+    memset((sval), 0, sizeof(type) + 256 * 2),\
+    TypedData_Wrap_Struct((klass),(data_type),(sval))\
+)
+#elif defined(__x86_64__) || defined(__CYGWIN__)
+#define TypedData_Make_Struct_Cache_Line_Aligned(klass, type, data_type, sval) (\
+    (sval) = ALLOC_With_Cache_Line_Padding(type),\
+    memset((sval), 0, sizeof(type) + 64 * 2),\
+    TypedData_Wrap_Struct((klass),(data_type),(sval))\
+)
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+#define TypedData_Make_Struct_Cache_Line_Aligned(klass, type, data_type, sval) (\
+    (sval) = ALLOC_With_Cache_Line_Padding(type),\
+    memset((sval), 0, sizeof(type) + 128 * 2),\
+    TypedData_Wrap_Struct((klass),(data_type),(sval))\
+)
+#else
+#define TypedData_Make_Struct_Cache_Line_Aligned(klass, type, data_type, sval) (\
+    (sval) = ALLOC(type),\
+    memset((sval), 0, sizeof(type)),\
+    TypedData_Wrap_Struct((klass),(data_type),(sval))\
+)
+#endif
+
 #define Data_Get_Struct(obj,type,sval) do {\
     Check_Type((obj), T_DATA); \
     (sval) = (type*)DATA_PTR(obj);\
@@ -1033,6 +1062,17 @@
 
 #define ALLOC_N(type,n) ((type*)xmalloc2((n),sizeof(type)))
 #define ALLOC(type) ((type*)xmalloc(sizeof(type)))
+/* We should #ifdef ALIGN_RB_THREAD_T,
+   but this file does not include vm_core.h. */
+#if defined(__370__)
+#define ALLOC_With_Cache_Line_Padding(type) ((type*)xmalloc(sizeof(type) + 256 * 2))
+#elif defined(__x86_64__) || defined(__CYGWIN__)
+#define ALLOC_With_Cache_Line_Padding(type) ((type*)xmalloc(sizeof(type) + 64 * 2))
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+#define ALLOC_With_Cache_Line_Padding(type) ((type*)xmalloc(sizeof(type) + 128 * 2))
+#else
+#define ALLOC_With_Cache_Line_Padding(type) ((type*)xmalloc(sizeof(type)))
+#endif
 #define REALLOC_N(var,type,n) ((var)=(type*)xrealloc2((char*)(var),(n),sizeof(type)))
 
 #define ALLOCA_N(type,n) ((type*)alloca(sizeof(type)*(n)))
@@ -1166,8 +1206,11 @@
 
 VALUE *rb_ruby_verbose_ptr(void);
 VALUE *rb_ruby_debug_ptr(void);
+int   *rb_ruby_use_gvl_ptr(void);
 #define ruby_verbose (*rb_ruby_verbose_ptr())
 #define ruby_debug   (*rb_ruby_debug_ptr())
+#define ruby_use_gvl (*rb_ruby_use_gvl_ptr())
+
 
 PRINTF_ARGS(NORETURN(void rb_raise(VALUE, const char*, ...)), 2, 3);
 PRINTF_ARGS(NORETURN(void rb_fatal(const char*, ...)), 1, 2);
diff -Naur ruby-1.9.3-p547.original/insns.def ruby-1.9.3-p547.htm/insns.def
--- ruby-1.9.3-p547.original/insns.def	2013-02-22 14:42:27.000000000 +0900
+++ ruby-1.9.3-p547.htm/insns.def	2014-09-12 06:37:35.905002000 +0900
@@ -5,6 +5,7 @@
   created at: 04/01/01 01:17:55 JST
 
   Copyright (C) 2004-2007 Koichi Sasada
+  Copyright (c) IBM Corp. 2014.
 */
 
 /** ##skip
@@ -1091,7 +1092,11 @@
 	}
     }
 
+#ifdef HTM_GVL
+    RUBY_VM_CHECK_INTS_EXEC_CORE(&GET_OPERAND(-1));
+#else
     RUBY_VM_CHECK_INTS();
+#endif
     vm_pop_frame(th);
     RESTORE_REGS();
 }
@@ -1130,7 +1135,11 @@
 (VALUE throwobj)
 (VALUE val)
 {
+#ifdef HTM_GVL
+    RUBY_VM_CHECK_INTS_EXEC_CORE(&GET_OPERAND(-2));
+#else
     RUBY_VM_CHECK_INTS();
+#endif
     val = vm_throw(th, GET_CFP(), throw_state, throwobj);
     THROW_EXCEPTION(val);
     /* unreachable */
@@ -1151,7 +1160,11 @@
 ()
 ()
 {
+#ifdef HTM_GVL
+    RUBY_VM_CHECK_INTS_EXEC_CORE(&GET_OPERAND(-2));
+#else
     RUBY_VM_CHECK_INTS();
+#endif
     JUMP(dst);
 }
 
@@ -1167,7 +1180,11 @@
 ()
 {
     if (RTEST(val)) {
+#ifdef HTM_GVL
+        RUBY_VM_CHECK_INTS_EXEC_CORE(&GET_OPERAND(-2));
+#else
 	RUBY_VM_CHECK_INTS();
+#endif
 	JUMP(dst);
     }
 }
@@ -1184,7 +1201,11 @@
 ()
 {
     if (!RTEST(val)) {
+#ifdef HTM_GVL
+        RUBY_VM_CHECK_INTS_EXEC_CORE(&GET_OPERAND(-2));
+#else
 	RUBY_VM_CHECK_INTS();
+#endif
 	JUMP(dst);
     }
 }
@@ -1233,7 +1254,11 @@
     }
     else if (ic->ic_value.value == Qundef)
     {
-    	RUBY_VM_CHECK_INTS();
+#ifdef HTM_GVL
+        RUBY_VM_CHECK_INTS_EXEC_CORE(&GET_OPERAND(-3));
+#else
+	RUBY_VM_CHECK_INTS();
+#endif
     	rb_thread_schedule();
 	goto retry;
     }
diff -Naur ruby-1.9.3-p547.original/insns_info.inc ruby-1.9.3-p547.htm/insns_info.inc
--- ruby-1.9.3-p547.original/insns_info.inc	2014-05-16 23:38:32.000000000 +0900
+++ ruby-1.9.3-p547.htm/insns_info.inc	2014-09-12 06:37:35.905002000 +0900
@@ -9,18 +9,18 @@
   or insns2vm.rb
  */
 
-#define TS_OFFSET 'O'
-#define TS_NUM 'N'
-#define TS_LINDEX 'L'
-#define TS_DINDEX 'D'
-#define TS_VALUE 'V'
+#define TS_FUNCPTR 'F'
+#define TS_IC 'C'
 #define TS_ID 'I'
 #define TS_GENTRY 'G'
-#define TS_IC 'C'
-#define TS_CDHASH 'H'
 #define TS_ISEQ 'S'
+#define TS_DINDEX 'D'
+#define TS_CDHASH 'H'
+#define TS_LINDEX 'L'
+#define TS_NUM 'N'
 #define TS_VARIABLE '.'
-#define TS_FUNCPTR 'F'
+#define TS_VALUE 'V'
+#define TS_OFFSET 'O'
 
 static const char *const insn_name_info[] = {
   "nop",
diff -Naur ruby-1.9.3-p547.original/internal.h ruby-1.9.3-p547.htm/internal.h
--- ruby-1.9.3-p547.original/internal.h	2014-01-29 14:24:28.000000000 +0900
+++ ruby-1.9.3-p547.htm/internal.h	2014-09-12 06:37:35.905002000 +0900
@@ -6,6 +6,7 @@
   created at: Tue May 17 11:42:20 JST 2011
 
   Copyright (C) 2011 Yukihiro Matsumoto
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
@@ -182,6 +183,11 @@
 void rb_clear_trace_func(void);
 VALUE rb_thread_backtrace(VALUE thval);
 VALUE rb_get_coverages(void);
+#ifdef HTM_GVL
+int rb_thread_alone_fast(void *th);
+void gvl_release(void *vm, void *th);
+void htm_gvl_acquire_multi_threads(void *th, VALUE *counter_addr);
+#endif
 
 /* thread_pthread.c, thread_win32.c */
 void Init_native_thread(void);
@@ -195,6 +201,9 @@
 void rb_vm_change_state(void);
 void rb_vm_inc_const_missing_count(void);
 void rb_thread_mark(void *th);
+#ifdef ALIGN_RB_THREAD_T
+void rb_thread_mark_aligned(void *th, int aligned);
+#endif
 const void **rb_vm_get_insns_address_table(void);
 
 /* vm_dump.c */
diff -Naur ruby-1.9.3-p547.original/iseq.c ruby-1.9.3-p547.htm/iseq.c
--- ruby-1.9.3-p547.original/iseq.c	2014-02-14 15:44:36.000000000 +0900
+++ ruby-1.9.3-p547.htm/iseq.c	2014-09-12 06:37:35.905002000 +0900
@@ -6,6 +6,7 @@
   created at: 2006-07-11(Tue) 09:00:03 +0900
 
   Copyright (C) 2006 Koichi Sasada
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
@@ -58,6 +59,51 @@
     }
 }
 
+#ifdef HTM_GVL
+void
+iseq_get_insn_counters(int64_t *counter_addr, uint32_t *counter0, uint32_t *counter1, uint32_t *counter2)
+{
+    uint32_t *counter1_addr;
+    uint32_t *counter2_addr;
+
+    counter1_addr = (uint32_t *)counter_addr + 1;
+    counter2_addr = (uint32_t *)counter_addr;
+
+    *counter0 = *counter2_addr & 0xFF;
+    *counter1 = *counter1_addr;
+    *counter2 = *counter2_addr >> 8;
+}
+
+void
+iseq_print_counter(int64_t *counter_addr, const char *insn_name, rb_iseq_t *iseq, int pos)
+{
+    uint32_t counter0;
+    uint32_t counter1;
+    uint32_t counter2;
+
+#ifdef HTM_GVL_INSN_STATS
+    htm_insn_stats_t *insn_stats_counter;
+    extern htm_insn_stats_t htm_insn_stats_counter_for_null;
+    if (pos == -1) {
+	insn_stats_counter = &htm_insn_stats_counter_for_null;
+    } else {
+	insn_stats_counter = &iseq->htm_insn_stats_counters[pos];
+    }
+#endif
+
+    iseq_get_insn_counters(counter_addr, &counter0, &counter1, &counter2);
+    fprintf(stderr, "#HTM_INSN_STATS %p %p %s %u %u %u"
+#ifndef HTM_GVL_INSN_STATS
+	    "\n"
+#endif
+	    , iseq, counter_addr, insn_name, counter0, counter1, counter2);
+    /*fprintf(stderr, "%s %u\n", insn_name(iseq->iseq[pos]), (uint32_t)(counter >> 32));*/
+#ifdef HTM_GVL_INSN_STATS
+    fprintf(stderr, "  %u %u\n", insn_stats_counter->c32.c0, insn_stats_counter->c32.c1);
+#endif
+}
+#endif
+
 static void
 iseq_free(void *ptr)
 {
@@ -66,6 +112,79 @@
 
     if (ptr) {
 	iseq = ptr;
+#ifdef HTM_GVL
+	if (getenv("RUBY_PRINT_HTM_INSN_STATS") ||
+	    getenv("RH_ISTATS")) {
+	    size_t i;
+	    uint64_t sum_counter1 = 0, sum_counter2 = 0;
+	    for (i = 1; i < iseq->insn_info_size; i++) {
+		int pos = iseq->insn_info_table[i].position;
+		int offset = 0;
+		switch (iseq->iseq[pos]) {
+		case BIN(getlocal):
+		    offset = 2;
+		    break;
+		case BIN(getinstancevariable):
+		    offset = 3;
+		    break;
+		case BIN(getclassvariable):
+		    offset = 2;
+		    break;
+		case BIN(send):
+		    offset = 6;
+		    break;
+		case BIN(leave):
+		    offset = 1;
+		    break;
+		case BIN(throw):
+		    offset = 2;
+		    break;
+		case BIN(jump):
+		    offset = 2;
+		    break;
+		case BIN(branchif):
+		    offset = 2;
+		    break;
+		case BIN(branchunless):
+		    offset = 2;
+		    break;
+		case BIN(onceinlinecache):
+		    offset = 3;
+		    break;
+		case BIN(opt_plus):
+		    offset = 2;
+		    break;
+		case BIN(opt_minus):
+		    offset = 2;
+		    break;
+		case BIN(opt_mult):
+		    offset = 2;
+		    break;
+		case BIN(opt_aref):
+		    offset = 2;
+		    break;
+		}
+		if (offset != 0) {
+		    int64_t *counter_addr = &iseq->htm_counters[pos];
+		    uint32_t counter0;
+		    uint32_t counter1;
+		    uint32_t counter2;
+
+		    iseq_print_counter(counter_addr, insn_name(iseq->iseq[pos]), iseq, pos);
+		    iseq_get_insn_counters(counter_addr, &counter0, &counter1, &counter2);
+
+		    sum_counter1 += counter1;
+		    sum_counter2 += counter2;
+		} else {
+		    fprintf(stderr, "#HTM_INSN_STATS %p %p %s 0 0 0\n", iseq, &iseq->iseq_encoded[pos], insn_name(iseq->iseq[pos]));
+		}
+	    }
+	    fprintf(stderr, "#HTM_INSN_STATS ISEQ %p %" PRIu64 " %" PRIu64 "\n",
+		    iseq, sum_counter1, sum_counter2
+		    /*, RSTRING_PTR(iseq->name)*/
+		    /*, !NIL_P(iseq->filename) ? RSTRING_PTR(iseq->filename) : "null"*/);
+	}
+#endif
 	if (!iseq->orig) {
 	    /* It's possible that strings are freed */
 	    if (0) {
diff -Naur ruby-1.9.3-p547.original/lib/webrick/utils.rb ruby-1.9.3-p547.htm/lib/webrick/utils.rb
--- ruby-1.9.3-p547.original/lib/webrick/utils.rb	2012-05-19 14:40:29.000000000 +0900
+++ ruby-1.9.3-p547.htm/lib/webrick/utils.rb	2014-09-12 06:37:35.905002000 +0900
@@ -175,12 +175,14 @@
         Thread.start{
           while true
             now = Time.now
+            TimeoutMutex.synchronie {
             @timeout_info.each{|thread, ary|
               ary.dup.each{|info|
                 time, exception = *info
                 interrupt(thread, info.object_id, exception) if time < now
               }
             }
+            }
             sleep 0.5
           end
         }
diff -Naur ruby-1.9.3-p547.original/ruby.c ruby-1.9.3-p547.htm/ruby.c
--- ruby-1.9.3-p547.original/ruby.c	2012-10-16 11:11:36.000000000 +0900
+++ ruby-1.9.3-p547.htm/ruby.c	2014-09-16 01:11:39.012549000 +0900
@@ -8,6 +8,7 @@
   Copyright (C) 1993-2007 Yukihiro Matsumoto
   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
   Copyright (C) 2000  Information-technology Promotion Agency, Japan
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
@@ -23,6 +24,9 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <ctype.h>
+#ifdef HTM_GVL
+#include <string.h>
+#endif
 
 #ifdef __hpux
 #include <sys/pstat.h>
@@ -57,6 +61,9 @@
     disable_gems,
     disable_rubyopt,
     disable_flag_count
+#ifdef HTM_GVL
+    ,disable_htm
+#endif
 };
 
 #define DUMP_BIT(bit) (1U << dump_##bit)
@@ -662,6 +669,9 @@
 #define SET_WHEN_DISABLE(bit) SET_WHEN(#bit, DISABLE_BIT(bit), str, len)
     SET_WHEN_DISABLE(gems);
     SET_WHEN_DISABLE(rubyopt);
+#ifdef HTM_GVL
+    SET_WHEN_DISABLE(htm);
+#endif
     if (NAME_MATCH_P("all", str, len)) {
 	*(unsigned int *)arg = ~0U;
 	return;
@@ -1376,6 +1386,17 @@
 	rb_define_module("Gem");
 #endif
     }
+#ifdef HTM_GVL
+    if (opt->disable & DISABLE_BIT(htm)) {
+	ruby_use_gvl = 1;
+    }
+    {
+	char *ruby_disable_htm = getenv("RUBY_DISABLE_HTM");
+	if (ruby_disable_htm && strcmp(ruby_disable_htm, "yes") == 0) {
+	    ruby_use_gvl = 1;
+	}
+    }
+#endif
     ruby_init_prelude();
     ruby_set_argv(argc, argv);
     process_sflag(&opt->sflag);
diff -Naur ruby-1.9.3-p547.original/thread.c ruby-1.9.3-p547.htm/thread.c
--- ruby-1.9.3-p547.original/thread.c	2014-02-17 18:09:32.000000000 +0900
+++ ruby-1.9.3-p547.htm/thread.c	2014-09-12 06:37:35.905002000 +0900
@@ -5,6 +5,7 @@
   $Author: usa $
 
   Copyright (C) 2004-2007 Koichi Sasada
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
@@ -110,22 +111,87 @@
 
 static inline void blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region);
 
+#ifdef HTM_GVL
+/* Store-to-store barrier is needed. */
+#if defined(__370__)
 #define RB_GC_SAVE_MACHINE_CONTEXT(th) \
   do { \
     rb_gc_save_machine_context(th); \
     SET_MACHINE_STACK_END(&(th)->machine_stack_end); \
+    th->gc_safe_point_reached = 1; \
   } while (0)
+#elif defined(__PPC__) && defined(__IBMC__)
+#define RB_GC_SAVE_MACHINE_CONTEXT(th) \
+  do { \
+    rb_gc_save_machine_context(th); \
+    SET_MACHINE_STACK_END(&(th)->machine_stack_end); \
+    __lwsync(); \
+    th->gc_safe_point_reached = 1; \
+  } while (0)
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+#define RB_GC_SAVE_MACHINE_CONTEXT(th) \
+  do { \
+    rb_gc_save_machine_context(th); \
+    SET_MACHINE_STACK_END(&(th)->machine_stack_end); \
+    asm volatile("lwsync" : : ); \
+    th->gc_safe_point_reached = 1; \
+  } while (0)
+#elif defined(__GNUC__) || defined(__IBMC__)
+#define RB_GC_SAVE_MACHINE_CONTEXT(th) \
+  do { \
+    rb_gc_save_machine_context(th); \
+    SET_MACHINE_STACK_END(&(th)->machine_stack_end); \
+    __sync_synchronize(); \
+    th->gc_safe_point_reached = 1; \
+  } while (0)
+#else
+#error
+#endif
+#else /* ! HTM_GVL */
+#define RB_GC_SAVE_MACHINE_CONTEXT(th) \
+  do { \
+    rb_gc_save_machine_context(th); \
+    SET_MACHINE_STACK_END(&(th)->machine_stack_end); \
+  } while (0)
+#endif /* ! HTM_GVL */
 
+#ifdef HTM_GVL
+#define GVL_UNLOCK_BEGIN() do { \
+  rb_thread_t *_th_stored = GET_THREAD(); \
+  RB_GC_SAVE_MACHINE_CONTEXT(_th_stored); \
+  gvl_release(_th_stored->vm, _th_stored);
+#else
 #define GVL_UNLOCK_BEGIN() do { \
   rb_thread_t *_th_stored = GET_THREAD(); \
   RB_GC_SAVE_MACHINE_CONTEXT(_th_stored); \
   gvl_release(_th_stored->vm);
+#endif
 
+#ifdef HTM_GVL
 #define GVL_UNLOCK_END() \
+  th->gc_safe_point_reached = 0; \
   gvl_acquire(_th_stored->vm, _th_stored); \
   rb_thread_set_current(_th_stored); \
 } while(0)
+#else
+#define GVL_UNLOCK_END() \
+  gvl_acquire(_th_stored->vm, _th_stored); \
+  rb_thread_set_current(_th_stored); \
+} while(0)
+#endif
 
+#ifdef HTM_GVL
+#define blocking_region_begin(th, region, func, arg) \
+  do { \
+    (region)->prev_status = (th)->status; \
+    set_unblock_function((th), (func), (arg), &(region)->oldubf); \
+    (th)->blocking_region_buffer = (region); \
+    (th)->status = THREAD_STOPPED; \
+    thread_debug("enter blocking region (%p)\n", (void *)(th)); \
+    RB_GC_SAVE_MACHINE_CONTEXT(th); \
+    gvl_release((th)->vm, (th));    \
+  } while (0)
+#else
 #define blocking_region_begin(th, region, func, arg) \
   do { \
     (region)->prev_status = (th)->status; \
@@ -136,6 +202,7 @@
     RB_GC_SAVE_MACHINE_CONTEXT(th); \
     gvl_release((th)->vm); \
   } while (0)
+#endif
 
 #define BLOCKING_REGION(exec, ubf, ubfarg) do { \
     rb_thread_t *__th = GET_THREAD(); \
@@ -258,7 +325,11 @@
 void
 rb_vm_gvl_destroy(rb_vm_t *vm)
 {
+#ifdef HTM_GVL
+    gvl_release(vm, GET_THREAD());
+#else
     gvl_release(vm);
+#endif
     gvl_destroy(vm);
 }
 
@@ -407,6 +478,63 @@
 #endif
 }
 
+#ifdef HTM_GVL
+#ifdef HTM_GVL_SUMMARY_STATS
+void
+accumulate_thr_htm_stats(rb_thread_t *th)
+{
+#if defined(__370__)
+    int i, j;
+#endif
+
+    th->vm->htm_stats.tx += th->htm_stats.tx;
+    th->vm->htm_stats.tx_enter += th->htm_stats.tx_enter;
+    th->vm->htm_stats.abort += th->htm_stats.abort;
+    th->vm->htm_stats.first_abort += th->htm_stats.first_abort;
+    th->vm->htm_stats.gvl_wait_before_tx_spin += th->htm_stats.gvl_wait_before_tx_spin;
+    th->vm->htm_stats.gvl_wait_before_tx_sleep += th->htm_stats.gvl_wait_before_tx_sleep;
+    th->vm->htm_stats.gvl_wait_and_retry_spin += th->htm_stats.gvl_wait_and_retry_spin;
+    th->vm->htm_stats.gvl_wait_and_retry_sleep += th->htm_stats.gvl_wait_and_retry_sleep;
+    th->vm->htm_stats.gvl_acquired += th->htm_stats.gvl_acquired;
+    th->vm->htm_stats.persistent_abort_retry += th->htm_stats.persistent_abort_retry;
+    th->vm->htm_stats.gvl_persistent_abort += th->htm_stats.gvl_persistent_abort;
+    th->vm->htm_stats.transient_abort_retry += th->htm_stats.transient_abort_retry;
+    th->vm->htm_stats.gvl_transient_abort += th->htm_stats.gvl_transient_abort;
+#if defined(__370__)
+    for (i = 0; i < 19; i++) {
+	for (j = 0; j < 3; j++) {
+	    th->vm->htm_stats.abort_reason_code[i][j] += th->htm_stats.abort_reason_code[i][j];
+	}
+    }
+#elif defined(__x86_64__)
+#define HTM_IA32_STAT(nam) th->vm->htm_stats.abort_reason_counters.nam += th->htm_stats.abort_reason_counters.nam;
+#include "htm_ia32_stat.h"
+#undef HTM_IA32_STAT
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+#define HTM_PPC_STAT(nam) th->vm->htm_stats.abort_reason_counters.nam += th->htm_stats.abort_reason_counters.nam;
+#include "htm_ppc_stat.h"
+#undef HTM_PPC_STAT
+#else
+#error
+#endif
+}
+#endif
+#ifdef HTM_GVL_CYCLE_STATS
+void
+accumulate_thr_htm_cycle_stats(rb_thread_t *th)
+{
+    th->vm->cycle_stats.tx += th->cycle_stats.tx;
+    th->vm->cycle_stats.abort += th->cycle_stats.abort;
+    th->vm->cycle_stats.gvl_wait_spin += th->cycle_stats.gvl_wait_spin;
+    th->vm->cycle_stats.gvl_wait_sleep += th->cycle_stats.gvl_wait_sleep;
+    th->vm->cycle_stats.gvl += th->cycle_stats.gvl;
+    th->vm->cycle_stats.between_tx += th->cycle_stats.between_tx;
+    th->vm->cycle_stats.mutex_sleep += th->cycle_stats.mutex_sleep;
+    th->vm->cycle_stats.native_sleep += th->cycle_stats.native_sleep;
+}
+#endif
+#endif /* HTM_GVL */
+
 static void
 thread_cleanup_func(void *th_ptr, int atfork)
 {
@@ -425,6 +553,14 @@
 
     native_mutex_destroy(&th->interrupt_lock);
     native_thread_destroy(th);
+#ifdef HTM_GVL
+#ifdef HTM_GVL_SUMMARY_STATS
+    accumulate_thr_htm_stats(th);
+#endif
+#ifdef HTM_GVL_CYCLE_STATS
+    accumulate_thr_htm_cycle_stats(th);
+#endif
+#endif
 }
 
 static VALUE rb_threadptr_raise(rb_thread_t *, int, VALUE *);
@@ -552,7 +688,11 @@
     }
     else {
 	thread_cleanup_func(th, FALSE);
+#ifdef HTM_GVL
+	gvl_release(th->vm, th);
+#else
 	gvl_release(th->vm);
+#endif
     }
 
     return 0;
@@ -1054,11 +1194,28 @@
     }
 }
 
+#ifdef HTM_GVL
+int
+rb_thread_alone_fast(void *ptr)
+{
+    rb_thread_t *th = (rb_thread_t *)ptr;
+    int num = 1;
+    if (th->vm->living_threads) {
+	num = th->vm->living_threads->num_entries;
+	thread_debug("rb_thread_alone: %d\n", num);
+    }
+    return num == 1;
+}
+#endif /* HTM_GVL */
+
 /* blocking region */
 
 static inline void
 blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region)
 {
+#ifdef HTM_GVL
+    th->gc_safe_point_reached = 0;
+#endif
     gvl_acquire(th->vm, th);
     rb_thread_set_current(th);
     thread_debug("leave blocking region (%p)\n", (void *)th);
@@ -3026,7 +3183,13 @@
     rb_vm_t *vm = GET_VM(); /* TODO: fix me for Multi-VM */
 
     /* for time slice */
+#if RUBY_VM_THREAD_MODEL == 3
+    if (vm->use_gvl) {
+	RUBY_VM_SET_TIMER_INTERRUPT(vm->running_thread);
+    }
+#else
     RUBY_VM_SET_TIMER_INTERRUPT(vm->running_thread);
+#endif
 
     /* check signal */
     rb_threadptr_check_signal(vm->main_thread);
@@ -3093,6 +3256,11 @@
     rb_thread_t *th = GET_THREAD();
     rb_vm_t *vm = th->vm;
     VALUE thval = th->self;
+#ifdef ALIGN_RB_THREAD_T
+    void *th_before_aligned;
+    TypedData_Get_Struct(thval, rb_thread_t, &ruby_threadptr_data_type, th_before_aligned);
+    vm->main_thread_before_aligned = th_before_aligned;
+#endif
     vm->main_thread = th;
 
     gvl_atfork(th->vm);
@@ -3513,6 +3681,7 @@
 	    break;
 	}
 
+	HTM_GVL_CHARGE_CYCLES_TO_SAVED_TARGET();
 	if (timeout_ms) {
 	    struct timespec timeout_rel;
 	    struct timespec timeout;
@@ -3526,6 +3695,7 @@
 	    native_cond_wait(&mutex->cond, &mutex->lock);
 	    err = 0;
 	}
+	HTM_GVL_CHARGE_CYCLES_TO_AND_START(mutex_sleep, between_tx);
     }
     mutex->cond_waiting--;
 
@@ -4774,6 +4944,7 @@
 	{
 	    /* acquire global vm lock */
 	    gvl_init(th->vm);
+	    HTM_GVL_START_CYCLES();
 	    gvl_acquire(th->vm, th);
 	    native_mutex_initialize(&th->interrupt_lock);
 	}
diff -Naur ruby-1.9.3-p547.original/thread_pthread.c ruby-1.9.3-p547.htm/thread_pthread.c
--- ruby-1.9.3-p547.original/thread_pthread.c	2014-02-14 15:06:14.000000000 +0900
+++ ruby-1.9.3-p547.htm/thread_pthread.c	2014-09-12 06:37:35.905002000 +0900
@@ -6,6 +6,7 @@
   $Author: usa $
 
   Copyright (C) 2004-2007 Koichi Sasada
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
@@ -27,6 +28,9 @@
 #if defined(HAVE_SYS_TIME_H)
 #include <sys/time.h>
 #endif
+#if defined(HTM_GVL)
+#include <math.h>
+#endif
 
 static void native_mutex_lock(pthread_mutex_t *lock);
 static void native_mutex_unlock(pthread_mutex_t *lock);
@@ -75,12 +79,390 @@
     vm->gvl.acquired = 1;
 }
 
+static inline void
+store_to_load_fence(void) {
+#if defined(__370__)
+    /* Nothing to do */
+#elif defined(__PPC__) && defined(__IBMC__)
+    __sync();
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+    asm volatile("sync" : : );
+#elif defined(__GNUC__) || defined(__IBMC__)
+    __sync_synchronize();
+#else
+#error
+#endif
+}
+
+static inline void
+store_to_store_fence(void) {
+#if defined(__370__)
+    /* Nothing to do */
+#elif defined(__PPC__) && defined(__IBMC__)
+    __lwsync();
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+    asm volatile("lwsync" : : );
+#elif defined(__GNUC__) || defined(__IBMC__)
+    __sync_synchronize();
+#else
+#error
+#endif
+}
+
+#ifdef USE_SIMPLE_GVL_2
+static int
+htm_fall_back_gvl_acquire(rb_vm_t *vm, rb_thread_t *th, int acquire)
+{
+    int spin_count = rb_gvl_spin_max;
+#ifdef __370__
+    unsigned long local_acquired;
+    unsigned long new_value = (unsigned long)th;
+#endif
+#ifdef HTM_GVL
+    RB_GC_SAVE_MACHINE_CONTEXT(th);
+#endif
+
+    /*fprintf(stderr, "thr %p start spinning on vm->gvl.waiting\n", th);*/
+    HTM_GVL_CHARGE_CYCLES_TO_SAVED_TARGET();
+    while (vm->gvl.acquired && --spin_count > 0)
+	;
+    if (! acquire && ! vm->gvl.acquired) {
+	HTM_GVL_CHARGE_CYCLES_TO(gvl_wait_spin);
+#ifdef HTM_GVL
+	th->gc_safe_point_reached = 0;
+#endif
+	return 0;
+    }
+ retry_acquiring_gvl:
+    if (spin_count <= 0)
+	spin_count = 1;
+#if defined(__370__)
+    local_acquired = 0;
+    while (cds((cds_t *)&local_acquired, (cds_t *)&vm->gvl.acquired, *(cds_t *)&new_value)) {
+	while (local_acquired = vm->gvl.acquired && --spin_count > 0)
+	    ;
+	if (spin_count <= 0)
+	    break;
+    }
+#elif defined(__GNUC__) || defined(__IBMC__)
+    while (__sync_val_compare_and_swap(&vm->gvl.acquired, 0, (unsigned long)th)) {
+	while (vm->gvl.acquired && --spin_count > 0)
+	    ;
+	if (spin_count <= 0)
+	    break;
+    }
+#else
+#error
+#endif
+    if (spin_count <= 0) {
+	native_mutex_lock(&vm->gvl.lock);
+	vm->gvl.waiting++;
+	/*fprintf(stderr, "thr %p increment vm->gvl.waiting to %d vm->gvl.acquired = %lx\n", th, vm->gvl.waiting, vm->gvl.acquired);*/
+	store_to_load_fence();
+	if (vm->gvl.acquired) {
+	    HTM_GVL_CHARGE_CYCLES_TO(gvl_wait_spin);
+	    native_cond_wait(&vm->gvl.cond, &vm->gvl.lock);
+	    HTM_GVL_CHARGE_CYCLES_TO(gvl_wait_sleep);
+	}
+	vm->gvl.waiting--;
+	/*fprintf(stderr, "thr %p decrement vm->gvl.waiting to %d\n", th, vm->gvl.waiting);*/
+	native_mutex_unlock(&vm->gvl.lock);
+	spin_count = rb_gvl_spin_max;
+	goto retry_acquiring_gvl;
+    } else {
+	HTM_GVL_CHARGE_CYCLES_TO_AND_START(gvl_wait_spin, gvl);
+    }
+    /*fprintf(stderr, "thr %p acquired vm->gvl.waiting\n", th);*/
+#ifdef HTM_GVL
+    th->gc_safe_point_reached = 0;
+#endif
+    return 1;
+}
+
+static void
+simple_gvl_release_2(rb_vm_t *vm, rb_thread_t *th)
+{
+    store_to_store_fence();
+    vm->gvl.acquired = 0;
+    store_to_load_fence();
+    /*fprintf(stderr, "thr %p look at vm->gvl.waiting as %d\n", th, vm->gvl.waiting);*/
+    if (vm->gvl.waiting > 0) {
+	native_mutex_lock(&vm->gvl.lock);
+	native_cond_signal(&vm->gvl.cond);
+	native_mutex_unlock(&vm->gvl.lock);
+    }
+}
+#endif
+
+#ifdef HTM_GVL
+#ifdef HTM_GVL_SUMMARY_STATS
+#define INCREMENT_STAT(field) th->htm_stats.field++;
+#else
+#define INCREMENT_STAT(field)
+#endif
+
+#define READ_FROM_COUNTER0(counter_addr)	\
+    ((*(uint32_t *)(counter_addr)) & 0xFF)
+
+#define WRITE_TO_COUNTER0(data, counter_addr)				\
+    do {								\
+	*(uint32_t *)(counter_addr) = (*(uint32_t *)(counter_addr) & ~0xFF) | (data); \
+    } while (0)
+
+#define READ_FROM_COUNTER1(counter_addr)	\
+    (*((uint32_t *)(counter_addr) + 1))
+
+#define WRITE_TO_COUNTER1(data, counter_addr)		\
+    do {						\
+	*((uint32_t *)(counter_addr) + 1) = (data);	\
+    } while (0)
+
+#define READ_FROM_COUNTER2(counter_addr)	\
+    ((*(uint32_t *)(counter_addr)) >> 8)
+
+#define WRITE_TO_COUNTER2(data, counter_addr)				\
+    do {								\
+	*(uint32_t *)(counter_addr) = (*(uint32_t *)(counter_addr) & 0xFF) | ((data) << 8); \
+    } while (0)
+
+#define GET_COUNTER0(counter02) ((counter02) & 0xFF)
+#define GET_COUNTER2(counter02) ((counter02) >> 8)
+
+#define READ_FROM_COUNTER02(counter_addr) \
+    (*(uint32_t *)(counter_addr))
+
+#define WRITE_TO_COUNTER02(counter0, counter2, counter_addr)		\
+    do {								\
+	*(uint32_t *)(counter_addr) = (counter2) << 8 | (counter0);	\
+    } while(0)
+
+#if defined(__370__)
+#define IS_PERSISTENT(reason, th) ((th)->diag.format != 1 || (reason) == 7 || (reason) == 8 || (11 <= (reason) && (reason) <= 13))
+#elif defined(__x86_64__)
+#define IS_PERSISTENT(reason, th) (! ((reason) & XABORT_RETRY))
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+#define IS_PERSISTENT(reason, th) ((reason) & 0x0100000000000000ULL)
+#endif
+
+int64_t htm_counter_for_null;
+
+void
+htm_gvl_acquire_multi_threads(void *ptr, VALUE *cnt_addr)
+{
+    rb_thread_t *th = (rb_thread_t *)ptr;
+    rb_vm_t *vm = th->vm;
+    int persistent_retry_count;
+    int transient_retry_count;
+    int gvl_retry_count;
+    int first_retry;
+    int tbegin_result;
+    int64_t *counter_addr;
+    uint32_t next_interval = 0;
+    uint32_t wait_and_see_counter = 0;
+    uint32_t tx_size_recalc_counter = 0;
+
+    if (cnt_addr == NULL) {
+	counter_addr = &htm_counter_for_null;
+    } else {
+	rb_iseq_t *iseq = th->cfp->iseq;
+	counter_addr = &iseq->htm_counters[cnt_addr - iseq->iseq_encoded];
+    }
+
+    if (rb_htm_schedule_interval > 0) {
+	th->htm_schedule_counter = rb_htm_schedule_interval;
+#if 0
+    } else if (rb_htm_schedule_interval == -1) {
+	uint32_t counter02;
+
+	counter02 = READ_FROM_COUNTER02(counter_addr);
+	next_interval = GET_COUNTER0(counter02);
+	if (next_interval == 0) {
+	    next_interval = 1;
+	    WRITE_TO_COUNTER02(next_interval, 1, counter_addr);
+	} else if (next_interval < 255) {
+	    tx_size_recalc_counter = READ_FROM_COUNTER1(counter_addr);
+	    if (tx_size_recalc_counter <= rb_htm_tx_size_recalc_threshold) {
+		wait_and_see_counter = GET_COUNTER2(counter02) + 1;
+		if (wait_and_see_counter >= HTM_WAIT_AND_SEE_PERIOD) {
+		    next_interval = (int)ceil((double)next_interval * 4 / 3);
+		    if (next_interval > 255)
+			next_interval = 255;
+		    wait_and_see_counter = 0;
+		    WRITE_TO_COUNTER1(0, counter_addr);
+		}
+		WRITE_TO_COUNTER02(next_interval, wait_and_see_counter, counter_addr);
+	    }
+	}
+	th->htm_schedule_counter = next_interval;
+#endif
+    } else {
+	uint32_t counter02;
+
+	counter02 = READ_FROM_COUNTER02(counter_addr);
+	next_interval = GET_COUNTER0(counter02);
+	if (next_interval == 0) {
+	    next_interval = -rb_htm_schedule_interval;
+	    WRITE_TO_COUNTER02(next_interval, 1, counter_addr);
+	} else if (1 < next_interval) {
+	    wait_and_see_counter = GET_COUNTER2(counter02);
+	    if (wait_and_see_counter < HTM_WAIT_AND_SEE_PERIOD) {
+		WRITE_TO_COUNTER02(next_interval, wait_and_see_counter + 1, counter_addr);
+	    }
+	}
+	th->htm_schedule_counter = next_interval;
+    }
+
+    INCREMENT_STAT(tx_enter);
+    if (vm->gvl.acquired) {
+	if (htm_fall_back_gvl_acquire(vm, th, 0)) {
+	    INCREMENT_STAT(gvl_wait_before_tx_sleep);
+	    return;
+	} else {
+	    INCREMENT_STAT(gvl_wait_before_tx_spin);
+	}
+    }
+    /*fprintf(stderr, "%p tbegin\n", th);*/
+    persistent_retry_count = rb_htm_persistent_retry_max;
+    transient_retry_count = rb_htm_transient_retry_max;
+    gvl_retry_count = rb_htm_gvl_retry_max;
+    first_retry = 1;
+    HTM_GVL_CHARGE_CYCLES_TO_AND_START(between_tx, tx);
+
+ tx_retry:
+    INCREMENT_STAT(tx);
+    tbegin_result = tbegin(&th->diag);
+    /*tbegin_result = 3;*/
+    if (tbegin_result == 0) {
+	/* tbegin succeeded */
+	if (vm->gvl.acquired)
+	    tabort(256);
+    } else {
+	/* transaction failed */
+	uint64_t reason = th->diag.transactionAbortCode;
+	INCREMENT_STAT(abort);
+	HTM_GVL_CHANGE_CYCLE_CHARGING_TO(abort);
+	if (first_retry) {
+	    first_retry = 0;
+	    INCREMENT_STAT(first_abort);
+	    if (rb_htm_schedule_interval == -1 /* Adaptive transaction size enlargement */ &&
+		next_interval < 255 /* Can enlarge the size */ &&
+		tx_size_recalc_counter <= rb_htm_tx_size_recalc_threshold /* Stats collection period */) {
+		WRITE_TO_COUNTER1(tx_size_recalc_counter + 1, counter_addr);
+	    } else if (rb_htm_schedule_interval < 0 /* Adaptive transaction size*/ &&
+		1 < next_interval /* Can shorten the size */ &&
+		wait_and_see_counter < HTM_WAIT_AND_SEE_PERIOD /* Stats collection period */) {
+		tx_size_recalc_counter = READ_FROM_COUNTER1(counter_addr) + 1;
+		/*tx_size_recalc_counter = READ_FROM_COUNTER1(counter_addr) + (IS_PERSISTENT(reason, th) ? 7 : 1);*/
+		if (tx_size_recalc_counter > rb_htm_tx_size_recalc_threshold) {
+		    next_interval = next_interval * 3 / 4;
+		    WRITE_TO_COUNTER0(next_interval, counter_addr);
+		    /* Reinitialize the stats counters. */
+		    WRITE_TO_COUNTER1(0, counter_addr);
+		    WRITE_TO_COUNTER2(0, counter_addr);
+		} else {
+		    WRITE_TO_COUNTER1(tx_size_recalc_counter, counter_addr);
+		}
+	    }
+	}
+
+	if (vm->gvl.acquired) {
+	    if (--gvl_retry_count > 0) {
+		if (htm_fall_back_gvl_acquire(vm, th, 0)) {
+		    INCREMENT_STAT(gvl_wait_and_retry_sleep);
+		    return;
+		} else {
+		    INCREMENT_STAT(gvl_wait_and_retry_spin);
+		}
+		HTM_GVL_CHARGE_CYCLES_TO_AND_START(abort, tx);
+		goto tx_retry;
+	    }
+	    INCREMENT_STAT(gvl_acquired);
+	    htm_fall_back_gvl_acquire(vm, th, 1);
+	} else {
+#ifdef HTM_GVL_SUMMARY_STATS
+#if defined(__370__)
+	    if (th->diag.format != 1) {
+		th->htm_stats.abort_reason_code[0][tbegin_result - 1]++;
+	    } else if (reason <= 16) {
+		th->htm_stats.abort_reason_code[reason][tbegin_result - 1]++;
+	    } else if (reason == 255) {
+		th->htm_stats.abort_reason_code[17][tbegin_result - 1]++;
+	    } else {
+		th->htm_stats.abort_reason_code[18][tbegin_result - 1]++;
+	    }
+#elif defined(__x86_64__)
+#define THCTR th->htm_stats.abort_reason_counters
+	    THCTR.XABORT                    += (reason & XABORT_EXPLICIT) ? 1L : 0L;
+	    THCTR.TRANSIENT                 += (reason & XABORT_RETRY) ? 1L : 0L;
+	    THCTR.MEMADDR_CONFLICT          += (reason & XABORT_CONFLICT) ? 1L : 0L;
+	    THCTR.BUFFER_OVERFLOW           += (reason & XABORT_CAPACITY) ? 1L : 0L;
+	    THCTR.HIT_DEBUG_BREAKPOINT      += (reason & XABORT_DEBUG) ? 1L : 0L;
+	    THCTR.DURING_NESTED_TRANSACTION += (reason & XABORT_NESTED) ? 1L : 0L;
+	    THCTR.OTHER                     += (reason & (XABORT_EXPLICIT | XABORT_RETRY | XABORT_CONFLICT | XABORT_CAPACITY | XABORT_DEBUG | XABORT_NESTED)) ? 0L : 1L;
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+#define THCTR th->htm_stats.abort_reason_counters
+#define PPC_BFIELD(x) ((0x1ULL) << (63 - x))
+	    THCTR.Failure_Persistent                += (reason & PPC_BFIELD( 7)) ? 1 : 0;
+	    THCTR.Disallowed                        += (reason & PPC_BFIELD( 8)) ? 1 : 0;
+	    THCTR.Nesting_Overflow                  += (reason & PPC_BFIELD( 9)) ? 1 : 0;
+	    THCTR.Footprint_Overflow                += (reason & PPC_BFIELD(10)) ? 1 : 0;
+	    THCTR.Self_Induced_Conflict             += (reason & PPC_BFIELD(11)) ? 1 : 0;
+	    THCTR.Non_Transactional_Conflict        += (reason & PPC_BFIELD(12)) ? 1 : 0;
+	    THCTR.Transaction_Conflict              += (reason & PPC_BFIELD(13)) ? 1 : 0;
+	    THCTR.Translation_Invalidation_Conflict += (reason & PPC_BFIELD(14)) ? 1 : 0;
+	    THCTR.Implementation_Specific           += (reason & PPC_BFIELD(15)) ? 1 : 0;
+	    THCTR.Instruction_Fetch_Conflict        += (reason & PPC_BFIELD(16)) ? 1 : 0;
+	    THCTR.Tabort_Treclaim                   += (reason & PPC_BFIELD(31)) ? 1 : 0;
+	    THCTR.Other                             += (reason & (PPC_BFIELD(7) | PPC_BFIELD(8) | PPC_BFIELD(9) | PPC_BFIELD(10) | PPC_BFIELD(11) | PPC_BFIELD(12) | PPC_BFIELD(13) | PPC_BFIELD(14) | PPC_BFIELD(15) | PPC_BFIELD(16) | PPC_BFIELD(31))) ? 0 : 1;
+#endif
+#endif
+	    /*if (tbegin_result == 3) {*/
+	    if (IS_PERSISTENT(reason, th)) {
+		if (--persistent_retry_count > 0) {
+		    INCREMENT_STAT(persistent_abort_retry);
+		    HTM_GVL_CHARGE_CYCLES_TO_AND_START(abort, tx);
+		    goto tx_retry;
+		}
+		/* persistent failure */
+		INCREMENT_STAT(gvl_persistent_abort);
+		htm_fall_back_gvl_acquire(vm, th, 1);
+	    } else
+	      {
+		if (--transient_retry_count > 0) {
+		    INCREMENT_STAT(transient_abort_retry);
+		    HTM_GVL_CHARGE_CYCLES_TO_AND_START(abort, tx);
+		    goto tx_retry;
+		}
+		INCREMENT_STAT(gvl_transient_abort);
+		htm_fall_back_gvl_acquire(vm, th, 1);
+	    }
+	}
+    }
+}
+#endif
+
 static void
 gvl_acquire(rb_vm_t *vm, rb_thread_t *th)
 {
+#if defined(USE_SIMPLE_GVL_2) && ! defined(HTM_GVL)
+    htm_fall_back_gvl_acquire(vm, th, 1);
+#else
+#if defined(HTM_GVL)
+    if (vm->use_gvl) {
+#endif
     native_mutex_lock(&vm->gvl.lock);
     gvl_acquire_common(vm);
     native_mutex_unlock(&vm->gvl.lock);
+#if defined(HTM_GVL)
+    } else {
+	if (rb_thread_alone()) {
+	    htm_fall_back_gvl_acquire(vm, th, 1);
+	} else {
+	    htm_gvl_acquire_multi_threads(th, NULL);
+	}
+    }
+#endif
+#endif
 }
 
 static void
@@ -91,17 +473,60 @@
 	native_cond_signal(&vm->gvl.cond);
 }
 
+#ifdef HTM_GVL
+void
+gvl_release(void *vm_ptr, void *th_ptr)
+#else
 static void
 gvl_release(rb_vm_t *vm)
+#endif
 {
+#if defined(USE_SIMPLE_GVL_2) && ! defined(HTM_GVL)
+    simple_gvl_release_2(vm, GET_THREAD());
+#else
+#if defined(HTM_GVL)
+    rb_vm_t *vm = (rb_vm_t *)vm_ptr;
+    if (vm->use_gvl) {
+#endif
     native_mutex_lock(&vm->gvl.lock);
     gvl_release_common(vm);
     native_mutex_unlock(&vm->gvl.lock);
+#if defined(HTM_GVL)
+    } else {
+	rb_thread_t *th = (rb_thread_t *)th_ptr;
+
+	if (vm->gvl.acquired) {
+#if defined (USE_SIMPLE_GVL_2)
+	    simple_gvl_release_2(vm, th);
+#else
+	    native_mutex_lock(&vm->gvl.lock);
+	    vm->gvl.acquired = 0;
+	    native_cond_signal(&vm->gvl.cond);
+	    /*native_cond_broadcast(&vm->gvl.cond);*/
+	    native_mutex_unlock(&vm->gvl.lock);
+#endif
+	    HTM_GVL_CHARGE_CYCLES_TO_AND_START(gvl, between_tx);
+	} else {
+	    tend();
+	    HTM_GVL_CHARGE_CYCLES_TO_AND_START(tx, between_tx);
+	    /*th->diag.reserved2 = 0;*/
+	}
+    }
+#endif /* HTM_GVL */
+#endif
 }
 
 static void
 gvl_yield(rb_vm_t *vm, rb_thread_t *th)
 {
+#if defined(USE_SIMPLE_GVL_2) && ! defined(HTM_GVL)
+    simple_gvl_release_2(vm, th);
+    sched_yield();
+    htm_fall_back_gvl_acquire(vm, th, 1);
+#else
+#if defined(HTM_GVL)
+    if (vm->use_gvl) {
+#endif
     native_mutex_lock(&vm->gvl.lock);
 
     gvl_release_common(vm);
@@ -131,6 +556,13 @@
   acquire:
     gvl_acquire_common(vm);
     native_mutex_unlock(&vm->gvl.lock);
+#if defined(HTM_GVL)
+    } else {
+	gvl_release(vm, th);
+	gvl_acquire(vm, th);
+    }
+#endif /* HTM_GVL */
+#endif
 }
 
 static void
@@ -416,11 +848,19 @@
     /* null */
 }
 
+#if RUBY_VM_THREAD_MODEL == 3
+rb_thread_t *
+ruby_thread_from_native(void)
+{
+    return pthread_getspecific(ruby_native_thread_key);
+}
+#else
 static rb_thread_t *
 ruby_thread_from_native(void)
 {
     return pthread_getspecific(ruby_native_thread_key);
 }
+#endif
 
 static int
 ruby_thread_set_native(rb_thread_t *th)
@@ -433,7 +873,11 @@
 void
 Init_native_thread(void)
 {
+#if RUBY_VM_THREAD_MODEL == 3
+    rb_thread_t *th = ruby_current_thread;
+#else
     rb_thread_t *th = GET_THREAD();
+#endif
 
     pthread_key_create(&ruby_native_thread_key, NULL);
     th->thread_id = pthread_self();
@@ -653,6 +1097,7 @@
 #endif
 	native_thread_init(th);
 	/* run */
+	HTM_GVL_START_CYCLES();
 #if defined USE_NATIVE_THREAD_INIT
 	thread_start_func_2(th, th->machine_stack_start, rb_ia64_bsp());
 #else
@@ -905,10 +1350,12 @@
 	    thread_debug("native_sleep: interrupted before sleep\n");
 	}
 	else {
+	    HTM_GVL_CHARGE_CYCLES_TO_SAVED_TARGET();
 	    if (!timeout_tv)
 		native_cond_wait(cond, lock);
 	    else
 		native_cond_timedwait(cond, lock, &timeout);
+	    HTM_GVL_CHARGE_CYCLES_TO_AND_START(native_sleep, between_tx);
 	}
 	th->unblock.func = 0;
 	th->unblock.arg = 0;
@@ -1147,7 +1594,11 @@
 	FD_ZERO(&rfds);
 	FD_SET(timer_thread_pipe[0], &rfds);
 
-	if (gvl->waiting > 0 || need_polling) {
+	if (gvl->waiting > 0 || need_polling
+#ifdef USE_SIMPLE_GVL_2
+	    || 1
+#endif
+	    ) {
 	    timeout.tv_sec = 0;
 	    timeout.tv_usec = TIME_QUANTUM_USEC;
 
diff -Naur ruby-1.9.3-p547.original/thread_pthread.h ruby-1.9.3-p547.htm/thread_pthread.h
--- ruby-1.9.3-p547.original/thread_pthread.h	2011-06-27 21:59:08.000000000 +0900
+++ ruby-1.9.3-p547.htm/thread_pthread.h	2014-09-12 06:37:35.905002000 +0900
@@ -5,6 +5,7 @@
   $Author: kosaki $
 
   Copyright (C) 2004-2007 Koichi Sasada
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
@@ -34,7 +35,11 @@
 
 typedef struct rb_global_vm_lock_struct {
     /* fast path */
+#if defined(USE_SIMPLE_GVL_2)
+    volatile unsigned long acquired;
+#else
     unsigned long acquired;
+#endif
     pthread_mutex_t lock;
 
     /* slow path */
diff -Naur ruby-1.9.3-p547.original/tool/instruction.rb ruby-1.9.3-p547.htm/tool/instruction.rb
--- ruby-1.9.3-p547.original/tool/instruction.rb	2011-05-15 20:55:52.000000000 +0900
+++ ruby-1.9.3-p547.htm/tool/instruction.rb	2014-09-12 06:37:35.905002000 +0900
@@ -798,6 +798,18 @@
     end
 
     def make_header_pc insn
+      if insn.name == "send" ||
+          insn.name == "getinstancevariable" ||
+          insn.name == "getclassvariable" ||
+          insn.name == "send" ||
+          insn.name == "getlocal" ||
+          insn.name == "opt_plus" ||
+          insn.name == "opt_minus" ||
+          insn.name == "opt_mult" ||
+          insn.name == "opt_aref"
+      then
+        commit "#if defined(HTM_GVL)\n  RUBY_VM_HTM_CHECK_SCHED(&GET_OPERAND(0));\n#endif"
+      end
       commit  "  ADD_PC(1+#{@opn});"
       commit  "  PREFETCH(GET_PC());"
     end
diff -Naur ruby-1.9.3-p547.original/vm.c ruby-1.9.3-p547.htm/vm.c
--- ruby-1.9.3-p547.original/vm.c	2014-01-29 12:42:50.000000000 +0900
+++ ruby-1.9.3-p547.htm/vm.c	2014-09-12 14:02:33.771548000 +0900
@@ -5,6 +5,7 @@
   $Author: usa $
 
   Copyright (C) 2004-2007 Koichi Sasada
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
@@ -1626,8 +1627,27 @@
 	rb_gc_force_recycle(vm->self);
 	vm->main_thread = 0;
 	if (th) {
+#ifdef HTM_GVL
+#ifdef HTM_GVL_SUMMARY_STATS
+	    {
+		extern void accumulate_thr_htm_stats(rb_thread_t *th);
+		accumulate_thr_htm_stats(th);
+	    }
+#endif
+#ifdef HTM_GVL_CYCLE_STATS
+           {
+               extern void accumulate_thr_htm_cycle_stats(rb_thread_t *th);
+               accumulate_thr_htm_cycle_stats(th);
+           }
+#endif
+#endif
 	    rb_fiber_reset_root_local_storage(th->self);
+#if defined(ALIGN_RB_THREAD_T)
+	    thread_free(vm->main_thread_before_aligned);
+	    vm->main_thread_before_aligned = 0;
+#else
 	    thread_free(th);
+#endif
 	}
 	if (vm->living_threads) {
 	    st_free_table(vm->living_threads);
@@ -1640,6 +1660,101 @@
 #endif
 	ruby_vm_run_at_exit_hooks(vm);
 	rb_vm_gvl_destroy(vm);
+#ifdef HTM_GVL
+	if (getenv("RUBY_PRINT_HTM_INSN_STATS") ||
+	    getenv("RH_ISTATS")) {
+	    extern void iseq_print_counter(int64_t *counter, const char *insn_name, rb_iseq_t *iseq, int pos);
+
+	    extern void iseq_get_insn_counters(int64_t *counter_addr, uint32_t *counter0, uint32_t *counter1, uint32_t *counter2);
+	    extern int64_t htm_counter_for_null;
+	    uint32_t counter0, counter1, counter2;
+	    iseq_print_counter(&htm_counter_for_null, "null", NULL, -1);
+	    iseq_get_insn_counters(&htm_counter_for_null, &counter0, &counter1, &counter2);
+	    fprintf(stderr, "#HTM_INSN_STATS ISEQ %p %" PRIu32 " %" PRIu32 " counter_for_null\n",
+		    NULL,
+		    counter1, counter2);
+	}
+	if (getenv("RUBY_PRINT_HTM_STATS") ||
+	    getenv("RH_STATS")) {
+#if defined(__370__)
+	    int i;
+	    const char *reason_string[] = {
+		"TDB_not_set",
+		"Restart_interruption",
+		"External_interruption",
+		NULL,
+		"Program_interruption",
+		"Machine-check_interruption",
+		"I/O_interruption",
+		"Fetch_overflow",
+		"Store_overflow",
+		"Fetch_conflict",
+		"Store_conflict",
+		"Restricted_instruction",
+		"Program-interruption_condition",
+		"Nesting_depth_exceeded",
+		"Cache_fetch-related",
+		"Cache_store-related",
+		"Cache_other",
+		"Undetermined_condition",
+		"TABORT_instruction"
+	    };
+#endif
+
+#ifdef HTM_GVL_SUMMARY_STATS
+	    fprintf(stderr, "#HTM_STATS %15llu           tx_enter\n", vm->htm_stats.tx_enter);
+	    fprintf(stderr, "#HTM_STATS %15llu           tx\n", vm->htm_stats.tx);
+	    fprintf(stderr, "#HTM_STATS %15llu %6.2f %%  gvl_wait_before_tx_spin\n", vm->htm_stats.gvl_wait_before_tx_spin, 100 * vm->htm_stats.gvl_wait_before_tx_spin / (double)vm->htm_stats.tx_enter);
+	    fprintf(stderr, "#HTM_STATS %15llu %6.2f %%  gvl_wait_before_tx_sleep\n", vm->htm_stats.gvl_wait_before_tx_sleep, 100 * vm->htm_stats.gvl_wait_before_tx_sleep / (double)vm->htm_stats.tx_enter);
+	    fprintf(stderr, "#HTM_STATS %15llu %6.2f %%  abort\n", vm->htm_stats.abort, 100 * vm->htm_stats.abort / (double)vm->htm_stats.tx);
+	    fprintf(stderr, "#HTM_STATS %15llu %6.2f %%  first_abort\n", vm->htm_stats.first_abort, 100 * vm->htm_stats.first_abort / (double)vm->htm_stats.tx_enter);
+	    fprintf(stderr, "#HTM_STATS %15llu %6.2f %%  gvl_wait_and_retry_spin\n", vm->htm_stats.gvl_wait_and_retry_spin, 100 * vm->htm_stats.gvl_wait_and_retry_spin / (double)vm->htm_stats.abort);
+	    fprintf(stderr, "#HTM_STATS %15llu %6.2f %%  gvl_wait_and_retry_sleep\n", vm->htm_stats.gvl_wait_and_retry_sleep, 100 * vm->htm_stats.gvl_wait_and_retry_sleep / (double)vm->htm_stats.abort);
+	    fprintf(stderr, "#HTM_STATS %15llu %6.2f %%  gvl_acquired\n", vm->htm_stats.gvl_acquired, 100 * vm->htm_stats.gvl_acquired / (double)vm->htm_stats.abort);
+	    fprintf(stderr, "#HTM_STATS %15llu %6.2f %%  persistent_abort_retry\n", vm->htm_stats.persistent_abort_retry, 100 * vm->htm_stats.persistent_abort_retry / (double)vm->htm_stats.abort);
+	    fprintf(stderr, "#HTM_STATS %15llu %6.2f %%  persistent_abort_gvl_acquired\n", vm->htm_stats.gvl_persistent_abort, 100 * vm->htm_stats.gvl_persistent_abort / (double)vm->htm_stats.abort);
+	    fprintf(stderr, "#HTM_STATS %15llu %6.2f %%  transient_abort_retry\n", vm->htm_stats.transient_abort_retry, 100 * vm->htm_stats.transient_abort_retry / (double)vm->htm_stats.abort);
+	    fprintf(stderr, "#HTM_STATS %15llu %6.2f %%  transient_abort_gvl_acquired\n", vm->htm_stats.gvl_transient_abort, 100 * vm->htm_stats.gvl_transient_abort / (double)vm->htm_stats.abort);
+
+#if defined(__370__)
+	    for (i = 0; i < 19; i++) {
+		if (reason_string[i]) {
+		    unsigned long long total = vm->htm_stats.abort_reason_code[i][0] + vm->htm_stats.abort_reason_code[i][1] + vm->htm_stats.abort_reason_code[i][2];
+		    fprintf(stderr, "#HTM_STATS %15llu %s\n", total, reason_string[i]);
+		}
+	    }
+#elif defined(__x86_64__)
+#define HTM_IA32_STAT(nam) fprintf(stderr, "#HTM_STATS %15llu " #nam "\n", vm->htm_stats.abort_reason_counters.nam );
+#include "htm_ia32_stat.h"
+#undef HTM_IA32_STAT
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+#define HTM_PPC_STAT(nam) fprintf(stderr, "#HTM_STATS %15llu " #nam "\n", vm->htm_stats.abort_reason_counters.nam );
+#include "htm_ppc_stat.h"
+#undef HTM_PPC_STAT
+#else
+#error
+#endif
+#endif /* HTM_GVL_SUMMARY_STATS */
+#ifdef HTM_GVL_CYCLE_STATS
+	    {
+		fprintf(stderr, "#HTM_CYCLE_STATS %20llu msec tx\n", (vm->cycle_stats.tx >> 12) / 1000);
+		fprintf(stderr, "#HTM_CYCLE_STATS %20llu msec abort\n", (vm->cycle_stats.abort >> 12) / 1000);
+#ifdef HTM_GVL_DEFER_GC
+		fprintf(stderr, "#HTM_CYCLE_STATS %20llu msec deferred_gc\n", (vm->cycle_stats.deferred_gc >> 12) / 1000);
+#endif
+		fprintf(stderr, "#HTM_CYCLE_STATS %20llu msec gvl_wait_spin\n", (vm->cycle_stats.gvl_wait_spin >> 12) / 1000);
+		fprintf(stderr, "#HTM_CYCLE_STATS %20llu msec gvl_wait_sleep\n", (vm->cycle_stats.gvl_wait_sleep >> 12) / 1000);
+		fprintf(stderr, "#HTM_CYCLE_STATS %20llu msec gvl\n", (vm->cycle_stats.gvl >> 12) / 1000);
+		fprintf(stderr, "#HTM_CYCLE_STATS %20llu msec between_tx\n", (vm->cycle_stats.between_tx >> 12) / 1000);
+#ifdef HTM_GVL_EAGER_TLH_FILLING
+		fprintf(stderr, "#HTM_CYCLE_STATS %20llu msec eager_gc\n", (vm->cycle_stats.eager_gc >> 12) / 1000);
+#endif
+		fprintf(stderr, "#HTM_CYCLE_STATS %20llu msec mutex_sleep\n", (vm->cycle_stats.mutex_sleep >> 12) / 1000);
+		fprintf(stderr, "#HTM_CYCLE_STATS %20llu msec native_sleep\n", (vm->cycle_stats.native_sleep >> 12) / 1000);
+	    }
+#endif
+	}
+#endif /* HTM_GVL */
 	ruby_xfree(vm);
 	ruby_current_vm = 0;
     }
@@ -1720,12 +1835,32 @@
 #endif
 
 void
+#ifdef ALIGN_RB_THREAD_T
+rb_thread_mark_aligned(void *ptr, int aligned)
+#else
 rb_thread_mark(void *ptr)
+#endif
 {
     rb_thread_t *th = NULL;
     RUBY_MARK_ENTER("thread");
     if (ptr) {
+#if defined(ALIGN_RB_THREAD_T)
+	if (aligned) {
+#if defined(__370__)
+	    th = (rb_thread_t *)(((uintptr_t)ptr + 255) & ~255);
+#elif defined(__x86_64__) || defined(__CYGWIN__)
+	    th = (rb_thread_t *)(((uintptr_t)ptr + 63) & ~63);
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+	    th = (rb_thread_t *)(((uintptr_t)ptr + 127) & ~127);
+#else
+#error
+#endif
+	} else {
+	    th = ptr;
+	}
+#else
 	th = ptr;
+#endif
 	if (th->stack) {
 	    VALUE *p = th->stack;
 	    VALUE *sp = th->cfp->sp;
@@ -1774,6 +1909,24 @@
 	rb_mark_tbl(th->local_storage);
 
 	if (GET_THREAD() != th && th->machine_stack_start && th->machine_stack_end) {
+#ifdef HTM_GVL
+	    if (! th->vm->use_gvl) {
+		while (! th->gc_safe_point_reached)
+		    ;
+	    /* Load-to-load barrier */
+#if defined(__370__)
+	    /* Nothing to do */
+#elif defined(__PPC__) && defined(__IBMC__)
+		__lwsync();
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+		asm volatile("lwsync" : : );
+#elif defined(__GNUC__) || defined(__IBMC__)
+		__sync_synchronize();
+#else
+#error
+#endif
+	    }
+#endif
 	    rb_gc_mark_machine_stack(th);
 	    rb_gc_mark_locations((VALUE *)&th->machine_regs,
 				 (VALUE *)(&th->machine_regs) +
@@ -1786,6 +1939,14 @@
     RUBY_MARK_LEAVE("thread");
 }
 
+#ifdef ALIGN_RB_THREAD_T
+void
+rb_thread_mark(void *ptr)
+{
+    rb_thread_mark_aligned(ptr, 1);
+}
+#endif
+
 static void
 thread_free(void *ptr)
 {
@@ -1793,7 +1954,19 @@
     RUBY_FREE_ENTER("thread");
 
     if (ptr) {
+#if defined(ALIGN_RB_THREAD_T)
+#if defined(__370__)
+	th = (rb_thread_t *)(((uintptr_t)ptr + 255) & ~255);
+#elif defined(__x86_64__) || defined(__CYGWIN__)
+	th = (rb_thread_t *)(((uintptr_t)ptr + 63) & ~63);
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+	th = (rb_thread_t *)(((uintptr_t)ptr + 127) & ~127);
+#else
+#error
+#endif
+#else
 	th = ptr;
+#endif
 
 	if (!th->root_fiber) {
 	    RUBY_FREE_UNLESS_NULL(th->stack);
@@ -1821,8 +1994,10 @@
 #endif
 	    ruby_xfree(ptr);
 	}
+#if RUBY_VM_THREAD_MODEL != 3
         if (ruby_current_thread == th)
             ruby_current_thread = NULL;
+#endif
     }
     RUBY_FREE_LEAVE("thread");
 }
@@ -1832,7 +2007,19 @@
 {
     if (ptr) {
 	const rb_thread_t *th = ptr;
+#if defined(ALIGN_RB_THREAD_T)
+#if defined(__370__)
+	size_t size = sizeof(rb_thread_t) + 256 * 2;
+#elif defined(__x86_64__) || defined(__CYGWIN__)
+	size_t size = sizeof(rb_thread_t) + 64 * 2;
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+	size_t size = sizeof(rb_thread_t) + 128 * 2;
+#else
+#error
+#endif
+#else
 	size_t size = sizeof(rb_thread_t);
+#endif
 
 	if (!th->root_fiber) {
 	    size += th->stack_size * sizeof(VALUE);
@@ -1877,8 +2064,12 @@
     obj = TypedData_Wrap_Struct(klass, &thread_data_type, th);
 #else
     rb_thread_t *th;
+#if defined(ALIGN_RB_THREAD_T)
+    obj = TypedData_Make_Struct_Cache_Line_Aligned(klass, rb_thread_t, &thread_data_type, th);
+#else
     obj = TypedData_Make_Struct(klass, rb_thread_t, &thread_data_type, th);
 #endif
+#endif
     return obj;
 }
 
@@ -1886,6 +2077,9 @@
 th_init(rb_thread_t *th, VALUE self)
 {
     th->self = self;
+#ifdef HTM_GVL
+    th->htm_schedule_counter = 1;
+#endif
 
     /* allocate thread stack */
 #ifdef USE_SIGALTSTACK
@@ -2183,7 +2377,11 @@
 	vm->self = TypedData_Wrap_Struct(rb_cRubyVM, &vm_data_type, vm);
 
 	/* create main thread */
+#if defined(ALIGN_RB_THREAD_T)
+	th_self = th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, vm->main_thread_before_aligned);
+#else
 	th_self = th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th);
+#endif
 	vm->main_thread = th;
 	vm->running_thread = th;
 	th->vm = vm;
@@ -2220,17 +2418,51 @@
 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
 struct rb_objspace *rb_objspace_alloc(void);
 #endif
+#ifdef HTM_GVL
+int rb_htm_schedule_interval;
+uint32_t rb_htm_tx_size_recalc_threshold;
+int rb_htm_persistent_retry_max;
+int rb_htm_transient_retry_max;
+int rb_htm_gvl_retry_max;
+#endif
+#if defined(USE_SIMPLE_GVL_2)
+int rb_gvl_spin_max;
+#endif
 
 void
 Init_BareVM(void)
 {
     /* VM bootstrap: phase 1 */
     rb_vm_t * vm = malloc(sizeof(*vm));
+#if defined(ALIGN_RB_THREAD_T)
+#if defined(__370__)
+    rb_thread_t *th = malloc(sizeof(*th) + 256 * 2);
+#elif defined(__x86_64__) || defined(__CYGWIN__)
+    rb_thread_t *th = malloc(sizeof(*th) + 64 * 2);
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+    rb_thread_t *th = malloc(sizeof(*th) + 128 * 2);
+#else
+#error
+#endif
+    void *th_before_aligned = th;
+#else
     rb_thread_t * th = malloc(sizeof(*th));
+#endif
     if (!vm || !th) {
 	fprintf(stderr, "[FATAL] failed to allocate memory\n");
 	exit(EXIT_FAILURE);
     }
+#if defined(ALIGN_RB_THREAD_T)
+#if defined(__370__)
+    th = (rb_thread_t *)(((uintptr_t)th + 255) & ~255);
+#elif defined(__x86_64__) || defined(__CYGWIN__)
+    th = (rb_thread_t *)(((uintptr_t)th + 63) & ~63);
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+    th = (rb_thread_t *)(((uintptr_t)th + 127) & ~127);
+#else
+#error
+#endif
+#endif
     MEMZERO(th, rb_thread_t, 1);
 
     rb_thread_set_current_raw(th);
@@ -2240,11 +2472,98 @@
     vm->objspace = rb_objspace_alloc();
 #endif
     ruby_current_vm = vm;
+#if defined(ALIGN_RB_THREAD_T)
+    vm->main_thread_before_aligned = th_before_aligned;
+#endif
 
     Init_native_thread();
     th_init(th, 0);
     th->vm = vm;
     ruby_thread_init_stack(th);
+#ifdef HTM_GVL
+    {
+	char *sched_interval;
+	char *tx_size_recalc_threshold;
+	char *persistent_retry_max;
+	char *transient_retry_max;
+	char *gvl_retry_max;
+	double recalc_threshold_percent;
+
+	sched_interval = getenv("RUBY_HTM_SCHED_INTERVAL");
+	if (! sched_interval)
+	    sched_interval = getenv("RH_INTV");
+	if (sched_interval) {
+	    rb_htm_schedule_interval = atoi(sched_interval);
+	    if (rb_htm_schedule_interval == 0)
+		rb_htm_schedule_interval = 1;
+	    else if (rb_htm_schedule_interval <= -256)
+		rb_htm_schedule_interval = -255;
+	    fprintf(stderr, "<RUBY_VM: RUBY_HTM_SCHED_INTERVAL set to %d>\n", rb_htm_schedule_interval);
+	} else {
+	    rb_htm_schedule_interval = -255;
+	}
+
+	tx_size_recalc_threshold = getenv("RUBY_HTM_TX_SIZE_RECALC_THRESHOLD");
+	if (! tx_size_recalc_threshold)
+	    tx_size_recalc_threshold = getenv("RH_RECALC");
+	if (tx_size_recalc_threshold) {
+	    recalc_threshold_percent = atof(tx_size_recalc_threshold);
+	    if (recalc_threshold_percent < 0.0 || 100.0 < recalc_threshold_percent) {
+		recalc_threshold_percent = 6.0;
+	    }
+	    fprintf(stderr, "<RUBY_VM: RUBY_HTM_TX_SIZE_RECALC_THRESHOLD set to %f>\n", recalc_threshold_percent);
+	} else {
+	    recalc_threshold_percent = 6.0;
+	}
+	rb_htm_tx_size_recalc_threshold = (int)(recalc_threshold_percent * HTM_WAIT_AND_SEE_PERIOD / 100);
+	if (rb_htm_tx_size_recalc_threshold <= 0)
+	    rb_htm_tx_size_recalc_threshold = 1;
+
+	persistent_retry_max = getenv("RUBY_HTM_PERSISTENT_RETRY_MAX");
+	if (! persistent_retry_max)
+	    persistent_retry_max = getenv("RH_PRETRY");
+	if (persistent_retry_max) {
+	    rb_htm_persistent_retry_max = atoi(persistent_retry_max);
+	    fprintf(stderr, "<RUBY_VM: RUBY_HTM_PERSISTENT_RETRY_MAX set to %d>\n", rb_htm_persistent_retry_max);
+	} else {
+	    rb_htm_persistent_retry_max = 3;
+	}
+
+	transient_retry_max = getenv("RUBY_HTM_TRANSIENT_RETRY_MAX");
+	if (! transient_retry_max)
+	    transient_retry_max = getenv("RH_TRETRY");
+	if (transient_retry_max) {
+	    rb_htm_transient_retry_max = atoi(transient_retry_max);
+	    fprintf(stderr, "<RUBY_VM: RUBY_HTM_TRANSIENT_RETRY_MAX set to %d>\n", rb_htm_transient_retry_max);
+	} else {
+	    rb_htm_transient_retry_max = 3;
+	}
+
+	gvl_retry_max = getenv("RUBY_HTM_GVL_RETRY_MAX");
+	if (! gvl_retry_max)
+	    gvl_retry_max = getenv("RH_GRETRY");
+	if (gvl_retry_max) {
+	    rb_htm_gvl_retry_max = atoi(gvl_retry_max);
+	    fprintf(stderr, "<RUBY_VM: RUBY_HTM_GVL_RETRY_MAX set to %d>\n", rb_htm_gvl_retry_max);
+	} else {
+	    rb_htm_gvl_retry_max = 16;
+	}
+    }
+#endif /* HTM_GVL */
+#if defined(USE_SIMPLE_GVL_2)
+    {
+	char *gvl_spin_max;
+	gvl_spin_max = getenv("RUBY_GVL_SPIN_MAX");
+	if (! gvl_spin_max)
+	    gvl_spin_max = getenv("RB_GSPIN");
+	if (gvl_spin_max) {
+	    rb_gvl_spin_max = atoi(gvl_spin_max);
+	    fprintf(stderr, "<RUBY_VM: RUBY_GVL_SPIN_MAX set to %d>\n", rb_gvl_spin_max);
+	} else {
+	    rb_gvl_spin_max = 100000000;
+	}
+    }
+#endif
 }
 
 /* top self */
@@ -2285,6 +2604,14 @@
     return &vm->debug;
 }
 
+#if RUBY_VM_THREAD_MODEL == 3
+int *
+ruby_vm_use_gvl_ptr(rb_vm_t *vm)
+{
+    return &vm->use_gvl;
+}
+#endif
+
 VALUE *
 rb_ruby_verbose_ptr(void)
 {
@@ -2296,3 +2623,14 @@
 {
     return ruby_vm_debug_ptr(GET_VM());
 }
+
+int *
+rb_ruby_use_gvl_ptr(void)
+{
+#if RUBY_VM_THREAD_MODEL == 3
+    return ruby_vm_use_gvl_ptr(GET_VM());
+#else
+    assert(0);
+    return NULL;
+#endif
+}
diff -Naur ruby-1.9.3-p547.original/vm_core.h ruby-1.9.3-p547.htm/vm_core.h
--- ruby-1.9.3-p547.original/vm_core.h	2013-01-11 17:13:17.000000000 +0900
+++ ruby-1.9.3-p547.htm/vm_core.h	2014-09-12 06:37:35.905002000 +0900
@@ -6,13 +6,20 @@
   created at: 04/01/01 19:41:38 JST
 
   Copyright (C) 2004-2007 Koichi Sasada
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
 #ifndef RUBY_VM_CORE_H
 #define RUBY_VM_CORE_H
 
+#ifdef HTM_GVL
+#if ! defined(RUBY_VM_THREAD_MODEL)
+#define RUBY_VM_THREAD_MODEL 3
+#endif
+#else
 #define RUBY_VM_THREAD_MODEL 2
+#endif
 
 #include "ruby/ruby.h"
 #include "ruby/st.h"
@@ -23,6 +30,33 @@
 #include "id.h"
 #include "method.h"
 #include "ruby_atomic.h"
+#ifdef HTM_GVL
+#include "htm_util.h"
+#endif
+
+#ifdef HTM_GVL
+#define HTM_WAIT_AND_SEE_PERIOD 300
+
+#define HTM_GVL_SUMMARY_STATS
+
+/*#define HTM_GVL_CYCLE_STATS*/
+
+#define USE_SIMPLE_GVL_2
+
+/* Enabled only for HTM */
+#define USE_TABLE_FOR_IC_IVAR
+#define ADAPTIVE_INLINE_METHOD_CACHE  /* This is not adaptive in fact, for now. */
+#define ADAPTIVE_GLOBAL_METHOD_CACHE  /* This is not adaptive in fact, for now. */
+
+#define USE_THREAD_LOCAL_HEAP
+
+#define ALIGN_RB_THREAD_T
+
+#endif /* HTM_GVL */
+
+#if defined(USE_SIMPLE_GVL_2)
+extern int rb_gvl_spin_max;
+#endif
 
 #if   defined(_WIN32)
 #include "thread_win32.h"
@@ -127,7 +161,14 @@
 
 struct iseq_inline_cache_entry {
     VALUE ic_vmstat;
+#ifdef USE_TABLE_FOR_IC_IVAR
+    union {
+	struct st_table *ic_tbl;
+	VALUE ic_class;
+    } ic_guard;
+#else
     VALUE ic_class;
+#endif
     union {
 	VALUE value;
 	rb_method_entry_t *method;
@@ -170,6 +211,9 @@
     VALUE filepath;      /* real file path or nil */
     VALUE *iseq;         /* iseq (insn number and operands) */
     VALUE *iseq_encoded; /* encoded iseq */
+#ifdef HTM_GVL
+    int64_t *htm_counters;
+#endif
     unsigned long iseq_size;
     VALUE mark_ary;	/* Array: includes operands which should be GC marked */
     VALUE coverage;     /* coverage array */
@@ -274,12 +318,69 @@
 void rb_objspace_free(struct rb_objspace *);
 #endif
 
+#ifdef HTM_GVL
+typedef struct rb_htm_stats_struct {
+    unsigned long long tx;
+    unsigned long long tx_enter;
+    unsigned long long abort;
+    unsigned long long first_abort;
+    unsigned long long gvl_wait_before_tx_spin;
+    unsigned long long gvl_wait_before_tx_sleep;
+    unsigned long long gvl_wait_and_retry_spin;
+    unsigned long long gvl_wait_and_retry_sleep;
+    unsigned long long gvl_acquired;
+    unsigned long long persistent_abort_retry;
+    unsigned long long gvl_persistent_abort;
+    unsigned long long transient_abort_retry;
+    unsigned long long gvl_transient_abort;
+#if defined(__370__)
+    unsigned long long abort_reason_code[19][3];
+#elif defined(__x86_64__)
+#define HTM_IA32_STAT(nam) unsigned long long nam;
+    struct {
+#include "htm_ia32_stat.h"
+    } abort_reason_counters;
+#undef HTM_IA32_STAT
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+#define HTM_PPC_STAT(NAM) unsigned long long NAM;
+    struct {
+#include "htm_ppc_stat.h"
+    } abort_reason_counters;
+#undef HTM_PPC_STAT
+#else
+#error
+#endif
+} rb_htm_stats_t;
+
+typedef struct rb_htm_cycle_stats_struct {
+    unsigned long long tx;
+    unsigned long long abort;
+    unsigned long long gvl_wait_spin;
+    unsigned long long gvl_wait_sleep;
+    unsigned long long gvl;
+    unsigned long long between_tx;
+    unsigned long long mutex_sleep;
+    unsigned long long native_sleep;
+} rb_htm_cycle_stats_t;
+
+extern int rb_htm_schedule_interval;
+extern uint64_t rb_htm_count_reason_code;
+extern int use_non_tx_store;
+extern uint32_t rb_htm_tx_size_recalc_threshold;
+extern int rb_htm_persistent_retry_max;
+extern int rb_htm_transient_retry_max;
+extern int rb_htm_gvl_retry_max;
+#endif /* HTM_GVL */
+
 typedef struct rb_vm_struct {
     VALUE self;
 
     rb_global_vm_lock_t gvl;
 
     struct rb_thread_struct *main_thread;
+#if defined(ALIGN_RB_THREAD_T)
+    void *main_thread_before_aligned;
+#endif
     struct rb_thread_struct *running_thread;
 
     st_table *living_threads;
@@ -327,6 +428,15 @@
      * objects so do *NOT* mark this when you GC.
      */
     struct RArray at_exit;
+#if RUBY_VM_THREAD_MODEL == 3
+    int use_gvl;
+#endif
+#if defined(HTM_GVL) && defined(HTM_GVL_SUMMARY_STATS)
+    rb_htm_stats_t htm_stats;
+#endif
+#if defined(HTM_GVL) && defined(HTM_GVL_CYCLE_STATS)
+    rb_htm_cycle_stats_t cycle_stats;
+#endif
 } rb_vm_t;
 
 typedef struct {
@@ -353,8 +463,29 @@
 
 extern const rb_data_type_t ruby_threadptr_data_type;
 
+#if defined(ALIGN_RB_THREAD_T)
+#if defined(__370__)
+#define GetThreadPtr(obj, ptr) do {					\
+	TypedData_Get_Struct((obj), rb_thread_t, &ruby_threadptr_data_type, (ptr)); \
+	(ptr) = (rb_thread_t *)(((uintptr_t)(ptr) + 255) & ~255);	\
+    } while (0)
+#elif defined(__x86_64__) || defined(__CYGWIN__)
+#define GetThreadPtr(obj, ptr) do {					\
+	TypedData_Get_Struct((obj), rb_thread_t, &ruby_threadptr_data_type, (ptr)); \
+	(ptr) = (rb_thread_t *)(((uintptr_t)(ptr) + 63) & ~63);	\
+    } while (0)
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+#define GetThreadPtr(obj, ptr) do {					\
+	TypedData_Get_Struct((obj), rb_thread_t, &ruby_threadptr_data_type, (ptr)); \
+	(ptr) = (rb_thread_t *)(((uintptr_t)(ptr) + 127) & ~127);	\
+    } while (0)
+#else
+#error
+#endif
+#else
 #define GetThreadPtr(obj, ptr) \
     TypedData_Get_Struct((obj), rb_thread_t, &ruby_threadptr_data_type, (ptr))
+#endif
 
 enum rb_thread_status {
     THREAD_TO_KILL,
@@ -393,6 +524,12 @@
 typedef struct rb_thread_struct {
     VALUE self;
     rb_vm_t *vm;
+#ifdef HTM_GVL
+    int htm_schedule_counter;
+#endif
+#ifdef USE_THREAD_LOCAL_HEAP
+    void *tlh_free_list;
+#endif
 
     /* execution information */
     VALUE *stack;		/* must free, must mark */
@@ -491,6 +628,20 @@
     void *altstack;
 #endif
     unsigned long running_time_us;
+#ifdef HTM_GVL
+    volatile int gc_safe_point_reached;
+    TransactionDiagnosticInfo diag;
+#ifdef HTM_GVL_SUMMARY_STATS
+    rb_htm_stats_t htm_stats;
+#endif
+#ifdef HTM_GVL_CYCLE_STATS
+    const char *saved_file;
+    int saved_line;
+    uint64_t saved_cycle;
+    unsigned long long *cycle_charging_target;
+    rb_htm_cycle_stats_t cycle_stats;
+#endif
+#endif
 } rb_thread_t;
 
 /* iseq.c */
@@ -697,6 +848,24 @@
     (th)->vm->running_thread = (th); \
 } while (0)
 
+#elif RUBY_VM_THREAD_MODEL == 3
+RUBY_EXTERN rb_thread_t *ruby_current_thread;
+extern rb_vm_t *ruby_current_vm;
+extern rb_thread_t *ruby_thread_from_native(void);
+
+#define GET_VM() ruby_current_vm
+#define GET_THREAD() ruby_thread_from_native()
+#define rb_thread_set_current_raw(th) (void)(ruby_current_thread = (th))
+#define rb_thread_set_current(th) do {				\
+    if ((th)->vm->use_gvl) {					\
+	if ((th)->vm->running_thread != (th)) {			\
+	    (th)->vm->running_thread->running_time_us = 0;	\
+	}							\
+	rb_thread_set_current_raw(th);				\
+	(th)->vm->running_thread = (th);			\
+    }								\
+} while (0)
+
 #else
 #error "unsupported thread model"
 #endif
@@ -718,6 +887,103 @@
 void rb_thread_lock_unlock(rb_thread_lock_t *);
 void rb_thread_lock_destroy(rb_thread_lock_t *);
 
+#if defined(HTM_GVL) && defined(HTM_GVL_CYCLE_STATS)
+#if 0
+#define HTM_GVL_DEBUG_CYCLES_1(trgt)						\
+	if (cycle - th->saved_cycle > 0x1000 * 1000)			\
+	    fprintf(stderr, "charge %llu " #trgt " %s %d\n", (cycle - th->saved_cycle) >> 12, __FILE__, __LINE__);
+#else
+#define HTM_GVL_DEBUG_CYCLES_1(trgt)
+#endif
+#if 0
+#define HTM_GVL_DEBUG_CYCLES_2()       \
+    th->saved_file = __FILE__; \
+    th->saved_line = __LINE__;
+#else
+#define HTM_GVL_DEBUG_CYCLES_2()
+#endif
+
+#define HTM_GVL_START_CYCLES()						\
+    do {								\
+	uint64_t cycle;							\
+	store_clock(&cycle);						\
+	th->saved_cycle = cycle;					\
+	th->cycle_charging_target = NULL;				\
+	HTM_GVL_DEBUG_CYCLES_2();					\
+    } while (0)
+#define HTM_GVL_CHARGE_CYCLES_TO_SAVED_TARGET()				\
+    do {								\
+	uint64_t cycle;							\
+	store_clock(&cycle);						\
+	if (th->cycle_charging_target != NULL)				\
+	    *th->cycle_charging_target += cycle - th->saved_cycle;	\
+	HTM_GVL_DEBUG_CYCLES_1(saved);					\
+	th->saved_cycle = cycle;					\
+	th->cycle_charging_target = NULL;				\
+	HTM_GVL_DEBUG_CYCLES_2();					\
+    } while (0)
+#define HTM_GVL_CHARGE_CYCLES_TO(trgt)					\
+    do {								\
+	uint64_t cycle;							\
+	store_clock(&cycle);						\
+	if (th->saved_cycle != 0)					\
+	    th->cycle_stats.trgt += cycle - th->saved_cycle;		\
+	HTM_GVL_DEBUG_CYCLES_1(trgt);					\
+	th->saved_cycle = cycle;					\
+	th->cycle_charging_target = NULL;				\
+	HTM_GVL_DEBUG_CYCLES_2();					\
+    } while (0)
+#define HTM_GVL_CHARGE_CYCLES_TO_AND_START(trgt1, trgt2)		\
+    do {								\
+	uint64_t cycle;							\
+	store_clock(&cycle);						\
+	if (th->saved_cycle != 0)					\
+	    th->cycle_stats.trgt1 += cycle - th->saved_cycle;		\
+	HTM_GVL_DEBUG_CYCLES_1(trgt1);					\
+	th->saved_cycle = cycle;					\
+	th->cycle_charging_target = &th->cycle_stats.trgt2;		\
+	HTM_GVL_DEBUG_CYCLES_2();					\
+    } while (0)
+#define HTM_GVL_CHANGE_CYCLE_CHARGING_TO(trgt)				\
+    do {								\
+	th->cycle_charging_target = &th->cycle_stats.trgt;		\
+    } while (0)
+#else /* HTM_GVL && HTM_GVL_CYCLE_STATS */
+#define HTM_GVL_START_CYCLES()
+#define HTM_GVL_CHARGE_CYCLES_TO_SAVED_TARGET()
+#define HTM_GVL_CHARGE_CYCLES_TO(trgt)
+#define HTM_GVL_CHARGE_CYCLES_TO_AND_START(trgt1, trgt2)
+#define HTM_GVL_CHANGE_CYCLE_CHARGING_TO(trgt)
+#endif /* HTM_GVL && HTM_GVL_CYCLE_STATS */
+
+#ifdef HTM_GVL
+#define RUBY_VM_CHECK_INTS_EXEC_CORE(cntaddr) do {		\
+    if (UNLIKELY((self_th)->interrupt_flag)) {			\
+	rb_threadptr_execute_interrupts(self_th);		\
+    }								\
+    if (! use_gvl) {						\
+	thread_alone = rb_thread_alone_fast(self_th);		\
+	RUBY_VM_HTM_CHECK_SCHED(cntaddr);			\
+    }								\
+} while (0)
+
+#define RUBY_VM_HTM_CHECK_SCHED(cntaddr) do {				\
+    if (! use_gvl && ! thread_alone) {					\
+	local_schedule_counter = --self_th->htm_schedule_counter;	\
+	if (local_schedule_counter <= 0) {				\
+	    if (self_th->vm->gvl.acquired) {				\
+		gvl_release(self_th->vm, self_th);			\
+	    } else {							\
+		tend();							\
+		HTM_GVL_CHARGE_CYCLES_TO_AND_START(tx, between_tx);	\
+	    }								\
+	    htm_gvl_acquire_multi_threads(self_th, (cntaddr));		\
+	    rb_thread_set_current(th);					\
+	}								\
+    }									\
+} while (0)
+#endif
+
 #define RUBY_VM_CHECK_INTS_TH(th) do { \
     if (UNLIKELY((th)->interrupt_flag)) { \
 	rb_threadptr_execute_interrupts(th); \
diff -Naur ruby-1.9.3-p547.original/vm_exec.c ruby-1.9.3-p547.htm/vm_exec.c
--- ruby-1.9.3-p547.original/vm_exec.c	2011-05-31 11:08:58.000000000 +0900
+++ ruby-1.9.3-p547.htm/vm_exec.c	2014-09-12 06:37:35.905002000 +0900
@@ -6,6 +6,7 @@
   $Author: naruse $
 
   Copyright (C) 2004-2007 Koichi Sasada
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
@@ -34,7 +35,11 @@
 #endif
 
 #if !OPT_CALL_THREADED_CODE
+#ifdef HTM_GVL
+VALUE
+#else
 static VALUE
+#endif
 vm_exec_core(rb_thread_t *th, VALUE initial)
 {
 
@@ -63,6 +68,12 @@
     register rb_control_frame_t *reg_cfp;
     VALUE *reg_pc;
 #endif
+#ifdef HTM_GVL
+    rb_thread_t *self_th = th ? th : GET_THREAD();
+    int thread_alone = rb_thread_alone_fast(self_th);
+    int use_gvl = self_th->vm->use_gvl;
+    int64_t local_schedule_counter;
+#endif
 
 #if USE_MACHINE_REGS
 
diff -Naur ruby-1.9.3-p547.original/vm.inc ruby-1.9.3-p547.htm/vm.inc
--- ruby-1.9.3-p547.original/vm.inc	2014-05-16 23:38:33.000000000 +0900
+++ ruby-1.9.3-p547.htm/vm.inc	2014-09-12 06:37:35.905002000 +0900
@@ -25,7 +25,7 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(nop));
 {
-#line 40 "insns.def"
+#line 41 "insns.def"
     /* none */
 
 #line 32 "vm.inc"
@@ -40,6 +40,9 @@
   lindex_t idx = (lindex_t)GET_OPERAND(1);
 
   DEBUG_ENTER_INSN("getlocal");
+#if defined(HTM_GVL)
+  RUBY_VM_HTM_CHECK_SCHED(&GET_OPERAND(0));
+#endif
   ADD_PC(1+1);
   PREFETCH(GET_PC());
   #define CURRENT_INSN_getlocal 1
@@ -49,10 +52,10 @@
   USAGE_ANALYSIS_INSN(BIN(getlocal));
   USAGE_ANALYSIS_OPERAND(BIN(getlocal), 0, idx);
 {
-#line 58 "insns.def"
+#line 59 "insns.def"
     val = *(GET_LFP() - idx);
 
-#line 56 "vm.inc"
+#line 59 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_getlocal
@@ -75,10 +78,10 @@
   USAGE_ANALYSIS_INSN(BIN(setlocal));
   USAGE_ANALYSIS_OPERAND(BIN(setlocal), 0, idx);
 {
-#line 72 "insns.def"
+#line 73 "insns.def"
     (*(GET_LFP() - idx)) = val;
 
-#line 82 "vm.inc"
+#line 85 "vm.inc"
 #undef CURRENT_INSN_setlocal
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -101,10 +104,10 @@
   USAGE_ANALYSIS_OPERAND(BIN(getspecial), 0, key);
   USAGE_ANALYSIS_OPERAND(BIN(getspecial), 1, type);
 {
-#line 86 "insns.def"
+#line 87 "insns.def"
     val = vm_getspecial(th, GET_LFP(), key, type);
 
-#line 108 "vm.inc"
+#line 111 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_getspecial
@@ -127,10 +130,10 @@
   USAGE_ANALYSIS_INSN(BIN(setspecial));
   USAGE_ANALYSIS_OPERAND(BIN(setspecial), 0, key);
 {
-#line 100 "insns.def"
+#line 101 "insns.def"
     lfp_svar_set(th, GET_LFP(), key, obj);
 
-#line 134 "vm.inc"
+#line 137 "vm.inc"
 #undef CURRENT_INSN_setspecial
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -153,7 +156,7 @@
   USAGE_ANALYSIS_OPERAND(BIN(getdynamic), 0, idx);
   USAGE_ANALYSIS_OPERAND(BIN(getdynamic), 1, level);
 {
-#line 116 "insns.def"
+#line 117 "insns.def"
     rb_num_t i;
     VALUE *dfp2 = GET_DFP();
     for (i = 0; i < level; i++) {
@@ -161,7 +164,7 @@
     }
     val = *(dfp2 - idx);
 
-#line 165 "vm.inc"
+#line 168 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_getdynamic
@@ -186,7 +189,7 @@
   USAGE_ANALYSIS_OPERAND(BIN(setdynamic), 0, idx);
   USAGE_ANALYSIS_OPERAND(BIN(setdynamic), 1, level);
 {
-#line 137 "insns.def"
+#line 138 "insns.def"
     rb_num_t i;
     VALUE *dfp2 = GET_DFP();
     for (i = 0; i < level; i++) {
@@ -194,7 +197,7 @@
     }
     *(dfp2 - idx) = val;
 
-#line 198 "vm.inc"
+#line 201 "vm.inc"
 #undef CURRENT_INSN_setdynamic
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -207,6 +210,9 @@
   ID id = (ID)GET_OPERAND(1);
 
   DEBUG_ENTER_INSN("getinstancevariable");
+#if defined(HTM_GVL)
+  RUBY_VM_HTM_CHECK_SCHED(&GET_OPERAND(0));
+#endif
   ADD_PC(1+2);
   PREFETCH(GET_PC());
   #define CURRENT_INSN_getinstancevariable 1
@@ -217,10 +223,10 @@
   USAGE_ANALYSIS_OPERAND(BIN(getinstancevariable), 0, id);
   USAGE_ANALYSIS_OPERAND(BIN(getinstancevariable), 1, ic);
 {
-#line 157 "insns.def"
+#line 158 "insns.def"
     val = vm_getivar(GET_SELF(), id, ic);
 
-#line 224 "vm.inc"
+#line 230 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_getinstancevariable
@@ -245,10 +251,10 @@
   USAGE_ANALYSIS_OPERAND(BIN(setinstancevariable), 0, id);
   USAGE_ANALYSIS_OPERAND(BIN(setinstancevariable), 1, ic);
 {
-#line 172 "insns.def"
+#line 173 "insns.def"
     vm_setivar(GET_SELF(), id, val, ic);
 
-#line 252 "vm.inc"
+#line 258 "vm.inc"
 #undef CURRENT_INSN_setinstancevariable
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -260,6 +266,9 @@
   ID id = (ID)GET_OPERAND(1);
 
   DEBUG_ENTER_INSN("getclassvariable");
+#if defined(HTM_GVL)
+  RUBY_VM_HTM_CHECK_SCHED(&GET_OPERAND(0));
+#endif
   ADD_PC(1+1);
   PREFETCH(GET_PC());
   #define CURRENT_INSN_getclassvariable 1
@@ -269,11 +278,11 @@
   USAGE_ANALYSIS_INSN(BIN(getclassvariable));
   USAGE_ANALYSIS_OPERAND(BIN(getclassvariable), 0, id);
 {
-#line 186 "insns.def"
+#line 187 "insns.def"
     NODE * const cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
     val = rb_cvar_get(vm_get_cvar_base(cref), id);
 
-#line 277 "vm.inc"
+#line 286 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_getclassvariable
@@ -296,11 +305,11 @@
   USAGE_ANALYSIS_INSN(BIN(setclassvariable));
   USAGE_ANALYSIS_OPERAND(BIN(setclassvariable), 0, id);
 {
-#line 201 "insns.def"
+#line 202 "insns.def"
     NODE * const cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
     rb_cvar_set(vm_get_cvar_base(cref), id, val);
 
-#line 304 "vm.inc"
+#line 313 "vm.inc"
 #undef CURRENT_INSN_setclassvariable
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -322,10 +331,10 @@
   USAGE_ANALYSIS_INSN(BIN(getconstant));
   USAGE_ANALYSIS_OPERAND(BIN(getconstant), 0, id);
 {
-#line 223 "insns.def"
+#line 224 "insns.def"
     val = vm_get_ev_const(th, GET_ISEQ(), klass, id, 0);
 
-#line 329 "vm.inc"
+#line 338 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_getconstant
@@ -349,12 +358,12 @@
   USAGE_ANALYSIS_INSN(BIN(setconstant));
   USAGE_ANALYSIS_OPERAND(BIN(setconstant), 0, id);
 {
-#line 245 "insns.def"
+#line 246 "insns.def"
     vm_check_if_namespace(cbase);
     rb_const_set(cbase, id, val);
     INC_VM_STATE_VERSION();
 
-#line 358 "vm.inc"
+#line 367 "vm.inc"
 #undef CURRENT_INSN_setconstant
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -375,10 +384,10 @@
   USAGE_ANALYSIS_INSN(BIN(getglobal));
   USAGE_ANALYSIS_OPERAND(BIN(getglobal), 0, entry);
 {
-#line 261 "insns.def"
+#line 262 "insns.def"
     val = GET_GLOBAL((VALUE)entry);
 
-#line 382 "vm.inc"
+#line 391 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_getglobal
@@ -401,10 +410,10 @@
   USAGE_ANALYSIS_INSN(BIN(setglobal));
   USAGE_ANALYSIS_OPERAND(BIN(setglobal), 0, entry);
 {
-#line 275 "insns.def"
+#line 276 "insns.def"
     SET_GLOBAL((VALUE)entry, val);
 
-#line 408 "vm.inc"
+#line 417 "vm.inc"
 #undef CURRENT_INSN_setglobal
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -424,10 +433,10 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(putnil));
 {
-#line 294 "insns.def"
+#line 295 "insns.def"
     val = Qnil;
 
-#line 431 "vm.inc"
+#line 440 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_putnil
@@ -449,10 +458,10 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(putself));
 {
-#line 308 "insns.def"
+#line 309 "insns.def"
     val = GET_SELF();
 
-#line 456 "vm.inc"
+#line 465 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_putself
@@ -474,10 +483,10 @@
   USAGE_ANALYSIS_INSN(BIN(putobject));
   USAGE_ANALYSIS_OPERAND(BIN(putobject), 0, val);
 {
-#line 324 "insns.def"
+#line 325 "insns.def"
     /* */
 
-#line 481 "vm.inc"
+#line 490 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_putobject
@@ -500,7 +509,7 @@
   USAGE_ANALYSIS_INSN(BIN(putspecialobject));
   USAGE_ANALYSIS_OPERAND(BIN(putspecialobject), 0, value_type);
 {
-#line 339 "insns.def"
+#line 340 "insns.def"
     enum vm_special_object_type type = (enum vm_special_object_type)value_type;
 
     switch (type) {
@@ -517,7 +526,7 @@
 	rb_bug("putspecialobject insn: unknown value_type");
     }
 
-#line 521 "vm.inc"
+#line 530 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_putspecialobject
@@ -540,10 +549,10 @@
   USAGE_ANALYSIS_INSN(BIN(putiseq));
   USAGE_ANALYSIS_OPERAND(BIN(putiseq), 0, iseq);
 {
-#line 367 "insns.def"
+#line 368 "insns.def"
     ret = iseq->self;
 
-#line 547 "vm.inc"
+#line 556 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(ret);
 #undef CURRENT_INSN_putiseq
@@ -566,10 +575,10 @@
   USAGE_ANALYSIS_INSN(BIN(putstring));
   USAGE_ANALYSIS_OPERAND(BIN(putstring), 0, str);
 {
-#line 381 "insns.def"
+#line 382 "insns.def"
     val = rb_str_resurrect(str);
 
-#line 573 "vm.inc"
+#line 582 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_putstring
@@ -592,7 +601,7 @@
   USAGE_ANALYSIS_INSN(BIN(concatstrings));
   USAGE_ANALYSIS_OPERAND(BIN(concatstrings), 0, num);
 {
-#line 395 "insns.def"
+#line 396 "insns.def"
     rb_num_t i = num - 1;
 
     val = rb_str_resurrect(TOPN(i));
@@ -602,7 +611,7 @@
     }
     POPN(num);
 
-#line 606 "vm.inc"
+#line 615 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_concatstrings
@@ -624,10 +633,10 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(tostring));
 {
-#line 416 "insns.def"
+#line 417 "insns.def"
     val = rb_obj_as_string(val);
 
-#line 631 "vm.inc"
+#line 640 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_tostring
@@ -652,7 +661,7 @@
   USAGE_ANALYSIS_OPERAND(BIN(toregexp), 0, opt);
   USAGE_ANALYSIS_OPERAND(BIN(toregexp), 1, cnt);
 {
-#line 431 "insns.def"
+#line 432 "insns.def"
     VALUE rb_reg_new_ary(VALUE ary, int options);
     rb_num_t i;
     const VALUE ary = rb_ary_tmp_new(cnt);
@@ -663,7 +672,7 @@
     val = rb_reg_new_ary(ary, (int)opt);
     rb_ary_clear(ary);
 
-#line 667 "vm.inc"
+#line 676 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_toregexp
@@ -686,11 +695,11 @@
   USAGE_ANALYSIS_INSN(BIN(newarray));
   USAGE_ANALYSIS_OPERAND(BIN(newarray), 0, num);
 {
-#line 453 "insns.def"
+#line 454 "insns.def"
     val = rb_ary_new4((long)num, STACK_ADDR_FROM_TOP(num));
     POPN(num);
 
-#line 694 "vm.inc"
+#line 703 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_newarray
@@ -713,10 +722,10 @@
   USAGE_ANALYSIS_INSN(BIN(duparray));
   USAGE_ANALYSIS_OPERAND(BIN(duparray), 0, ary);
 {
-#line 468 "insns.def"
+#line 469 "insns.def"
     val = rb_ary_resurrect(ary);
 
-#line 720 "vm.inc"
+#line 729 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_duparray
@@ -741,10 +750,10 @@
   USAGE_ANALYSIS_OPERAND(BIN(expandarray), 0, num);
   USAGE_ANALYSIS_OPERAND(BIN(expandarray), 1, flag);
 {
-#line 489 "insns.def"
+#line 490 "insns.def"
     vm_expandarray(GET_CFP(), ary, num, (int)flag);
 
-#line 748 "vm.inc"
+#line 757 "vm.inc"
 #undef CURRENT_INSN_expandarray
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -766,7 +775,7 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(concatarray));
 {
-#line 503 "insns.def"
+#line 504 "insns.def"
     const VALUE ary2 = ary2st;
     VALUE tmp1 = rb_check_convert_type(ary1, T_ARRAY, "Array", "to_a");
     VALUE tmp2 = rb_check_convert_type(ary2, T_ARRAY, "Array", "to_a");
@@ -784,7 +793,7 @@
     }
     ary = rb_ary_concat(tmp1, tmp2);
 
-#line 788 "vm.inc"
+#line 797 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(ary);
 #undef CURRENT_INSN_concatarray
@@ -808,7 +817,7 @@
   USAGE_ANALYSIS_INSN(BIN(splatarray));
   USAGE_ANALYSIS_OPERAND(BIN(splatarray), 0, flag);
 {
-#line 532 "insns.def"
+#line 533 "insns.def"
     VALUE tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a");
     if (NIL_P(tmp)) {
 	tmp = rb_ary_new3(1, ary);
@@ -818,7 +827,7 @@
     }
     obj = tmp;
 
-#line 822 "vm.inc"
+#line 831 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(obj);
 #undef CURRENT_INSN_splatarray
@@ -843,7 +852,7 @@
   USAGE_ANALYSIS_INSN(BIN(checkincludearray));
   USAGE_ANALYSIS_OPERAND(BIN(checkincludearray), 0, flag);
 {
-#line 553 "insns.def"
+#line 554 "insns.def"
     int i;
     result = Qfalse;
 
@@ -872,7 +881,7 @@
 	}
     }
 
-#line 876 "vm.inc"
+#line 885 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 2);
   PUSH(obj);
   PUSH(result);
@@ -896,7 +905,7 @@
   USAGE_ANALYSIS_INSN(BIN(newhash));
   USAGE_ANALYSIS_OPERAND(BIN(newhash), 0, num);
 {
-#line 594 "insns.def"
+#line 595 "insns.def"
     rb_num_t i;
     val = rb_hash_new();
 
@@ -907,7 +916,7 @@
     }
     POPN(num);
 
-#line 911 "vm.inc"
+#line 920 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_newhash
@@ -932,10 +941,10 @@
   USAGE_ANALYSIS_INSN(BIN(newrange));
   USAGE_ANALYSIS_OPERAND(BIN(newrange), 0, flag);
 {
-#line 616 "insns.def"
+#line 617 "insns.def"
     val = rb_range_new(low, high, (int)flag);
 
-#line 939 "vm.inc"
+#line 948 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_newrange
@@ -957,11 +966,11 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(pop));
 {
-#line 634 "insns.def"
+#line 635 "insns.def"
     (void)val;
     /* none */
 
-#line 965 "vm.inc"
+#line 974 "vm.inc"
 #undef CURRENT_INSN_pop
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -983,10 +992,10 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(dup));
 {
-#line 649 "insns.def"
+#line 650 "insns.def"
     val1 = val2 = val;
 
-#line 990 "vm.inc"
+#line 999 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 2);
   PUSH(val1);
   PUSH(val2);
@@ -1009,7 +1018,7 @@
   USAGE_ANALYSIS_INSN(BIN(dupn));
   USAGE_ANALYSIS_OPERAND(BIN(dupn), 0, n);
 {
-#line 663 "insns.def"
+#line 664 "insns.def"
     rb_num_t i;
     VALUE *sp = STACK_ADDR_FROM_TOP(n);
     for (i = 0; i < n; i++) {
@@ -1017,7 +1026,7 @@
     }
     INC_SP(n);
 
-#line 1021 "vm.inc"
+#line 1030 "vm.inc"
 #undef CURRENT_INSN_dupn
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -1038,10 +1047,10 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(swap));
 {
-#line 683 "insns.def"
+#line 684 "insns.def"
     /* none */
 
-#line 1045 "vm.inc"
+#line 1054 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 2);
   PUSH(obj);
   PUSH(val);
@@ -1064,10 +1073,10 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(reput));
 {
-#line 697 "insns.def"
+#line 698 "insns.def"
     /* none */
 
-#line 1071 "vm.inc"
+#line 1080 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_reput
@@ -1090,10 +1099,10 @@
   USAGE_ANALYSIS_INSN(BIN(topn));
   USAGE_ANALYSIS_OPERAND(BIN(topn), 0, n);
 {
-#line 711 "insns.def"
+#line 712 "insns.def"
     val = TOPN(n);
 
-#line 1097 "vm.inc"
+#line 1106 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_topn
@@ -1116,10 +1125,10 @@
   USAGE_ANALYSIS_INSN(BIN(setn));
   USAGE_ANALYSIS_OPERAND(BIN(setn), 0, n);
 {
-#line 725 "insns.def"
+#line 726 "insns.def"
     TOPN(n-1) = val;
 
-#line 1123 "vm.inc"
+#line 1132 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_setn
@@ -1141,10 +1150,10 @@
   USAGE_ANALYSIS_INSN(BIN(adjuststack));
   USAGE_ANALYSIS_OPERAND(BIN(adjuststack), 0, n);
 {
-#line 739 "insns.def"
+#line 740 "insns.def"
     DEC_SP(n);
 
-#line 1148 "vm.inc"
+#line 1157 "vm.inc"
 #undef CURRENT_INSN_adjuststack
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -1170,7 +1179,7 @@
   USAGE_ANALYSIS_OPERAND(BIN(defined), 1, obj);
   USAGE_ANALYSIS_OPERAND(BIN(defined), 2, needstr);
 {
-#line 758 "insns.def"
+#line 759 "insns.def"
     VALUE klass;
     const char *expr_type = 0;
     enum defined_type type = (enum defined_type)op_type;
@@ -1277,7 +1286,7 @@
 	}
     }
 
-#line 1281 "vm.inc"
+#line 1290 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_defined
@@ -1299,12 +1308,12 @@
   USAGE_ANALYSIS_INSN(BIN(trace));
   USAGE_ANALYSIS_OPERAND(BIN(trace), 0, nf);
 {
-#line 876 "insns.def"
+#line 877 "insns.def"
     rb_event_flag_t flag = (rb_event_flag_t)nf;
 
     EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* TODO: id, klass */);
 
-#line 1308 "vm.inc"
+#line 1317 "vm.inc"
 #undef CURRENT_INSN_trace
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -1331,7 +1340,7 @@
   USAGE_ANALYSIS_OPERAND(BIN(defineclass), 1, class_iseq);
   USAGE_ANALYSIS_OPERAND(BIN(defineclass), 2, define_type);
 {
-#line 900 "insns.def"
+#line 901 "insns.def"
     VALUE klass;
 
     switch ((int)define_type) {
@@ -1415,7 +1424,7 @@
     INC_VM_STATE_VERSION();
     NEXT_INSN();
 
-#line 1419 "vm.inc"
+#line 1428 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_defineclass
@@ -1433,6 +1442,9 @@
   ID op_id = (ID)GET_OPERAND(1);
 
   DEBUG_ENTER_INSN("send");
+#if defined(HTM_GVL)
+  RUBY_VM_HTM_CHECK_SCHED(&GET_OPERAND(0));
+#endif
   ADD_PC(1+5);
   PREFETCH(GET_PC());
   #define CURRENT_INSN_send 1
@@ -1446,7 +1458,7 @@
   USAGE_ANALYSIS_OPERAND(BIN(send), 3, op_flag);
   USAGE_ANALYSIS_OPERAND(BIN(send), 4, ic);
 {
-#line 1006 "insns.def"
+#line 1007 "insns.def"
     const rb_method_entry_t *me;
     VALUE recv, klass;
     rb_block_t *blockptr = 0;
@@ -1461,7 +1473,7 @@
     me = vm_method_search(id, klass, ic);
     CALL_METHOD(num, blockptr, flag, id, me, recv);
 
-#line 1465 "vm.inc"
+#line 1477 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_send
@@ -1488,7 +1500,7 @@
   USAGE_ANALYSIS_OPERAND(BIN(invokesuper), 1, blockiseq);
   USAGE_ANALYSIS_OPERAND(BIN(invokesuper), 2, op_flag);
 {
-#line 1034 "insns.def"
+#line 1035 "insns.def"
     rb_block_t *blockptr = !(op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? GET_BLOCK_PTR() : 0;
     VALUE flag = op_flag;
     int num = caller_setup_args(th, GET_CFP(), flag,
@@ -1511,7 +1523,7 @@
 
     CALL_METHOD(num, blockptr, flag, id, me, recv);
 
-#line 1515 "vm.inc"
+#line 1527 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_invokesuper
@@ -1536,14 +1548,14 @@
   USAGE_ANALYSIS_OPERAND(BIN(invokeblock), 0, num);
   USAGE_ANALYSIS_OPERAND(BIN(invokeblock), 1, flag);
 {
-#line 1069 "insns.def"
+#line 1070 "insns.def"
     val = vm_invoke_block(th, GET_CFP(), num, flag);
     if (val == Qundef) {
 	RESTORE_REGS();
 	NEXT_INSN();
     }
 
-#line 1547 "vm.inc"
+#line 1559 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_invokeblock
@@ -1565,7 +1577,7 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(leave));
 {
-#line 1087 "insns.def"
+#line 1088 "insns.def"
     if (OPT_CHECKED_RUN) {
 	if (reg_cfp->sp != reg_cfp->bp) {
 	    rb_bug("Stack consistency error (sp: %"PRIdPTRDIFF", bp: %"PRIdPTRDIFF")",
@@ -1573,11 +1585,15 @@
 	}
     }
 
+#ifdef HTM_GVL
+    RUBY_VM_CHECK_INTS_EXEC_CORE(&GET_OPERAND(-1));
+#else
     RUBY_VM_CHECK_INTS();
+#endif
     vm_pop_frame(th);
     RESTORE_REGS();
 
-#line 1581 "vm.inc"
+#line 1597 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_leave
@@ -1599,7 +1615,7 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(finish));
 {
-#line 1110 "insns.def"
+#line 1115 "insns.def"
 #if OPT_CALL_THREADED_CODE
     rb_bug("unused instruction on OPT_CALL_THREADED_CODE");
 #else
@@ -1607,7 +1623,7 @@
     return val;
 #endif
 
-#line 1611 "vm.inc"
+#line 1627 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_finish
@@ -1631,13 +1647,17 @@
   USAGE_ANALYSIS_INSN(BIN(throw));
   USAGE_ANALYSIS_OPERAND(BIN(throw), 0, throw_state);
 {
-#line 1133 "insns.def"
+#line 1138 "insns.def"
+#ifdef HTM_GVL
+    RUBY_VM_CHECK_INTS_EXEC_CORE(&GET_OPERAND(-2));
+#else
     RUBY_VM_CHECK_INTS();
+#endif
     val = vm_throw(th, GET_CFP(), throw_state, throwobj);
     THROW_EXCEPTION(val);
     /* unreachable */
 
-#line 1641 "vm.inc"
+#line 1661 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_throw
@@ -1659,11 +1679,15 @@
   USAGE_ANALYSIS_INSN(BIN(jump));
   USAGE_ANALYSIS_OPERAND(BIN(jump), 0, dst);
 {
-#line 1154 "insns.def"
+#line 1163 "insns.def"
+#ifdef HTM_GVL
+    RUBY_VM_CHECK_INTS_EXEC_CORE(&GET_OPERAND(-2));
+#else
     RUBY_VM_CHECK_INTS();
+#endif
     JUMP(dst);
 
-#line 1667 "vm.inc"
+#line 1691 "vm.inc"
 #undef CURRENT_INSN_jump
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -1684,13 +1708,17 @@
   USAGE_ANALYSIS_INSN(BIN(branchif));
   USAGE_ANALYSIS_OPERAND(BIN(branchif), 0, dst);
 {
-#line 1169 "insns.def"
+#line 1182 "insns.def"
     if (RTEST(val)) {
+#ifdef HTM_GVL
+        RUBY_VM_CHECK_INTS_EXEC_CORE(&GET_OPERAND(-2));
+#else
 	RUBY_VM_CHECK_INTS();
+#endif
 	JUMP(dst);
     }
 
-#line 1694 "vm.inc"
+#line 1722 "vm.inc"
 #undef CURRENT_INSN_branchif
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -1711,13 +1739,17 @@
   USAGE_ANALYSIS_INSN(BIN(branchunless));
   USAGE_ANALYSIS_OPERAND(BIN(branchunless), 0, dst);
 {
-#line 1186 "insns.def"
+#line 1203 "insns.def"
     if (!RTEST(val)) {
+#ifdef HTM_GVL
+        RUBY_VM_CHECK_INTS_EXEC_CORE(&GET_OPERAND(-2));
+#else
 	RUBY_VM_CHECK_INTS();
+#endif
 	JUMP(dst);
     }
 
-#line 1721 "vm.inc"
+#line 1753 "vm.inc"
 #undef CURRENT_INSN_branchunless
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -1740,7 +1772,7 @@
   USAGE_ANALYSIS_OPERAND(BIN(getinlinecache), 0, dst);
   USAGE_ANALYSIS_OPERAND(BIN(getinlinecache), 1, ic);
 {
-#line 1208 "insns.def"
+#line 1229 "insns.def"
     if (ic->ic_vmstat == GET_VM_STATE_VERSION()) {
 	val = ic->ic_value.value;
 	JUMP(dst);
@@ -1750,7 +1782,7 @@
 	val = Qnil;
     }
 
-#line 1754 "vm.inc"
+#line 1786 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_getinlinecache
@@ -1775,7 +1807,7 @@
   USAGE_ANALYSIS_OPERAND(BIN(onceinlinecache), 0, dst);
   USAGE_ANALYSIS_OPERAND(BIN(onceinlinecache), 1, ic);
 {
-#line 1229 "insns.def"
+#line 1250 "insns.def"
   retry:
     if (ic->ic_vmstat) {
 	val = ic->ic_value.value;
@@ -1783,7 +1815,11 @@
     }
     else if (ic->ic_value.value == Qundef)
     {
-    	RUBY_VM_CHECK_INTS();
+#ifdef HTM_GVL
+        RUBY_VM_CHECK_INTS_EXEC_CORE(&GET_OPERAND(-3));
+#else
+	RUBY_VM_CHECK_INTS();
+#endif
     	rb_thread_schedule();
 	goto retry;
     }
@@ -1793,7 +1829,7 @@
 	val = Qnil;
     }
 
-#line 1797 "vm.inc"
+#line 1833 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_onceinlinecache
@@ -1816,7 +1852,7 @@
   USAGE_ANALYSIS_INSN(BIN(setinlinecache));
   USAGE_ANALYSIS_OPERAND(BIN(setinlinecache), 0, ic);
 {
-#line 1258 "insns.def"
+#line 1283 "insns.def"
     if (ic->ic_value.value == Qundef) {
 	rb_ary_push(GET_ISEQ()->mark_ary, val);
     }
@@ -1824,7 +1860,7 @@
     ic->ic_vmstat = GET_VM_STATE_VERSION() - ruby_vm_const_missing_count;
     ruby_vm_const_missing_count = 0;
 
-#line 1828 "vm.inc"
+#line 1864 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_setinlinecache
@@ -1849,7 +1885,7 @@
   USAGE_ANALYSIS_OPERAND(BIN(opt_case_dispatch), 0, hash);
   USAGE_ANALYSIS_OPERAND(BIN(opt_case_dispatch), 1, else_offset);
 {
-#line 1277 "insns.def"
+#line 1302 "insns.def"
     switch(TYPE(key)) {
       case T_FLOAT: {
 	double ival;
@@ -1875,7 +1911,7 @@
 	break;
     }
 
-#line 1879 "vm.inc"
+#line 1915 "vm.inc"
 #undef CURRENT_INSN_opt_case_dispatch
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -1894,7 +1930,7 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(opt_checkenv));
 {
-#line 1314 "insns.def"
+#line 1339 "insns.def"
     if (GET_CFP()->bp != GET_DFP() + 1) {
 	VALUE *new_dfp = GET_CFP()->bp - 1;
 	/* TODO: copy env and clean stack at creating env? */
@@ -1902,7 +1938,7 @@
 	SET_DFP(new_dfp);
     }
 
-#line 1906 "vm.inc"
+#line 1942 "vm.inc"
 #undef CURRENT_INSN_opt_checkenv
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -1915,6 +1951,9 @@
   VALUE recv = TOPN(1);
   VALUE obj = TOPN(0);
   DEBUG_ENTER_INSN("opt_plus");
+#if defined(HTM_GVL)
+  RUBY_VM_HTM_CHECK_SCHED(&GET_OPERAND(0));
+#endif
   ADD_PC(1+1);
   PREFETCH(GET_PC());
   POPN(2);
@@ -1925,7 +1964,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_plus));
   USAGE_ANALYSIS_OPERAND(BIN(opt_plus), 0, ic);
 {
-#line 1336 "insns.def"
+#line 1361 "insns.def"
     if (0) {
 
     }
@@ -1990,7 +2029,7 @@
 	CALL_SIMPLE_METHOD(1, idPLUS, recv);
     }
 
-#line 1994 "vm.inc"
+#line 2033 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_plus
@@ -2005,6 +2044,9 @@
   VALUE recv = TOPN(1);
   VALUE obj = TOPN(0);
   DEBUG_ENTER_INSN("opt_minus");
+#if defined(HTM_GVL)
+  RUBY_VM_HTM_CHECK_SCHED(&GET_OPERAND(0));
+#endif
   ADD_PC(1+1);
   PREFETCH(GET_PC());
   POPN(2);
@@ -2015,7 +2057,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_minus));
   USAGE_ANALYSIS_OPERAND(BIN(opt_minus), 0, ic);
 {
-#line 1412 "insns.def"
+#line 1437 "insns.def"
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_MINUS)) {
 	long a, b, c;
@@ -2053,7 +2095,7 @@
 	CALL_SIMPLE_METHOD(1, idMINUS, recv);
     }
 
-#line 2057 "vm.inc"
+#line 2099 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_minus
@@ -2068,6 +2110,9 @@
   VALUE recv = TOPN(1);
   VALUE obj = TOPN(0);
   DEBUG_ENTER_INSN("opt_mult");
+#if defined(HTM_GVL)
+  RUBY_VM_HTM_CHECK_SCHED(&GET_OPERAND(0));
+#endif
   ADD_PC(1+1);
   PREFETCH(GET_PC());
   POPN(2);
@@ -2078,7 +2123,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_mult));
   USAGE_ANALYSIS_OPERAND(BIN(opt_mult), 0, ic);
 {
-#line 1461 "insns.def"
+#line 1486 "insns.def"
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_MULT)) {
 	long a, b;
@@ -2121,7 +2166,7 @@
 	CALL_SIMPLE_METHOD(1, idMULT, recv);
     }
 
-#line 2125 "vm.inc"
+#line 2170 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_mult
@@ -2146,7 +2191,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_div));
   USAGE_ANALYSIS_OPERAND(BIN(opt_div), 0, ic);
 {
-#line 1515 "insns.def"
+#line 1540 "insns.def"
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_DIV)) {
 	long x, y, div;
@@ -2199,7 +2244,7 @@
 	CALL_SIMPLE_METHOD(1, idDIV, recv);
     }
 
-#line 2203 "vm.inc"
+#line 2248 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_div
@@ -2224,7 +2269,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_mod));
   USAGE_ANALYSIS_OPERAND(BIN(opt_mod), 0, ic);
 {
-#line 1579 "insns.def"
+#line 1604 "insns.def"
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_MOD)) {
 	long x, y, mod;
@@ -2276,7 +2321,7 @@
 	CALL_SIMPLE_METHOD(1, idMOD, recv);
     }
 
-#line 2280 "vm.inc"
+#line 2325 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_mod
@@ -2301,7 +2346,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_eq));
   USAGE_ANALYSIS_OPERAND(BIN(opt_eq), 0, ic);
 {
-#line 1642 "insns.def"
+#line 1667 "insns.def"
     val = opt_eq_func(recv, obj, ic);
 
     if (val == Qundef) {
@@ -2311,7 +2356,7 @@
 	CALL_SIMPLE_METHOD(1, idEq, recv);
     }
 
-#line 2315 "vm.inc"
+#line 2360 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_eq
@@ -2338,7 +2383,7 @@
   USAGE_ANALYSIS_OPERAND(BIN(opt_neq), 0, ic);
   USAGE_ANALYSIS_OPERAND(BIN(opt_neq), 1, ic_eq);
 {
-#line 1663 "insns.def"
+#line 1688 "insns.def"
     extern VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2);
     const rb_method_entry_t *me = vm_method_search(idNeq, CLASS_OF(recv), ic);
     val = Qundef;
@@ -2358,7 +2403,7 @@
 	CALL_SIMPLE_METHOD(1, idNeq, recv);
     }
 
-#line 2362 "vm.inc"
+#line 2407 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_neq
@@ -2383,7 +2428,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_lt));
   USAGE_ANALYSIS_OPERAND(BIN(opt_lt), 0, ic);
 {
-#line 1694 "insns.def"
+#line 1719 "insns.def"
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_LT)) {
 	SIGNED_VALUE a = recv, b = obj;
@@ -2422,7 +2467,7 @@
 	CALL_SIMPLE_METHOD(1, idLT, recv);
     }
 
-#line 2426 "vm.inc"
+#line 2471 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_lt
@@ -2447,7 +2492,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_le));
   USAGE_ANALYSIS_OPERAND(BIN(opt_le), 0, ic);
 {
-#line 1744 "insns.def"
+#line 1769 "insns.def"
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_LE)) {
 	SIGNED_VALUE a = recv, b = obj;
@@ -2466,7 +2511,7 @@
 	CALL_SIMPLE_METHOD(1, idLE, recv);
     }
 
-#line 2470 "vm.inc"
+#line 2515 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_le
@@ -2491,7 +2536,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_gt));
   USAGE_ANALYSIS_OPERAND(BIN(opt_gt), 0, ic);
 {
-#line 1774 "insns.def"
+#line 1799 "insns.def"
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_GT)) {
 	SIGNED_VALUE a = recv, b = obj;
@@ -2530,7 +2575,7 @@
 	CALL_SIMPLE_METHOD(1, idGT, recv);
     }
 
-#line 2534 "vm.inc"
+#line 2579 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_gt
@@ -2555,7 +2600,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_ge));
   USAGE_ANALYSIS_OPERAND(BIN(opt_ge), 0, ic);
 {
-#line 1824 "insns.def"
+#line 1849 "insns.def"
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_GE)) {
 	SIGNED_VALUE a = recv, b = obj;
@@ -2573,7 +2618,7 @@
 	CALL_SIMPLE_METHOD(1, idGE, recv);
     }
 
-#line 2577 "vm.inc"
+#line 2622 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_ge
@@ -2598,7 +2643,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_ltlt));
   USAGE_ANALYSIS_OPERAND(BIN(opt_ltlt), 0, ic);
 {
-#line 1853 "insns.def"
+#line 1878 "insns.def"
     if (!SPECIAL_CONST_P(recv)) {
 	if (0) {
 	}
@@ -2621,7 +2666,7 @@
 	CALL_SIMPLE_METHOD(1, idLTLT, recv);
     }
 
-#line 2625 "vm.inc"
+#line 2670 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_ltlt
@@ -2636,6 +2681,9 @@
   VALUE recv = TOPN(1);
   VALUE obj = TOPN(0);
   DEBUG_ENTER_INSN("opt_aref");
+#if defined(HTM_GVL)
+  RUBY_VM_HTM_CHECK_SCHED(&GET_OPERAND(0));
+#endif
   ADD_PC(1+1);
   PREFETCH(GET_PC());
   POPN(2);
@@ -2646,7 +2694,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_aref));
   USAGE_ANALYSIS_OPERAND(BIN(opt_aref), 0, ic);
 {
-#line 1887 "insns.def"
+#line 1912 "insns.def"
     if (!SPECIAL_CONST_P(recv) && BASIC_OP_UNREDEFINED_P(BOP_AREF)) {
 	if (HEAP_CLASS_OF(recv) == rb_cArray && FIXNUM_P(obj)) {
 	    val = rb_ary_entry(recv, FIX2LONG(obj));
@@ -2665,7 +2713,7 @@
 	CALL_SIMPLE_METHOD(1, idAREF, recv);
     }
 
-#line 2669 "vm.inc"
+#line 2717 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_aref
@@ -2691,7 +2739,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_aset));
   USAGE_ANALYSIS_OPERAND(BIN(opt_aset), 0, ic);
 {
-#line 1917 "insns.def"
+#line 1942 "insns.def"
     if (!SPECIAL_CONST_P(recv) &&
 	BASIC_OP_UNREDEFINED_P(BOP_ASET)) {
 	if (HEAP_CLASS_OF(recv) == rb_cArray && FIXNUM_P(obj)) {
@@ -2714,7 +2762,7 @@
 	CALL_SIMPLE_METHOD(2, idASET, recv);
     }
 
-#line 2718 "vm.inc"
+#line 2766 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_aset
@@ -2738,7 +2786,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_length));
   USAGE_ANALYSIS_OPERAND(BIN(opt_length), 0, ic);
 {
-#line 1951 "insns.def"
+#line 1976 "insns.def"
     if (LIKELY(!SPECIAL_CONST_P(recv) &&
 	       BASIC_OP_UNREDEFINED_P(BOP_LENGTH))) {
 	if (HEAP_CLASS_OF(recv) == rb_cString) {
@@ -2760,7 +2808,7 @@
 	CALL_SIMPLE_METHOD(0, idLength, recv);
     }
 
-#line 2764 "vm.inc"
+#line 2812 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_length
@@ -2784,7 +2832,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_size));
   USAGE_ANALYSIS_OPERAND(BIN(opt_size), 0, ic);
 {
-#line 1984 "insns.def"
+#line 2009 "insns.def"
     if (LIKELY(BASIC_OP_UNREDEFINED_P(BOP_SIZE) &&
 	       !SPECIAL_CONST_P(recv))) {
 	if (HEAP_CLASS_OF(recv) == rb_cString) {
@@ -2806,7 +2854,7 @@
 	CALL_SIMPLE_METHOD(0, idSize, recv);
     }
 
-#line 2810 "vm.inc"
+#line 2858 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_size
@@ -2830,7 +2878,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_succ));
   USAGE_ANALYSIS_OPERAND(BIN(opt_succ), 0, ic);
 {
-#line 2017 "insns.def"
+#line 2042 "insns.def"
     if (SPECIAL_CONST_P(recv)) {
 	if (FIXNUM_P(recv) &&
 	    BASIC_OP_UNREDEFINED_P(BOP_SUCC)) {
@@ -2866,7 +2914,7 @@
 	CALL_SIMPLE_METHOD(0, idSucc, recv);
     }
 
-#line 2870 "vm.inc"
+#line 2918 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_succ
@@ -2890,7 +2938,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_not));
   USAGE_ANALYSIS_OPERAND(BIN(opt_not), 0, ic);
 {
-#line 2064 "insns.def"
+#line 2089 "insns.def"
     extern VALUE rb_obj_not(VALUE obj);
     const rb_method_entry_t *me = vm_method_search(idNot, CLASS_OF(recv), ic);
 
@@ -2902,7 +2950,7 @@
 	CALL_SIMPLE_METHOD(0, idNot, recv);
     }
 
-#line 2906 "vm.inc"
+#line 2954 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_not
@@ -2926,10 +2974,10 @@
   USAGE_ANALYSIS_INSN(BIN(opt_regexpmatch1));
   USAGE_ANALYSIS_OPERAND(BIN(opt_regexpmatch1), 0, r);
 {
-#line 2088 "insns.def"
+#line 2113 "insns.def"
     val = rb_reg_match(r, obj);
 
-#line 2933 "vm.inc"
+#line 2981 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_regexpmatch1
@@ -2953,7 +3001,7 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(opt_regexpmatch2));
 {
-#line 2102 "insns.def"
+#line 2127 "insns.def"
     if (TYPE(obj2) == T_STRING) {
 	val = rb_reg_match(obj1, obj2);
     }
@@ -2961,7 +3009,7 @@
 	val = rb_funcall(obj2, idEqTilde, 1, obj1);
     }
 
-#line 2965 "vm.inc"
+#line 3013 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(val);
 #undef CURRENT_INSN_opt_regexpmatch2
@@ -2983,7 +3031,7 @@
   USAGE_ANALYSIS_INSN(BIN(opt_call_c_function));
   USAGE_ANALYSIS_OPERAND(BIN(opt_call_c_function), 0, funcptr);
 {
-#line 2121 "insns.def"
+#line 2146 "insns.def"
     reg_cfp = (funcptr)(th, reg_cfp);
 
     if (reg_cfp == 0) {
@@ -2995,7 +3043,7 @@
     RESTORE_REGS();
     NEXT_INSN();
 
-#line 2999 "vm.inc"
+#line 3047 "vm.inc"
 #undef CURRENT_INSN_opt_call_c_function
 #undef INSN_IS_SC
 #undef INSN_LABEL
@@ -3015,10 +3063,10 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(bitblt));
 {
-#line 2144 "insns.def"
+#line 2169 "insns.def"
     ret = rb_str_new2("a bit of bacon, lettuce and tomato");
 
-#line 3022 "vm.inc"
+#line 3070 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(ret);
 #undef CURRENT_INSN_bitblt
@@ -3040,10 +3088,10 @@
   #define LABEL_IS_SC(lab) LABEL_##lab##_##t
   USAGE_ANALYSIS_INSN(BIN(answer));
 {
-#line 2158 "insns.def"
+#line 2183 "insns.def"
     ret = INT2FIX(42);
 
-#line 3047 "vm.inc"
+#line 3095 "vm.inc"
   CHECK_STACK_OVERFLOW(REG_CFP, 1);
   PUSH(ret);
 #undef CURRENT_INSN_answer
diff -Naur ruby-1.9.3-p547.original/vm_insnhelper.c ruby-1.9.3-p547.htm/vm_insnhelper.c
--- ruby-1.9.3-p547.original/vm_insnhelper.c	2013-02-22 14:42:27.000000000 +0900
+++ ruby-1.9.3-p547.htm/vm_insnhelper.c	2014-09-12 06:37:35.905002000 +0900
@@ -5,6 +5,7 @@
   $Author: usa $
 
   Copyright (C) 2007 Koichi Sasada
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
@@ -1264,8 +1265,12 @@
 }
 
 #ifndef USE_IC_FOR_IVAR
+#if defined(HTM_GVL) && ! defined(USE_TABLE_FOR_IC_IVAR)
+#define USE_IC_FOR_IVAR 0
+#else
 #define USE_IC_FOR_IVAR 1
 #endif
+#endif
 
 static VALUE
 vm_getivar(VALUE obj, ID id, IC ic)
@@ -1273,10 +1278,21 @@
 #if USE_IC_FOR_IVAR
     if (TYPE(obj) ==  T_OBJECT) {
 	VALUE val = Qundef;
+#ifdef USE_TABLE_FOR_IC_IVAR
+	struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+#else
 	VALUE klass = RBASIC(obj)->klass;
+#endif
 
-	if (LIKELY(ic->ic_class == klass &&
-		   ic->ic_vmstat == GET_VM_STATE_VERSION())) {
+	if (
+#ifdef USE_TABLE_FOR_IC_IVAR
+	    LIKELY(iv_index_tbl != NULL && ic->ic_guard.ic_tbl == iv_index_tbl &&
+		   ic->ic_vmstat == GET_VM_STATE_VERSION())
+#else
+	    LIKELY(ic->ic_class == klass &&
+		   ic->ic_vmstat == GET_VM_STATE_VERSION())
+#endif
+	    ) {
 	    long index = ic->ic_value.index;
 	    long len = ROBJECT_NUMIV(obj);
 	    VALUE *ptr = ROBJECT_IVPTR(obj);
@@ -1289,14 +1305,20 @@
 	    st_data_t index;
 	    long len = ROBJECT_NUMIV(obj);
 	    VALUE *ptr = ROBJECT_IVPTR(obj);
+#ifndef USE_TABLE_FOR_IC_IVAR
 	    struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+#endif
 
 	    if (iv_index_tbl) {
 		if (st_lookup(iv_index_tbl, id, &index)) {
 		    if ((long)index < len) {
 			val = ptr[index];
 		    }
+#ifdef USE_TABLE_FOR_IC_IVAR
+		    ic->ic_guard.ic_tbl = iv_index_tbl;
+#else
 		    ic->ic_class = klass;
+#endif
 		    ic->ic_value.index = index;
 		    ic->ic_vmstat = GET_VM_STATE_VERSION();
 		}
@@ -1327,11 +1349,22 @@
     rb_check_frozen(obj);
 
     if (TYPE(obj) == T_OBJECT) {
+#ifdef USE_TABLE_FOR_IC_IVAR
+	struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+#else
 	VALUE klass = RBASIC(obj)->klass;
+#endif
 	st_data_t index;
 
-	if (LIKELY(ic->ic_class == klass &&
-		   ic->ic_vmstat == GET_VM_STATE_VERSION())) {
+	if (
+#ifdef USE_TABLE_FOR_IC_IVAR
+	    LIKELY(iv_index_tbl != NULL && ic->ic_guard.ic_tbl == iv_index_tbl &&
+		   ic->ic_vmstat == GET_VM_STATE_VERSION())
+#else
+	    LIKELY(ic->ic_class == klass &&
+		   ic->ic_vmstat == GET_VM_STATE_VERSION())
+#endif
+	    ) {
 	    long index = ic->ic_value.index;
 	    long len = ROBJECT_NUMIV(obj);
 	    VALUE *ptr = ROBJECT_IVPTR(obj);
@@ -1342,10 +1375,16 @@
 	    }
 	}
 	else {
+#ifndef USE_TABLE_FOR_IC_IVAR
 	    struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+#endif
 
 	    if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
+#ifdef USE_TABLE_FOR_IC_IVAR
+		ic->ic_guard.ic_tbl = iv_index_tbl;
+#else
 		ic->ic_class = klass;
+#endif
 		ic->ic_value.index = index;
 		ic->ic_vmstat = GET_VM_STATE_VERSION();
 	    }
@@ -1363,15 +1402,39 @@
 {
     rb_method_entry_t *me;
 #if OPT_INLINE_METHOD_CACHE
-    if (LIKELY(klass == ic->ic_class &&
-	GET_VM_STATE_VERSION() == ic->ic_vmstat)) {
+    if (
+#ifdef USE_TABLE_FOR_IC_IVAR
+	LIKELY(klass == ic->ic_guard.ic_class &&
+	GET_VM_STATE_VERSION() == ic->ic_vmstat)
+#else
+	LIKELY(klass == ic->ic_class &&
+	GET_VM_STATE_VERSION() == ic->ic_vmstat)
+#endif
+	) {
 	me = ic->ic_value.method;
     }
     else {
 	me = rb_method_entry(klass, id);
+#ifdef ADAPTIVE_INLINE_METHOD_CACHE
+	/* Fill a cache only at the first time */
+	if (
+#ifdef USE_TABLE_FOR_IC_IVAR
+	    ic->ic_guard.ic_class == 0
+#else
+	    ic->ic_class == 0
+#endif
+	    ) {
+#endif /* ADAPTIVE_INLINE_METHOD_CACHE */
+#ifdef USE_TABLE_FOR_IC_IVAR
+	ic->ic_guard.ic_class = klass;
+#else
 	ic->ic_class = klass;
+#endif
 	ic->ic_value.method = me;
 	ic->ic_vmstat = GET_VM_STATE_VERSION();
+#ifdef ADAPTIVE_INLINE_METHOD_CACHE
+	}
+#endif /* ADAPTIVE_INLINE_METHOD_CACHE */
     }
 #else
     me = rb_method_entry(klass, id);
diff -Naur ruby-1.9.3-p547.original/vm_method.c ruby-1.9.3-p547.htm/vm_method.c
--- ruby-1.9.3-p547.original/vm_method.c	2013-02-22 14:42:27.000000000 +0900
+++ ruby-1.9.3-p547.htm/vm_method.c	2014-09-12 06:37:35.905002000 +0900
@@ -1,5 +1,6 @@
 /*
  * This file is included by vm.c
+  Copyright (c) IBM Corp. 2014.
  */
 
 #define CACHE_SIZE 0x800
@@ -395,6 +396,14 @@
     if (ruby_running) {
 	struct cache_entry *ent;
 	ent = cache + EXPR1(klass, id);
+#ifdef ADAPTIVE_GLOBAL_METHOD_CACHE
+	if (ent->mid != 0) {
+	    if (UNDEFINED_METHOD_ENTRY_P(me)) {
+		me = 0;
+	    }
+	    return me;
+	}
+#endif
 	ent->filled_version = GET_VM_STATE_VERSION();
 	ent->klass = klass;
 
diff -Naur ruby-1.9.3-p547.original/vm_opts.h ruby-1.9.3-p547.htm/vm_opts.h
--- ruby-1.9.3-p547.original/vm_opts.h	2009-10-02 21:04:37.000000000 +0900
+++ ruby-1.9.3-p547.htm/vm_opts.h	2014-09-12 06:37:35.905002000 +0900
@@ -6,6 +6,7 @@
   $Author: akr $
 
   Copyright (C) 2004-2007 Koichi Sasada
+  Copyright (c) IBM Corp. 2014.
 
 **********************************************************************/
 
@@ -36,7 +37,11 @@
 
 /* VM running option */
 #define OPT_CHECKED_RUN              1
+#if defined(HTM_GVL) && ! defined(ADAPTIVE_INLINE_METHOD_CACHE)
+#define OPT_INLINE_METHOD_CACHE      0
+#else
 #define OPT_INLINE_METHOD_CACHE      1
+#endif
 #define OPT_BLOCKINLINING            0
 
 /* architecture independent, affects generated code */
