<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>kernel/common/pack.rb</filename>
    </added>
    <added>
      <filename>kernel/delta/profiler.rb</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/.gitignore</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/Makefile</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/README</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/arithchk.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/dmisc.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/dtoa.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/g_Qfmt.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/g__fmt.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/g_ddfmt.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/g_dfmt.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/g_ffmt.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/g_xLfmt.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/g_xfmt.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/gdtoa.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/gdtoa.h</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/gdtoaimp.h</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/gethex.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/gmisc.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/hd_init.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/hexnan.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/makefile.orig</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/misc.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/qnan.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/smisc.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtoIQ.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtoId.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtoIdd.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtoIf.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtoIg.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtoIx.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtoIxL.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtod.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtodI.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtodg.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtodnrp.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtof.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtopQ.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtopd.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtopdd.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtopf.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtopx.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtopxL.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtorQ.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtord.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtordd.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtorf.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtorx.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/strtorxL.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/sum.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/Q.ou0</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/Q.ou1</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/Qtest.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/README</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/d.out</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/dI.out</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/dIsi.out</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/dItest.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/dd.out</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/ddsi.out</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/ddtest.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/dt.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/dtest.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/dtst.out</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/f.out</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/ftest.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/getround.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/makefile</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/rtestnos</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/strtoIdSI.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/strtoIddSI.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/strtodISI.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/strtodt.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/strtopddSI.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/strtorddSI.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/testnos</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/testnos1</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/testnos3</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/x.ou0</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/x.ou1</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/xL.ou0</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/xL.ou1</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/xLtest.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/xQtest.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/xsum0.out</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/test/xtest.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/ulp.c</filename>
    </added>
    <added>
      <filename>vm/external_libs/libgdtoa/xsum0.out</filename>
    </added>
    <added>
      <filename>vm/strtod.hpp</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -158,6 +158,15 @@ To run a ruby file named 'code.rb':
     bin/rbx code.rb
 
 
+## Rubinius Configuration
+
+Rubinius provides a -X command line switch for manipulating the internal
+configuration options. For example,
+
+    -Xrbx.jit enables the jit if it's supported by the platform
+    -Xrbx.dyni enables the dynamic interpreter if it's supported
+
+
 ## Troubleshooting
 
 See [Common Problems](/common_problems.html) or ask questions in the #rubinius</diff>
      <filename>doc/getting_started.txt</filename>
    </modified>
    <modified>
      <diff>@@ -9,14 +9,9 @@ class Rubinius::VM
     raise PrimitiveFailure, &quot;primitive failed&quot;
   end
 
-  def self.start_profiler
-    Ruby.primitive :vm_start_profiler
-    raise PrimitiveFailure, &quot;unable to start profiler&quot;
-  end
-
-  def self.stop_profiler(path)
-    Ruby.primitive :vm_stop_profiler
-    raise PrimitiveFailure, &quot;unable to stop profiler&quot;
+  def self.gc_info
+    Ruby.primitive :vm_gc_info
+    raise PrimitiveFailure, &quot;primitive failed&quot;
   end
 
   def self.write_error(str)</diff>
      <filename>kernel/bootstrap/vm.rb</filename>
    </modified>
    <modified>
      <diff>@@ -322,7 +322,7 @@ class Array
   # Array that do not appear in the other Array, effectively
   # 'deducting' those items. The matching method is Hash-based.
   def -(other)
-    other = Type.coerce_to other, Array, :to_ary
+    other = Type.check_and_coerce_to other, Array, :to_ary
     out, exclude = [], {}
 
     other.each { |x| exclude[x] = true }
@@ -966,284 +966,8 @@ class Array
   #       Z     |  Same as ``a'', except that null is added with *
 
   def pack schema
-    # The schema is an array of arrays like [[&quot;A&quot;, &quot;6&quot;], [&quot;u&quot;, &quot;*&quot;],
-    # [&quot;X&quot;, &quot;&quot;]]. It represents the parsed form of &quot;A6u*X&quot;.  Remove
-    # strings in the schema between # and \n
-    schema = schema.gsub(/#.*/, '')
-    schema = schema.scan(/([^\s\d\*][\d\*]*)/).flatten.map {|x|
-      x.match(/([^\s\d\*])([\d\*]*)/)[1..-1]
-    }
-
-    ret = &quot;&quot;
-    arr_idx = 0
-
-    schema.each do |kind, t|
-      # p :iter =&gt; [kind, t]
-      item = self[arr_idx]
-      t = nil if t.empty?
-
-      # MRI nil compatibilty for string functions
-      item = &quot;&quot; if item.nil? &amp;&amp; kind =~ /[aAZbBhH]/
-
-      # if there's no item, that means there's more schema items than
-      # array items, so throw an error. All actions that DON'T
-      # increment arr_idx must occur before this test.
-      raise ArgumentError, &quot;too few array elements&quot; if
-        arr_idx &gt;= self.length and kind !~ /x/i
-
-      case kind # TODO: switch kind to ints
-      when 'X' then
-        size = (t || 1).to_i
-        raise ArgumentError, &quot;you're backing up too far&quot; if size &gt; ret.size
-        ret[-size..-1] = '' if size &gt; 0
-      when 'x' then
-        size = (t || 1).to_i
-        ret &lt;&lt; &quot;\000&quot; * size
-      when 'a', 'A', 'Z' then
-        item = Type.coerce_to(item, String, :to_str)
-        size = case t
-               when nil
-                 1
-               when '*' then
-                 item.size + (kind == &quot;Z&quot; ? 1 : 0)
-               else
-                 t.to_i
-               end
-
-        padsize = size - item.size
-        filler  = kind == &quot;A&quot; ? &quot; &quot; : &quot;\0&quot;
-
-        ret &lt;&lt; item.split(//).first(size).join
-        ret &lt;&lt; filler * padsize if padsize &gt; 0
-
-        arr_idx += 1
-      when 'b', 'B' then
-        item = Type.coerce_to(item, String, :to_str)
-        byte = 0
-        lsb  = (kind == &quot;b&quot;)
-        size = case t
-               when nil
-                 1
-               when '*' then
-                 item.size
-               else
-                 t.to_i
-               end
-
-        bits = item.split(//).map { |c| c[0] &amp; 01 }
-        min = [size, item.size].min
-
-        bits.first(min).each_with_index do |bit, i| # TODO: this can be cleaner
-          i &amp;= 07
-
-          byte |= bit &lt;&lt; (lsb ? i : 07 - i)
-
-          if i == 07 then
-            ret &lt;&lt; byte.chr
-            byte = 0
-          end
-        end
-
-        # always output an incomplete byte
-        if ((size &amp; 07) != 0 || min != size) &amp;&amp; item.size &gt; 0 then
-          ret &lt;&lt; byte.chr
-        end
-
-        # Emulate the weird MRI spec for every 2 chars over output a \000 # FIX
-        (item.length).step(size-1, 2) { |i| ret &lt;&lt; 0 } if size &gt; item.length
-
-        arr_idx += 1
-      when 'c', 'C' then
-        size = case t
-               when nil
-                 1
-               when '*' then
-                 self.size # TODO: - arr_idx?
-               else
-                 t.to_i
-               end
-
-        # FIX: uhh... size is the same as length. just tests that arr_idx == 0
-        raise ArgumentError, &quot;too few array elements&quot; if
-          arr_idx + size &gt; self.length
-
-        sub = self[arr_idx...arr_idx+size]
-        sub.map! { |o| (Type.coerce_to(o, Integer, :to_int) &amp; 0xff).chr }
-        ret &lt;&lt; sub.join
-
-        arr_idx += size
-      when 'M' then
-        # for some reason MRI responds to to_s here
-        item = Type.coerce_to(item, String, :to_s)
-        ret &lt;&lt; item.scan(/.{1,73}/m).map { |line| # 75 chars per line incl =\n
-          line.gsub(/[^ -&lt;&gt;-~\t\n]/) { |m| &quot;=%02X&quot; % m[0] } + &quot;=\n&quot;
-        }.join
-        arr_idx += 1
-      when 'm' then # REFACTOR: merge with u
-        item = Type.coerce_to(item, String, :to_str)
-
-        ret &lt;&lt; item.scan(/.{1,45}/m).map { |line|
-          encoded = line.scan(/(.)(.?)(.?)/m).map { |a,b,c|
-            a = a[0]
-            b = b[0] || 0
-            c = c[0] || 0
-
-            [BASE_64_B2A[( a &gt;&gt; 2                    ) &amp; 077],
-             BASE_64_B2A[((a &lt;&lt; 4) | ((b &gt;&gt; 4) &amp; 017)) &amp; 077],
-             BASE_64_B2A[((b &lt;&lt; 2) | ((c &gt;&gt; 6) &amp; 003)) &amp; 077],
-             BASE_64_B2A[( c                         ) &amp; 077]]
-          }
-
-          &quot;#{encoded.flatten.join}\n&quot;
-        }.join.sub(/(A{1,2})\n\Z/) { &quot;#{'=' * $1.size}\n&quot; }
-
-        arr_idx += 1
-      when 'w' then
-        item = Type.coerce_to(item, Integer, :to_int)
-        raise ArgumentError, &quot;can't compress negative numbers&quot; if item &lt; 0
-
-        ret &lt;&lt; (item &amp; 0x7f)
-        while (item &gt;&gt;= 7) &gt; 0 do
-          ret &lt;&lt; ((item &amp; 0x7f) | 0x80)
-        end
-
-        ret.reverse! # FIX - breaks anything following BER?
-        arr_idx += 1
-      when 'u' then # REFACTOR: merge with m
-        item = Type.coerce_to(item, String, :to_str)
-
-        # http://www.opengroup.org/onlinepubs/009695399/utilities/uuencode.html
-        ret &lt;&lt; item.scan(/.{1,45}/m).map { |line|
-          encoded = line.scan(/(.)(.?)(.?)/m).map { |a,b,c|
-            a = a[0]
-            b = b[0] || 0
-            c = c[0] || 0
-
-            [(?\s + (( a &gt;&gt; 2                    ) &amp; 077)).chr,
-             (?\s + (((a &lt;&lt; 4) | ((b &gt;&gt; 4) &amp; 017)) &amp; 077)).chr,
-             (?\s + (((b &lt;&lt; 2) | ((c &gt;&gt; 6) &amp; 003)) &amp; 077)).chr,
-             (?\s + (( c                         ) &amp; 077)).chr]
-          }.flatten
-
-          &quot;#{(line.size + ?\s).chr}#{encoded.join}\n&quot;
-        }.join.gsub(/ /, '`')
-        arr_idx += 1
-      when 'i', 's', 'l', 'n', 'I', 'S', 'L', 'V', 'v', 'N', 'n' then
-        size = case t
-               when nil
-                 1
-               when '*' then
-                 self.size - arr_idx
-               else
-                 t.to_i
-               end
-
-        native        = t &amp;&amp; t == '_'
-        unsigned      = (kind =~ /I|S|L/)
-        little_endian = case kind
-                        when 'V', 'v' then true
-                        when 'N', 'n' then false
-                        else endian?(:little)
-                        end
-
-        raise &quot;unsupported - fix me&quot; if native
-
-        unless native then
-          bytes = case kind
-                  when 'L', 'l' then 4
-                  when 'I', 'i' then 4
-                  when 'S', 's' then 2
-                  when 'V'      then 4
-                  when 'v'      then 2
-                  when 'N'      then 4
-                  when 'n'      then 2
-                  end
-        end
-
-        size.times do |i|
-          item = Type.coerce_to(self[arr_idx], Integer, :to_int)
-
-          if item.abs &gt;= 2**Rubinius::WORDSIZE
-            raise RangeError, &quot;bignum too big to convert into 'unsigned long'&quot;
-          end
-
-            ret &lt;&lt; if little_endian then
-                     item += 2 ** (8 * bytes) if item &lt; 0
-                     (0...bytes).map { |b| ((item &gt;&gt; (b * 8)) &amp; 0xFF).chr }
-                   else # ugly
-                     (0...bytes).map {n=(item % 256).chr;item /= 256; n}.reverse
-                   end.join
-          arr_idx += 1
-        end
-      when 'H', 'h' then
-        size = if t.nil?
-                 0
-               elsif t == &quot;*&quot;
-                 item.length
-               else
-                 t.to_i
-               end
-        str = item.scan(/..?/).first(size)
-
-        ret &lt;&lt; if kind == &quot;h&quot; then
-                 str.map { |b| b.reverse.hex.chr }.join
-               else
-                 str.map { |b| b.        hex.chr }.join
-               end
-
-        arr_idx += 1
-      when 'U' then
-        count = if t.nil? then
-                  1
-                elsif t == &quot;*&quot;
-                  self.size - arr_idx
-                else
-                  t.to_i
-                end
-
-        raise ArgumentError, &quot;too few array elements&quot; if
-          arr_idx + count &gt; self.length
-
-        count.times do
-          item = Type.coerce_to(self[arr_idx], Integer, :to_i)
-
-          raise RangeError, &quot;pack(U): value out of range&quot; if item &lt; 0
-
-          bytes = 0
-          f = [2 ** 7, 2 ** 11, 2 ** 16, 2 ** 21, 2 ** 26, 2 ** 31].find { |n|
-            bytes += 1
-            item &lt; n
-          }
-
-          raise RangeError, &quot;pack(U): value out of range&quot; if f.nil?
-
-          if bytes == 1 then
-            ret &lt;&lt; item
-            bytes = 0
-          end
-
-          i = bytes
-
-          buf = []
-          if i &gt; 0 then
-            (i-1).times do
-              buf.unshift((item | 0x80) &amp; 0xBF)
-              item &gt;&gt;= 6
-            end
-            # catch the highest bits - the mask depends on the byte count
-            buf.unshift(item | ((0x3F00 &gt;&gt; bytes)) &amp; 0xFC)
-          end
-
-          ret &lt;&lt; buf.map { |n| n.chr }.join
-
-          arr_idx += 1
-        end
-      else
-        raise ArgumentError, &quot;Unknown kind #{kind}&quot;
-      end
-    end
-
-    return ret
+    # see pack.rb for Array::Packer
+    Packer.new(self,schema).dispatch
   end
 
   # Removes and returns the last element from the Array.
@@ -1327,7 +1051,7 @@ class Array
     while(j &gt;= @start) do
       tuple.put i, @tuple.at(j)
       i += 1
-      j -= 1      
+      j -= 1
     end
 
     @tuple = tuple</diff>
      <filename>kernel/common/array.rb</filename>
    </modified>
    <modified>
      <diff>@@ -122,6 +122,10 @@ class CompiledMethod &lt; Executable
     attr_reader   :visibility
   end
 
+  # Any CompiledMethod with this value in it's serial slot
+  # is expected to be the default, kernel version
+  KernelMethodSerial = 47
+
   # Ivars: instance_variables, primitive, serial, name, iseq, stack_size,
   # local_count, required_args, total_args, splat, literals, exceptions,
   # lines, file, compiled, scope</diff>
      <filename>kernel/common/compiled_method.rb</filename>
    </modified>
    <modified>
      <diff>@@ -235,11 +235,20 @@ module Kernel
   # sequence number
   #++
 
-  def srand(seed)
+  def srand(seed=0)
     cur = Kernel.current_srand
+    if seed == 0
+      begin
+        File.open(&quot;/dev/urandom&quot;, &quot;r&quot;) do |f|
+          seed = f.read(10).unpack(&quot;I*&quot;)[0]
+        end
+      rescue Errno::ENOENT, Errno::EPERM, Errno::EACCES
+        seed = Time.now.to_i    
+      end
+    end
     Platform::POSIX.srand(seed.to_i)
     Kernel.current_srand = seed.to_i
-    return cur
+    cur
   end
   module_function :srand
 </diff>
      <filename>kernel/common/kernel.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2375,356 +2375,7 @@ class String
   #     -------+---------+-----------------------------------------
 
   def unpack(format)
-
-    # some of the directives work when repeat == 0 because of this behavior:
-    # str[0...0] == '' and str[1..0] == ''
-
-    raise TypeError, &quot;can't convert nil into String&quot; if format.nil?
-
-    i = 0
-    elements = []
-    length = self.length
-
-    schema = format.scan(/([@a-zA-Z])(-?\d+|[\*_])?/).map { |c, n|
-      # n in (nil, -num, num, &quot;*&quot;, &quot;_&quot;)
-      [c, n.nil? || n =~ /\*|_/ ? n : Integer(n)]
-    }
-
-    schema.each do |code, count|
-
-      count = nil if Fixnum === count and count &lt; 0
-      count ||= code == &quot;@&quot; ? 0 : 1
-
-      # TODO: profile avg occurances and reorder case
-      case code
-      when 'A' then
-        new_pos, str = if i &gt;= length then
-                         [i, '']
-                       elsif count == '*' then
-                         [length, self[i..-1]]
-                       else
-                         new_pos = i + count
-                         [new_pos,
-                          new_pos &lt;= length ? self[i...new_pos] : self[i..-1]]
-                       end
-        i = new_pos
-        elements &lt;&lt; str.sub(/[\x00\x20]+\Z/, '')
-      when 'a' then
-        if i &gt;= length then
-          elements &lt;&lt; ''
-        elsif count == '*' then
-          elements &lt;&lt; self[i..-1]
-          i = length
-        else
-          nnd = i + count
-          s = if i + count &lt;= length then
-                self[i...nnd]
-              else
-                self[i..-1]
-              end
-          elements &lt;&lt; s
-          i = nnd
-        end
-      when 'B', 'b', 'H', 'h' then
-        lsb = code =~ /[bh]/
-        fmt = case code
-              when /[Bb]/ then &quot;%08b&quot;
-              when /[Hh]/ then &quot;%02x&quot;
-              end
-
-        if i &gt;= length then
-          elements &lt;&lt; ''
-        elsif count == '*' then
-          a = self[i..-1].split(//).map { |c| fmt % c[0] }
-          a.map! { |s| s.reverse } if lsb
-          elements &lt;&lt; a.join
-          i = length
-        else
-          case code
-          when /[Bb]/ then
-            num_bytes, r = count.divmod(8)
-            num_drop = r != 0 ? 8 - r : 0
-          when /[Hh]/ then
-            num_bytes, r = (count * 4).divmod(8)
-            num_drop = r != 0 ? 1 : 0
-          end
-          num_bytes += 1 if r != 0
-          str0 = if i + num_bytes &lt;= length then
-                   self[i...(i + num_bytes)]
-                 else
-                   self[i..-1]
-                 end
-          len = str0.length
-          str1 = ''
-          str0.each_byte { |n|
-            len -= 1
-            s = fmt % n
-            str1 &lt;&lt; if lsb then
-                      len == 0 ? s[num_drop..-1].reverse : s.reverse
-                    else
-                      len == 0 ? s[0..-num_drop.succ]    : s
-                    end
-          }
-          elements &lt;&lt; str1
-          i += num_bytes
-        end
-      when /[CcDdEeFfGgIiLlNnQqSsVv]/ then
-        num_bytes = case code
-                    when /[DdEGQq]/ then 8
-                    when /[eFfgNV]/ then 4
-                    when /[nSsv]/   then 2
-                    when /[Cc]/     then 1
-                    when /[IiLl]/   then 1.size
-                    end
-
-        size = case code
-               when /[NncGg]/          then :big
-               when /[CILQSilqsFfDd]/ then :native
-               when /[VveE]/          then :little
-               else
-                 raise &quot;huh? #{code.inspect}&quot;
-               end
-
-        star = count == '*'
-        count = length - i if star
-        count.times do |j|
-          if i + num_bytes &gt; length
-            break if star
-            elements &lt;&lt; nil if code != 'Q'
-          else
-            start    = i
-            offset   = num_bytes - 1
-            endian   = size
-            n        = exp = 0
-            bytebits = 8
-
-            if :big == endian || (:native == endian &amp;&amp; endian?(:big)) then
-              exp      =  bytebits * offset
-              bytebits = -bytebits
-            end
-
-            (start..start + offset).each do |x|
-              n   += (self[x] * 2**exp)
-              exp += bytebits
-            end
-
-            case code
-            when /[NnCILQSVv]/ then
-              elements &lt;&lt; n
-            when /[ilqsc]/ then
-              max = 2 ** (num_bytes * 8 - 1)
-              n = n &gt;= max ? -(2**(num_bytes*8) - n) : n
-              elements &lt;&lt; n
-            when /[eFfg]/ then
-              sign   = (2**31 &amp; n != 0) ? -1 : 1
-              expo   = ((0xFF * 2**23) &amp; n) &gt;&gt; 23
-              frac   = (2**23 - 1) &amp; n
-              result = if expo == 0 and frac == 0 then
-                         sign.to_f * 0.0    # zero
-                       elsif expo == 0 then # denormalized
-                         sign * 2**(expo - 126) * (frac.to_f / 2**23.to_f)
-                       elsif expo == 0xFF and frac == 0 then
-                         sign.to_f / 0.0    # Infinity
-                       elsif expo == 0xFF then
-                         0.0 / 0.0          # NaN
-                       else                 # normalized
-                         sign * 2**(expo - 127) * (1.0 + (frac.to_f / 2**23.to_f))
-                       end
-              elements &lt;&lt; result
-            when /[DdEG]/ then
-              sign   = (2**63 &amp; n != 0) ? -1 : 1
-              expo   = ((0x7FF * 2**52) &amp; n) &gt;&gt; 52
-              frac   = (2**52 - 1) &amp; n
-              result = if expo == 0 and frac == 0 then
-                         sign.to_f * 0.0    # zero
-                       elsif expo == 0 then # denormalized
-                         sign * 2**(expo - 1022) * (frac.to_f / 2**52.to_f)
-                       elsif expo == 0x7FF and frac == 0 then
-                         sign.to_f / 0.0    # Infinity
-                       elsif expo == 0x7FF then
-                         0.0 / 0.0          # NaN
-                       else                 # normalized
-                         sign * 2**(expo-1023) * (1.0 + (frac.to_f / 2**52.to_f))
-                       end
-              elements &lt;&lt; result
-            end
-            i += num_bytes
-          end
-        end
-      when 'M' then
-        if i &gt;= length then
-          elements &lt;&lt; ''
-        else
-          str              = ''
-          num_bytes        = 0
-          regex_permissive = / \= [0-9A-Fa-f]{2} | [^=]+ | [\x00-\xFF]+ /x
-          regex_junk       = / \A ( \= [0-9A-Fa-f]{0,1} )               /x
-          regex_strict     = / \A (?: \= [0-9A-Fa-f]{2} | [^=]+ )    \Z /x
-          regex_hex        = / \A \= ([0-9A-Fa-f]{2})                \Z /x
-
-          self[i..-1].scan(regex_permissive) do |s|
-            if s =~ regex_strict then
-              num_bytes += s.length
-              s = $1.hex.chr if s =~ regex_hex
-              str &lt;&lt; s
-            elsif s =~ regex_junk
-              num_bytes += $1.length
-            end
-          end
-
-          elements &lt;&lt; str
-          i += num_bytes
-        end
-      when 'm' then
-        if i &gt;= length
-          elements &lt;&lt; ''
-        else
-          buffer    = ''
-          str       = ''
-          num_bytes = 0
-
-          b64_regex_permissive = /[A-Za-z0-9+\/]{4} |[A-Za-z0-9+\/]{3} \=?
-            |[A-Za-z0-9+\/]{2}\={0,2} |[A-Za-z0-9+\/]\={0,3} |[^A-Za-z0-9+\/]+/x
-
-          self[i..-1].scan(b64_regex_permissive) do |s|
-            num_bytes += s.length
-
-            b64_regex_strict = /\A (?:[A-Za-z0-9+\/]{4} |[A-Za-z0-9+\/]{3} \=?
-              |[A-Za-z0-9+\/]{2} \={0,2} |[A-Za-z0-9+\/] \={0,3} ) \Z /x
-
-            if s =~ b64_regex_strict then
-
-              s &lt;&lt; '=' while s.length != 4 if s =~ /=\Z/
-
-              # TODO: WHY?
-              if buffer == '' and s =~ /\A([A-Za-z0-9+\/])\=+\Z/ then
-                buffer &lt;&lt; $1
-              else
-                buffer &lt;&lt; s
-              end
-
-              process = buffer.length &gt;= 4
-
-              if process then
-                s      = buffer[0..3]
-                buffer = buffer[4..-1]
-
-                a = BASE_64_A2B[s[0]]
-                b = BASE_64_A2B[s[1]]
-                c = BASE_64_A2B[s[2]]
-                d = BASE_64_A2B[s[3]]
-
-                # http://www.opengroup.org/onlinepubs/009695399/utilities/uuencode.html
-                decoded = [a &lt;&lt; 2 | b &gt;&gt; 4,
-                           (b &amp; (2**4 - 1)) &lt;&lt; 4 | c &gt;&gt; 2,
-                           (c &amp; (2**2 - 1)) &lt;&lt; 6 | d].pack('CCC')
-
-                if s[3].chr == '='
-                  num_bytes -= 1
-                  decoded = decoded[0..-2]
-                  decoded = decoded[0..-2] if s[2].chr == '='
-                  str &lt;&lt; decoded
-                  break
-                else
-                  str &lt;&lt; decoded
-                end
-              end
-            end
-          end
-          elements &lt;&lt; str
-          i += num_bytes
-        end
-      when 'U' then
-        utf8_regex_strict = /\A(?:[\x00-\x7F]
-                                 |[\xC2-\xDF][\x80-\xBF]
-                                 |[\xE1-\xEF][\x80-\xBF]{2}
-                                 |[\xF1-\xF7][\x80-\xBF]{3}
-                                 |[\xF9-\xFB][\x80-\xBF]{4}
-                                 |[\xFD-\xFD][\x80-\xBF]{5} )\Z/x
-
-        utf8_regex_permissive = / [\x00-\x7F]
-                                 |[\xC0-\xDF][\x80-\xBF]
-                                 |[\xE0-\xEF][\x80-\xBF]{2}
-                                 |[\xF0-\xF7][\x80-\xBF]{3}
-                                 |[\xF8-\xFB][\x80-\xBF]{4}
-                                 |[\xFC-\xFD][\x80-\xBF]{5}
-                                 |[\x00-\xFF]+ /x
-
-        if i &gt;= length then
-          # do nothing?!?
-        else
-          num_bytes = 0
-          self[i..-1].scan(utf8_regex_permissive) do |c|
-            raise ArgumentError, &quot;malformed UTF-8 character&quot; if
-              c !~ utf8_regex_strict
-
-            break if count == 0
-
-            if false then
-              elements &lt;&lt; c.utf8_code_value
-              num_bytes += c.length
-            else
-              len = c.length
-              if len == 1
-                result = c[0]
-              else
-                shift = (len - 1) * 2
-                result = (((2 ** (8 - len.succ) - 1) &amp; c[0]) *
-                          2 ** ((len - 1) * 8)) &gt;&gt; shift
-                (1...(len - 1)).each do |x|
-                  shift -= 2
-                  result |= (((2 ** 6 - 1) &amp; c[x]) *
-                               2 ** ((len - x.succ) * 8)) &gt;&gt; shift
-                end
-                result |= (2 ** 6 - 1) &amp; c[-1]
-              end
-              elements &lt;&lt; result
-              num_bytes += len
-            end
-
-            count -= 1 if count != '*'
-          end
-          i += num_bytes
-        end
-      when 'X' then
-        count = length - i if count == '*'
-
-        raise ArgumentError, &quot;X outside of string&quot; if count &lt; 0 or i - count &lt; 0
-        i -= count
-      when 'x' then
-        if count == '*' then
-          raise ArgumentError, &quot;x outside of string&quot; if i &gt; length
-          i = length
-        else
-          raise ArgumentError, &quot;x outside of string&quot; if i + count &gt; length
-          i += count
-        end
-      when 'Z' then
-        if i &gt;= length then
-          elements &lt;&lt; ''
-        elsif count == '*' then
-          self[i..-1] =~ / \A ( [^\x00]* ) ( [\x00]? ) /x
-          elements &lt;&lt; $1
-          i += $1.length
-          i += 1 if $2 == &quot;\0&quot;
-        else
-          str = i + count &lt;= length ? self[i...(i + count)] : self[i..-1]
-          str =~ / \A ( [^\x00]* ) /x
-          elements &lt;&lt; $1
-          i += count
-        end
-      when '@' then
-        if count == '*' then
-          i = length
-        else
-          raise ArgumentError, &quot;@ outside of string&quot; if count &gt; length
-          i = count &gt; 0 ? count : 0
-        end
-      else
-        # raise &quot;unknown directive: #{code.inspect}&quot;
-      end
-    end
-
-    elements
+    # see pack.rb for String::Unpacker
+    Unpacker.new(self,format).dispatch
   end
 end</diff>
      <filename>kernel/common/string.rb</filename>
    </modified>
    <modified>
      <diff>@@ -43,3 +43,6 @@ class Class
 
   alias_method :dup, :clone
 end
+
+cm = Class.method_table[:new]
+cm.serial = CompiledMethod::KernelMethodSerial</diff>
      <filename>kernel/delta/class.rb</filename>
    </modified>
    <modified>
      <diff>@@ -106,10 +106,16 @@ module Rubinius
           str = next_string.chop
 
           # handle the special NaN, Infinity and -Infinity differently
-          c = str[0]
-          c = str[1] if c == ?-
-          if c.between?(?0, ?9)
-            return str.to_f
+          if str[0] == ?\     # leading space
+            x = str.to_f
+            e = str[-5..-1].to_i
+
+            # This is necessary because (2**1024).to_f yields Infinity
+            if e == 1024
+              return x * 2 ** 512 * 2 ** 512
+            else
+              return x * 2 ** e
+            end
           else
             case str.downcase
             when &quot;infinity&quot;
@@ -289,7 +295,16 @@ module Rubinius
             str &lt;&lt; marshal(ele)
           end
         when Float
-          str &lt;&lt; &quot;d\n#{val}\n&quot;
+          str &lt;&lt; &quot;d\n&quot;
+          if val.infinite?
+            str &lt;&lt; &quot;-&quot; if val &lt; 0.0
+            str &lt;&lt; &quot;Infinity&quot;
+          elsif val.nan?
+            str &lt;&lt; &quot;NaN&quot;
+          else
+            str &lt;&lt; &quot; %+.54f %5d&quot; % Math.frexp(val)
+          end
+          str &lt;&lt; &quot;\n&quot;
         when InstructionSequence
           str &lt;&lt; &quot;i\n#{val.size}\n&quot;
           val.opcodes.each do |op|</diff>
      <filename>kernel/delta/compiled_file.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,12 +1,4 @@
 class String
-  BASE_64_A2B = {}
-  (?A..?Z).each {|x| BASE_64_A2B[x] = x - ?A}
-  (?a..?z).each {|x| BASE_64_A2B[x] = x - ?a + 26}
-  (?0..?9).each {|x| BASE_64_A2B[x] = x - ?0 + 52}
-  BASE_64_A2B[?+]  = ?&gt;
-  BASE_64_A2B[?\/] = ??
-  BASE_64_A2B[?=]  = 0
-
   def self.sydney_parser
     alias_method :to_sexp, :to_sexp_sydney_parser
   end</diff>
      <filename>kernel/delta/string.rb</filename>
    </modified>
    <modified>
      <diff>@@ -14,10 +14,6 @@ rescue Object =&gt; e
   exit 2
 end
 
-if profile = ENV['PROFILE']
-  Rubinius::VM.start_profiler
-end
-
 # Set up a handler for SIGINT that raises Interrupt on the main thread
 Signal.action(&quot;INT&quot;) do |_|
   thread = Thread.main
@@ -82,12 +78,12 @@ Options:
   -e 'code'      Directly compile and execute code (no file provided).
   -Idir1[:dir2]  Add directories to $LOAD_PATH.
   -S script      Run script using PATH environment variable to find it.
-  -p             Run the profiler.
-  -ps            Run the Selector profiler.
-  -pss           Run the SendSite profiler.
+  -P             Run the profiler.
+  -Ps            Run the Selector profiler.
+  -Pss           Run the SendSite profiler.
   -rlibrary      Require library before execution.
-  -P             Use SydneyParser.
-  -R             Use RubyParser.
+  --sydney       Use SydneyParser.
+  --ruby_parser  Use RubyParser.
   -w             Enable warnings. (currently does nothing--compatibility)
   -v             Display the version and set $VERBOSE to true.
 END
@@ -108,6 +104,7 @@ eval_code = nil
 script = nil
 
 begin
+
   script_debug_requested = false
   until ARGV.empty?
     arg = ARGV.shift
@@ -118,11 +115,11 @@ begin
       puts RBS_USAGE
       exit 1
     when &quot;-v&quot;
-      puts &quot;rubinius #{Rubinius::RBX_VERSION} (ruby #{RUBY_VERSION} compatible) (#{Rubinius::BUILDREV[0..8]}) (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]&quot;
+      puts &quot;rubinius #{Rubinius::RBX_VERSION} (ruby #{RUBY_VERSION}) (#{Rubinius::BUILDREV[0..8]} #{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]&quot;
       $VERBOSE = true
       exit 0 if ARGV.empty?
     when &quot;-vv&quot;
-      puts &quot;rubinius #{Rubinius::RBX_VERSION} (ruby #{RUBY_VERSION} compatible) (#{Rubinius::BUILDREV[0..8]}) (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]&quot;
+      puts &quot;rubinius #{Rubinius::RBX_VERSION} (ruby #{RUBY_VERSION}) (#{Rubinius::BUILDREV[0..8]} #{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]&quot;
       $VERBOSE = true
       puts &quot;Options:&quot;
       puts &quot;  Interpreter type: #{Rubinius::INTERPRETER}&quot;
@@ -156,12 +153,12 @@ begin
       end
       $DEBUG_SERVER.listen
       script_debug_requested = true
-    when '-p'
+    when '-P'
       require 'profile'
-    when '-ps'
+    when '-Ps'
       count = (ARGV.first =~ /^\d+$/) ? ARGV.shift : '30'
       show_selectors = count.to_i
-    when '-pss'
+    when '-Pss'
       count = (ARGV.first =~ /^\d+$/) ? ARGV.shift : '30'
       show_sendsites = count.to_i
     when '-S'
@@ -174,9 +171,9 @@ begin
 
       # if missing, let it die a natural death
       ARGV.unshift file ? file : script
-    when '-P'
+    when '--sydney'
       String.sydney_parser
-    when '-R'
+    when '--ruby_parser'
       String.ruby_parser
     when '-e'
       $0 = &quot;(eval)&quot;
@@ -342,7 +339,7 @@ rescue Object =&gt; e
 end
 
 if show_selectors
-  ps = Sampler::Selectors.new
+  ps = Rubinius::Profiler::Selectors.new
   begin
     ps.show_stats show_selectors
   rescue Object =&gt; e
@@ -355,7 +352,7 @@ if show_selectors
 end
 
 if show_sendsites
-  ps = Sampler::SendSites.new
+  ps = Rubinius::Profiler::SendSites.new
   begin
     ps.show_stats show_sendsites
   rescue Object =&gt; e
@@ -367,16 +364,15 @@ if show_sendsites
   end
 end
 
-if profile
-  Rubinius::VM.stop_profiler profile
-  puts &quot;[Saved profiling data to '#{profile}']&quot;
-end
-
 if Rubinius::RUBY_CONFIG['rbx.jit_stats']
   stats = Rubinius::VM.jit_info
   puts &quot;JIT time spent: #{stats[0] / 1000000}ms&quot;
   puts &quot; JITed methods: #{stats[1]}&quot;
 end
 
-Process.exit(code || 0)
+if Rubinius::RUBY_CONFIG['rbx.gc_stats']
+  timing = Rubinius::VM.gc_info
+  puts &quot;Time spent in GC: #{timing / 1000000}ms&quot;
+end
 
+Process.exit(code || 0)</diff>
      <filename>kernel/loader.rb</filename>
    </modified>
    <modified>
      <diff>@@ -183,6 +183,7 @@ class Compiler
     activate :const_epxr if Config['rbx-kernel']
     activate_default :fastsystem
     activate_default :fastgeneric
+    activate_default :fastnew
     # AutoPrimitiveDetection is currently disabled
     # TODO - Implement the opt_* primitives it requires and reactivate
     # activate_default :auto_primitive</diff>
      <filename>lib/compiler/compiler.rb</filename>
    </modified>
    <modified>
      <diff>@@ -642,8 +642,9 @@ class Compiler
     end
 
     def check_serial(sym, serial)
-      idx = find_literal(sym)
+      idx = add_literal SendSite.new(:new)
       add :check_serial, idx, serial.to_i
+      return idx
     end
 
     def create_block(desc)</diff>
      <filename>lib/compiler/generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -185,6 +185,53 @@ class Compiler
     end
 
     ##
+    # Handles speeding up #new
+
+    class FastNew &lt; Plugin
+      plugin :fastnew
+
+      # FIXME duplicated from kernel/common/compiled_method.rb
+      KernelMethodSerial = 47
+
+      def handle(g, call)
+        return false unless call.method == :new
+        return false if call.block or !call.static_args?
+
+        slow = g.new_label
+        done = g.new_label
+
+        call.receiver_bytecode(g)
+        g.dup
+        idx = g.check_serial idx, KernelMethodSerial
+        g.gif slow
+
+        # fast path
+        g.send :allocate, 0
+        g.dup
+        call.emit_args(g)
+        g.send :initialize, call.argcount, true
+        g.pop
+
+        g.goto done
+
+        # slow path
+        slow.set!
+        call.emit_args(g)
+        g.add :set_call_flags, 1
+        count = call.argcount
+        if count == 0
+          g.add :send_method, idx
+        else
+          g.add :send_stack, idx, count
+        end
+
+        done.set!
+
+        return true
+      end
+    end
+
+    ##
     # Handles emitting save VM instructions for redifinition of math operators.
 
     class SafeMathOperators &lt; Plugin</diff>
      <filename>lib/compiler/plugins.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 require 'profiler'
 
 at_exit do
-  Profiler__::print_profile(STDERR)
+  Profiler__.print_profile(STDERR)
 end
-Profiler__::start_profile
+Profiler__.start_profile</diff>
      <filename>lib/profile.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,17 +1,17 @@
 module Profiler__
   def start_profile
-    @p = Sampler.new
+    @p = Rubinius::Profiler::Instrumenter.new
     @p.start
   end
-  
+
   def stop_profile
     @p.stop
   end
-  
+
   def print_profile(f)
     stop_profile
     @p.display(f)
   end
-  
+
   module_function :start_profile, :stop_profile, :print_profile
 end</diff>
      <filename>lib/profiler.rb</filename>
    </modified>
    <modified>
      <diff>@@ -146,6 +146,7 @@ end
 COMPILER_SOURCES = Dir[&quot;lib/compiler/*.rb&quot;] +
   %w(strscan stringio racc/parser ruby_lexer ruby_parser
      ruby_parser_extras sexp sexp_processor).map { |f| &quot;lib/#{f}.rb&quot; }
+COMPILER_SOURCES &lt;&lt; &quot;kernel/delta/compiled_file.rb&quot;
 COMPILER_MTIME = COMPILER_SOURCES.map { |f| File::Stat.new(f).mtime }.max
 compiler = []
 </diff>
      <filename>rakelib/kernel.rake</filename>
    </modified>
    <modified>
      <diff>@@ -53,7 +53,7 @@ if config.use_jit
   srcs += jit_srcs
 end
 
-EX_INC      = %w[ libtommath onig libffi/include
+EX_INC      = %w[ libtommath libgdtoa onig libffi/include
                   libbstring libcchash libmquark libmpa
                   libltdl libev llvm/include
                 ].map { |f| &quot;vm/external_libs/#{f}&quot; }
@@ -129,6 +129,7 @@ EXTERNALS   = %W[ vm/external_libs/libmpa/libptr_array.a
                   vm/external_libs/libmquark/libmquark.a
                   vm/external_libs/libtommath/libtommath.a
                   vm/external_libs/libbstring/libbstring.a
+                  vm/external_libs/libgdtoa/libgdtoa.a
                   vm/external_libs/onig/.libs/libonig.a
                   vm/external_libs/libffi/.libs/libffi.a
                   vm/external_libs/libltdl/.libs/libltdl.a</diff>
      <filename>rakelib/vm.rake</filename>
    </modified>
    <modified>
      <diff>@@ -1,52 +1,52 @@
 require File.dirname(__FILE__) + '/../../spec_helper'
 
-describe &quot;Float#CONSTANTS&quot; do 
+describe &quot;Float#CONSTANTS&quot; do
   specify  &quot;the DIG value is  15&quot; do
     Float::DIG.should == 15
   end
-  
+
   it &quot;the EPSILON value is &quot; do
-    Float::EPSILON.should == 0.0000000000000002220446049250313080847263336181640625
+    Float::EPSILON.should == eval(&quot;0.0000000000000002220446049250313080847263336181640625&quot;)
   end
-  
+
   it &quot;the MANT_DIG is 53&quot; do
     Float::MANT_DIG.should == 53
   end
-  
+
   it &quot;the MAX_10_EXP is 308&quot; do
     Float::MAX_10_EXP.should == 308
   end
-  
-  it &quot;the MIN_10_EXP is -308&quot; do    
+
+  it &quot;the MIN_10_EXP is -308&quot; do
     Float::MIN_10_EXP.should == -307
-  end  
-  
-  it &quot;the MAX_EXP is 1024&quot; do    
+  end
+
+  it &quot;the MAX_EXP is 1024&quot; do
     Float::MAX_EXP.should == 1024
   end
-  
+
   it &quot;the MIN_EXP is -1021&quot; do
     Float::MIN_EXP.should == -1021
-  end   
-  
+  end
+
   it &quot;the MAX is 1.79769313486232e+308&quot; do
-    Float::MAX.should == 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0
-  end 
-  
+    Float::MAX.should == eval(&quot;179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0&quot;)
+  end
+
   # TODO: file a bug report for MRI
   not_compliant_on :ruby, :jruby do
-    it &quot;the MIN is 2.2250738585072e-308&quot; do    
-      Float::MIN.should == 2.225073858507201383090232717332404064219215980462331830553327416887204434813918195854283159012511020564067339731035811005152434161553460108856012385377718821130777993532002330479610147442583636071921565046942503734208375250806650616658158948720491179968591639648500635908770118304874799780887753749949451580451605050915399856582470818645113537935804992115981085766051992433352114352390148795699609591288891602992641511063466313393663477586513029371762047325631781485664350872122828637642044846811407613911477062801689853244110024161447421618567166150540154285084716752901903161322778896729707373123334086988983175067838846926092773977972858659654941091369095406136467568702398678315290680984617210924625396728515625e-308
+    it &quot;the MIN is 2.2250738585072e-308&quot; do
+      Float::MIN.should == eval(&quot;2.225073858507201383090232717332404064219215980462331830553327416887204434813918195854283159012511020564067339731035811005152434161553460108856012385377718821130777993532002330479610147442583636071921565046942503734208375250806650616658158948720491179968591639648500635908770118304874799780887753749949451580451605050915399856582470818645113537935804992115981085766051992433352114352390148795699609591288891602992641511063466313393663477586513029371762047325631781485664350872122828637642044846811407613911477062801689853244110024161447421618567166150540154285084716752901903161322778896729707373123334086988983175067838846926092773977972858659654941091369095406136467568702398678315290680984617210924625396728515625e-308&quot;)
     end
   end
-  
+
   # TODO: Does this actually constitute noncompliance?
   deviates_on :jruby do
     it &quot;the MIN is 4.9e-324&quot; do
       Float::MIN.should == 4.9e-324
     end
   end
-  
+
   it &quot;the RADIX is 2&quot; do
     Float::RADIX.should == 2
   end</diff>
      <filename>spec/frozen/core/float/constants_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,13 +11,13 @@ describe &quot;Time#_dump&quot; do
   ruby_bug(&quot;http://redmine.ruby-lang.org/issues/show/627&quot;, &quot;1.8.7&quot;) do
     it &quot;preserves the GMT flag&quot; do
       @t.gmt?.should == true
-      dump = @t._dump.unpack(&quot;LL&quot;).first
+      dump = @t._dump.unpack(&quot;VV&quot;).first
       ((dump &gt;&gt; 30) &amp; 0x1).should == 1
     end
 
     it &quot;dumps a Time object to a bytestring&quot; do
       @s.should be_kind_of(String)
-      @s.should == [3222863947, 2235564032].pack(&quot;LL&quot;)
+      @s.should == [3222863947, 2235564032].pack(&quot;VV&quot;)
     end
 
     it &quot;dumps an array with a date as first element&quot; do
@@ -28,7 +28,7 @@ describe &quot;Time#_dump&quot; do
                        @t.mday &lt;&lt; 5 |
                             @t.hour
 
-      high.should == @s.unpack(&quot;LL&quot;).first
+      high.should == @s.unpack(&quot;VV&quot;).first
     end
   end
 
@@ -36,7 +36,7 @@ describe &quot;Time#_dump&quot; do
     low =  @t.min  &lt;&lt; 26 |
            @t.sec  &lt;&lt; 20 |
            @t.usec
-    low.should == @s.unpack(&quot;LL&quot;).last
+    low.should == @s.unpack(&quot;VV&quot;).last
   end
 end
 </diff>
      <filename>spec/frozen/core/time/_dump_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,7 +18,7 @@ describe &quot;Time#_load&quot; do
              t.sec  &lt;&lt; 20 |
                    t.usec
 
-      Time._load([high, low].pack(&quot;LL&quot;)).should == t
+      Time._load([high, low].pack(&quot;VV&quot;)).should == t
     end
   end
 
@@ -30,6 +30,6 @@ describe &quot;Time#_load&quot; do
 
     low =  t.usec
 
-    Time._load([high, low].pack(&quot;LL&quot;)).should == t
+    Time._load([high, low].pack(&quot;VV&quot;)).should == t
   end
 end</diff>
      <filename>spec/frozen/core/time/_load_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,3 @@
-fails:Array#pack just ignores unknown format
 fails:Array#pack with format 'H' encodes hexadecimal digits to byte sequence in the order of high-nibble first
 fails:Array#pack with format 'H' ignores rest of the pack argument when the argument is too long
 fails:Array#pack with format 'H' fills low-nibble of the last byte with 0 when count is odd
@@ -6,34 +5,20 @@ fails:Array#pack with format 'H' fills the rest bytes with 0 if pack argument ha
 fails:Array#pack with format 'H' fills low-nibble of the last byte with 0 when count is odd even if pack argument has insufficient length
 fails:Array#pack with format 'H' considers count = 1 if count omited
 fails:Array#pack with format 'H' consumes only one array item per a format
-fails:Array#pack with format 'H' tries to convert the pack argument to a String using #to_str
-fails:Array#pack with format 'H' checks whether the pack argument responds to #to_str
-fails:Array#pack with format 'h' encodes hexadecimal digits to byte sequence in the order of low-nibble first
 fails:Array#pack with format 'h' ignores rest of the pack argument when the argument is too long
 fails:Array#pack with format 'h' fills low-nibble of the last byte with 0 when count is odd
 fails:Array#pack with format 'h' fills the rest bytes with 0 if pack argument has insufficient length
 fails:Array#pack with format 'h' fills high-nibble of the last byte with 0 when count is odd even if pack argument has insufficient length
 fails:Array#pack with format 'h' considers count = 1 if count omited
 fails:Array#pack with format 'h' consumes only one array item per a format
-fails:Array#pack with format 'h' tries to convert the pack argument to a String using #to_str
-fails:Array#pack with format 'h' checks whether the pack argument responds to #to_str
 fails:Array#pack with format 'n' regards negative values as 2's complement in order to converts it to positive
-fails:Array#pack with format 'n' raises an ArgumentError if count is greater than array elements left
-fails:Array#pack with format 'v' raises an ArgumentError if count is greater than array elements left
 fails:Array#pack with format 'N' regards negative values as 2's complement in order to converts it to positive
-fails:Array#pack with format 'N' raises an ArgumentError if count is greater than array elements left
-fails:Array#pack with format 'V' raises an ArgumentError if count is greater than array elements left
-fails:Array#pack with format 's' raises an ArgumentError if count is greater than array elements left
-fails:Array#pack with format 'S' raises an ArgumentError if count is greater than array elements left
-fails:Array#pack with format 'l' raises an ArgumentError if count is greater than array elements left
-fails:Array#pack with format 'L' raises an ArgumentError if count is greater than array elements left
 fails:Array#pack with format 'q' returns a string containing 8 bytes for an integer
 fails:Array#pack with format 'q' regards negative values as 2's complement in order to converts it to positive
 fails:Array#pack with format 'q' raises a RangeError when a pack argument is &gt;= 2**64
 fails:Array#pack with format 'q' raises a RangeError when a pack argument is &lt;= -2**64
 fails:Array#pack with format 'q' tries to convert the pack argument to an Integer using #to_int
 fails:Array#pack with format 'q' checks whether the pack argument responds to #to_int
-fails:Array#pack with format 'q' raises a TypeError if a pack argument can't be coerced to Integer
 fails:Array#pack with format 'q' processes count number of array elements if count given
 fails:Array#pack with format 'q' returns empty string if count = 0
 fails:Array#pack with format 'q' with star parameter processes all remaining array items
@@ -43,7 +28,6 @@ fails:Array#pack with format 'Q' raises a RangeError when a pack argument is &gt;=
 fails:Array#pack with format 'Q' raises a RangeError when a pack argument is &lt;= -2**64
 fails:Array#pack with format 'Q' tries to convert the pack argument to an Integer using #to_int
 fails:Array#pack with format 'Q' checks whether the pack argument responds to #to_int
-fails:Array#pack with format 'Q' raises a TypeError if a pack argument can't be coerced to Integer
 fails:Array#pack with format 'Q' processes count number of array elements if count given
 fails:Array#pack with format 'Q' returns empty string if count = 0
 fails:Array#pack with format 'Q' with star parameter processes all remaining array items
@@ -54,7 +38,6 @@ fails:Array#pack with format 's!' drops higher bytes when a pack argument is &lt; -
 fails:Array#pack with format 's!' tries to convert the pack argument to an Integer using #to_int
 fails:Array#pack with format 's!' checks whether the pack argument responds to #to_int
 fails:Array#pack with format 's!' processes count number of array elements if count given
-fails:Array#pack with format 's!' returns empty string if count = 0
 fails:Array#pack with format 's!' with star parameter processes all remaining array items
 fails:Array#pack with format 's_' returns a string containing 2 bytes for an integer
 fails:Array#pack with format 's_' regards negative values as 2's complement in order to converts it to positive
@@ -63,9 +46,7 @@ fails:Array#pack with format 's_' drops higher bytes when a pack argument is &lt; -
 fails:Array#pack with format 's_' tries to convert the pack argument to an Integer using #to_int
 fails:Array#pack with format 's_' checks whether the pack argument responds to #to_int
 fails:Array#pack with format 's_' processes count number of array elements if count given
-fails:Array#pack with format 's_' returns empty string if count = 0
 fails:Array#pack with format 's_' with star parameter processes all remaining array items
-fails:Array#pack with format 'S!' raises an ArgumentError if count is greater than array elements left
 fails:Array#pack with format 'S_' returns a string containing 2 bytes for an integer
 fails:Array#pack with format 'S_' regards negative values as 2's complement in order to converts it to positive
 fails:Array#pack with format 'S_' drops higher bytes when a pack argument is &gt;= 2**16
@@ -73,65 +54,54 @@ fails:Array#pack with format 'S_' drops higher bytes when a pack argument is &lt; -
 fails:Array#pack with format 'S_' tries to convert the pack argument to an Integer using #to_int
 fails:Array#pack with format 'S_' checks whether the pack argument responds to #to_int
 fails:Array#pack with format 'S_' processes count number of array elements if count given
-fails:Array#pack with format 'S_' returns empty string if count = 0
 fails:Array#pack with format 'S_' with star parameter processes all remaining array items
-fails:Array#pack with format 'i' raises an ArgumentError if count is greater than array elements left
 fails:Array#pack with format 'i!' returns a string containing 4 bytes for an integer
 fails:Array#pack with format 'i!' regards negative values as 2's complement in order to converts it to positive
 fails:Array#pack with format 'i!' tries to convert the pack argument to an Integer using #to_int
 fails:Array#pack with format 'i!' checks whether the pack argument responds to #to_int
 fails:Array#pack with format 'i!' processes count number of array elements if count given
-fails:Array#pack with format 'i!' returns empty string if count = 0
 fails:Array#pack with format 'i!' with star parameter processes all remaining array items
 fails:Array#pack with format 'i_' returns a string containing 4 bytes for an integer
 fails:Array#pack with format 'i_' regards negative values as 2's complement in order to converts it to positive
 fails:Array#pack with format 'i_' tries to convert the pack argument to an Integer using #to_int
 fails:Array#pack with format 'i_' checks whether the pack argument responds to #to_int
 fails:Array#pack with format 'i_' processes count number of array elements if count given
-fails:Array#pack with format 'i_' returns empty string if count = 0
 fails:Array#pack with format 'i_' with star parameter processes all remaining array items
-fails:Array#pack with format 'I' raises an ArgumentError if count is greater than array elements left
 fails:Array#pack with format 'I!' returns a string containing 4 bytes for an integer
 fails:Array#pack with format 'I!' regards negative values as 2's complement in order to converts it to positive
 fails:Array#pack with format 'I!' tries to convert the pack argument to an Integer using #to_int
 fails:Array#pack with format 'I!' checks whether the pack argument responds to #to_int
 fails:Array#pack with format 'I!' processes count number of array elements if count given
-fails:Array#pack with format 'I!' returns empty string if count = 0
 fails:Array#pack with format 'I!' with star parameter processes all remaining array items
 fails:Array#pack with format 'I_' returns a string containing 4 bytes for an integer
 fails:Array#pack with format 'I_' regards negative values as 2's complement in order to converts it to positive
 fails:Array#pack with format 'I_' tries to convert the pack argument to an Integer using #to_int
 fails:Array#pack with format 'I_' checks whether the pack argument responds to #to_int
 fails:Array#pack with format 'I_' processes count number of array elements if count given
-fails:Array#pack with format 'I_' returns empty string if count = 0
 fails:Array#pack with format 'I_' with star parameter processes all remaining array items
 fails:Array#pack with format 'l!' returns a string containing 4 bytes for an integer
 fails:Array#pack with format 'l!' regards negative values as 2's complement in order to converts it to positive
 fails:Array#pack with format 'l!' tries to convert the pack argument to an Integer using #to_int
 fails:Array#pack with format 'l!' checks whether the pack argument responds to #to_int
 fails:Array#pack with format 'l!' processes count number of array elements if count given
-fails:Array#pack with format 'l!' returns empty string if count = 0
 fails:Array#pack with format 'l!' with star parameter processes all remaining array items
 fails:Array#pack with format 'l_' returns a string containing 4 bytes for an integer
 fails:Array#pack with format 'l_' regards negative values as 2's complement in order to converts it to positive
 fails:Array#pack with format 'l_' tries to convert the pack argument to an Integer using #to_int
 fails:Array#pack with format 'l_' checks whether the pack argument responds to #to_int
 fails:Array#pack with format 'l_' processes count number of array elements if count given
-fails:Array#pack with format 'l_' returns empty string if count = 0
 fails:Array#pack with format 'l_' with star parameter processes all remaining array items
 fails:Array#pack with format 'L!' returns a string containing 4 bytes for an integer
 fails:Array#pack with format 'L!' regards negative values as 2's complement in order to converts it to positive
 fails:Array#pack with format 'L!' tries to convert the pack argument to an Integer using #to_int
 fails:Array#pack with format 'L!' checks whether the pack argument responds to #to_int
 fails:Array#pack with format 'L!' processes count number of array elements if count given
-fails:Array#pack with format 'L!' returns empty string if count = 0
 fails:Array#pack with format 'L!' with star parameter processes all remaining array items
 fails:Array#pack with format 'L_' returns a string containing 4 bytes for an integer
 fails:Array#pack with format 'L_' regards negative values as 2's complement in order to converts it to positive
 fails:Array#pack with format 'L_' tries to convert the pack argument to an Integer using #to_int
 fails:Array#pack with format 'L_' checks whether the pack argument responds to #to_int
 fails:Array#pack with format 'L_' processes count number of array elements if count given
-fails:Array#pack with format 'L_' returns empty string if count = 0
 fails:Array#pack with format 'L_' with star parameter processes all remaining array items
 fails:Array#pack with format 'f' consumes as many Floats as specified
 fails:Array#pack with format 'f' tries to convert the pack argument to a Float using #to_f
@@ -228,23 +198,15 @@ fails:Array#pack with format 'u' appends newline whenever after consumes [number
 fails:Array#pack with format 'w' converts to BER-compressed integer
 fails:Array#pack with format 'w' raises an ArgumentError if the count is greater than the number of remaining array elements
 fails:Array#pack with format 'w' raises TypeError on nil and non-numeric arguments
-fails:Array#pack with '@' moves the end of result string into the specified position by offset from head
-fails:Array#pack with '@' fills blank with NUL bytes if the position exceeds the end of string
-fails:Array#pack with '@' concatenates successing formats at the position '@' moves it into
-fails:Array#pack with '@' does not recover lost bytes when shorten the string and then extends it again
-fails:Array#pack with '@' is able to work with 'X'
 fails:Array#pack with format 'p' consumes a String
 fails:Array#pack with format 'p' tries to convert the pack argument to a String using #to_str
 fails:Array#pack with format 'p' checks whether the pack argument responds to #to_str
-fails:Array#pack with format 'p' raises a TypeError if corresponding array item is not String
-fails:Array#pack with format 'p' returns empty string if count = 0 with
 fails:Array#pack with format 'p' only takes as many elements as specified after ('p')
 fails:Array#pack with format 'p' consumes the whole argument string with star parameter
 fails:Array#pack with format 'P' consumes a String
 fails:Array#pack with format 'P' returns null pointer when passed nil
 fails:Array#pack with format 'P' tries to convert the pack argument to a String using #to_str
 fails:Array#pack with format 'P' checks whether the pack argument responds to #to_str
-fails:Array#pack with format 'P' raises a TypeError if corresponding array item is not String
 fails:Array#pack with format 'P' consumes one array item per a format
 fails:Array#pack with format 'P' ignores '*' parameter
 fails:Array#pack with format 'P' returns a pointer to zero-length byte sequence if count = 0 with</diff>
      <filename>spec/tags/frozen/core/array/pack_tags.txt</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1 @@
 fails:Float#/ properly handles BigDecimal argument
-fails:Float#/ does NOT raise ZeroDivisionError if other is zero
-fails:Float#/ returns self divided by other</diff>
      <filename>spec/tags/frozen/core/float/divide_tags.txt</filename>
    </modified>
    <modified>
      <diff>@@ -48,14 +48,9 @@ namespace rubinius {
     }
     task-&gt;pop(); // Remove this from the stack.
     BlockContext* ctx = create_context(state, task-&gt;active());
-    if(task-&gt;profiler) {
-      profiler::Method* prof_meth = task-&gt;profiler-&gt;enter_method(
-          as&lt;Symbol&gt;(home_-&gt;name()), home_-&gt;module()-&gt;name(), profiler::kBlock);
 
-      if(!prof_meth-&gt;file()) {
-        prof_meth-&gt;set_position(method_-&gt;file(), method_-&gt;start_line(state));
-      }
-    }
+    if(unlikely(task-&gt;profiler)) task-&gt;profiler-&gt;enter_block(state, home_, method_);
+
     task-&gt;make_active(ctx);
     task-&gt;push(val);
   }
@@ -73,14 +68,8 @@ namespace rubinius {
       val = Qnil;
     }
     BlockContext* ctx = create_context(state, task-&gt;active());
-    if(task-&gt;profiler) {
-      profiler::Method* prof_meth = task-&gt;profiler-&gt;enter_method(
-          as&lt;Symbol&gt;(home_-&gt;name()), home_-&gt;module()-&gt;name(), profiler::kBlock);
 
-      if(!prof_meth-&gt;file()) {
-        prof_meth-&gt;set_position(method_-&gt;file(), method_-&gt;start_line(state));
-      }
-    }
+    if(unlikely(task-&gt;profiler)) task-&gt;profiler-&gt;enter_block(state, home_, method_);
 
     // HACK: manually clear the stack used as args.
     task-&gt;active()-&gt;clear_stack(msg.stack);</diff>
      <filename>vm/builtin/block_environment.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -20,7 +20,7 @@ namespace rubinius {
   private:
     MethodContext* home_;       // slot
     MethodContext* home_block_; // slot
-    Object* local_count_;        // slot
+    Object* local_count_;       // slot
     CompiledMethod* method_;    // slot
 
   public:</diff>
      <filename>vm/builtin/block_environment.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -213,7 +213,10 @@ namespace rubinius {
     return Bignum::from_double(state, this-&gt;val);
   }
 
-#define FLOAT_TO_S_STRLEN   1024
+/* It requires &quot;%.1022f&quot; to print all digits of Float::MIN.
+ * If you really need more digits than that, change this constant.
+ */
+#define FLOAT_TO_S_STRLEN   1280
 
   String* Float::to_s_formatted(STATE, String* format) {
     char str[FLOAT_TO_S_STRLEN];</diff>
      <filename>vm/builtin/float.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -57,12 +57,12 @@ namespace rubinius {
     const static object_type type = IncludedModuleType;
 
   private:
-    Object* module_; // slot
+    Module* module_; // slot
 
   public:
     /* accessors */
 
-    attr_accessor(module, Object);
+    attr_accessor(module, Module);
 
     /* interface */
     static IncludedModule* create(STATE);</diff>
      <filename>vm/builtin/module.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,5 @@
 #include &lt;iostream&gt;
+#include &lt;sstream&gt;
 
 #include &lt;cstdarg&gt;
 
@@ -397,6 +398,36 @@ namespace rubinius {
     return val;
   }
 
+  String* Object::to_s(STATE, bool address) {
+    std::stringstream name;
+
+    name &lt;&lt; &quot;#&lt;&quot;;
+    if(Module* mod = try_as&lt;Module&gt;(this)) {
+      if(mod-&gt;name()-&gt;nil_p()) {
+        name &lt;&lt; &quot;Class&quot;;
+      } else {
+        name &lt;&lt; mod-&gt;name()-&gt;c_str(state);
+      }
+      name &lt;&lt; &quot;(&quot; &lt;&lt; this-&gt;class_object(state)-&gt;name()-&gt;c_str(state) &lt;&lt; &quot;)&quot;;
+    } else {
+      if(this-&gt;class_object(state)-&gt;name()-&gt;nil_p()) {
+        name &lt;&lt; &quot;Object&quot;;
+      } else {
+        name &lt;&lt; this-&gt;class_object(state)-&gt;name()-&gt;c_str(state);
+      }
+    }
+
+    name &lt;&lt; &quot;:&quot;;
+    if(address) {
+      name &lt;&lt; reinterpret_cast&lt;void*&gt;(this);
+    } else {
+      name &lt;&lt; &quot;0x&quot; &lt;&lt; std::hex &lt;&lt; this-&gt;id(state)-&gt;to_native();
+    }
+    name &lt;&lt; &quot;&gt;&quot;;
+
+    return String::create(state, name.str().c_str());
+  }
+
   Object* Object::show(STATE) {
     return show(state, 0);
   }</diff>
      <filename>vm/builtin/object.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -336,6 +336,14 @@ namespace rubinius {
     // Ruby.primitive :object_untaint
     Object*   untaint();
 
+    /**
+     *  Returns an #inspect-like representation of an Object for
+     *  use in C++ code. Not called from Ruby code.
+     *
+     *  If address is true, uses the actual address of the object.
+     *  Otherwise, uses the object's id().
+     */
+    String* to_s(STATE, bool address = false);
 
   public:   /* accessors */
 </diff>
      <filename>vm/builtin/object.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -147,6 +147,36 @@ namespace rubinius {
     return true;
   }
 
+  bool SendSite::check_serial(STATE, MethodContext* current, Object* recv, int serial) {
+    // If empty, fill.
+    if(method_ == Qnil) {
+      Message msg(state);
+      msg.recv = recv;
+      msg.lookup_from = recv-&gt;lookup_begin(state);
+      msg.name = name_;
+      msg.priv = false;
+      msg.set_caller(current);
+
+      // Can't be resolved initially? bail.
+      if(!GlobalCacheResolver::resolve(state, msg)) {
+        return false;
+      }
+
+      module(state, msg.module);
+      method(state, msg.method);
+      recv_class(state, msg.lookup_from);
+      method_missing = msg.method_missing;
+
+      if(unlikely(method_missing)) {
+        this-&gt;performer = performer::mono_mm_performer;
+      } else {
+        this-&gt;performer = performer::mono_performer;
+      }
+    }
+
+    return method_-&gt;serial()-&gt;to_native() == serial;
+  }
+
   /* Fill in details about +msg+ by looking up the class heirarchy
    * and in method tables. Returns true if lookup was successful
    * and +msg+ is now filled in. */</diff>
      <filename>vm/builtin/sendsite.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -9,6 +9,7 @@ namespace rubinius {
   class Selector;
   class Message;
   class SendSite;
+  class MethodContext;
 
   typedef bool (*MethodResolver)(STATE, Message&amp; msg);
 
@@ -63,6 +64,10 @@ namespace rubinius {
     void initialize(STATE);
     bool locate(STATE, Message&amp; msg);
 
+    // Check and see if the method referenced has the given serial
+    // Sideffect: populates the sendsite if empty
+    bool check_serial(STATE, MethodContext* current, Object* reciever, int serial);
+
     class Info : public TypeInfo {
     public:
       BASIC_TYPEINFO(TypeInfo)</diff>
      <filename>vm/builtin/sendsite.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -10,9 +10,10 @@
 #include &quot;parser/grammar.hpp&quot;
 
 #include &quot;vm.hpp&quot;
-#include &quot;vm/object_utils.hpp&quot;
-#include &quot;primitives.hpp&quot;
+#include &quot;object_utils.hpp&quot;
 #include &quot;objectmemory.hpp&quot;
+#include &quot;primitives.hpp&quot;
+#include &quot;strtod.hpp&quot;
 
 #include &quot;bstrlib.h&quot;
 </diff>
      <filename>vm/builtin/string.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -95,10 +95,6 @@ namespace rubinius {
   }
 
   Object* System::vm_exit(STATE, Fixnum* code) {
-    if(getenv(&quot;JIT_STATS&quot;)) {
-      std::cout &lt;&lt; &quot;JITed methods: &quot; &lt;&lt; state-&gt;jitted_methods &lt;&lt; &quot;\n&quot;;
-      std::cout &lt;&lt; &quot;     JIT Time: &quot; &lt;&lt; (state-&gt;jit_timing / 1000000) &lt;&lt; &quot;ms\n&quot;;
-    }
     ::exit(code-&gt;to_native());
     return code;
   }
@@ -172,14 +168,13 @@ namespace rubinius {
     return Qnil;
   }
 
-  Object* System::vm_start_profiler(STATE) {
+  Object* System::vm_profiler_instrumenter_start(STATE) {
     G(current_task)-&gt;enable_profiler();
     return Qtrue;
   }
 
-  Object* System::vm_stop_profiler(STATE, String* path) {
-    G(current_task)-&gt;disable_profiler(path-&gt;c_str());
-    return path;
+  LookupTable* System::vm_profiler_instrumenter_stop(STATE) {
+    return G(current_task)-&gt;disable_profiler();
   }
 
   Object* System::vm_write_error(STATE, String* str) {
@@ -193,10 +188,14 @@ namespace rubinius {
     }
 
     Array* ary = Array::create(state, 2);
-    ary-&gt;set(state, 0, Integer::from(state, state-&gt;jit_timing));
-    ary-&gt;set(state, 1, Integer::from(state, state-&gt;jitted_methods));
+    ary-&gt;set(state, 0, Integer::from(state, state-&gt;stats.jit_timing));
+    ary-&gt;set(state, 1, Integer::from(state, state-&gt;stats.jitted_methods));
 
     return ary;
   }
 
+  Object*  System::vm_gc_info(STATE) {
+    return Integer::from(state, state-&gt;stats.time_in_gc);
+  }
+
 }</diff>
      <filename>vm/builtin/system.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -114,16 +114,16 @@ namespace rubinius {
     static Object*  vm_show_backtrace(STATE, Object* ctx);
 
     /**
-     *  Starts the profiler.
+     *  Starts the instrumenting profiler.
      */
-    // Ruby.primitive :vm_start_profiler
-    static Object*  vm_start_profiler(STATE);
+    // Ruby.primitive :vm_profiler_instrumenter_start
+    static Object*  vm_profiler_instrumenter_start(STATE);
 
     /**
-     *  Stops the profiler.
+     *  Stops the instrumenting profiler.
      */
-    // Ruby.primitive :vm_stop_profiler
-    static Object*  vm_stop_profiler(STATE, String* path);
+    // Ruby.primitive :vm_profiler_instrumenter_stop
+    static LookupTable*  vm_profiler_instrumenter_stop(STATE);
 
     /**
      *  Writes String to standard error stream.
@@ -137,6 +137,12 @@ namespace rubinius {
     // Ruby.primitive :vm_jit_info
     static Object*  vm_jit_info(STATE);
 
+    /**
+     *  Returns information about the GC.
+     */
+    // Ruby.primitive :vm_gc_info
+    static Object*  vm_gc_info(STATE);
+
 
   public:   /* Type info */
 </diff>
      <filename>vm/builtin/system.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -557,14 +557,16 @@ namespace rubinius {
     profiler = new profiler::Profiler();
   }
 
-  void Task::disable_profiler(const char* results) {
+  LookupTable* Task::disable_profiler() {
+    LookupTable* tbl = (LookupTable*)Qnil;
+
     if(profiler) {
-      std::ofstream stream(results);
-      profiler-&gt;print_results(state, stream);
+      tbl = profiler-&gt;results(state);
       delete profiler;
     }
-
     profiler = NULL;
+
+    return tbl;
   }
 
   /* This should only ever run for CompiledMethods currently. */</diff>
      <filename>vm/builtin/task.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -21,6 +21,7 @@ namespace rubinius {
   class Exception;
   class TaskProbe;
   class Tuple;
+  class LookupTable;
   class LookupTableAssociation;
 
   class Task;
@@ -153,7 +154,7 @@ namespace rubinius {
     void tragic_failure(Message&amp; msg);
 
     void enable_profiler();
-    void disable_profiler(const char* results);
+    LookupTable* disable_profiler();
 
     // Add +ctx+ to the context chain by setting the active context
     // to +ctx+'s sender and making +ctx+ active.</diff>
      <filename>vm/builtin/task.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -67,21 +67,32 @@ namespace rubinius {
     int olength = length-&gt;to_native();
 
     // left end should be within range
-    if(olend &lt; 0 || (size_t)olend &gt; osize) Exception::object_bounds_exceeded_error(state, other, olend);
-    if(lend &lt; 0 || (size_t)lend &gt; size) Exception::object_bounds_exceeded_error(state, this, lend);
+    if(olend &lt; 0 || (size_t)olend &gt; osize) {
+      Exception::object_bounds_exceeded_error(state, other, olend);
+    }
+
+    if(lend &lt; 0 || (size_t)lend &gt; size) {
+      Exception::object_bounds_exceeded_error(state, this, lend);
+    }
 
     // length can not be negative and must fit in src/dest
     if(olength &lt; 0) {
       Exception::object_bounds_exceeded_error(state, &quot;length must be positive&quot;);
     }
+
     if((size_t)(olend + olength) &gt; osize) {
-      Exception::object_bounds_exceeded_error(state, &quot;length should not exceed size of source&quot;);
+      Exception::object_bounds_exceeded_error(state,
+          &quot;length should not exceed size of source&quot;);
     }
+
     if((size_t)olength &gt; (size - lend)) {
-      Exception::object_bounds_exceeded_error(state, &quot;length should not exceed space in destination&quot;);
+      Exception::object_bounds_exceeded_error(state,
+          &quot;length should not exceed space in destination&quot;);
     }
 
-    for(size_t src = olend, dst = lend; src &lt; (size_t)(olend + olength); ++src, ++dst) {
+    for(size_t src = olend, dst = lend;
+        src &lt; (size_t)(olend + olength);
+        ++src, ++dst) {
       // Since we have carefully checked the bounds we don't need to do it in at/put
       Object *obj = other-&gt;field[src];
       this-&gt;field[dst] = obj;
@@ -98,31 +109,36 @@ namespace rubinius {
     int rend = lend + length-&gt;to_native();
 
     if(size == 0) return Fixnum::from(0);
-    if(lend &lt; 0 || lend &gt;= size) Exception::object_bounds_exceeded_error(state, this, lend);
-    if(rend &lt; 0 || rend &gt; size) Exception::object_bounds_exceeded_error(state, this, rend);
+    if(lend &lt; 0 || lend &gt;= size) {
+      Exception::object_bounds_exceeded_error(state, this, lend);
+    }
+
+    if(rend &lt; 0 || rend &gt; size) {
+      Exception::object_bounds_exceeded_error(state, this, rend);
+    }
 
     int i = lend;
     while(i &lt; rend) {
       if(this-&gt;at(state,i) == obj) {
-	int j = i;
-	++i;
-	while(i &lt; rend) {
-	  Object *val = this-&gt;field[i];
-	  if(val != obj) {
-	    // no need to set write_barrier since it's already
-	    // referenced to this object
-	    this-&gt;field[j] = val;
-	    ++j;
-	  }
-	  ++i;
-	}
-	// cleanup all the bins after
-	i = j;
-	while(i &lt; rend) {
-	  this-&gt;field[i] = Qnil;
-	  ++i;
-	}
-	return Fixnum::from(rend-j);
+        int j = i;
+        ++i;
+        while(i &lt; rend) {
+          Object *val = this-&gt;field[i];
+          if(val != obj) {
+            // no need to set write_barrier since it's already
+            // referenced to this object
+            this-&gt;field[j] = val;
+            ++j;
+          }
+          ++i;
+        }
+        // cleanup all the bins after
+        i = j;
+        while(i &lt; rend) {
+          this-&gt;field[i] = Qnil;
+          ++i;
+        }
+        return Fixnum::from(rend-j);
       }
       ++i;
     }
@@ -179,9 +195,9 @@ namespace rubinius {
       indent(level);
       Object* obj = tup-&gt;at(state, i);
       if(obj == tup) {
-	class_info(state, self, true);
+        class_info(state, self, true);
       } else {
-	obj-&gt;show(state, level);
+        obj-&gt;show(state, level);
       }
     }
     if(tup-&gt;num_fields() &gt; stop) ellipsis(level);
@@ -205,10 +221,10 @@ namespace rubinius {
       indent(level);
       Object* obj = tup-&gt;at(state, i);
       if(Tuple* t = try_as&lt;Tuple&gt;(obj)) {
-	class_info(state, self);
-	std::cout &lt;&lt; &quot;: &quot; &lt;&lt; t-&gt;num_fields() &lt;&lt; &quot;&gt;&quot; &lt;&lt; std::endl;
+        class_info(state, self);
+        std::cout &lt;&lt; &quot;: &quot; &lt;&lt; t-&gt;num_fields() &lt;&lt; &quot;&gt;&quot; &lt;&lt; std::endl;
       } else {
-	obj-&gt;show_simple(state, level);
+        obj-&gt;show_simple(state, level);
       }
     }
     if(tup-&gt;num_fields() &gt; stop) ellipsis(level);</diff>
      <filename>vm/builtin/tuple.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -39,7 +39,9 @@ class BasicPrimitive
   def output_call(str, call, args)
     str &lt;&lt; &quot;\n&quot;
     str &lt;&lt; &quot;  try {\n&quot;
+    str &lt;&lt; &quot;    if(unlikely(task-&gt;profiler)) task-&gt;profiler-&gt;enter_primitive(state, msg);\n&quot;
     str &lt;&lt; &quot;    ret = #{call}(#{args.join(', ')});\n&quot;
+    str &lt;&lt; &quot;    if(unlikely(task-&gt;profiler)) task-&gt;profiler-&gt;leave_method();\n&quot;
     str &lt;&lt; &quot;  } catch(const RubyException&amp; exc) {\n&quot;
     str &lt;&lt; &quot;    task-&gt;raise_exception(exc.exception);\n&quot;
     str &lt;&lt; &quot;    return cExecuteRestart;\n&quot;
@@ -144,11 +146,14 @@ class CPPOverloadedPrimitive &lt; BasicPrimitive
       type = prim.arg_types.first
       str &lt;&lt; &quot;    if(#{type}* arg = try_as&lt;#{type}&gt;(msg.get_argument(0))) {\n&quot;
       str &lt;&lt; &quot;      try {\n&quot;
+      str &lt;&lt; &quot;        if(unlikely(task-&gt;profiler))\n&quot;
+      str &lt;&lt; &quot;          task-&gt;profiler-&gt;enter_primitive(state, msg);\n&quot;
       if @pass_state
         str &lt;&lt; &quot;      ret = recv-&gt;#{@cpp_name}(state, arg);\n&quot;
       else
         str &lt;&lt; &quot;      ret = recv-&gt;#{@cpp_name}(arg);\n&quot;
       end
+      str &lt;&lt; &quot;        if(unlikely(task-&gt;profiler)) task-&gt;profiler-&gt;leave_method();\n&quot;
       str &lt;&lt; &quot;      } catch(const RubyException&amp; exc) {\n&quot;
       str &lt;&lt; &quot;        task-&gt;raise_exception(exc.exception);\n&quot;
       str &lt;&lt; &quot;        return cExecuteRestart;\n&quot;</diff>
      <filename>vm/codegen/field_extract.rb</filename>
    </modified>
    <modified>
      <diff>@@ -400,7 +400,7 @@ class Instructions
   # [Operation]
   #   Checks if the specified method serial number matches an expected value
   # [Format]
-  #   \check_serial method serial
+  #   \check_serial sendsite serial
   # [Stack Before]
   #   * obj
   #   * ...
@@ -429,10 +429,10 @@ class Instructions
 
   def check_serial(index, serial)
     &lt;&lt;-CODE
-    Object* t1 = stack_pop();
-    Symbol* sym = as&lt;Symbol&gt;(task-&gt;literals()-&gt;at(state, index));
+    Object* recv = stack_pop();
+    SendSite* ss = as&lt;SendSite&gt;(task-&gt;literals()-&gt;at(state, index));
 
-    if(task-&gt;check_serial(t1, sym, serial)) {
+    if(ss-&gt;check_serial(state, ctx, recv, serial)) {
       stack_push(Qtrue);
     } else {
       stack_push(Qfalse);
@@ -444,7 +444,8 @@ class Instructions
     &lt;&lt;-CODE
       Fixnum* s = Fixnum::from(100);
       Symbol* sym = String::create(state, &quot;to_s&quot;)-&gt;to_sym(state);
-      task-&gt;literals()-&gt;put(state, 0, sym);
+      SendSite* ss = SendSite::create(state, sym);
+      task-&gt;literals()-&gt;put(state, 0, ss);
 
       TS_ASSERT_EQUALS(Qnil, cm-&gt;serial());
       task-&gt;add_method(G(fixnum_class), sym, cm);
@@ -2959,7 +2960,8 @@ slow_path:
       // === manual inline ===
       // == restore_sender ==
 
-      // if(unlikely(profiler)) profiler-&gt;leave_method();
+      if(unlikely(task-&gt;profiler)) task-&gt;profiler-&gt;leave_method();
+
       /* Try to recycle this context to be used again. */
       if(active_context-&gt;young_object_p()) {
         state-&gt;om-&gt;deallocate_context(active_context);</diff>
      <filename>vm/instructions.rb</filename>
    </modified>
    <modified>
      <diff>@@ -24,6 +24,7 @@
 #include &quot;objectmemory.hpp&quot;
 #include &quot;message.hpp&quot;
 #include &quot;instructions.hpp&quot;
+#include &quot;profiler.hpp&quot;
 
 using namespace rubinius;
 </diff>
      <filename>vm/llvm/instructions.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,13 @@
 #include &lt;cctype&gt;
 #include &lt;cstring&gt;
+#include &lt;cmath&gt;
+#include &lt;iomanip&gt;
 
 #include &quot;objectmemory.hpp&quot;
 #include &quot;marshal.hpp&quot;
 
-#include &quot;vm/object_utils.hpp&quot;
+#include &quot;object_utils.hpp&quot;
+#include &quot;strtod.hpp&quot;
 
 #include &quot;builtin/sendsite.hpp&quot;
 #include &quot;builtin/array.hpp&quot;
@@ -144,8 +147,30 @@ namespace rubinius {
     return tup;
   }
 
+#define FLOAT_EXP_OFFSET    58
+#define FLOAT_MAX_BUFFER    65
+
   void Marshaller::set_float(Float* flt) {
-    stream &lt;&lt; &quot;d&quot; &lt;&lt; endl &lt;&lt; flt-&gt;val &lt;&lt; endl;
+    double val = flt-&gt;val;
+
+    stream &lt;&lt; &quot;d&quot; &lt;&lt; endl;
+
+    if(std::isinf(val)) {
+      if(val &lt; 0.0) stream &lt;&lt; &quot;-&quot;;
+      stream &lt;&lt; &quot;Infinity&quot;;
+    } else if(std::isnan(val)) {
+      stream &lt;&lt; &quot;NaN&quot;;
+    } else {
+      char   data[FLOAT_MAX_BUFFER];
+      double x;
+      int    e;
+
+      x = ::frexp(val, &amp;e);
+      snprintf(data, FLOAT_MAX_BUFFER, &quot; %+.54f %5d&quot;, x, e);
+      stream &lt;&lt; data;
+    }
+
+    stream &lt;&lt; endl;
   }
 
   Float* UnMarshaller::get_float() {
@@ -159,12 +184,20 @@ namespace rubinius {
       Exception::type_error(state, &quot;Unable to unmarshal Float: failed to read value&quot;);
     }
 
-    char c = data[0];
-    if(c == '-') c = data[1];
+    if(data[0] == ' ') {
+      double x;
+      long   e;
+
+      x = strtod(data, NULL);
+      e = strtol(data+FLOAT_EXP_OFFSET, NULL, 10);
 
-    if(std::isdigit(c)) {
-      // @todo use ruby_strtod
-      return Float::create(state, strtod(data, NULL));
+      // This is necessary because exp2(1024) yields inf
+      if(e == 1024) {
+        double root_exp = ::exp2(512);
+        return Float::create(state, x * root_exp * root_exp);
+      } else {
+        return Float::create(state, x * ::exp2(e));
+      }
     } else {
       // avoid compiler warning
       double zero = 0.0;
@@ -172,9 +205,9 @@ namespace rubinius {
 
       if(!strncasecmp(data, &quot;Infinity&quot;, 8U)) {
         val = 1.0;
-      } else if(!strncmp(data, &quot;-Infinity&quot;, 9U)) {
+      } else if(!strncasecmp(data, &quot;-Infinity&quot;, 9U)) {
         val = -1.0;
-      } else if(!strncmp(data, &quot;NaN&quot;, 3U)) {
+      } else if(!strncasecmp(data, &quot;NaN&quot;, 3U)) {
         val = zero;
       } else {
         Exception::type_error(state, &quot;Unable to unmarshal Float: invalid format&quot;);</diff>
      <filename>vm/marshal.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -9120,21 +9120,6 @@ yylex(void *yylval_v, void *vstate)
                 yyerror(tmp);
             }
             if (is_float) {
-                /* Some implementations of strtod() don't guarantee to
-                 * set errno, so we need to reset it ourselves.
-                 */
-                errno = 0;
-
-		/* HACK: gcc 4.3.2 refuses to accept (void) to ignore
-		 * the return value so we have to invent something
-		 * fake for it to do instead
-		 */
-                if(strtod(tok(), 0));
-
-                if (errno == ERANGE) {
-                    rb_warn(&quot;Float %s out of range&quot;, tok());
-                    errno = 0;
-                }
                 pslval-&gt;node = NEW_FLOAT(string_new2(tok()));
                 return tFLOAT;
             }</diff>
      <filename>vm/parser/grammar.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -4084,21 +4084,6 @@ yylex(void *yylval_v, void *vstate)
                 yyerror(tmp);
             }
             if (is_float) {
-                /* Some implementations of strtod() don't guarantee to
-                 * set errno, so we need to reset it ourselves.
-                 */
-                errno = 0;
-
-		/* HACK: gcc 4.3.2 refuses to accept (void) to ignore
-		 * the return value so we have to invent something
-		 * fake for it to do instead
-		 */
-                if(strtod(tok(), 0));
-
-                if (errno == ERANGE) {
-                    rb_warn(&quot;Float %s out of range&quot;, tok());
-                    errno = 0;
-                }
                 pslval-&gt;node = NEW_FLOAT(string_new2(tok()));
                 return tFLOAT;
             }</diff>
      <filename>vm/parser/grammar.y</filename>
    </modified>
    <modified>
      <diff>@@ -4,6 +4,7 @@
 #include &quot;event.hpp&quot;
 #include &quot;gen/includes.hpp&quot;
 #include &quot;message.hpp&quot;
+#include &quot;profiler.hpp&quot;
 
 #include &lt;iostream&gt;
 </diff>
      <filename>vm/primitives.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -1,38 +1,20 @@
 #include &quot;vm/profiler.hpp&quot;
 
 #include &quot;vm/object_utils.hpp&quot;
-#include &quot;vm/vm.hpp&quot;
 
+#include &quot;builtin/array.hpp&quot;
+#include &quot;builtin/class.hpp&quot;
+#include &quot;builtin/compiledmethod.hpp&quot;
+#include &quot;builtin/contexts.hpp&quot;
+#include &quot;builtin/integer.hpp&quot;
+#include &quot;builtin/lookuptable.hpp&quot;
+#include &quot;builtin/module.hpp&quot;
+#include &quot;builtin/string.hpp&quot;
 #include &quot;builtin/symbol.hpp&quot;
 #include &quot;detection.hpp&quot;
+#include &quot;message.hpp&quot;
 
-// HACK figure out a better way to detect if we should use
-// mach_absolute_time
-#if defined(OS_X_ANCIENT) || \
-	defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) &amp;&amp; \
-    __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ &gt;= 1050
-  #define USE_MACH_TIME
-#endif
-
-#ifdef USE_MACH_TIME
-
-#include &lt;mach/mach_time.h&gt;
-#define current_time() mach_absolute_time()
-#define METHOD &quot;mach_absolute_time&quot;
-
-#else
-
-uint64_t current_time() {
-  timespec tp;
-  if (clock_gettime(CLOCK_REALTIME, &amp;tp)) {
-    // error! Do something about it?
-    return 0U;
-  }
-  return tp.tv_sec * 1000000000UL + tp.tv_nsec;
-}
-#define METHOD &quot;clock_gettime&quot;
-
-#endif
+#include &quot;timing.hpp&quot;
 
 #include &lt;time.h&gt;
 
@@ -54,11 +36,11 @@ namespace rubinius {
     }
 
     void Invocation::start() {
-      start_time_ = current_time();
+      start_time_ = get_current_time();
     }
 
     void Invocation::stop() {
-      leaf_-&gt;add_total_time(current_time() - start_time_);
+      leaf_-&gt;add_total_time(get_current_time() - start_time_);
     }
 
     Method::~Method() {
@@ -84,6 +66,35 @@ namespace rubinius {
 
     }
 
+    String* Method::name(STATE) {
+      const char *module = &quot;&quot;;
+      const char *method_name = method()-&gt;c_str(state);
+
+      if(Symbol* klass = try_as&lt;Symbol&gt;(container())) {
+        module = klass-&gt;c_str(state);
+      }
+
+      String* name = String::create(state, module);
+
+      switch(kind()) {
+      case kNormal:
+        name-&gt;append(state, &quot;#&quot;);
+        name-&gt;append(state, method_name);
+        break;
+      case kSingleton:
+        name-&gt;append(state, &quot;.&quot;);
+        name-&gt;append(state, method_name);
+        break;
+      case kBlock:
+        name-&gt;append(state, &quot;#&quot;);
+        name-&gt;append(state, method_name);
+        name-&gt;append(state, &quot; {}&quot;);
+        break;
+      }
+
+      return name;
+    }
+
     uint64_t Method::total_time_in_ns() {
       return in_nanoseconds(total_time_);
     }
@@ -124,32 +135,69 @@ namespace rubinius {
       delete top_;
     }
 
-    Method* Profiler::enter_method(Symbol* name, Object* container, Kind kind) {
-      Key key(name, container, kind);
+    Symbol* Profiler::module_name(Module* module) {
+      if(IncludedModule* im = try_as&lt;IncludedModule&gt;(module)) {
+        return im-&gt;module()-&gt;name();
+      } else {
+        return module-&gt;name();
+      }
+    }
+
+    void Profiler::enter_block(STATE, MethodContext* ctx, CompiledMethod* cm) {
+      record_method(state, cm, as&lt;Symbol&gt;(ctx-&gt;name()),
+          module_name(ctx-&gt;module()), kBlock);
+    }
+
+    void Profiler::enter_primitive(STATE, Message&amp; msg) {
+      enter_method(state, msg, (CompiledMethod*)Qnil);
+    }
+
+    void Profiler::enter_method(STATE, Message &amp;msg, CompiledMethod* cm) {
+      if(MetaClass* mc = try_as&lt;MetaClass&gt;(msg.module)) {
+        Object* attached = mc-&gt;attached_instance();
+
+        if(Module* mod = try_as&lt;Module&gt;(attached)) {
+          record_method(state, cm, msg.name, mod-&gt;name(), kSingleton);
+        } else {
+          Symbol* name = msg.recv-&gt;to_s(state)-&gt;to_sym(state);
+          record_method(state, cm, msg.name, name, kSingleton);
+        }
+      } else {
+        record_method(state, cm, msg.name, module_name(msg.module), kNormal);
+      }
+    }
 
-      Method* meth;
+    Method* Profiler::record_method(STATE, CompiledMethod* cm, Symbol* name,
+                                 Object* container, Kind kind) {
+      Key key(name, container, kind);
 
-      meth = find_key(key);
-      if(!meth) {
-        meth = new Method(methods_.size(), name, container, kind);
-        methods_[key] = meth;
+      Method* method = find_key(key);
+      if(!method) {
+        method = new Method(methods_.size(), name, container, kind);
+        methods_[key] = method;
       }
 
-      Leaf* leaf = current_-&gt;find_leaf(meth);
+      Leaf* leaf = current_-&gt;find_leaf(method);
 
-      current_ = meth;
+      current_ = method;
 
-      meth-&gt;called();
+      method-&gt;called();
+
+      if(!method-&gt;file() &amp;&amp; !cm-&gt;nil_p()) {
+        method-&gt;set_position(cm-&gt;file(), cm-&gt;start_line(state));
+      }
 
       Invocation invoke(leaf);
       invoke.start();
       running_.push(invoke);
 
-      return meth;
+      return method;
     }
 
     void Profiler::leave_method() {
-      assert(!running_.empty());
+      // Depending on when we started profiling, there could be calls
+      // above the first time we entered a method, so ignore these.
+      if(running_.empty()) return;
 
       Invocation&amp; invoke = running_.top();
       invoke.stop();
@@ -175,11 +223,7 @@ namespace rubinius {
       return methods_[key];
     }
 
-    static bool method_cmp(Method* a, Method* b) {
-      return a-&gt;total_time() &gt; b-&gt;total_time();
-    }
-
-    void Profiler::print_results(STATE, std::ostream&amp; stream) {
+    LookupTable* Profiler::results(STATE) {
       std::vector&lt;Method*&gt; all_methods(0);
 
       for(MethodMap::iterator i = methods_.begin();
@@ -188,36 +232,28 @@ namespace rubinius {
         all_methods.push_back(i-&gt;second);
       }
 
-      std::sort(all_methods.begin(), all_methods.end(), method_cmp);
+      LookupTable* profile = LookupTable::create(state);
+      profile-&gt;store(state, state-&gt;symbol(&quot;num_methods&quot;),
+                     Integer::from(state, methods_.size()));
+      profile-&gt;store(state, state-&gt;symbol(&quot;method&quot;),
+                     String::create(state, TIMING_METHOD));
 
-      stream &lt;&lt; &quot;&lt;profile methods='&quot; &lt;&lt; methods_.size() &lt;&lt;
-        &quot;' method='&quot; &lt;&lt; METHOD &lt;&lt; &quot;'&gt;\n&quot;;
+      LookupTable* methods = LookupTable::create(state);
+      profile-&gt;store(state, state-&gt;symbol(&quot;methods&quot;), methods);
 
       for(std::vector&lt;Method*&gt;::iterator i = all_methods.begin();
           i != all_methods.end();
           i++) {
         Method* meth = *i;
-        stream &lt;&lt; &quot;&lt;method id='&quot; &lt;&lt; meth-&gt;id() &lt;&lt; &quot;' name='&quot;;
+        LookupTable* method = LookupTable::create(state);
 
-        if(Symbol* klass = try_as&lt;Symbol&gt;(meth-&gt;container())) {
-          stream &lt;&lt; klass-&gt;c_str(state);
-        } else {
-          stream &lt;&lt; &quot;unknown&quot;;
-        }
+        methods-&gt;store(state, Fixnum::from(meth-&gt;id()), method);
 
-        Kind kind = meth-&gt;kind();
-        if(kind == kNormal) {
-          stream &lt;&lt; &quot;.&quot;;
-        } else if(kind == kSingleton) {
-          stream &lt;&lt; &quot;#&quot;;
-        } else if(kind == kBlock) {
-          stream &lt;&lt; &quot;#.&quot;;
-        }
-
-        stream &lt;&lt; meth-&gt;method()-&gt;c_str(state);
-
-        stream &lt;&lt; &quot;' total='&quot; &lt;&lt; meth-&gt;total_time_in_ns() &lt;&lt;
-          &quot;' called='&quot; &lt;&lt; meth-&gt;called_times();
+        method-&gt;store(state, state-&gt;symbol(&quot;name&quot;), meth-&gt;name(state));
+        method-&gt;store(state, state-&gt;symbol(&quot;total&quot;),
+                      Integer::from(state, meth-&gt;total_time_in_ns()));
+        method-&gt;store(state, state-&gt;symbol(&quot;called&quot;),
+                      Fixnum::from(meth-&gt;called_times()));
 
         if(meth-&gt;file()) {
           const char *file;
@@ -226,23 +262,29 @@ namespace rubinius {
           } else {
             file = meth-&gt;file()-&gt;c_str(state);
           }
-          stream &lt;&lt; &quot;' file='&quot; &lt;&lt; file &lt;&lt;
-                    &quot;' line='&quot; &lt;&lt; meth-&gt;line();
+
+          method-&gt;store(state, state-&gt;symbol(&quot;file&quot;), String::create(state, file));
+          method-&gt;store(state, state-&gt;symbol(&quot;line&quot;), Fixnum::from(meth-&gt;line()));
         }
 
-        stream &lt;&lt; &quot;'&gt;\n&quot;;
+        Array* leaves = Array::create(state, meth-&gt;number_of_leaves());
+        method-&gt;store(state, state-&gt;symbol(&quot;leaves&quot;), leaves);
 
+        size_t idx = 0;
         for(Leaves::iterator li = meth-&gt;leaves_begin();
             li != meth-&gt;leaves_end();
             li++) {
           Leaf* leaf = li-&gt;second;
-          stream &lt;&lt; &quot;  &lt;leaf id='&quot; &lt;&lt; leaf-&gt;method()-&gt;id() &lt;&lt;
-            &quot;' total='&quot; &lt;&lt; leaf-&gt;total_time_in_ns() &lt;&lt; &quot;'/&gt;\n&quot;;
+
+          Array* l = Array::create(state, 2);
+          leaves-&gt;set(state, idx++, l);
+
+          l-&gt;set(state, 0, Fixnum::from(leaf-&gt;method()-&gt;id()));
+          l-&gt;set(state, 1, Integer::from(state, leaf-&gt;total_time_in_ns()));
         }
-        stream &lt;&lt; &quot;&lt;/method&gt;\n&quot;;
       }
 
-      stream &lt;&lt; &quot;&lt;/profile&gt;\n&quot;;
+      return profile;
     }
   }
 }</diff>
      <filename>vm/profiler.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,8 @@
 #ifndef RBX_PROFILER_HPP
 #define RBX_PROFILER_HPP
 
+#include &quot;vm/vm.hpp&quot;
+
 #include &lt;stdint.h&gt;
 #include &lt;stdio.h&gt;
 
@@ -13,6 +15,8 @@ namespace rubinius {
   class VM;
   class Symbol;
   class Object;
+  class LookupTable;
+  class String;
 
   namespace profiler {
 
@@ -67,7 +71,7 @@ namespace rubinius {
       Object*  container_;
       Kind     kind_;
       uint64_t total_time_;
-      Leaves leaves_;
+      Leaves   leaves_;
       uint64_t called_times_;
       Symbol*  file_;
       int      line_;
@@ -110,6 +114,8 @@ namespace rubinius {
         return kind_;
       }
 
+      String* name(STATE);
+
       Symbol* file() {
         return file_;
       }
@@ -151,7 +157,7 @@ namespace rubinius {
     class Invocation {
     private:
       uint64_t start_time_;
-      Leaf* leaf_;
+      Leaf*    leaf_;
 
     public:
       Invocation(Leaf* meth) : leaf_(meth) { }
@@ -177,8 +183,12 @@ namespace std {
 }
 
 namespace rubinius {
+    class CompiledMethod;
+    class Message;
+    class MethodContext;
 
   namespace profiler {
+
     class Profiler {
       typedef std::tr1::unordered_map&lt;Key, Method*&gt; MethodMap;
 
@@ -191,12 +201,19 @@ namespace rubinius {
     public:
       Profiler();
       ~Profiler();
-      Method* enter_method(Symbol* meth, Object* container, Kind kind = kNormal);
+
+      Symbol* module_name(Module* module);
+      void enter_method(STATE, Message&amp;, CompiledMethod*);
+      void enter_primitive(STATE, Message&amp;);
+      void enter_block(STATE, MethodContext*, CompiledMethod*);
+      Method* record_method(STATE, CompiledMethod*, Symbol*, Object*, Kind kind = kNormal);
       void leave_method();
+
       size_t number_of_entries();
       Method* find_key(Key&amp; key);
       size_t depth();
-      void   print_results(VM* state, std::ostream&amp; stream);
+
+      LookupTable* results(STATE);
 
       Method* current_method() {
         return current_;</diff>
      <filename>vm/profiler.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -314,7 +314,7 @@ class TestFloat : public CxxTest::TestSuite {
     TS_ASSERT_SAME_DATA(&quot;3.14159000000000&quot;, s-&gt;c_str(), 16);
     TS_ASSERT_EQUALS(16U, s-&gt;size());
 
-    format = String::create(state, &quot;%#.1024g&quot;);
+    format = String::create(state, &quot;%#.1280g&quot;);
     TS_ASSERT_THROWS_ASSERT(f-&gt;to_s_formatted(state, format), const RubyException &amp;e,
                             TS_ASSERT(Exception::argument_error_p(state, e.exception)));
   }</diff>
      <filename>vm/test/test_float.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -109,8 +109,9 @@ public:
   }
 
   void test_float() {
-    mar-&gt;marshal(Float::create(state, 15.5));
-    TS_ASSERT_EQUALS(mar-&gt;sstream.str(), std::string(&quot;d\n15.5\n&quot;));
+    mar-&gt;marshal(Float::create(state, 1.0 / 6.0));
+    TS_ASSERT_EQUALS(mar-&gt;sstream.str(),
+        std::string(&quot;d\n +0.666666666666666629659232512494781985878944396972656250    -2\n&quot;));
   }
 
   void test_iseq() {</diff>
      <filename>vm/test/test_marshal.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -17,13 +17,142 @@ class TestProfiler : public CxxTest::TestSuite {
     delete state;
   }
 
+  void test_method_name_normal() {
+    Symbol* meth = state-&gt;symbol(&quot;meth&quot;);
+    Symbol* klass = state-&gt;symbol(&quot;Object&quot;);
+
+    profiler::Method method(0U, meth, klass, profiler::kNormal);
+    String* name = method.name(state);
+
+    TS_ASSERT_SAME_DATA(&quot;Object#meth&quot;, name-&gt;byte_address(), 11);
+  }
+
+  void test_method_name_singleton() {
+    Symbol* meth = state-&gt;symbol(&quot;meth&quot;);
+    Symbol* klass = state-&gt;symbol(&quot;Object&quot;);
+
+    profiler::Method method(0U, meth, klass, profiler::kSingleton);
+    String* name = method.name(state);
+
+    TS_ASSERT_SAME_DATA(&quot;Object.meth&quot;, name-&gt;byte_address(), 11);
+  }
+
+  void test_method_name_block() {
+    Symbol* meth = state-&gt;symbol(&quot;meth&quot;);
+    Symbol* klass = state-&gt;symbol(&quot;Object&quot;);
+
+    profiler::Method method(0U, meth, klass, profiler::kBlock);
+    String* name = method.name(state);
+
+    TS_ASSERT_SAME_DATA(&quot;Object#meth {}&quot;, name-&gt;byte_address(), 14);
+  }
+
+  void test_module_name() {
+    Symbol* name = state-&gt;symbol(&quot;ModName&quot;);
+
+    Module* mod = Module::create(state);
+    mod-&gt;name(state, name);
+
+    IncludedModule* im = IncludedModule::create(state);
+    im-&gt;module(state, mod);
+
+    profiler::Profiler prof;
+
+    TS_ASSERT_EQUALS(name, prof.module_name(im));
+    TS_ASSERT_EQUALS(name, prof.module_name(mod));
+  }
+
+  void test_enter_block() {
+    Symbol* meth = state-&gt;symbol(&quot;meth&quot;);
+    Symbol* klass = state-&gt;symbol(&quot;Object&quot;);
+
+    MethodContext* ctx = MethodContext::create(state, 10);
+    ctx-&gt;name(state, meth);
+    ctx-&gt;module(state, G(object));
+
+    CompiledMethod* cm = CompiledMethod::create(state);
+    cm-&gt;name(state, meth);
+
+    profiler::Profiler prof;
+
+    prof.enter_block(state, ctx, cm);
+    TS_ASSERT_EQUALS(prof.depth(), 1U);
+    TS_ASSERT_EQUALS(prof.number_of_entries(), 1U);
+
+    profiler::Key key(meth, klass, profiler::kBlock);
+    profiler::Method* mo = prof.find_key(key);
+    TS_ASSERT(mo);
+  }
+
   void test_enter_method() {
+    Symbol* meth = state-&gt;symbol(&quot;meth&quot;);
+    Symbol* klass = state-&gt;symbol(&quot;Object&quot;);
+
+    CompiledMethod* cm = CompiledMethod::create(state);
+    cm-&gt;name(state, meth);
+
+    profiler::Profiler prof;
+
+    Message msg(state);
+    msg.module = G(object);
+    msg.name = meth;
+
+    prof.enter_method(state, msg, cm);
+    TS_ASSERT_EQUALS(prof.depth(), 1U);
+    TS_ASSERT_EQUALS(prof.number_of_entries(), 1U);
+
+    profiler::Key key(meth, klass, profiler::kNormal);
+    TS_ASSERT(prof.find_key(key));
+
+    msg.module = G(object)-&gt;metaclass(state);
+
+    prof.enter_method(state, msg, cm);
+    TS_ASSERT_EQUALS(prof.depth(), 2U);
+    TS_ASSERT_EQUALS(prof.number_of_entries(), 2U);
+
+    profiler::Key key1(meth, klass, profiler::kNormal);
+    TS_ASSERT(prof.find_key(key1));
+  }
+
+  void test_enter_primitive() {
+    Symbol* meth = state-&gt;symbol(&quot;meth&quot;);
+    Symbol* klass = state-&gt;symbol(&quot;Object&quot;);
+
+    CompiledMethod* cm = CompiledMethod::create(state);
+    cm-&gt;name(state, meth);
+
+    profiler::Profiler prof;
+
+    Message msg(state);
+    msg.module = G(object);
+    msg.name = meth;
+
+    prof.enter_primitive(state, msg);
+    TS_ASSERT_EQUALS(prof.depth(), 1U);
+    TS_ASSERT_EQUALS(prof.number_of_entries(), 1U);
+
+    profiler::Key key(meth, klass, profiler::kNormal);
+    TS_ASSERT(prof.find_key(key));
+
+    msg.module = G(object)-&gt;metaclass(state);
+
+    prof.enter_primitive(state, msg);
+    TS_ASSERT_EQUALS(prof.depth(), 2U);
+    TS_ASSERT_EQUALS(prof.number_of_entries(), 2U);
+
+    profiler::Key key1(meth, klass, profiler::kNormal);
+    TS_ASSERT(prof.find_key(key1));
+  }
+
+  void test_record_method() {
     Symbol* meth = state-&gt;symbol(&quot;blah&quot;);
     Symbol* klass = state-&gt;symbol(&quot;Sweet&quot;);
 
+    CompiledMethod* cm = CompiledMethod::create(state);
+
     profiler::Profiler prof;
 
-    prof.enter_method(meth, klass);
+    prof.record_method(state, cm, meth, klass);
     TS_ASSERT_EQUALS(prof.depth(), 1U);
     TS_ASSERT_EQUALS(prof.number_of_entries(), 1U);
 
@@ -35,12 +164,12 @@ class TestProfiler : public CxxTest::TestSuite {
     TS_ASSERT_EQUALS(mo-&gt;method(), meth);
     TS_ASSERT_EQUALS(mo-&gt;total_time(), 0ULL);
 
-    prof.enter_method(meth, klass);
+    prof.record_method(state, cm, meth, klass);
     TS_ASSERT_EQUALS(prof.number_of_entries(), 1U);
     TS_ASSERT_EQUALS(prof.depth(), 2U);
 
     Symbol* meth2 = state-&gt;symbol(&quot;woo&quot;);
-    prof.enter_method(meth2, klass);
+    prof.record_method(state, cm, meth2, klass);
     TS_ASSERT_EQUALS(prof.number_of_entries(), 2U);
 
     TS_ASSERT_EQUALS(prof.depth(), 3U);
@@ -50,9 +179,11 @@ class TestProfiler : public CxxTest::TestSuite {
     Symbol* meth = state-&gt;symbol(&quot;blah&quot;);
     Symbol* klass = state-&gt;symbol(&quot;Sweet&quot;);
 
+    CompiledMethod* cm = CompiledMethod::create(state);
+
     profiler::Profiler prof;
 
-    prof.enter_method(meth, klass);
+    prof.record_method(state, cm, meth, klass);
     profiler::Key key(meth, klass);
     profiler::Method* mo = prof.find_key(key);
     TS_ASSERT_EQUALS(mo-&gt;total_time(), 0ULL);
@@ -68,14 +199,16 @@ class TestProfiler : public CxxTest::TestSuite {
     Symbol* meth = state-&gt;symbol(&quot;blah&quot;);
     Symbol* klass = state-&gt;symbol(&quot;Sweet&quot;);
 
+    CompiledMethod* cm = CompiledMethod::create(state);
+
     profiler::Profiler prof;
 
-    profiler::Method* outer = prof.enter_method(meth, klass);
+    profiler::Method* outer = prof.record_method(state, cm, meth, klass);
     TS_ASSERT_EQUALS(prof.current_method(), outer);
 
     Symbol* meth2 = state-&gt;symbol(&quot;fun&quot;);
 
-    profiler::Method* inner = prof.enter_method(meth2, klass);
+    profiler::Method* inner = prof.record_method(state, cm, meth2, klass);
     TS_ASSERT_EQUALS(prof.current_method(), inner);
 
     prof.leave_method();
@@ -98,36 +231,54 @@ class TestProfiler : public CxxTest::TestSuite {
     TS_ASSERT_EQUALS(leaf-&gt;total_time(), mo2-&gt;total_time());
   }
 
-  void test_print_results() {
+  void test_results() {
     Symbol* meth = state-&gt;symbol(&quot;blah&quot;);
     Symbol* meth2 = state-&gt;symbol(&quot;foo&quot;);
     Symbol* meth3 = state-&gt;symbol(&quot;done&quot;);
     Symbol* klass = state-&gt;symbol(&quot;Sweet&quot;);
 
+    CompiledMethod* cm = CompiledMethod::create(state);
+
     profiler::Profiler prof;
 
-    profiler::Method* top = prof.enter_method(meth, klass);
-    prof.enter_method(meth2, klass);
+    profiler::Method* top = prof.record_method(state, cm, meth, klass);
+    prof.record_method(state, cm, meth2, klass);
     prof.leave_method();
 
     TS_ASSERT_EQUALS(prof.current_method(), top);
-    prof.enter_method(meth3, klass);
+    prof.record_method(state, cm, meth3, klass);
     prof.leave_method();
 
     TS_ASSERT_EQUALS(prof.current_method(), top);
 
-    prof.enter_method(meth2, klass);
-    prof.enter_method(meth3, klass);
+    prof.record_method(state, cm, meth2, klass);
+    prof.record_method(state, cm, meth3, klass);
     prof.leave_method();
     prof.leave_method();
 
     prof.leave_method();
 
-    std::stringstream stream;
-    prof.print_results(state, stream);
-
-    // This is a bullshit test, but i'm too lazy to test the entire
-    // form of the XML for now.
-    TS_ASSERT(stream.str().find(&quot;profile&quot;) != std::string::npos);
+    LookupTable* results = prof.results(state);
+
+    TS_ASSERT(!results-&gt;nil_p());
+    TS_ASSERT(!results-&gt;fetch(state, state-&gt;symbol(&quot;method&quot;))-&gt;nil_p());
+    TS_ASSERT_EQUALS(Fixnum::from(3),
+        results-&gt;fetch(state, state-&gt;symbol(&quot;num_methods&quot;)));
+
+    LookupTable* methods = as&lt;LookupTable&gt;(
+        results-&gt;fetch(state, state-&gt;symbol(&quot;methods&quot;)));
+    TS_ASSERT_EQUALS(Integer::from(state, 3), methods-&gt;entries());
+
+    LookupTable* method = as&lt;LookupTable&gt;(
+        methods-&gt;fetch(state, Fixnum::from(1)));
+    TS_ASSERT_EQUALS(Integer::from(state, 6), method-&gt;entries());
+    TS_ASSERT_EQUALS(Fixnum::from(1),
+        method-&gt;fetch(state, state-&gt;symbol(&quot;called&quot;)));
+    TS_ASSERT_SAME_DATA(&quot;Sweet#blah&quot;, as&lt;String&gt;(method-&gt;fetch(state,
+          state-&gt;symbol(&quot;name&quot;)))-&gt;byte_address(), 9);
+    TS_ASSERT(kind_of&lt;Array&gt;(method-&gt;fetch(state, state-&gt;symbol(&quot;leaves&quot;))));
+    TS_ASSERT(method-&gt;has_key(state, state-&gt;symbol(&quot;total&quot;))-&gt;true_p());
+    TS_ASSERT(method-&gt;has_key(state, state-&gt;symbol(&quot;file&quot;))-&gt;true_p());
+    TS_ASSERT(method-&gt;has_key(state, state-&gt;symbol(&quot;line&quot;))-&gt;true_p());
   }
 };</diff>
      <filename>vm/test/test_profiler.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -131,7 +131,8 @@ public:
   }
 
   void test_float() {
-    mar-&gt;sstream.str(std::string(&quot;d\n15.5\n&quot;));
+    mar-&gt;sstream.str(
+        std::string(&quot;d\n +0.666666666666666629659232512494781985878944396972656250    -2\n&quot;));
 
     Object* obj = mar-&gt;unmarshal();
 
@@ -139,7 +140,17 @@ public:
 
     Float* flt = as&lt;Float&gt;(obj);
 
-    TS_ASSERT_EQUALS(flt-&gt;val, 15.5);
+    TS_ASSERT_EQUALS(flt-&gt;val, 1.0 / 6.0);
+
+    mar-&gt;sstream.str(
+        std::string(&quot;d\n +0.999999999999999888977697537484345957636833190917968750  1024\n&quot;));
+    obj = mar-&gt;unmarshal();
+
+    TS_ASSERT(kind_of&lt;Float&gt;(obj));
+
+    flt = as&lt;Float&gt;(obj);
+
+    TS_ASSERT_EQUALS(flt-&gt;val, DBL_MAX);
   }
 
   void test_float_infinity() {</diff>
      <filename>vm/test/test_unmarshal.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -8,12 +8,13 @@
 
 #include &lt;mach/mach_time.h&gt;
 #define get_current_time() mach_absolute_time()
+#define TIMING_METHOD &quot;mach_absolute_time&quot;
 
-#else
+#elif defined(CLOCK_REALTIME)
 
 #include &lt;time.h&gt;
 
-uint64_t get_current_time() {
+static inline uint64_t get_current_time() {
   timespec tp;
   if(clock_gettime(CLOCK_REALTIME, &amp;tp)) {
     // error! Do something about it?
@@ -22,6 +23,24 @@ uint64_t get_current_time() {
   return tp.tv_sec * 1000000000UL + tp.tv_nsec;
 }
 
+#define TIMING_METHOD &quot;clock_gettime&quot;
+
+#else
+
+#include &lt;sys/time.h&gt;
+
+static inline uint64_t get_current_time() {
+  struct timeval tv;
+  if(gettimeofday(&amp;tv, NULL) != 0) {
+    // Fudge.
+    return 0U;
+  }
+
+  return tv.tv_sec * 1000000000UL + tv.tv_usec * 1000L;
+}
+
+#define TIMING_METHOD &quot;gettimeofday&quot;
+
 #endif
 
 #endif</diff>
      <filename>vm/timing.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -91,15 +91,8 @@ namespace rubinius {
   }
 
   void TypeInfo::class_info(STATE, const Object* self, bool newline) {
-    if(const Module* mod = try_as&lt;Module&gt;(self)) {
-      const char *name = mod-&gt;name()-&gt;nil_p() ? &quot;&lt;anonymous&gt;&quot; : mod-&gt;name()-&gt;c_str(state);
-      std::cout &lt;&lt; &quot;#&lt;&quot; &lt;&lt; name &lt;&lt; &quot;(&quot; &lt;&lt;
-        self-&gt;class_object(state)-&gt;name()-&gt;c_str(state) &lt;&lt; &quot;)&quot;;
-    } else {
-      std::cout &lt;&lt; &quot;#&lt;&quot; &lt;&lt; self-&gt;class_object(state)-&gt;name()-&gt;c_str(state);
-    }
-    std::cout &lt;&lt; &quot;:&quot; &lt;&lt; (void*)self;
-    if(newline) std::cout &lt;&lt; &quot;&gt;\n&quot;;
+    std::cout &lt;&lt; const_cast&lt;Object*&gt;(self)-&gt;to_s(state, true)-&gt;c_str();
+    if(newline) std::cout &lt;&lt; std::endl;
   }
 
   void TypeInfo::class_header(STATE, const Object* self) {</diff>
      <filename>vm/type_info.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -18,6 +18,7 @@
 
 #include &quot;config_parser.hpp&quot;
 #include &quot;config.h&quot;
+#include &quot;timing.hpp&quot;
 
 #include &lt;iostream&gt;
 #include &lt;signal.h&gt;
@@ -32,8 +33,6 @@ namespace rubinius {
   VM::VM(size_t bytes, bool boot)
     : current_mark(NULL)
     , reuse_llvm(true)
-    , jit_timing(0)
-    , jitted_methods(0)
     , use_safe_position(false)
   {
     config.compile_up_front = false;
@@ -203,20 +202,32 @@ namespace rubinius {
   }
 
   void VM::collect() {
+    uint64_t start = get_current_time();
+
     om-&gt;collect_young(globals.roots);
     om-&gt;collect_mature(globals.roots);
+
+    stats.time_in_gc += (get_current_time() - start);
   }
 
   void VM::collect_maybe() {
     if(om-&gt;collect_young_now) {
       om-&gt;collect_young_now = false;
+
+      uint64_t start = get_current_time();
       om-&gt;collect_young(globals.roots);
+      stats.time_in_gc += (get_current_time() - start);
+
       global_cache-&gt;clear();
     }
 
     if(om-&gt;collect_mature_now) {
       om-&gt;collect_mature_now = false;
+
+      uint64_t start = get_current_time();
       om-&gt;collect_mature(globals.roots);
+      stats.time_in_gc += (get_current_time() - start);
+
       global_cache-&gt;clear();
     }
 </diff>
      <filename>vm/vm.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -59,6 +59,23 @@ namespace rubinius {
     { }
   };
 
+  struct Stats {
+    // How much time is spent running the JIT
+    uint64_t jit_timing;
+
+    // How many methods have been compiled by the JIT
+    uint64_t jitted_methods;
+
+    // How much time is spent in the GC
+    uint64_t time_in_gc;
+
+    Stats()
+      : jit_timing(0)
+      , jitted_methods(0)
+      , time_in_gc(0)
+    {}
+  };
+
   class VM {
   public:
     /* Data members */
@@ -74,6 +91,8 @@ namespace rubinius {
     SymbolTable symbols;
     ConfigParser *user_config;
 
+    Stats stats;
+
     // Temporary holder for rb_gc_mark() in subtend
     ObjectMark current_mark;
 
@@ -82,12 +101,6 @@ namespace rubinius {
     // The thread used to trigger preemptive thread switching
     pthread_t preemption_thread;
 
-    // How much time is spent running the JIT
-    uint64_t jit_timing;
-
-    // How many methods have been compiled by the JIT
-    uint64_t jitted_methods;
-
     // The safe position on the stack used to handle rare
     // events.
     sigjmp_buf safe_position;</diff>
      <filename>vm/vm.hpp</filename>
    </modified>
    <modified>
      <diff>@@ -336,12 +336,12 @@ namespace rubinius {
     // for this method.
     if(vmm-&gt;call_count &gt;= 0) {
       if(vmm-&gt;call_count &gt;= CALLS_TIL_JIT) {
-        state-&gt;jitted_methods++;
+        state-&gt;stats.jitted_methods++;
         uint64_t start = get_current_time();
         MachineMethod* mm = cm-&gt;make_machine_method(state);
         mm-&gt;activate();
         vmm-&gt;call_count = -1;
-        state-&gt;jit_timing += (get_current_time() - start);
+        state-&gt;stats.jit_timing += (get_current_time() - start);
       } else {
         vmm-&gt;call_count++;
       }
@@ -380,23 +380,7 @@ namespace rubinius {
 
     task-&gt;make_active(ctx);
 
-    if(unlikely(task-&gt;profiler)) {
-      profiler::Method* prof_meth;
-      if(MetaClass* mc = try_as&lt;MetaClass&gt;(msg.module)) {
-        Object* attached = mc-&gt;attached_instance();
-        if(Module* mod = try_as&lt;Module&gt;(attached)) {
-          prof_meth = task-&gt;profiler-&gt;enter_method(msg.name, mod-&gt;name(), profiler::kNormal);
-        } else {
-          prof_meth = task-&gt;profiler-&gt;enter_method(msg.name, attached-&gt;id(state), profiler::kNormal);
-        }
-      } else {
-        prof_meth = task-&gt;profiler-&gt;enter_method(msg.name, msg.module-&gt;name(), profiler::kSingleton);
-      }
-
-      if(!prof_meth-&gt;file()) {
-        prof_meth-&gt;set_position(cm-&gt;file(), cm-&gt;start_line(state));
-      }
-    }
+    if(unlikely(task-&gt;profiler)) task-&gt;profiler-&gt;enter_method(state, msg, cm);
 
     return cExecuteRestart;
   }
@@ -481,23 +465,7 @@ namespace rubinius {
 
     task-&gt;make_active(ctx);
 
-    if(unlikely(task-&gt;profiler)) {
-      profiler::Method* prof_meth;
-      if(MetaClass* mc = try_as&lt;MetaClass&gt;(msg.module)) {
-        Object* attached = mc-&gt;attached_instance();
-        if(Module* mod = try_as&lt;Module&gt;(attached)) {
-          prof_meth = task-&gt;profiler-&gt;enter_method(msg.name, mod-&gt;name(), profiler::kNormal);
-        } else {
-          prof_meth = task-&gt;profiler-&gt;enter_method(msg.name, attached-&gt;id(state), profiler::kNormal);
-        }
-      } else {
-        prof_meth = task-&gt;profiler-&gt;enter_method(msg.name, msg.module-&gt;name(), profiler::kSingleton);
-      }
-
-      if(!prof_meth-&gt;file()) {
-        prof_meth-&gt;set_position(cm-&gt;file(), cm-&gt;start_line(state));
-      }
-    }
+    if(unlikely(task-&gt;profiler)) task-&gt;profiler-&gt;enter_method(state, msg, cm);
 
     return cExecuteRestart;
   }</diff>
      <filename>vm/vmmethod.cpp</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>kernel/bootstrap/sampler.rb</filename>
    </removed>
    <removed>
      <filename>kernel/common/sampler.rb</filename>
    </removed>
    <removed>
      <filename>kernel/delta/array.rb</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/array/initialize_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/array/minus_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/array/new_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/bignum/divide_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/bignum/divmod_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/bignum/exponent_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/bignum/minus_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/bignum/multiply_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/bignum/plus_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/bignum/to_f_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/fixnum/abs_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/fixnum/element_reference_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/fixnum/minus_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/fixnum/plus_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/float/ceil_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/float/coerce_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/float/constants_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/float/divmod_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/float/floor_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/float/induced_from_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/float/infinite_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/float/minus_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/float/multiply_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/float/plus_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/float/to_i_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/float/to_int_tags.txt</filename>
    </removed>
    <removed>
      <filename>spec/tags/frozen/core/float/truncate_tags.txt</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>c14849545471092318f3db3accc81957c1179473</id>
    </parent>
    <parent>
      <id>5e95249ef8ca5e6f0cec14fb4aae14113e269489</id>
    </parent>
  </parents>
  <author>
    <name>Konstantin Haase</name>
    <email>konstantin.mailinglists@googlemail.com</email>
  </author>
  <url>http://github.com/evanphx/rubinius/commit/fac3883d3ec82f4766927e56e6aefb28588d7d5b</url>
  <id>fac3883d3ec82f4766927e56e6aefb28588d7d5b</id>
  <committed-date>2009-01-09T01:18:18-08:00</committed-date>
  <authored-date>2009-01-09T01:18:18-08:00</authored-date>
  <message>merge conflict</message>
  <tree>f083efc1d0c964ae1230bc407ad72b434182d259</tree>
  <committer>
    <name>Konstantin Haase</name>
    <email>konstantin.mailinglists@googlemail.com</email>
  </committer>
</commit>
