2010-03-22: Version 2.1.7

Fixed issue 650.

Fixed a bug where __proto__ was sometimes enumerated (issue 646).

Performance improvements for arithmetic operations.

Performance improvements for string operations.

Print script name and line number information in stack trace.


git-svn-id: http://v8.googlecode.com/svn/trunk@4209 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/SConscript b/src/SConscript
index f4bba6b..bf42fd4 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -43,6 +43,7 @@
     bootstrapper.cc
     builtins.cc
     checks.cc
+    circular-queue.cc
     code-stubs.cc
     codegen.cc
     compilation-cache.cc
@@ -50,11 +51,13 @@
     contexts.cc
     conversions.cc
     counters.cc
+    cpu-profiler.cc
     data-flow.cc
     dateparser.cc
     debug-agent.cc
     debug.cc
     disassembler.cc
+    diy-fp.cc
     execution.cc
     factory.cc
     flags.cc
@@ -63,6 +66,7 @@
     full-codegen.cc
     func-name-inferrer.cc
     global-handles.cc
+    fast-dtoa.cc
     handles.cc
     hashmap.cc
     heap-profiler.cc
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index 354436c..3f0854e 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -144,12 +144,21 @@
 
 
 bool RelocInfo::IsPatchedReturnSequence() {
-  // On ARM a "call instruction" is actually two instructions.
-  //   mov lr, pc
-  //   ldr pc, [pc, #XXX]
-  return (Assembler::instr_at(pc_) == kMovLrPc)
-          && ((Assembler::instr_at(pc_ + Assembler::kInstrSize) & kLdrPCPattern)
-              == kLdrPCPattern);
+  Instr current_instr = Assembler::instr_at(pc_);
+  Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize);
+#ifdef USE_BLX
+  // A patched return sequence is:
+  //  ldr ip, [pc, #0]
+  //  blx ip
+  return ((current_instr & kLdrPCMask) == kLdrPCPattern)
+          && ((next_instr & kBlxRegMask) == kBlxRegPattern);
+#else
+  // A patched return sequence is:
+  //  mov lr, pc
+  //  ldr pc, [pc, #-4]
+  return (current_instr == kMovLrPc)
+          && ((next_instr & kLdrPCMask) == kLdrPCPattern);
+#endif
 }
 
 
@@ -225,6 +234,16 @@
     target_pc -= kInstrSize;
     instr = Memory::int32_at(target_pc);
   }
+
+#ifdef USE_BLX
+  // If we have a blx instruction, the instruction before it is
+  // what needs to be patched.
+  if ((instr & kBlxRegMask) == kBlxRegPattern) {
+    target_pc -= kInstrSize;
+    instr = Memory::int32_at(target_pc);
+  }
+#endif
+
   // Verify that the instruction to patch is a
   // ldr<cond> <Rd>, [pc +/- offset_12].
   ASSERT((instr & 0x0f7f0000) == 0x051f0000);
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 6b226fd..d4cd818 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -240,8 +240,14 @@
     al | B26 | L | 4 | PostIndex | sp.code() * B16;
 // mov lr, pc
 const Instr kMovLrPc = al | 13*B21 | pc.code() | lr.code() * B12;
-// ldr pc, [pc, #XXX]
-const Instr kLdrPCPattern = al | B26 | L | pc.code() * B16;
+// ldr rd, [pc, #offset]
+const Instr kLdrPCMask = CondMask | 15 * B24 | 7 * B20 | 15 * B16;
+const Instr kLdrPCPattern = al | 5 * B24 | L | pc.code() * B16;
+// blxcc rm
+const Instr kBlxRegMask =
+    15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
+const Instr kBlxRegPattern =
+    B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | 3 * B4;
 
 // Spare buffer.
 static const int kMinimalBufferSize = 4*KB;
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index c972c57..539a6b8 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -509,7 +509,10 @@
 
 
 extern const Instr kMovLrPc;
+extern const Instr kLdrPCMask;
 extern const Instr kLdrPCPattern;
+extern const Instr kBlxRegMask;
+extern const Instr kBlxRegPattern;
 
 
 class Assembler : public Malloced {
@@ -590,12 +593,34 @@
   static const int kInstrSize = sizeof(Instr);
 
   // Distance between the instruction referring to the address of the call
-  // target (ldr pc, [target addr in const pool]) and the return address
+  // target and the return address.
+#ifdef USE_BLX
+  // Call sequence is:
+  //  ldr  ip, [pc, #...] @ call address
+  //  blx  ip
+  //                      @ return address
+  static const int kCallTargetAddressOffset = 2 * kInstrSize;
+#else
+  // Call sequence is:
+  //  mov  lr, pc
+  //  ldr  pc, [pc, #...] @ call address
+  //                      @ return address
   static const int kCallTargetAddressOffset = kInstrSize;
+#endif
 
   // Distance between start of patched return sequence and the emitted address
   // to jump to.
-  static const int kPatchReturnSequenceAddressOffset = kInstrSize;
+#ifdef USE_BLX
+  // Return sequence is:
+  //  ldr  ip, [pc, #0]   @ emited address and start
+  //  blx  ip
+  static const int kPatchReturnSequenceAddressOffset =  0 * kInstrSize;
+#else
+  // Return sequence is:
+  //  mov  lr, pc         @ start of sequence
+  //  ldr  pc, [pc, #-4]  @ emited address
+  static const int kPatchReturnSequenceAddressOffset =  kInstrSize;
+#endif
 
   // Difference between address of current opcode and value read from pc
   // register.
diff --git a/src/arm/constants-arm.h b/src/arm/constants-arm.h
index 8a32c95..2b883f3 100644
--- a/src/arm/constants-arm.h
+++ b/src/arm/constants-arm.h
@@ -72,6 +72,11 @@
 # define CAN_USE_THUMB_INSTRUCTIONS 1
 #endif
 
+// Using blx may yield better code, so use it when required or when available
+#if defined(USE_THUMB_INTERWORK) || defined(CAN_USE_ARMV5_INSTRUCTIONS)
+#define USE_BLX 1
+#endif
+
 namespace assembler {
 namespace arm {
 
diff --git a/src/arm/debug-arm.cc b/src/arm/debug-arm.cc
index e6b61b4..bc81b19 100644
--- a/src/arm/debug-arm.cc
+++ b/src/arm/debug-arm.cc
@@ -46,13 +46,23 @@
   //   add sp, sp, #4
   //   bx lr
   // to a call to the debug break return code.
+  // #if USE_BLX
+  //   ldr ip, [pc, #0]
+  //   blx ip
+  // #else
   //   mov lr, pc
   //   ldr pc, [pc, #-4]
+  // #endif
   //   <debug break return code entry point address>
   //   bktp 0
   CodePatcher patcher(rinfo()->pc(), 4);
+#ifdef USE_BLX
+  patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0));
+  patcher.masm()->blx(v8::internal::ip);
+#else
   patcher.masm()->mov(v8::internal::lr, v8::internal::pc);
   patcher.masm()->ldr(v8::internal::pc, MemOperand(v8::internal::pc, -4));
+#endif
   patcher.Emit(Debug::debug_break_return()->entry());
   patcher.masm()->bkpt(0);
 }
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index bc779eb..691c08c 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -58,11 +58,6 @@
 #endif
 
 
-// Using blx may yield better code, so use it when required or when available
-#if defined(USE_THUMB_INTERWORK) || defined(CAN_USE_ARMV5_INSTRUCTIONS)
-#define USE_BLX 1
-#endif
-
 // Using bx does not yield better code, so use it only when required
 #if defined(USE_THUMB_INTERWORK)
 #define USE_BX 1
@@ -117,16 +112,33 @@
 
 void MacroAssembler::Call(intptr_t target, RelocInfo::Mode rmode,
                           Condition cond) {
+#if USE_BLX
+  // On ARMv5 and after the recommended call sequence is:
+  //  ldr ip, [pc, #...]
+  //  blx ip
+
+  // The two instructions (ldr and blx) could be separated by a literal
+  // pool and the code would still work. The issue comes from the
+  // patching code which expect the ldr to be just above the blx.
+  BlockConstPoolFor(2);
+  // Statement positions are expected to be recorded when the target
+  // address is loaded. The mov method will automatically record
+  // positions when pc is the target, since this is not the case here
+  // we have to do it explicitly.
+  WriteRecordedPositions();
+
+  mov(ip, Operand(target, rmode), LeaveCC, cond);
+  blx(ip, cond);
+
+  ASSERT(kCallTargetAddressOffset == 2 * kInstrSize);
+#else
   // Set lr for return at current pc + 8.
   mov(lr, Operand(pc), LeaveCC, cond);
   // Emit a ldr<cond> pc, [pc + offset of target in constant pool].
   mov(pc, Operand(target, rmode), LeaveCC, cond);
-  // If USE_BLX is defined, we could emit a 'mov ip, target', followed by a
-  // 'blx ip'; however, the code would not be shorter than the above sequence
-  // and the target address of the call would be referenced by the first
-  // instruction rather than the second one, which would make it harder to patch
-  // (two instructions before the return address, instead of one).
+
   ASSERT(kCallTargetAddressOffset == kInstrSize);
+#endif
 }
 
 
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 5d9e513..8c70d95 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -415,7 +415,7 @@
                                                   Register object2,
                                                   Register scratch1,
                                                   Register scratch2,
-                                                  Label *failure);
+                                                  Label* failure);
 
   // Checks if both objects are sequential ASCII strings and jumps to label
   // if either is not.
diff --git a/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
index f621be4..13d464d 100644
--- a/src/arm/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -648,16 +648,17 @@
   __ ldr(r0, MemOperand(frame_pointer(), kInputStart));
   // Find negative length (offset of start relative to end).
   __ sub(current_input_offset(), r0, end_of_input_address());
-  // Set r0 to address of char before start of input
+  // Set r0 to address of char before start of the input string
   // (effectively string position -1).
+  __ ldr(r1, MemOperand(frame_pointer(), kStartIndex));
   __ sub(r0, current_input_offset(), Operand(char_size()));
+  __ sub(r0, r0, Operand(r1, LSL, (mode_ == UC16) ? 1 : 0));
   // Store this value in a local variable, for use when clearing
   // position registers.
   __ str(r0, MemOperand(frame_pointer(), kInputStartMinusOne));
 
   // Determine whether the start index is zero, that is at the start of the
   // string, and store that value in a local variable.
-  __ ldr(r1, MemOperand(frame_pointer(), kStartIndex));
   __ tst(r1, Operand(r1));
   __ mov(r1, Operand(1), LeaveCC, eq);
   __ mov(r1, Operand(0), LeaveCC, ne);
@@ -700,12 +701,15 @@
       // copy captures to output
       __ ldr(r1, MemOperand(frame_pointer(), kInputStart));
       __ ldr(r0, MemOperand(frame_pointer(), kRegisterOutput));
+      __ ldr(r2, MemOperand(frame_pointer(), kStartIndex));
       __ sub(r1, end_of_input_address(), r1);
       // r1 is length of input in bytes.
       if (mode_ == UC16) {
         __ mov(r1, Operand(r1, LSR, 1));
       }
       // r1 is length of input in characters.
+      __ add(r1, r1, Operand(r2));
+      // r1 is length of string in characters.
 
       ASSERT_EQ(0, num_saved_registers_ % 2);
       // Always an even number of capture registers. This allows us to
diff --git a/src/arm/virtual-frame-arm.h b/src/arm/virtual-frame-arm.h
index 7375b31..9ac7a05 100644
--- a/src/arm/virtual-frame-arm.h
+++ b/src/arm/virtual-frame-arm.h
@@ -365,6 +365,7 @@
   inline void Nip(int num_dropped);
 
   inline void SetTypeForLocalAt(int index, NumberInfo info);
+  inline void SetTypeForParamAt(int index, NumberInfo info);
 
  private:
   static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
diff --git a/src/array.js b/src/array.js
index 914b82a..a29015a 100644
--- a/src/array.js
+++ b/src/array.js
@@ -994,11 +994,16 @@
     // If index is still negative, search the entire array.
     if (index < 0) index = 0;
   }
+  if (!IS_UNDEFINED(element)) {
+    for (var i = index; i < length; i++) {
+      if (this[i] === element) return i;
+    }
+    return -1;
+  }
   // Lookup through the array.
   for (var i = index; i < length; i++) {
-    var current = this[i];
-    if (!IS_UNDEFINED(current) || i in this) {
-      if (current === element) return i;
+    if (IS_UNDEFINED(this[i]) && i in this) {
+      return i;
     }
   }
   return -1;
@@ -1018,10 +1023,15 @@
     else if (index >= length) index = length - 1;
   }
   // Lookup through the array.
+  if (!IS_UNDEFINED(element)) {
+    for (var i = index; i >= 0; i--) {
+      if (this[i] === element) return i;
+    }
+    return -1;
+  }
   for (var i = index; i >= 0; i--) {
-    var current = this[i];
-    if (!IS_UNDEFINED(current) || i in this) {
-      if (current === element) return i;
+    if (IS_UNDEFINED(this[i]) && i in this) {
+      return i;
     }
   }
   return -1;
diff --git a/src/ast.h b/src/ast.h
index 262bf17..8248f62 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -196,10 +196,7 @@
     kTestValue
   };
 
-  Expression()
-      : bitfields_(0),
-        def_(NULL),
-        defined_vars_(NULL) {}
+  Expression() : bitfields_(0) {}
 
   virtual Expression* AsExpression()  { return this; }
 
@@ -233,15 +230,6 @@
   // Static type information for this expression.
   StaticType* type() { return &type_; }
 
-  // Data flow information.
-  DefinitionInfo* var_def() { return def_; }
-  void set_var_def(DefinitionInfo* def) { def_ = def; }
-
-  ZoneList<DefinitionInfo*>* defined_vars() { return defined_vars_; }
-  void set_defined_vars(ZoneList<DefinitionInfo*>* defined_vars) {
-    defined_vars_ = defined_vars;
-  }
-
   // AST analysis results
 
   // True if the expression rooted at this node can be compiled by the
@@ -284,9 +272,6 @@
   uint32_t bitfields_;
   StaticType type_;
 
-  DefinitionInfo* def_;
-  ZoneList<DefinitionInfo*>* defined_vars_;
-
   // Using template BitField<type, start, size>.
   class SideEffectFreeField : public BitField<bool, 0, 1> {};
   class NoNegativeZeroField : public BitField<bool, 1, 1> {};
diff --git a/src/cached-powers.h b/src/cached-powers.h
new file mode 100644
index 0000000..314ccca
--- /dev/null
+++ b/src/cached-powers.h
@@ -0,0 +1,119 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_CACHED_POWERS_H_
+#define V8_CACHED_POWERS_H_
+
+#include "diy-fp.h"
+
+namespace v8 {
+namespace internal {
+
+struct CachedPower {
+  uint64_t significand;
+  int16_t binary_exponent;
+  int16_t decimal_exponent;
+};
+
+// The following defines implement the interface between this file and the
+// generated 'powers_ten.h'.
+// GRISU_CACHE_NAME(1) contains all possible cached powers.
+// GRISU_CACHE_NAME(i) contains GRISU_CACHE_NAME(1) where only every 'i'th
+// element is kept. More formally GRISU_CACHE_NAME(i) contains the elements j*i
+// with 0 <= j < k with k such that j*k < the size of GRISU_CACHE_NAME(1).
+// The higher 'i' is the fewer elements we use.
+// Given that there are less elements, the exponent-distance between two
+// elements in the cache grows. The variable GRISU_CACHE_MAX_DISTANCE(i) stores
+// the maximum distance between two elements.
+#define GRISU_CACHE_STRUCT CachedPower
+#define GRISU_CACHE_NAME(i) kCachedPowers##i
+#define GRISU_CACHE_MAX_DISTANCE(i) kCachedPowersMaxDistance##i
+#define GRISU_CACHE_OFFSET kCachedPowerOffset
+#define GRISU_UINT64_C V8_2PART_UINT64_C
+// The following include imports the precompiled cached powers.
+#include "powers-ten.h"  // NOLINT
+
+static const double kD_1_LOG2_10 = 0.30102999566398114;  //  1 / lg(10)
+
+// We can't use a function since we reference variables depending on the 'i'.
+// This way the compiler is able to see at compile time that only one
+// cache-array variable is used and thus can remove all the others.
+#define COMPUTE_FOR_CACHE(i) \
+  if (!found && (gamma - alpha + 1 >= GRISU_CACHE_MAX_DISTANCE(i))) {   \
+    int kQ = DiyFp::kSignificandSize;                                   \
+    double k = ceiling((alpha - e + kQ - 1) * kD_1_LOG2_10);            \
+    int index = (GRISU_CACHE_OFFSET + static_cast<int>(k) - 1) / i + 1; \
+    cached_power = GRISU_CACHE_NAME(i)[index];                          \
+    found = true;                                                       \
+  }                                                                     \
+
+static void GetCachedPower(int e, int alpha, int gamma, int* mk, DiyFp* c_mk) {
+  // The following if statement should be optimized by the compiler so that only
+  // one array is referenced and the others are not included in the object file.
+  bool found = false;
+  CachedPower cached_power;
+  COMPUTE_FOR_CACHE(20);
+  COMPUTE_FOR_CACHE(19);
+  COMPUTE_FOR_CACHE(18);
+  COMPUTE_FOR_CACHE(17);
+  COMPUTE_FOR_CACHE(16);
+  COMPUTE_FOR_CACHE(15);
+  COMPUTE_FOR_CACHE(14);
+  COMPUTE_FOR_CACHE(13);
+  COMPUTE_FOR_CACHE(12);
+  COMPUTE_FOR_CACHE(11);
+  COMPUTE_FOR_CACHE(10);
+  COMPUTE_FOR_CACHE(9);
+  COMPUTE_FOR_CACHE(8);
+  COMPUTE_FOR_CACHE(7);
+  COMPUTE_FOR_CACHE(6);
+  COMPUTE_FOR_CACHE(5);
+  COMPUTE_FOR_CACHE(4);
+  COMPUTE_FOR_CACHE(3);
+  COMPUTE_FOR_CACHE(2);
+  COMPUTE_FOR_CACHE(1);
+  if (!found) {
+    UNIMPLEMENTED();
+    // Silence compiler warnings.
+    cached_power.significand = 0;
+    cached_power.binary_exponent = 0;
+    cached_power.decimal_exponent = 0;
+  }
+  *c_mk = DiyFp(cached_power.significand, cached_power.binary_exponent);
+  *mk = cached_power.decimal_exponent;
+  ASSERT((alpha <= c_mk->e() + e) && (c_mk->e() + e <= gamma));
+}
+#undef GRISU_REDUCTION
+#undef GRISU_CACHE_STRUCT
+#undef GRISU_CACHE_NAME
+#undef GRISU_CACHE_MAX_DISTANCE
+#undef GRISU_CACHE_OFFSET
+#undef GRISU_UINT64_C
+
+} }  // namespace v8::internal
+
+#endif  // V8_CACHED_POWERS_H_
diff --git a/src/checks.h b/src/checks.h
index eeb748b..cdcd18a 100644
--- a/src/checks.h
+++ b/src/checks.h
@@ -80,6 +80,7 @@
   }
 }
 
+
 // Helper function used by the CHECK_EQ function when given int64_t
 // arguments.  Should not be called directly.
 static inline void CheckEqualsHelper(const char* file, int line,
@@ -202,6 +203,27 @@
 }
 
 
+static inline void CheckNonEqualsHelper(const char* file,
+                                     int line,
+                                     const char* expected_source,
+                                     double expected,
+                                     const char* value_source,
+                                     double value) {
+  // Force values to 64 bit memory to truncate 80 bit precision on IA32.
+  volatile double* exp = new double[1];
+  *exp = expected;
+  volatile double* val = new double[1];
+  *val = value;
+  if (*exp == *val) {
+    V8_Fatal(file, line,
+             "CHECK_NE(%s, %s) failed\n#   Value: %f",
+             expected_source, value_source, *val);
+  }
+  delete[] exp;
+  delete[] val;
+}
+
+
 namespace v8 {
   class Value;
   template <class T> class Handle;
diff --git a/src/circular-queue-inl.h b/src/circular-queue-inl.h
new file mode 100644
index 0000000..ffe8fb0
--- /dev/null
+++ b/src/circular-queue-inl.h
@@ -0,0 +1,101 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_CIRCULAR_BUFFER_INL_H_
+#define V8_CIRCULAR_BUFFER_INL_H_
+
+#include "circular-queue.h"
+
+namespace v8 {
+namespace internal {
+
+
+template<typename Record>
+CircularQueue<Record>::CircularQueue(int desired_buffer_size_in_bytes)
+    : buffer_(NewArray<Record>(desired_buffer_size_in_bytes / sizeof(Record))),
+      buffer_end_(buffer_ + desired_buffer_size_in_bytes / sizeof(Record)),
+      enqueue_semaphore_(OS::CreateSemaphore((buffer_end_ - buffer_) - 1)),
+      enqueue_pos_(buffer_),
+      dequeue_pos_(buffer_) {
+  // To be able to distinguish between a full and an empty queue
+  // state, the queue must be capable of containing at least 2
+  // records.
+  ASSERT((buffer_end_ - buffer_) >= 2);
+}
+
+
+template<typename Record>
+CircularQueue<Record>::~CircularQueue() {
+  DeleteArray(buffer_);
+  delete enqueue_semaphore_;
+}
+
+
+template<typename Record>
+void CircularQueue<Record>::Dequeue(Record* rec) {
+  ASSERT(!IsEmpty());
+  *rec = *dequeue_pos_;
+  dequeue_pos_ = Next(dequeue_pos_);
+  // Tell we have a spare record.
+  enqueue_semaphore_->Signal();
+}
+
+
+template<typename Record>
+void CircularQueue<Record>::Enqueue(const Record& rec) {
+  // Wait until we have at least one spare record.
+  enqueue_semaphore_->Wait();
+  ASSERT(Next(enqueue_pos_) != dequeue_pos_);
+  *enqueue_pos_ = rec;
+  enqueue_pos_ = Next(enqueue_pos_);
+}
+
+
+template<typename Record>
+Record* CircularQueue<Record>::Next(Record* curr) {
+  return ++curr != buffer_end_ ? curr : buffer_;
+}
+
+
+void* SamplingCircularQueue::Enqueue() {
+  Cell* enqueue_pos = reinterpret_cast<Cell*>(
+      Thread::GetThreadLocal(producer_key_));
+  WrapPositionIfNeeded(&enqueue_pos);
+  Thread::SetThreadLocal(producer_key_, enqueue_pos + record_size_);
+  return enqueue_pos;
+}
+
+
+void SamplingCircularQueue::WrapPositionIfNeeded(
+    SamplingCircularQueue::Cell** pos) {
+  if (**pos == kEnd) *pos = buffer_;
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_CIRCULAR_BUFFER_INL_H_
diff --git a/src/circular-queue.cc b/src/circular-queue.cc
new file mode 100644
index 0000000..5f7a33e
--- /dev/null
+++ b/src/circular-queue.cc
@@ -0,0 +1,131 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "circular-queue-inl.h"
+
+namespace v8 {
+namespace internal {
+
+
+SamplingCircularQueue::SamplingCircularQueue(int record_size_in_bytes,
+                                             int desired_chunk_size_in_bytes,
+                                             int buffer_size_in_chunks)
+    : record_size_(record_size_in_bytes / sizeof(Cell)),
+      chunk_size_in_bytes_(desired_chunk_size_in_bytes / record_size_in_bytes *
+                        record_size_in_bytes),
+      chunk_size_(chunk_size_in_bytes_ / sizeof(Cell)),
+      buffer_size_(chunk_size_ * buffer_size_in_chunks),
+      // The distance ensures that producer and consumer never step on
+      // each other's chunks and helps eviction of produced data from
+      // the CPU cache (having that chunk size is bigger than the cache.)
+      producer_consumer_distance_(2 * chunk_size_),
+      buffer_(NewArray<Cell>(buffer_size_ + 1)) {
+  ASSERT(buffer_size_in_chunks > 2);
+  // Only need to keep the first cell of a chunk clean.
+  for (int i = 0; i < buffer_size_; i += chunk_size_) {
+    buffer_[i] = kClear;
+  }
+  buffer_[buffer_size_] = kEnd;
+}
+
+
+SamplingCircularQueue::~SamplingCircularQueue() {
+  DeleteArray(buffer_);
+}
+
+
+void SamplingCircularQueue::SetUpProducer() {
+  producer_key_ = Thread::CreateThreadLocalKey();
+  Thread::SetThreadLocal(producer_key_, buffer_);
+}
+
+
+void SamplingCircularQueue::TearDownProducer() {
+  Thread::DeleteThreadLocalKey(producer_key_);
+}
+
+
+void SamplingCircularQueue::SetUpConsumer() {
+  consumer_key_ = Thread::CreateThreadLocalKey();
+  ConsumerPosition* cp = new ConsumerPosition;
+  cp->dequeue_chunk_pos = buffer_;
+  cp->dequeue_chunk_poll_pos = buffer_ + producer_consumer_distance_;
+  cp->dequeue_pos = NULL;
+  Thread::SetThreadLocal(consumer_key_, cp);
+}
+
+
+void SamplingCircularQueue::TearDownConsumer() {
+  delete reinterpret_cast<ConsumerPosition*>(
+      Thread::GetThreadLocal(consumer_key_));
+  Thread::DeleteThreadLocalKey(consumer_key_);
+}
+
+
+void* SamplingCircularQueue::StartDequeue() {
+  ConsumerPosition* cp = reinterpret_cast<ConsumerPosition*>(
+      Thread::GetThreadLocal(consumer_key_));
+  if (cp->dequeue_pos != NULL) {
+    return cp->dequeue_pos;
+  } else {
+    if (*cp->dequeue_chunk_poll_pos != kClear) {
+      cp->dequeue_pos = cp->dequeue_chunk_pos;
+      cp->dequeue_end_pos = cp->dequeue_pos + chunk_size_;
+      return cp->dequeue_pos;
+    } else {
+      return NULL;
+    }
+  }
+}
+
+
+void SamplingCircularQueue::FinishDequeue() {
+  ConsumerPosition* cp = reinterpret_cast<ConsumerPosition*>(
+      Thread::GetThreadLocal(consumer_key_));
+  cp->dequeue_pos += record_size_;
+  if (cp->dequeue_pos < cp->dequeue_end_pos) return;
+  // Move to next chunk.
+  cp->dequeue_pos = NULL;
+  *cp->dequeue_chunk_pos = kClear;
+  cp->dequeue_chunk_pos += chunk_size_;
+  WrapPositionIfNeeded(&cp->dequeue_chunk_pos);
+  cp->dequeue_chunk_poll_pos += chunk_size_;
+  WrapPositionIfNeeded(&cp->dequeue_chunk_poll_pos);
+}
+
+
+void SamplingCircularQueue::FlushResidualRecords() {
+  ConsumerPosition* cp = reinterpret_cast<ConsumerPosition*>(
+      Thread::GetThreadLocal(consumer_key_));
+  // Eliminate producer / consumer distance.
+  cp->dequeue_chunk_poll_pos = cp->dequeue_chunk_pos;
+}
+
+
+} }  // namespace v8::internal
diff --git a/src/circular-queue.h b/src/circular-queue.h
new file mode 100644
index 0000000..11159e0
--- /dev/null
+++ b/src/circular-queue.h
@@ -0,0 +1,130 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_CIRCULAR_QUEUE_H_
+#define V8_CIRCULAR_QUEUE_H_
+
+namespace v8 {
+namespace internal {
+
+
+// Lock-based blocking circular queue for small records.  Intended for
+// transfer of small records between a single producer and a single
+// consumer. Blocks on enqueue operation if the queue is full.
+template<typename Record>
+class CircularQueue {
+ public:
+  inline explicit CircularQueue(int desired_buffer_size_in_bytes);
+  inline ~CircularQueue();
+
+  INLINE(void Dequeue(Record* rec));
+  INLINE(void Enqueue(const Record& rec));
+  INLINE(bool IsEmpty()) { return enqueue_pos_ == dequeue_pos_; }
+
+ private:
+  INLINE(Record* Next(Record* curr));
+
+  Record* buffer_;
+  Record* const buffer_end_;
+  Semaphore* enqueue_semaphore_;
+  Record* enqueue_pos_;
+  Record* dequeue_pos_;
+
+  DISALLOW_COPY_AND_ASSIGN(CircularQueue);
+};
+
+
+// Lock-free cache-friendly sampling circular queue for large
+// records. Intended for fast transfer of large records between a
+// single producer and a single consumer. If the queue is full,
+// previous unread records are overwritten. The queue is designed with
+// a goal in mind to evade cache lines thrashing by preventing
+// simultaneous reads and writes to adjanced memory locations.
+//
+// IMPORTANT: as a producer never checks for chunks cleanness, it is
+// possible that it can catch up and overwrite a chunk that a consumer
+// is currently reading, resulting in a corrupt record being read.
+class SamplingCircularQueue {
+ public:
+  // Executed on the application thread.
+  SamplingCircularQueue(int record_size_in_bytes,
+                        int desired_chunk_size_in_bytes,
+                        int buffer_size_in_chunks);
+  ~SamplingCircularQueue();
+
+  // Executed on the producer (sampler) or application thread.
+  void SetUpProducer();
+  // Enqueue returns a pointer to a memory location for storing the next
+  // record.
+  INLINE(void* Enqueue());
+  void TearDownProducer();
+
+  // Executed on the consumer (analyzer) thread.
+  void SetUpConsumer();
+  // StartDequeue returns a pointer to a memory location for retrieving
+  // the next record. After the record had been read by a consumer,
+  // FinishDequeue must be called. Until that moment, subsequent calls
+  // to StartDequeue will return the same pointer.
+  void* StartDequeue();
+  void FinishDequeue();
+  // Due to a presence of slipping between the producer and the consumer,
+  // the queue must be notified whether producing has been finished in order
+  // to process remaining records from the buffer.
+  void FlushResidualRecords();
+  void TearDownConsumer();
+
+  typedef AtomicWord Cell;
+  // Reserved values for the first cell of a record.
+  static const Cell kClear = 0;  // Marks clean (processed) chunks.
+  static const Cell kEnd = -1;   // Marks the end of the buffer.
+
+ private:
+  struct ConsumerPosition {
+    Cell* dequeue_chunk_pos;
+    Cell* dequeue_chunk_poll_pos;
+    Cell* dequeue_pos;
+    Cell* dequeue_end_pos;
+  };
+
+  INLINE(void WrapPositionIfNeeded(Cell** pos));
+
+  const int record_size_;
+  const int chunk_size_in_bytes_;
+  const int chunk_size_;
+  const int buffer_size_;
+  const int producer_consumer_distance_;
+  Cell* buffer_;
+  // Store producer and consumer data in TLS to avoid modifying the
+  // same CPU cache line from two threads simultaneously.
+  Thread::LocalStorageKey consumer_key_;
+  Thread::LocalStorageKey producer_key_;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_CIRCULAR_QUEUE_H_
diff --git a/src/conversions.cc b/src/conversions.cc
index fd6d38d..d0abc2b 100644
--- a/src/conversions.cc
+++ b/src/conversions.cc
@@ -31,6 +31,7 @@
 
 #include "conversions-inl.h"
 #include "factory.h"
+#include "fast-dtoa.h"
 #include "scanner.h"
 
 namespace v8 {
@@ -382,8 +383,17 @@
       int decimal_point;
       int sign;
 
-      char* decimal_rep = dtoa(v, 0, 0, &decimal_point, &sign, NULL);
-      int length = StrLength(decimal_rep);
+      char* decimal_rep;
+      bool used_gay_dtoa = false;
+      char fast_dtoa_buffer[kFastDtoaMaximalLength + 1];
+      int length;
+      if (FastDtoa(v, fast_dtoa_buffer, &sign, &length, &decimal_point)) {
+        decimal_rep = fast_dtoa_buffer;
+      } else {
+        decimal_rep = dtoa(v, 0, 0, &decimal_point, &sign, NULL);
+        used_gay_dtoa = true;
+        length = StrLength(decimal_rep);
+      }
 
       if (sign) builder.AddCharacter('-');
 
@@ -418,7 +428,7 @@
         builder.AddFormatted("%d", exponent);
       }
 
-      freedtoa(decimal_rep);
+      if (used_gay_dtoa) freedtoa(decimal_rep);
     }
   }
   return builder.Finalize();
diff --git a/src/counters.h b/src/counters.h
index 5f4dca9..aed46cf 100644
--- a/src/counters.h
+++ b/src/counters.h
@@ -65,7 +65,7 @@
   // may receive a different location to store it's counter.
   // The return value must not be cached and re-used across
   // threads, although a single thread is free to cache it.
-  static int *FindLocation(const char* name) {
+  static int* FindLocation(const char* name) {
     if (!lookup_function_) return NULL;
     return lookup_function_(name);
   }
diff --git a/src/cpu-profiler-inl.h b/src/cpu-profiler-inl.h
new file mode 100644
index 0000000..26ab643
--- /dev/null
+++ b/src/cpu-profiler-inl.h
@@ -0,0 +1,50 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_CPU_PROFILER_INL_H_
+#define V8_CPU_PROFILER_INL_H_
+
+#include "circular-queue-inl.h"
+#include "profile-generator-inl.h"
+
+#include "cpu-profiler.h"
+
+namespace v8 {
+namespace internal {
+
+
+TickSample* ProfilerEventsProcessor::TickSampleEvent() {
+  TickSampleEventRecord* evt =
+      reinterpret_cast<TickSampleEventRecord*>(ticks_buffer_.Enqueue());
+  evt->order = enqueue_order_;  // No increment!
+  return &evt->sample;
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_CPU_PROFILER_INL_H_
diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
new file mode 100644
index 0000000..d36f511
--- /dev/null
+++ b/src/cpu-profiler.cc
@@ -0,0 +1,201 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "cpu-profiler-inl.h"
+
+namespace v8 {
+namespace internal {
+
+
+static const int kEventsBufferSize = 256*KB;
+static const int kTickSamplesBufferChunkSize = 64*KB;
+static const int kTickSamplesBufferChunksCount = 16;
+
+
+ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
+    : generator_(generator),
+      running_(false),
+      events_buffer_(kEventsBufferSize),
+      ticks_buffer_(sizeof(TickSampleEventRecord),
+                    kTickSamplesBufferChunkSize,
+                    kTickSamplesBufferChunksCount),
+      enqueue_order_(0) { }
+
+
+void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
+                                              String* name,
+                                              String* resource_name,
+                                              int line_number,
+                                              Address start,
+                                              unsigned size) {
+  CodeEventsContainer evt_rec;
+  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+  rec->type = CodeEventRecord::CODE_CREATION;
+  rec->order = ++enqueue_order_;
+  rec->start = start;
+  rec->entry = generator_->NewCodeEntry(tag, name, resource_name, line_number);
+  rec->size = size;
+  events_buffer_.Enqueue(evt_rec);
+}
+
+
+void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
+                                              const char* name,
+                                              Address start,
+                                              unsigned size) {
+  CodeEventsContainer evt_rec;
+  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+  rec->type = CodeEventRecord::CODE_CREATION;
+  rec->order = ++enqueue_order_;
+  rec->start = start;
+  rec->entry = generator_->NewCodeEntry(tag, name);
+  rec->size = size;
+  events_buffer_.Enqueue(evt_rec);
+}
+
+
+void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
+                                              int args_count,
+                                              Address start,
+                                              unsigned size) {
+  CodeEventsContainer evt_rec;
+  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+  rec->type = CodeEventRecord::CODE_CREATION;
+  rec->order = ++enqueue_order_;
+  rec->start = start;
+  rec->entry = generator_->NewCodeEntry(tag, args_count);
+  rec->size = size;
+  events_buffer_.Enqueue(evt_rec);
+}
+
+
+void ProfilerEventsProcessor::CodeMoveEvent(Address from, Address to) {
+  CodeEventsContainer evt_rec;
+  CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
+  rec->type = CodeEventRecord::CODE_MOVE;
+  rec->order = ++enqueue_order_;
+  rec->from = from;
+  rec->to = to;
+  events_buffer_.Enqueue(evt_rec);
+}
+
+
+void ProfilerEventsProcessor::CodeDeleteEvent(Address from) {
+  CodeEventsContainer evt_rec;
+  CodeDeleteEventRecord* rec = &evt_rec.CodeDeleteEventRecord_;
+  rec->type = CodeEventRecord::CODE_DELETE;
+  rec->order = ++enqueue_order_;
+  rec->start = from;
+  events_buffer_.Enqueue(evt_rec);
+}
+
+
+void ProfilerEventsProcessor::FunctionCreateEvent(Address alias,
+                                                  Address start) {
+  CodeEventsContainer evt_rec;
+  CodeAliasEventRecord* rec = &evt_rec.CodeAliasEventRecord_;
+  rec->type = CodeEventRecord::CODE_ALIAS;
+  rec->order = ++enqueue_order_;
+  rec->alias = alias;
+  rec->start = start;
+  events_buffer_.Enqueue(evt_rec);
+}
+
+
+void ProfilerEventsProcessor::FunctionMoveEvent(Address from, Address to) {
+  CodeMoveEvent(from, to);
+}
+
+
+void ProfilerEventsProcessor::FunctionDeleteEvent(Address from) {
+  CodeDeleteEvent(from);
+}
+
+
+bool ProfilerEventsProcessor::ProcessCodeEvent(unsigned* dequeue_order) {
+  if (!events_buffer_.IsEmpty()) {
+    CodeEventsContainer record;
+    events_buffer_.Dequeue(&record);
+    switch (record.generic.type) {
+#define PROFILER_TYPE_CASE(type, clss)                          \
+      case CodeEventRecord::type:                               \
+        record.clss##_.UpdateCodeMap(generator_->code_map());   \
+        break;
+
+      CODE_EVENTS_TYPE_LIST(PROFILER_TYPE_CASE)
+
+#undef PROFILER_TYPE_CASE
+      default: return true;  // Skip record.
+    }
+    *dequeue_order = record.generic.order;
+    return true;
+  }
+  return false;
+}
+
+
+bool ProfilerEventsProcessor::ProcessTicks(unsigned dequeue_order) {
+  while (true) {
+    const TickSampleEventRecord* rec =
+        reinterpret_cast<TickSampleEventRecord*>(ticks_buffer_.StartDequeue());
+    if (rec == NULL) return false;
+    if (rec->order == dequeue_order) {
+      generator_->RecordTickSample(rec->sample);
+      ticks_buffer_.FinishDequeue();
+    } else {
+      return true;
+    }
+  }
+}
+
+
+void ProfilerEventsProcessor::Run() {
+  ticks_buffer_.SetUpConsumer();
+  unsigned dequeue_order = 0;
+  running_ = true;
+
+  while (running_) {
+    // Process ticks until we have any.
+    if (ProcessTicks(dequeue_order)) {
+      // All ticks of the current dequeue_order are processed,
+      // proceed to the next code event.
+      ProcessCodeEvent(&dequeue_order);
+    }
+    YieldCPU();
+  }
+
+  // Process remaining tick events.
+  ticks_buffer_.FlushResidualRecords();
+  // Perform processing until we have tick events, skip remaining code events.
+  while (ProcessTicks(dequeue_order) && ProcessCodeEvent(&dequeue_order)) { }
+  ticks_buffer_.TearDownConsumer();
+}
+
+
+} }  // namespace v8::internal
diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h
new file mode 100644
index 0000000..ccfac5c
--- /dev/null
+++ b/src/cpu-profiler.h
@@ -0,0 +1,188 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_CPU_PROFILER_H_
+#define V8_CPU_PROFILER_H_
+
+#include "circular-queue.h"
+#include "profile-generator.h"
+
+namespace v8 {
+namespace internal {
+
+
+#define CODE_EVENTS_TYPE_LIST(V)                \
+  V(CODE_CREATION, CodeCreateEventRecord)       \
+  V(CODE_MOVE,     CodeMoveEventRecord)         \
+  V(CODE_DELETE,   CodeDeleteEventRecord)       \
+  V(CODE_ALIAS,    CodeAliasEventRecord)
+
+
+class CodeEventRecord {
+ public:
+#define DECLARE_TYPE(type, ignore) type,
+  enum Type {
+    NONE = 0,
+    CODE_EVENTS_TYPE_LIST(DECLARE_TYPE)
+    NUMBER_OF_TYPES
+  };
+#undef DECLARE_TYPE
+
+  Type type;
+  unsigned order;
+};
+
+
+class CodeCreateEventRecord : public CodeEventRecord {
+ public:
+  Address start;
+  CodeEntry* entry;
+  unsigned size;
+
+  INLINE(void UpdateCodeMap(CodeMap* code_map)) {
+    code_map->AddCode(start, entry, size);
+  }
+};
+
+
+class CodeMoveEventRecord : public CodeEventRecord {
+ public:
+  Address from;
+  Address to;
+
+  INLINE(void UpdateCodeMap(CodeMap* code_map)) {
+    code_map->MoveCode(from, to);
+  }
+};
+
+
+class CodeDeleteEventRecord : public CodeEventRecord {
+ public:
+  Address start;
+
+  INLINE(void UpdateCodeMap(CodeMap* code_map)) {
+    code_map->DeleteCode(start);
+  }
+};
+
+
+class CodeAliasEventRecord : public CodeEventRecord {
+ public:
+  Address alias;
+  Address start;
+
+  INLINE(void UpdateCodeMap(CodeMap* code_map)) {
+    code_map->AddAlias(alias, start);
+  }
+};
+
+
+class TickSampleEventRecord {
+ public:
+  // In memory, the first machine word of a TickSampleEventRecord will be the
+  // first entry of TickSample, that is -- a program counter field.
+  // TickSample is put first, because 'order' can become equal to
+  // SamplingCircularQueue::kClear, while program counter can't.
+  TickSample sample;
+  unsigned order;
+
+#if defined(__GNUC__) && (__GNUC__ < 4)
+  // Added to avoid 'all member functions in class are private' warning.
+  INLINE(unsigned get_order() const) { return order; }
+  // Added to avoid 'class only defines private constructors and
+  // has no friends' warning.
+  friend class TickSampleEventRecordFriend;
+#endif
+ private:
+  // Disable instantiation.
+  TickSampleEventRecord();
+
+  DISALLOW_COPY_AND_ASSIGN(TickSampleEventRecord);
+};
+
+
+// This class implements both the profile events processor thread and
+// methods called by event producers: VM and stack sampler threads.
+class ProfilerEventsProcessor : public Thread {
+ public:
+  explicit ProfilerEventsProcessor(ProfileGenerator* generator);
+  virtual ~ProfilerEventsProcessor() { }
+
+  // Thread control.
+  virtual void Run();
+  inline void Stop() { running_ = false; }
+  INLINE(bool running()) { return running_; }
+
+  // Events adding methods. Called by VM threads.
+  void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                       String* name,
+                       String* resource_name, int line_number,
+                       Address start, unsigned size);
+  void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                       const char* name,
+                       Address start, unsigned size);
+  void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                       int args_count,
+                       Address start, unsigned size);
+  void CodeMoveEvent(Address from, Address to);
+  void CodeDeleteEvent(Address from);
+  void FunctionCreateEvent(Address alias, Address start);
+  void FunctionMoveEvent(Address from, Address to);
+  void FunctionDeleteEvent(Address from);
+
+  // Tick sampler registration. Called by sampler thread or signal handler.
+  inline void SetUpSamplesProducer() { ticks_buffer_.SetUpProducer(); }
+  // Tick sample events are filled directly in the buffer of the circular
+  // queue (because the structure is of fixed width, but usually not all
+  // stack frame entries are filled.) This method returns a pointer to the
+  // next record of the buffer.
+  INLINE(TickSample* TickSampleEvent());
+  inline void TearDownSamplesProducer() { ticks_buffer_.TearDownProducer(); }
+
+ private:
+  union CodeEventsContainer {
+    CodeEventRecord generic;
+#define DECLARE_CLASS(ignore, type) type type##_;
+    CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
+#undef DECLARE_TYPE
+  };
+
+  // Called from events processing thread (Run() method.)
+  bool ProcessCodeEvent(unsigned* dequeue_order);
+  bool ProcessTicks(unsigned dequeue_order);
+
+  ProfileGenerator* generator_;
+  bool running_;
+  CircularQueue<CodeEventsContainer> events_buffer_;
+  SamplingCircularQueue ticks_buffer_;
+  unsigned enqueue_order_;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_CPU_PROFILER_H_
diff --git a/src/data-flow.cc b/src/data-flow.cc
index 278b82b..141718d 100644
--- a/src/data-flow.cc
+++ b/src/data-flow.cc
@@ -770,293 +770,6 @@
 }
 
 
-ZoneList<Expression*>* VarUseMap::Lookup(Variable* var) {
-  HashMap::Entry* entry = HashMap::Lookup(var, var->name()->Hash(), true);
-  if (entry->value == NULL) {
-    entry->value = new ZoneList<Expression*>(1);
-  }
-  return reinterpret_cast<ZoneList<Expression*>*>(entry->value);
-}
-
-
-void LivenessAnalyzer::Analyze(FunctionLiteral* fun) {
-  // Process the function body.
-  VisitStatements(fun->body());
-
-  // All variables are implicitly defined at the function start.
-  // Record a definition of all variables live at function entry.
-  for (HashMap::Entry* p = live_vars_.Start();
-       p != NULL;
-       p = live_vars_.Next(p)) {
-    Variable* var = reinterpret_cast<Variable*>(p->key);
-    RecordDef(var, fun);
-  }
-}
-
-
-void LivenessAnalyzer::VisitStatements(ZoneList<Statement*>* stmts) {
-  // Visit statements right-to-left.
-  for (int i = stmts->length() - 1; i >= 0; i--) {
-    Visit(stmts->at(i));
-  }
-}
-
-
-void LivenessAnalyzer::RecordUse(Variable* var, Expression* expr) {
-  ASSERT(var->is_global() || var->is_this());
-  ZoneList<Expression*>* uses = live_vars_.Lookup(var);
-  uses->Add(expr);
-}
-
-
-void LivenessAnalyzer::RecordDef(Variable* var, Expression* expr) {
-  ASSERT(var->is_global() || var->is_this());
-
-  // We do not support other expressions that can define variables.
-  ASSERT(expr->AsFunctionLiteral() != NULL);
-
-  // Add the variable to the list of defined variables.
-  if (expr->defined_vars() == NULL) {
-    expr->set_defined_vars(new ZoneList<DefinitionInfo*>(1));
-  }
-  DefinitionInfo* def = new DefinitionInfo();
-  expr->AsFunctionLiteral()->defined_vars()->Add(def);
-
-  // Compute the last use of the definition. The variable uses are
-  // inserted in reversed evaluation order. The first element
-  // in the list of live uses is the last use.
-  ZoneList<Expression*>* uses = live_vars_.Lookup(var);
-  while (uses->length() > 0) {
-    Expression* use_site = uses->RemoveLast();
-    use_site->set_var_def(def);
-    if (uses->length() == 0) {
-      def->set_last_use(use_site);
-    }
-  }
-}
-
-
-// Visitor functions for live variable analysis.
-void LivenessAnalyzer::VisitDeclaration(Declaration* decl) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitBlock(Block* stmt) {
-  VisitStatements(stmt->statements());
-}
-
-
-void LivenessAnalyzer::VisitExpressionStatement(
-    ExpressionStatement* stmt) {
-  Visit(stmt->expression());
-}
-
-
-void LivenessAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) {
-  // Do nothing.
-}
-
-
-void LivenessAnalyzer::VisitIfStatement(IfStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitContinueStatement(ContinueStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitBreakStatement(BreakStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitReturnStatement(ReturnStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitWithEnterStatement(
-    WithEnterStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitWithExitStatement(WithExitStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitWhileStatement(WhileStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitForStatement(ForStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitForInStatement(ForInStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitTryCatchStatement(TryCatchStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitTryFinallyStatement(
-    TryFinallyStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitDebuggerStatement(
-    DebuggerStatement* stmt) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitFunctionBoilerplateLiteral(
-    FunctionBoilerplateLiteral* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitConditional(Conditional* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitSlot(Slot* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitVariableProxy(VariableProxy* expr) {
-  Variable* var = expr->var();
-  ASSERT(var->is_global());
-  ASSERT(!var->is_this());
-  RecordUse(var, expr);
-}
-
-
-void LivenessAnalyzer::VisitLiteral(Literal* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitCatchExtensionObject(
-    CatchExtensionObject* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitAssignment(Assignment* expr) {
-  Property* prop = expr->target()->AsProperty();
-  ASSERT(prop != NULL);
-  ASSERT(prop->key()->IsPropertyName());
-  VariableProxy* proxy = prop->obj()->AsVariableProxy();
-  ASSERT(proxy != NULL && proxy->var()->is_this());
-
-  // Record use of this at the assignment node. Assignments to
-  // this-properties are treated like unary operations.
-  RecordUse(proxy->var(), expr);
-
-  // Visit right-hand side.
-  Visit(expr->value());
-}
-
-
-void LivenessAnalyzer::VisitThrow(Throw* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitProperty(Property* expr) {
-  ASSERT(expr->key()->IsPropertyName());
-  VariableProxy* proxy = expr->obj()->AsVariableProxy();
-  ASSERT(proxy != NULL && proxy->var()->is_this());
-  RecordUse(proxy->var(), expr);
-}
-
-
-void LivenessAnalyzer::VisitCall(Call* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitCallNew(CallNew* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitCallRuntime(CallRuntime* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitUnaryOperation(UnaryOperation* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitCountOperation(CountOperation* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitBinaryOperation(BinaryOperation* expr) {
-  // Visit child nodes in reverse evaluation order.
-  Visit(expr->right());
-  Visit(expr->left());
-}
-
-
-void LivenessAnalyzer::VisitCompareOperation(CompareOperation* expr) {
-  UNREACHABLE();
-}
-
-
-void LivenessAnalyzer::VisitThisFunction(ThisFunction* expr) {
-  UNREACHABLE();
-}
-
-
 AssignedVariablesAnalyzer::AssignedVariablesAnalyzer(FunctionLiteral* fun)
     : fun_(fun),
       av_(fun->scope()->num_parameters() + fun->scope()->num_stack_slots()) {}
diff --git a/src/data-flow.h b/src/data-flow.h
index 9702013..74a370c 100644
--- a/src/data-flow.h
+++ b/src/data-flow.h
@@ -550,55 +550,6 @@
 };
 
 
-class VarUseMap : public HashMap {
- public:
-  VarUseMap() : HashMap(VarMatch) {}
-
-  ZoneList<Expression*>* Lookup(Variable* var);
-
- private:
-  static bool VarMatch(void* key1, void* key2) { return key1 == key2; }
-};
-
-
-class DefinitionInfo : public ZoneObject {
- public:
-  explicit DefinitionInfo() : last_use_(NULL) {}
-
-  Expression* last_use() { return last_use_; }
-  void set_last_use(Expression* expr) { last_use_ = expr; }
-
- private:
-  Expression* last_use_;
-  Register location_;
-};
-
-
-class LivenessAnalyzer : public AstVisitor {
- public:
-  LivenessAnalyzer() {}
-
-  void Analyze(FunctionLiteral* fun);
-
- private:
-  void VisitStatements(ZoneList<Statement*>* stmts);
-
-  void RecordUse(Variable* var, Expression* expr);
-  void RecordDef(Variable* var, Expression* expr);
-
-
-  // AST node visit functions.
-#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
-  AST_NODE_LIST(DECLARE_VISIT)
-#undef DECLARE_VISIT
-
-  // Map for tracking the live variables.
-  VarUseMap live_vars_;
-
-  DISALLOW_COPY_AND_ASSIGN(LivenessAnalyzer);
-};
-
-
 // Computes the set of assigned variables and annotates variables proxies
 // that are trivial sub-expressions and for-loops where the loop variable
 // is guaranteed to be a smi.
diff --git a/src/diy-fp.cc b/src/diy-fp.cc
new file mode 100644
index 0000000..c54bd1d
--- /dev/null
+++ b/src/diy-fp.cc
@@ -0,0 +1,58 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "diy-fp.h"
+
+namespace v8 {
+namespace internal {
+
+void DiyFp::Multiply(const DiyFp& other) {
+  // Simply "emulates" a 128 bit multiplication.
+  // However: the resulting number only contains 64 bits. The least
+  // significant 64 bits are only used for rounding the most significant 64
+  // bits.
+  const uint64_t kM32 = 0xFFFFFFFFu;
+  uint64_t a = f_ >> 32;
+  uint64_t b = f_ & kM32;
+  uint64_t c = other.f_ >> 32;
+  uint64_t d = other.f_ & kM32;
+  uint64_t ac = a * c;
+  uint64_t bc = b * c;
+  uint64_t ad = a * d;
+  uint64_t bd = b * d;
+  uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32);
+  // By adding 1U << 31 to tmp we round the final result.
+  // Halfway cases will be round up.
+  tmp += 1U << 31;
+  uint64_t result_f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
+  e_ += other.e_ + 64;
+  f_ = result_f;
+}
+
+} }  // namespace v8::internal
diff --git a/src/diy-fp.h b/src/diy-fp.h
new file mode 100644
index 0000000..cfe05ef
--- /dev/null
+++ b/src/diy-fp.h
@@ -0,0 +1,117 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_DIY_FP_H_
+#define V8_DIY_FP_H_
+
+namespace v8 {
+namespace internal {
+
+// This "Do It Yourself Floating Point" class implements a floating-point number
+// with a uint64 significand and an int exponent. Normalized DiyFp numbers will
+// have the most significant bit of the significand set.
+// Multiplication and Subtraction do not normalize their results.
+// DiyFp are not designed to contain special doubles (NaN and Infinity).
+class DiyFp {
+ public:
+  static const int kSignificandSize = 64;
+
+  DiyFp() : f_(0), e_(0) {}
+  DiyFp(uint64_t f, int e) : f_(f), e_(e) {}
+
+  // this = this - other.
+  // The exponents of both numbers must be the same and the significand of this
+  // must be bigger than the significand of other.
+  // The result will not be normalized.
+  void Subtract(const DiyFp& other) {
+    ASSERT(e_ == other.e_);
+    ASSERT(f_ >= other.f_);
+    f_ -= other.f_;
+  }
+
+  // Returns a - b.
+  // The exponents of both numbers must be the same and this must be bigger
+  // than other. The result will not be normalized.
+  static DiyFp Minus(const DiyFp& a, const DiyFp& b) {
+    DiyFp result = a;
+    result.Subtract(b);
+    return result;
+  }
+
+
+  // this = this * other.
+  void Multiply(const DiyFp& other);
+
+  // returns a * b;
+  static DiyFp Times(const DiyFp& a, const DiyFp& b) {
+    DiyFp result = a;
+    result.Multiply(b);
+    return result;
+  }
+
+  void Normalize() {
+    ASSERT(f_ != 0);
+    uint64_t f = f_;
+    int e = e_;
+
+    // This method is mainly called for normalizing boundaries. In general
+    // boundaries need to be shifted by 10 bits. We thus optimize for this case.
+    const uint64_t k10MSBits = V8_2PART_UINT64_C(0xFFC00000, 00000000);
+    while ((f & k10MSBits) == 0) {
+      f <<= 10;
+      e -= 10;
+    }
+    while ((f & kUint64MSB) == 0) {
+      f <<= 1;
+      e--;
+    }
+    f_ = f;
+    e_ = e;
+  }
+
+  static DiyFp Normalize(const DiyFp& a) {
+    DiyFp result = a;
+    result.Normalize();
+    return result;
+  }
+
+  uint64_t f() const { return f_; }
+  int e() const { return e_; }
+
+  void set_f(uint64_t new_value) { f_ = new_value; }
+  void set_e(int new_value) { e_ = new_value; }
+
+ private:
+  static const uint64_t kUint64MSB = V8_2PART_UINT64_C(0x80000000, 00000000);
+
+  uint64_t f_;
+  int e_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_DIY_FP_H_
diff --git a/src/double.h b/src/double.h
new file mode 100644
index 0000000..65f8c94
--- /dev/null
+++ b/src/double.h
@@ -0,0 +1,169 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_DOUBLE_H_
+#define V8_DOUBLE_H_
+
+#include "diy-fp.h"
+
+namespace v8 {
+namespace internal {
+
+// We assume that doubles and uint64_t have the same endianness.
+static uint64_t double_to_uint64(double d) { return BitCast<uint64_t>(d); }
+static double uint64_to_double(uint64_t d64) { return BitCast<double>(d64); }
+
+// Helper functions for doubles.
+class Double {
+ public:
+  static const uint64_t kSignMask = V8_2PART_UINT64_C(0x80000000, 00000000);
+  static const uint64_t kExponentMask = V8_2PART_UINT64_C(0x7FF00000, 00000000);
+  static const uint64_t kSignificandMask =
+      V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF);
+  static const uint64_t kHiddenBit = V8_2PART_UINT64_C(0x00100000, 00000000);
+
+  Double() : d64_(0) {}
+  explicit Double(double d) : d64_(double_to_uint64(d)) {}
+  explicit Double(uint64_t d64) : d64_(d64) {}
+
+  DiyFp AsDiyFp() const {
+    ASSERT(!IsSpecial());
+    return DiyFp(Significand(), Exponent());
+  }
+
+  // this->Significand() must not be 0.
+  DiyFp AsNormalizedDiyFp() const {
+    uint64_t f = Significand();
+    int e = Exponent();
+
+    ASSERT(f != 0);
+
+    // The current double could be a denormal.
+    while ((f & kHiddenBit) == 0) {
+      f <<= 1;
+      e--;
+    }
+    // Do the final shifts in one go. Don't forget the hidden bit (the '-1').
+    f <<= DiyFp::kSignificandSize - kSignificandSize - 1;
+    e -= DiyFp::kSignificandSize - kSignificandSize - 1;
+    return DiyFp(f, e);
+  }
+
+  // Returns the double's bit as uint64.
+  uint64_t AsUint64() const {
+    return d64_;
+  }
+
+  int Exponent() const {
+    if (IsDenormal()) return kDenormalExponent;
+
+    uint64_t d64 = AsUint64();
+    int biased_e = static_cast<int>((d64 & kExponentMask) >> kSignificandSize);
+    return biased_e - kExponentBias;
+  }
+
+  uint64_t Significand() const {
+    uint64_t d64 = AsUint64();
+    uint64_t significand = d64 & kSignificandMask;
+    if (!IsDenormal()) {
+      return significand + kHiddenBit;
+    } else {
+      return significand;
+    }
+  }
+
+  // Returns true if the double is a denormal.
+  bool IsDenormal() const {
+    uint64_t d64 = AsUint64();
+    return (d64 & kExponentMask) == 0;
+  }
+
+  // We consider denormals not to be special.
+  // Hence only Infinity and NaN are special.
+  bool IsSpecial() const {
+    uint64_t d64 = AsUint64();
+    return (d64 & kExponentMask) == kExponentMask;
+  }
+
+  bool IsNan() const {
+    uint64_t d64 = AsUint64();
+    return ((d64 & kExponentMask) == kExponentMask) &&
+        ((d64 & kSignificandMask) != 0);
+  }
+
+
+  bool IsInfinite() const {
+    uint64_t d64 = AsUint64();
+    return ((d64 & kExponentMask) == kExponentMask) &&
+        ((d64 & kSignificandMask) == 0);
+  }
+
+
+  int Sign() const {
+    uint64_t d64 = AsUint64();
+    return (d64 & kSignMask) == 0? 1: -1;
+  }
+
+
+  // Returns the two boundaries of this.
+  // The bigger boundary (m_plus) is normalized. The lower boundary has the same
+  // exponent as m_plus.
+  void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
+    DiyFp v = this->AsDiyFp();
+    bool significand_is_zero = (v.f() == kHiddenBit);
+    DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
+    DiyFp m_minus;
+    if (significand_is_zero && v.e() != kDenormalExponent) {
+      // The boundary is closer. Think of v = 1000e10 and v- = 9999e9.
+      // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
+      // at a distance of 1e8.
+      // The only exception is for the smallest normal: the largest denormal is
+      // at the same distance as its successor.
+      // Note: denormals have the same exponent as the smallest normals.
+      m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
+    } else {
+      m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
+    }
+    m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
+    m_minus.set_e(m_plus.e());
+    *out_m_plus = m_plus;
+    *out_m_minus = m_minus;
+  }
+
+  double value() const { return uint64_to_double(d64_); }
+
+ private:
+  static const int kSignificandSize = 52;  // Excludes the hidden bit.
+  static const int kExponentBias = 0x3FF + kSignificandSize;
+  static const int kDenormalExponent = -kExponentBias + 1;
+
+  uint64_t d64_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_DOUBLE_H_
diff --git a/src/fast-codegen.cc b/src/fast-codegen.cc
index 602d6b8..5d0b9c1 100644
--- a/src/fast-codegen.cc
+++ b/src/fast-codegen.cc
@@ -436,9 +436,6 @@
   AstLabeler labeler;
   labeler.Label(info);
 
-  LivenessAnalyzer analyzer;
-  analyzer.Analyze(info->function());
-
   CodeGenerator::MakeCodePrologue(info);
 
   const int kInitialBufferSize = 4 * KB;
@@ -598,8 +595,8 @@
     Comment cmnt(masm(), ";; Global");
     if (FLAG_print_ir) {
       SmartPointer<char> name = expr->name()->ToCString();
-      PrintF("%d: t%d = Global(%s)  // last_use = %d\n", expr->num(),
-             expr->num(), *name, expr->var_def()->last_use()->num());
+      PrintF("%d: t%d = Global(%s)\n", expr->num(),
+             expr->num(), *name);
     }
     EmitGlobalVariableLoad(cell);
   }
@@ -653,9 +650,8 @@
     SmartPointer<char> name_string = name->ToCString();
     PrintF("%d: ", expr->num());
     if (!destination().is(no_reg)) PrintF("t%d = ", expr->num());
-    PrintF("Store(this, \"%s\", t%d)  // last_use(this) = %d\n", *name_string,
-           expr->value()->num(),
-           expr->var_def()->last_use()->num());
+    PrintF("Store(this, \"%s\", t%d)\n", *name_string,
+           expr->value()->num());
   }
 
   EmitThisPropertyStore(name);
@@ -678,9 +674,8 @@
     Comment cmnt(masm(), ";; Load from this");
     if (FLAG_print_ir) {
       SmartPointer<char> name_string = name->ToCString();
-      PrintF("%d: t%d = Load(this, \"%s\")  // last_use(this) = %d\n",
-             expr->num(), expr->num(), *name_string,
-             expr->var_def()->last_use()->num());
+      PrintF("%d: t%d = Load(this, \"%s\")\n",
+             expr->num(), expr->num(), *name_string);
     }
     EmitThisPropertyLoad(name);
   }
diff --git a/src/fast-dtoa.cc b/src/fast-dtoa.cc
new file mode 100644
index 0000000..0299544
--- /dev/null
+++ b/src/fast-dtoa.cc
@@ -0,0 +1,508 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "fast-dtoa.h"
+
+#include "cached-powers.h"
+#include "diy-fp.h"
+#include "double.h"
+
+namespace v8 {
+namespace internal {
+
+// The minimal and maximal target exponent define the range of w's binary
+// exponent, where 'w' is the result of multiplying the input by a cached power
+// of ten.
+//
+// A different range might be chosen on a different platform, to optimize digit
+// generation, but a smaller range requires more powers of ten to be cached.
+static const int minimal_target_exponent = -60;
+static const int maximal_target_exponent = -32;
+
+
+// Adjusts the last digit of the generated number, and screens out generated
+// solutions that may be inaccurate. A solution may be inaccurate if it is
+// outside the safe interval, or if we ctannot prove that it is closer to the
+// input than a neighboring representation of the same length.
+//
+// Input: * buffer containing the digits of too_high / 10^kappa
+//        * the buffer's length
+//        * distance_too_high_w == (too_high - w).f() * unit
+//        * unsafe_interval == (too_high - too_low).f() * unit
+//        * rest = (too_high - buffer * 10^kappa).f() * unit
+//        * ten_kappa = 10^kappa * unit
+//        * unit = the common multiplier
+// Output: returns true if the buffer is guaranteed to contain the closest
+//    representable number to the input.
+//  Modifies the generated digits in the buffer to approach (round towards) w.
+bool RoundWeed(char* buffer,
+               int length,
+               uint64_t distance_too_high_w,
+               uint64_t unsafe_interval,
+               uint64_t rest,
+               uint64_t ten_kappa,
+               uint64_t unit) {
+  uint64_t small_distance = distance_too_high_w - unit;
+  uint64_t big_distance = distance_too_high_w + unit;
+  // Let w_low  = too_high - big_distance, and
+  //     w_high = too_high - small_distance.
+  // Note: w_low < w < w_high
+  //
+  // The real w (* unit) must lie somewhere inside the interval
+  // ]w_low; w_low[ (often written as "(w_low; w_low)")
+
+  // Basically the buffer currently contains a number in the unsafe interval
+  // ]too_low; too_high[ with too_low < w < too_high
+  //
+  //  too_high - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  //                     ^v 1 unit            ^      ^                 ^      ^
+  //  boundary_high ---------------------     .      .                 .      .
+  //                     ^v 1 unit            .      .                 .      .
+  //   - - - - - - - - - - - - - - - - - - -  +  - - + - - - - - -     .      .
+  //                                          .      .         ^       .      .
+  //                                          .  big_distance  .       .      .
+  //                                          .      .         .       .    rest
+  //                              small_distance     .         .       .      .
+  //                                          v      .         .       .      .
+  //  w_high - - - - - - - - - - - - - - - - - -     .         .       .      .
+  //                     ^v 1 unit                   .         .       .      .
+  //  w ----------------------------------------     .         .       .      .
+  //                     ^v 1 unit                   v         .       .      .
+  //  w_low  - - - - - - - - - - - - - - - - - - - - -         .       .      .
+  //                                                           .       .      v
+  //  buffer --------------------------------------------------+-------+--------
+  //                                                           .       .
+  //                                                  safe_interval    .
+  //                                                           v       .
+  //   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -     .
+  //                     ^v 1 unit                                     .
+  //  boundary_low -------------------------                     unsafe_interval
+  //                     ^v 1 unit                                     v
+  //  too_low  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  //
+  //
+  // Note that the value of buffer could lie anywhere inside the range too_low
+  // to too_high.
+  //
+  // boundary_low, boundary_high and w are approximations of the real boundaries
+  // and v (the input number). They are guaranteed to be precise up to one unit.
+  // In fact the error is guaranteed to be strictly less than one unit.
+  //
+  // Anything that lies outside the unsafe interval is guaranteed not to round
+  // to v when read again.
+  // Anything that lies inside the safe interval is guaranteed to round to v
+  // when read again.
+  // If the number inside the buffer lies inside the unsafe interval but not
+  // inside the safe interval then we simply do not know and bail out (returning
+  // false).
+  //
+  // Similarly we have to take into account the imprecision of 'w' when rounding
+  // the buffer. If we have two potential representations we need to make sure
+  // that the chosen one is closer to w_low and w_high since v can be anywhere
+  // between them.
+  //
+  // By generating the digits of too_high we got the largest (closest to
+  // too_high) buffer that is still in the unsafe interval. In the case where
+  // w_high < buffer < too_high we try to decrement the buffer.
+  // This way the buffer approaches (rounds towards) w.
+  // There are 3 conditions that stop the decrementation process:
+  //   1) the buffer is already below w_high
+  //   2) decrementing the buffer would make it leave the unsafe interval
+  //   3) decrementing the buffer would yield a number below w_high and farther
+  //      away than the current number. In other words:
+  //              (buffer{-1} < w_high) && w_high - buffer{-1} > buffer - w_high
+  // Instead of using the buffer directly we use its distance to too_high.
+  // Conceptually rest ~= too_high - buffer
+  while (rest < small_distance &&  // Negated condition 1
+         unsafe_interval - rest >= ten_kappa &&  // Negated condition 2
+         (rest + ten_kappa < small_distance ||  // buffer{-1} > w_high
+          small_distance - rest >= rest + ten_kappa - small_distance)) {
+    buffer[length - 1]--;
+    rest += ten_kappa;
+  }
+
+  // We have approached w+ as much as possible. We now test if approaching w-
+  // would require changing the buffer. If yes, then we have two possible
+  // representations close to w, but we cannot decide which one is closer.
+  if (rest < big_distance &&
+      unsafe_interval - rest >= ten_kappa &&
+      (rest + ten_kappa < big_distance ||
+       big_distance - rest > rest + ten_kappa - big_distance)) {
+    return false;
+  }
+
+  // Weeding test.
+  //   The safe interval is [too_low + 2 ulp; too_high - 2 ulp]
+  //   Since too_low = too_high - unsafe_interval this is equivalent to
+  //      [too_high - unsafe_interval + 4 ulp; too_high - 2 ulp]
+  //   Conceptually we have: rest ~= too_high - buffer
+  return (2 * unit <= rest) && (rest <= unsafe_interval - 4 * unit);
+}
+
+
+
+static const uint32_t kTen4 = 10000;
+static const uint32_t kTen5 = 100000;
+static const uint32_t kTen6 = 1000000;
+static const uint32_t kTen7 = 10000000;
+static const uint32_t kTen8 = 100000000;
+static const uint32_t kTen9 = 1000000000;
+
+// Returns the biggest power of ten that is less than or equal than the given
+// number. We furthermore receive the maximum number of bits 'number' has.
+// If number_bits == 0 then 0^-1 is returned
+// The number of bits must be <= 32.
+// Precondition: (1 << number_bits) <= number < (1 << (number_bits + 1)).
+static void BiggestPowerTen(uint32_t number,
+                            int number_bits,
+                            uint32_t* power,
+                            int* exponent) {
+  switch (number_bits) {
+    case 32:
+    case 31:
+    case 30:
+      if (kTen9 <= number) {
+        *power = kTen9;
+        *exponent = 9;
+        break;
+      }  // else fallthrough
+    case 29:
+    case 28:
+    case 27:
+      if (kTen8 <= number) {
+        *power = kTen8;
+        *exponent = 8;
+        break;
+      }  // else fallthrough
+    case 26:
+    case 25:
+    case 24:
+      if (kTen7 <= number) {
+        *power = kTen7;
+        *exponent = 7;
+        break;
+      }  // else fallthrough
+    case 23:
+    case 22:
+    case 21:
+    case 20:
+      if (kTen6 <= number) {
+        *power = kTen6;
+        *exponent = 6;
+        break;
+      }  // else fallthrough
+    case 19:
+    case 18:
+    case 17:
+      if (kTen5 <= number) {
+        *power = kTen5;
+        *exponent = 5;
+        break;
+      }  // else fallthrough
+    case 16:
+    case 15:
+    case 14:
+      if (kTen4 <= number) {
+        *power = kTen4;
+        *exponent = 4;
+        break;
+      }  // else fallthrough
+    case 13:
+    case 12:
+    case 11:
+    case 10:
+      if (1000 <= number) {
+        *power = 1000;
+        *exponent = 3;
+        break;
+      }  // else fallthrough
+    case 9:
+    case 8:
+    case 7:
+      if (100 <= number) {
+        *power = 100;
+        *exponent = 2;
+        break;
+      }  // else fallthrough
+    case 6:
+    case 5:
+    case 4:
+      if (10 <= number) {
+        *power = 10;
+        *exponent = 1;
+        break;
+      }  // else fallthrough
+    case 3:
+    case 2:
+    case 1:
+      if (1 <= number) {
+        *power = 1;
+        *exponent = 0;
+        break;
+      }  // else fallthrough
+    case 0:
+      *power = 0;
+      *exponent = -1;
+      break;
+    default:
+      // Following assignments are here to silence compiler warnings.
+      *power = 0;
+      *exponent = 0;
+      UNREACHABLE();
+  }
+}
+
+
+// Generates the digits of input number w.
+// w is a floating-point number (DiyFp), consisting of a significand and an
+// exponent. Its exponent is bounded by minimal_target_exponent and
+// maximal_target_exponent.
+//       Hence -60 <= w.e() <= -32.
+//
+// Returns false if it fails, in which case the generated digits in the buffer
+// should not be used.
+// Preconditions:
+//  * low, w and high are correct up to 1 ulp (unit in the last place). That
+//    is, their error must be less that a unit of their last digits.
+//  * low.e() == w.e() == high.e()
+//  * low < w < high, and taking into account their error: low~ <= high~
+//  * minimal_target_exponent <= w.e() <= maximal_target_exponent
+// Postconditions: returns false if procedure fails.
+//   otherwise:
+//     * buffer is not null-terminated, but len contains the number of digits.
+//     * buffer contains the shortest possible decimal digit-sequence
+//       such that LOW < buffer * 10^kappa < HIGH, where LOW and HIGH are the
+//       correct values of low and high (without their error).
+//     * if more than one decimal representation gives the minimal number of
+//       decimal digits then the one closest to W (where W is the correct value
+//       of w) is chosen.
+// Remark: this procedure takes into account the imprecision of its input
+//   numbers. If the precision is not enough to guarantee all the postconditions
+//   then false is returned. This usually happens rarely (~0.5%).
+//
+// Say, for the sake of example, that
+//   w.e() == -48, and w.f() == 0x1234567890abcdef
+// w's value can be computed by w.f() * 2^w.e()
+// We can obtain w's integral digits by simply shifting w.f() by -w.e().
+//  -> w's integral part is 0x1234
+//  w's fractional part is therefore 0x567890abcdef.
+// Printing w's integral part is easy (simply print 0x1234 in decimal).
+// In order to print its fraction we repeatedly multiply the fraction by 10 and
+// get each digit. Example the first digit after the comma would be computed by
+//   (0x567890abcdef * 10) >> 48. -> 3
+// The whole thing becomes slightly more complicated because we want to stop
+// once we have enough digits. That is, once the digits inside the buffer
+// represent 'w' we can stop. Everything inside the interval low - high
+// represents w. However we have to pay attention to low, high and w's
+// imprecision.
+bool DigitGen(DiyFp low,
+              DiyFp w,
+              DiyFp high,
+              char* buffer,
+              int* length,
+              int* kappa) {
+  ASSERT(low.e() == w.e() && w.e() == high.e());
+  ASSERT(low.f() + 1 <= high.f() - 1);
+  ASSERT(minimal_target_exponent <= w.e() && w.e() <= maximal_target_exponent);
+  // low, w and high are imprecise, but by less than one ulp (unit in the last
+  // place).
+  // If we remove (resp. add) 1 ulp from low (resp. high) we are certain that
+  // the new numbers are outside of the interval we want the final
+  // representation to lie in.
+  // Inversely adding (resp. removing) 1 ulp from low (resp. high) would yield
+  // numbers that are certain to lie in the interval. We will use this fact
+  // later on.
+  // We will now start by generating the digits within the uncertain
+  // interval. Later we will weed out representations that lie outside the safe
+  // interval and thus _might_ lie outside the correct interval.
+  uint64_t unit = 1;
+  DiyFp too_low = DiyFp(low.f() - unit, low.e());
+  DiyFp too_high = DiyFp(high.f() + unit, high.e());
+  // too_low and too_high are guaranteed to lie outside the interval we want the
+  // generated number in.
+  DiyFp unsafe_interval = DiyFp::Minus(too_high, too_low);
+  // We now cut the input number into two parts: the integral digits and the
+  // fractionals. We will not write any decimal separator though, but adapt
+  // kappa instead.
+  // Reminder: we are currently computing the digits (stored inside the buffer)
+  // such that:   too_low < buffer * 10^kappa < too_high
+  // We use too_high for the digit_generation and stop as soon as possible.
+  // If we stop early we effectively round down.
+  DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.e(), w.e());
+  // Division by one is a shift.
+  uint32_t integrals = static_cast<uint32_t>(too_high.f() >> -one.e());
+  // Modulo by one is an and.
+  uint64_t fractionals = too_high.f() & (one.f() - 1);
+  uint32_t divider;
+  int divider_exponent;
+  BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),
+                  &divider, &divider_exponent);
+  *kappa = divider_exponent + 1;
+  *length = 0;
+  // Loop invariant: buffer = too_high / 10^kappa  (integer division)
+  // The invariant holds for the first iteration: kappa has been initialized
+  // with the divider exponent + 1. And the divider is the biggest power of ten
+  // that is smaller than integrals.
+  while (*kappa > 0) {
+    int digit = integrals / divider;
+    buffer[*length] = '0' + digit;
+    (*length)++;
+    integrals %= divider;
+    (*kappa)--;
+    // Note that kappa now equals the exponent of the divider and that the
+    // invariant thus holds again.
+    uint64_t rest =
+        (static_cast<uint64_t>(integrals) << -one.e()) + fractionals;
+    // Invariant: too_high = buffer * 10^kappa + DiyFp(rest, one.e())
+    // Reminder: unsafe_interval.e() == one.e()
+    if (rest < unsafe_interval.f()) {
+      // Rounding down (by not emitting the remaining digits) yields a number
+      // that lies within the unsafe interval.
+      return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f(),
+                       unsafe_interval.f(), rest,
+                       static_cast<uint64_t>(divider) << -one.e(), unit);
+    }
+    divider /= 10;
+  }
+
+  // The integrals have been generated. We are at the point of the decimal
+  // separator. In the following loop we simply multiply the remaining digits by
+  // 10 and divide by one. We just need to pay attention to multiply associated
+  // data (like the interval or 'unit'), too.
+  // Instead of multiplying by 10 we multiply by 5 (cheaper operation) and
+  // increase its (imaginary) exponent. At the same time we decrease the
+  // divider's (one's) exponent and shift its significand.
+  // Basically, if fractionals was a DiyFp (with fractionals.e == one.e):
+  //      fractionals.f *= 10;
+  //      fractionals.f >>= 1; fractionals.e++; // value remains unchanged.
+  //      one.f >>= 1; one.e++;                 // value remains unchanged.
+  //      and we have again fractionals.e == one.e which allows us to divide
+  //           fractionals.f() by one.f()
+  // We simply combine the *= 10 and the >>= 1.
+  while (true) {
+    fractionals *= 5;
+    unit *= 5;
+    unsafe_interval.set_f(unsafe_interval.f() * 5);
+    unsafe_interval.set_e(unsafe_interval.e() + 1);  // Will be optimized out.
+    one.set_f(one.f() >> 1);
+    one.set_e(one.e() + 1);
+    // Integer division by one.
+    int digit = static_cast<int>(fractionals >> -one.e());
+    buffer[*length] = '0' + digit;
+    (*length)++;
+    fractionals &= one.f() - 1;  // Modulo by one.
+    (*kappa)--;
+    if (fractionals < unsafe_interval.f()) {
+      return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f() * unit,
+                       unsafe_interval.f(), fractionals, one.f(), unit);
+    }
+  }
+}
+
+
+// Provides a decimal representation of v.
+// Returns true if it succeeds, otherwise the result cannot be trusted.
+// There will be *length digits inside the buffer (not null-terminated).
+// If the function returns true then
+//        v == (double) (buffer * 10^decimal_exponent).
+// The digits in the buffer are the shortest representation possible: no
+// 0.09999999999999999 instead of 0.1. The shorter representation will even be
+// chosen even if the longer one would be closer to v.
+// The last digit will be closest to the actual v. That is, even if several
+// digits might correctly yield 'v' when read again, the closest will be
+// computed.
+bool grisu3(double v, char* buffer, int* length, int* decimal_exponent) {
+  DiyFp w = Double(v).AsNormalizedDiyFp();
+  // boundary_minus and boundary_plus are the boundaries between v and its
+  // closest floating-point neighbors. Any number strictly between
+  // boundary_minus and boundary_plus will round to v when convert to a double.
+  // Grisu3 will never output representations that lie exactly on a boundary.
+  DiyFp boundary_minus, boundary_plus;
+  Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus);
+  ASSERT(boundary_plus.e() == w.e());
+  DiyFp ten_mk;  // Cached power of ten: 10^-k
+  int mk;        // -k
+  GetCachedPower(w.e() + DiyFp::kSignificandSize, minimal_target_exponent,
+                 maximal_target_exponent, &mk, &ten_mk);
+  ASSERT(minimal_target_exponent <= w.e() + ten_mk.e() +
+         DiyFp::kSignificandSize &&
+         maximal_target_exponent >= w.e() + ten_mk.e() +
+         DiyFp::kSignificandSize);
+  // Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
+  // 64 bit significand and ten_mk is thus only precise up to 64 bits.
+
+  // The DiyFp::Times procedure rounds its result, and ten_mk is approximated
+  // too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now
+  // off by a small amount.
+  // In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.
+  // In other words: let f = scaled_w.f() and e = scaled_w.e(), then
+  //           (f-1) * 2^e < w*10^k < (f+1) * 2^e
+  DiyFp scaled_w = DiyFp::Times(w, ten_mk);
+  ASSERT(scaled_w.e() ==
+         boundary_plus.e() + ten_mk.e() + DiyFp::kSignificandSize);
+  // In theory it would be possible to avoid some recomputations by computing
+  // the difference between w and boundary_minus/plus (a power of 2) and to
+  // compute scaled_boundary_minus/plus by subtracting/adding from
+  // scaled_w. However the code becomes much less readable and the speed
+  // enhancements are not terriffic.
+  DiyFp scaled_boundary_minus = DiyFp::Times(boundary_minus, ten_mk);
+  DiyFp scaled_boundary_plus  = DiyFp::Times(boundary_plus,  ten_mk);
+
+  // DigitGen will generate the digits of scaled_w. Therefore we have
+  // v == (double) (scaled_w * 10^-mk).
+  // Set decimal_exponent == -mk and pass it to DigitGen. If scaled_w is not an
+  // integer than it will be updated. For instance if scaled_w == 1.23 then
+  // the buffer will be filled with "123" und the decimal_exponent will be
+  // decreased by 2.
+  int kappa;
+  bool result = DigitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus,
+                         buffer, length, &kappa);
+  *decimal_exponent = -mk + kappa;
+  return result;
+}
+
+
+bool FastDtoa(double v, char* buffer, int* sign, int* length, int* point) {
+  ASSERT(v != 0);
+  ASSERT(!Double(v).IsSpecial());
+
+  if (v < 0) {
+    v = -v;
+    *sign = 1;
+  } else {
+    *sign = 0;
+  }
+  int decimal_exponent;
+  bool result = grisu3(v, buffer, length, &decimal_exponent);
+  *point = *length + decimal_exponent;
+  buffer[*length] = '\0';
+  return result;
+}
+
+} }  // namespace v8::internal
diff --git a/src/fast-dtoa.h b/src/fast-dtoa.h
new file mode 100644
index 0000000..91f6ce7
--- /dev/null
+++ b/src/fast-dtoa.h
@@ -0,0 +1,55 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_FAST_DTOA_H_
+#define V8_FAST_DTOA_H_
+
+namespace v8 {
+namespace internal {
+
+// FastDtoa will produce at most kFastDtoaMaximalLength digits. This does not
+// include the terminating '\0' character.
+static const int kFastDtoaMaximalLength = 17;
+
+// Provides a decimal representation of v.
+// v must not be (positive or negative) zero and it must not be Infinity or NaN.
+// Returns true if it succeeds, otherwise the result can not be trusted.
+// There will be *length digits inside the buffer followed by a null terminator.
+// If the function returns true then
+//   v == (double) (buffer * 10^(point - length)).
+// The digits in the buffer are the shortest representation possible: no
+// 0.099999999999 instead of 0.1.
+// The last digit will be closest to the actual v. That is, even if several
+// digits might correctly yield 'v' when read again, the buffer will contain the
+// one closest to v.
+// The variable 'sign' will be '0' if the given number is positive, and '1'
+//   otherwise.
+bool FastDtoa(double d, char* buffer, int* sign, int* length, int* point);
+
+} }  // namespace v8::internal
+
+#endif  // V8_FAST_DTOA_H_
diff --git a/src/frames.cc b/src/frames.cc
index 3bf4c93..24550a2 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -306,14 +306,12 @@
 
 
 void StackHandler::Cook(Code* code) {
-  ASSERT(MarkCompactCollector::IsCompacting());
   ASSERT(code->contains(pc()));
   set_pc(AddressFrom<Address>(pc() - code->instruction_start()));
 }
 
 
 void StackHandler::Uncook(Code* code) {
-  ASSERT(MarkCompactCollector::HasCompacted());
   set_pc(code->instruction_start() + OffsetFrom(pc()));
   ASSERT(code->contains(pc()));
 }
@@ -329,9 +327,6 @@
 
 
 void StackFrame::CookFramesForThread(ThreadLocalTop* thread) {
-  // Only cooking frames when the collector is compacting and thus moving code
-  // around.
-  ASSERT(MarkCompactCollector::IsCompacting());
   ASSERT(!thread->stack_is_cooked());
   for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
     it.frame()->Cook();
@@ -341,9 +336,6 @@
 
 
 void StackFrame::UncookFramesForThread(ThreadLocalTop* thread) {
-  // Only uncooking frames when the collector is compacting and thus moving code
-  // around.
-  ASSERT(MarkCompactCollector::HasCompacted());
   ASSERT(thread->stack_is_cooked());
   for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
     it.frame()->Uncook();
@@ -520,6 +512,31 @@
   Code* code = NULL;
   if (IsConstructor()) accumulator->Add("new ");
   accumulator->PrintFunction(function, receiver, &code);
+
+  if (function->IsJSFunction()) {
+    Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
+    Object* script_obj = shared->script();
+    if (script_obj->IsScript()) {
+      Handle<Script> script(Script::cast(script_obj));
+      accumulator->Add(" [");
+      accumulator->PrintName(script->name());
+
+      Address pc = this->pc();
+      if (code != NULL && code->kind() == Code::FUNCTION &&
+          pc >= code->instruction_start() && pc < code->relocation_start()) {
+        int source_pos = code->SourcePosition(pc);
+        int line = GetScriptLineNumberSafe(script, source_pos) + 1;
+        accumulator->Add(":%d", line);
+      } else {
+        int function_start_pos = shared->start_position();
+        int line = GetScriptLineNumberSafe(script, function_start_pos) + 1;
+        accumulator->Add(":~%d", line);
+      }
+
+      accumulator->Add("] ");
+    }
+  }
+
   accumulator->Add("(this=%o", receiver);
 
   // Get scope information for nicer output, if possible. If code is
diff --git a/src/globals.h b/src/globals.h
index 0a23f82..cb7f27e 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -98,6 +98,11 @@
 #define V8_PTR_PREFIX ""
 #endif  // V8_HOST_ARCH_64_BIT
 
+// The following macro works on both 32 and 64-bit platforms.
+// Usage: instead of writing 0x1234567890123456
+//      write V8_2PART_UINT64_C(0x12345678,90123456);
+#define V8_2PART_UINT64_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
+
 #define V8PRIxPTR V8_PTR_PREFIX "x"
 #define V8PRIdPTR V8_PTR_PREFIX "d"
 
diff --git a/src/handles.cc b/src/handles.cc
index 53c16a4..4ebeaa7 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -514,6 +514,30 @@
 }
 
 
+int GetScriptLineNumberSafe(Handle<Script> script, int code_pos) {
+  AssertNoAllocation no_allocation;
+  if (!script->line_ends()->IsUndefined()) {
+    return GetScriptLineNumber(script, code_pos);
+  }
+  // Slow mode: we do not have line_ends. We have to iterate through source.
+  if (!script->source()->IsString()) {
+    return -1;
+  }
+  String* source = String::cast(script->source());
+  int line = 0;
+  int len = source->length();
+  for (int pos = 0; pos < len; pos++) {
+    if (pos == code_pos) {
+      break;
+    }
+    if (source->Get(pos) == '\n') {
+      line++;
+    }
+  }
+  return line;
+}
+
+
 void CustomArguments::IterateInstance(ObjectVisitor* v) {
   v->VisitPointers(values_, values_ + 4);
 }
diff --git a/src/handles.h b/src/handles.h
index 0c137a4..f241da2 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -267,6 +267,8 @@
 // Script line number computations.
 void InitScriptLineEnds(Handle<Script> script);
 int GetScriptLineNumber(Handle<Script> script, int code_position);
+// The safe version does not make heap allocations but may work much slower.
+int GetScriptLineNumberSafe(Handle<Script> script, int code_position);
 
 // Computes the enumerable keys from interceptors. Used for debug mirrors and
 // by GetKeysInFixedArrayFor below.
diff --git a/src/heap.h b/src/heap.h
index 18ab44b..1aee874 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -1165,26 +1165,26 @@
 
 class HeapStats {
  public:
-  int *start_marker;
-  int *new_space_size;
-  int *new_space_capacity;
-  int *old_pointer_space_size;
-  int *old_pointer_space_capacity;
-  int *old_data_space_size;
-  int *old_data_space_capacity;
-  int *code_space_size;
-  int *code_space_capacity;
-  int *map_space_size;
-  int *map_space_capacity;
-  int *cell_space_size;
-  int *cell_space_capacity;
-  int *lo_space_size;
-  int *global_handle_count;
-  int *weak_global_handle_count;
-  int *pending_global_handle_count;
-  int *near_death_global_handle_count;
-  int *destroyed_global_handle_count;
-  int *end_marker;
+  int* start_marker;
+  int* new_space_size;
+  int* new_space_capacity;
+  int* old_pointer_space_size;
+  int* old_pointer_space_capacity;
+  int* old_data_space_size;
+  int* old_data_space_capacity;
+  int* code_space_size;
+  int* code_space_capacity;
+  int* map_space_size;
+  int* map_space_capacity;
+  int* cell_space_size;
+  int* cell_space_capacity;
+  int* lo_space_size;
+  int* global_handle_count;
+  int* weak_global_handle_count;
+  int* pending_global_handle_count;
+  int* near_death_global_handle_count;
+  int* destroyed_global_handle_count;
+  int* end_marker;
 };
 
 
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index 26fd1db..67c9cc1 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -832,7 +832,7 @@
     Comment cmnt(masm_, "ONLY_INTEGER_32");
     if (FLAG_debug_code) {
       Label ok;
-      __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number.");
+      __ AbortIfNotNumber(value.reg());
       __ test(value.reg(), Immediate(kSmiTagMask));
       __ j(zero, &ok);
       __ fldz();
@@ -852,7 +852,7 @@
     Comment cmnt(masm_, "ONLY_NUMBER");
     // Fast case if NumberInfo indicates only numbers.
     if (FLAG_debug_code) {
-      __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number.");
+      __ AbortIfNotNumber(value.reg());
     }
     // Smi => false iff zero.
     ASSERT(kSmiTag == 0);
@@ -1038,6 +1038,8 @@
       __ jmp(&load_right);
 
       __ bind(&left_smi);
+    } else {
+      if (FLAG_debug_code) __ AbortIfNotSmi(left_);
     }
     __ SmiUntag(left_);
     __ cvtsi2sd(xmm0, Operand(left_));
@@ -1070,6 +1072,8 @@
       __ jmp(&do_op);
 
       __ bind(&right_smi);
+    } else {
+      if (FLAG_debug_code) __ AbortIfNotSmi(right_);
     }
     __ SmiUntag(right_);
     __ cvtsi2sd(xmm1, Operand(right_));
@@ -1575,7 +1579,7 @@
                                           overwrite_mode);
 
     Label do_op, left_nonsmi;
-    // if right is a smi we make a fast case if left is either a smi
+    // If right is a smi we make a fast case if left is either a smi
     // or a heapnumber.
     if (CpuFeatures::IsSupported(SSE2) && right->number_info().IsSmi()) {
       CpuFeatures::Scope use_sse2(SSE2);
@@ -1584,7 +1588,10 @@
       if (!left->number_info().IsSmi()) {
         __ test(answer.reg(), Immediate(kSmiTagMask));
         __ j(not_zero, &left_nonsmi);
+      } else {
+        if (FLAG_debug_code) __ AbortIfNotSmi(left->reg());
       }
+      if (FLAG_debug_code) __ AbortIfNotSmi(right->reg());
       __ SmiUntag(answer.reg());
       __ jmp(&do_op);
 
@@ -2003,6 +2010,8 @@
       if (!operand->number_info().IsSmi()) {
         __ test(operand->reg(), Immediate(kSmiTagMask));
         deferred->Branch(not_zero);
+      } else {
+        if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
       }
       deferred->BindExit();
       answer = *operand;
@@ -2040,6 +2049,8 @@
       if (!operand->number_info().IsSmi()) {
         __ test(answer.reg(), Immediate(kSmiTagMask));
         deferred->Branch(not_zero);
+      } else {
+        if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
       }
       deferred->BindExit();
       operand->Unuse();
@@ -2073,6 +2084,7 @@
           }
           deferred->BindExit();
         } else {
+          if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
           if (shift_value > 0) {
             __ sar(operand->reg(), shift_value);
             __ and_(operand->reg(), ~kSmiTagMask);
@@ -2104,6 +2116,8 @@
         if (!operand->number_info().IsSmi()) {
           __ test(operand->reg(), Immediate(kSmiTagMask));
           deferred->Branch(not_zero);
+        } else {
+          if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
         }
         __ mov(answer.reg(), operand->reg());
         __ SmiUntag(answer.reg());
@@ -2152,6 +2166,8 @@
         __ sar(ecx, kSmiTagSize);
         if (!right.number_info().IsSmi()) {
           deferred->Branch(carry);
+        } else {
+          if (FLAG_debug_code) __ AbortIfNotSmi(right.reg());
         }
         __ shl_cl(answer.reg());
         __ cmp(answer.reg(), 0xc0000000);
@@ -2192,6 +2208,8 @@
           if (!operand->number_info().IsSmi()) {
             __ test(operand->reg(), Immediate(kSmiTagMask));
             deferred->Branch(not_zero);
+          } else {
+            if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
           }
           __ mov(answer.reg(), operand->reg());
           ASSERT(kSmiTag == 0);  // adjust code if not the case
@@ -2234,6 +2252,8 @@
       if (!operand->number_info().IsSmi()) {
         __ test(operand->reg(), Immediate(kSmiTagMask));
         deferred->Branch(not_zero);
+      } else {
+        if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg());
       }
       if (op == Token::BIT_AND) {
         __ and_(Operand(operand->reg()), Immediate(value));
@@ -2427,9 +2447,7 @@
       // by reconstituting them on the non-fall-through path.
 
       if (left_side.is_smi()) {
-        if (FLAG_debug_code) {
-          __ AbortIfNotSmi(left_side.reg(), "Argument not a smi");
-        }
+        if (FLAG_debug_code) __ AbortIfNotSmi(left_side.reg());
       } else {
         JumpTarget is_smi;
         __ test(left_side.reg(), Immediate(kSmiTagMask));
@@ -3634,6 +3652,26 @@
 }
 
 
+void CodeGenerator::SetTypeForStackSlot(Slot* slot, NumberInfo info) {
+  ASSERT(slot->type() == Slot::LOCAL || slot->type() == Slot::PARAMETER);
+  if (slot->type() == Slot::LOCAL) {
+    frame_->SetTypeForLocalAt(slot->index(), info);
+  } else {
+    frame_->SetTypeForParamAt(slot->index(), info);
+  }
+  if (FLAG_debug_code && info.IsSmi()) {
+    if (slot->type() == Slot::LOCAL) {
+      frame_->PushLocalAt(slot->index());
+    } else {
+      frame_->PushParameterAt(slot->index());
+    }
+    Result var = frame_->Pop();
+    var.ToRegister();
+    __ AbortIfNotSmi(var.reg());
+  }
+}
+
+
 void CodeGenerator::VisitForStatement(ForStatement* node) {
   ASSERT(!in_spilled_code());
   Comment cmnt(masm_, "[ ForStatement");
@@ -3727,21 +3765,14 @@
 
   CheckStack();  // TODO(1222600): ignore if body contains calls.
 
-  // If we have (a) a loop with a compile-time constant trip count
-  // and (b) the loop induction variable is not assignend inside the
-  // loop we update the number type of the induction variable to be smi.
-
+  // We know that the loop index is a smi if it is not modified in the
+  // loop body and it is checked against a constant limit in the loop
+  // condition.  In this case, we reset the static type information of the
+  // loop index to smi before compiling the body, the update expression, and
+  // the bottom check of the loop condition.
   if (node->is_fast_smi_loop()) {
     // Set number type of the loop variable to smi.
-    Slot* slot = node->loop_variable()->slot();
-    ASSERT(slot->type() == Slot::LOCAL);
-    frame_->SetTypeForLocalAt(slot->index(), NumberInfo::Smi());
-    if (FLAG_debug_code) {
-      frame_->PushLocalAt(slot->index());
-      Result var = frame_->Pop();
-      var.ToRegister();
-      __ AbortIfNotSmi(var.reg(), "Loop variable not a smi.");
-    }
+    SetTypeForStackSlot(node->loop_variable()->slot(), NumberInfo::Smi());
   }
 
   Visit(node->body());
@@ -3763,19 +3794,11 @@
     }
   }
 
-  // The update expression resets the type of the loop variable. So we
-  // set it to smi before compiling the test expression.
+  // Set the type of the loop variable to smi before compiling the test
+  // expression if we are in a fast smi loop condition.
   if (node->is_fast_smi_loop() && has_valid_frame()) {
     // Set number type of the loop variable to smi.
-    Slot* slot = node->loop_variable()->slot();
-    ASSERT(slot->type() == Slot::LOCAL);
-    frame_->SetTypeForLocalAt(slot->index(), NumberInfo::Smi());
-    if (FLAG_debug_code) {
-      frame_->PushLocalAt(slot->index());
-      Result var = frame_->Pop();
-      var.ToRegister();
-      __ AbortIfNotSmi(var.reg(), "Loop variable not a smi.");
-    }
+    SetTypeForStackSlot(node->loop_variable()->slot(), NumberInfo::Smi());
   }
 
   // Based on the condition analysis, compile the backward jump as
@@ -6691,9 +6714,7 @@
           NumberInfo operand_info = operand.number_info();
           operand.ToRegister();
           if (operand_info.IsSmi()) {
-            if (FLAG_debug_code) {
-              __ AbortIfNotSmi(operand.reg(), "Operand not a smi.");
-            }
+            if (FLAG_debug_code) __ AbortIfNotSmi(operand.reg());
             frame_->Spill(operand.reg());
             // Set smi tag bit. It will be reset by the not operation.
             __ lea(operand.reg(), Operand(operand.reg(), kSmiTagMask));
@@ -6893,9 +6914,7 @@
 
     Result tmp;
     if (new_value.is_smi()) {
-      if (FLAG_debug_code) {
-        __ AbortIfNotSmi(new_value.reg(), "Operand not a smi");
-      }
+      if (FLAG_debug_code) __ AbortIfNotSmi(new_value.reg());
     } else {
       // We don't know statically if the input is a smi.
       // In order to combine the overflow and the smi tag check, we need
@@ -7859,6 +7878,8 @@
     if (!key.is_smi()) {
       __ test(key.reg(), Immediate(kSmiTagMask));
       deferred->Branch(not_zero);
+    } else {
+      if (FLAG_debug_code) __ AbortIfNotSmi(key.reg());
     }
 
     // Get the elements array from the receiver and check that it
@@ -8012,6 +8033,8 @@
     if (!left_info.IsSmi()) {
       __ test(left, Immediate(kSmiTagMask));
       deferred->Branch(not_zero);
+    } else {
+      if (FLAG_debug_code) __ AbortIfNotSmi(left);
     }
   } else if (!left_info.IsSmi()) {
     if (!right_info.IsSmi()) {
@@ -8022,11 +8045,15 @@
     } else {
       __ test(left, Immediate(kSmiTagMask));
       deferred->Branch(not_zero);
+      if (FLAG_debug_code) __ AbortIfNotSmi(right);
     }
   } else {
+    if (FLAG_debug_code) __ AbortIfNotSmi(left);
     if (!right_info.IsSmi()) {
       __ test(right, Immediate(kSmiTagMask));
       deferred->Branch(not_zero);
+    } else {
+      if (FLAG_debug_code) __ AbortIfNotSmi(right);
     }
   }
 }
@@ -8533,6 +8560,10 @@
   }
 
   if (static_operands_type_.IsSmi()) {
+    if (FLAG_debug_code) {
+      __ AbortIfNotSmi(left);
+      __ AbortIfNotSmi(right);
+    }
     if (op_ == Token::BIT_OR) {
       __ or_(right, Operand(left));
       GenerateReturn(masm);
@@ -8887,12 +8918,14 @@
           if (static_operands_type_.IsNumber()) {
             if (FLAG_debug_code) {
               // Assert at runtime that inputs are only numbers.
-              __ AbortIfNotNumber(edx,
-                                  "GenericBinaryOpStub operand not a number.");
-              __ AbortIfNotNumber(eax,
-                                  "GenericBinaryOpStub operand not a number.");
+              __ AbortIfNotNumber(edx);
+              __ AbortIfNotNumber(eax);
             }
             if (static_operands_type_.IsSmi()) {
+              if (FLAG_debug_code) {
+                __ AbortIfNotSmi(edx);
+                __ AbortIfNotSmi(eax);
+              }
               FloatingPointHelper::LoadSSE2Smis(masm, ecx);
             } else {
               FloatingPointHelper::LoadSSE2Operands(masm);
@@ -8915,10 +8948,8 @@
           if (static_operands_type_.IsNumber()) {
             if (FLAG_debug_code) {
               // Assert at runtime that inputs are only numbers.
-              __ AbortIfNotNumber(edx,
-                                  "GenericBinaryOpStub operand not a number.");
-              __ AbortIfNotNumber(eax,
-                                  "GenericBinaryOpStub operand not a number.");
+              __ AbortIfNotNumber(edx);
+              __ AbortIfNotNumber(eax);
             }
           } else {
             FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
@@ -9648,6 +9679,8 @@
     if (!number_info.IsSmi()) {
       __ test(edx, Immediate(kSmiTagMask));
       __ j(not_zero, &arg1_is_object);
+    } else {
+      if (FLAG_debug_code) __ AbortIfNotSmi(edx);
     }
     __ SmiUntag(edx);
     __ jmp(&load_arg2);
@@ -9666,6 +9699,8 @@
     if (!number_info.IsSmi()) {
       __ test(eax, Immediate(kSmiTagMask));
       __ j(not_zero, &arg2_is_object);
+    } else {
+      if (FLAG_debug_code) __ AbortIfNotSmi(eax);
     }
     __ SmiUntag(eax);
     __ mov(ecx, eax);
@@ -10553,15 +10588,7 @@
   __ j(negative, &done);
   // Read the value from the static offsets vector buffer.
   __ mov(edi, Operand(ecx, edx, times_int_size, 0));
-  // Perform explicit shift
-  ASSERT_EQ(0, kSmiTag);
-  __ shl(edi, kSmiTagSize);
-  // Add previous index (from its stack slot) if value is not negative.
-  Label capture_negative;
-  // Carry flag set by shift above.
-  __ j(negative, &capture_negative, not_taken);
-  __ add(edi, Operand(eax));  // Add previous index (adding smi to smi).
-  __ bind(&capture_negative);
+  __ SmiTag(edi);
   // Store the smi value in the last match info.
   __ mov(FieldOperand(ebx,
                       edx,
diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h
index 89318ce..c7ff2e8 100644
--- a/src/ia32/codegen-ia32.h
+++ b/src/ia32/codegen-ia32.h
@@ -500,7 +500,7 @@
   bool FoldConstantSmis(Token::Value op, int left, int right);
 
   // Emit code to perform a binary operation on a constant
-  // smi and a likely smi.  Consumes the Result *operand.
+  // smi and a likely smi.  Consumes the Result operand.
   Result ConstantSmiBinaryOperation(Token::Value op,
                                     Result* operand,
                                     Handle<Object> constant_operand,
@@ -511,7 +511,7 @@
 
   // Emit code to perform a binary operation on two likely smis.
   // The code to handle smi arguments is produced inline.
-  // Consumes the Results *left and *right.
+  // Consumes the Results left and right.
   Result LikelySmiBinaryOperation(Token::Value op,
                                   Result* left,
                                   Result* right,
@@ -652,6 +652,8 @@
   void CodeForDoWhileConditionPosition(DoWhileStatement* stmt);
   void CodeForSourcePosition(int pos);
 
+  void SetTypeForStackSlot(Slot* slot, NumberInfo info);
+
 #ifdef DEBUG
   // True if the registers are valid for entry to a block.  There should
   // be no frame-external references to (non-reserved) registers.
diff --git a/src/ia32/fast-codegen-ia32.cc b/src/ia32/fast-codegen-ia32.cc
index 4dcf232..01190a5 100644
--- a/src/ia32/fast-codegen-ia32.cc
+++ b/src/ia32/fast-codegen-ia32.cc
@@ -436,9 +436,6 @@
   AstLabeler labeler;
   labeler.Label(info);
 
-  LivenessAnalyzer analyzer;
-  analyzer.Analyze(info->function());
-
   CodeGenerator::MakeCodePrologue(info);
 
   const int kInitialBufferSize = 4 * KB;
@@ -802,8 +799,8 @@
     Comment cmnt(masm(), ";; Global");
     if (FLAG_print_ir) {
       SmartPointer<char> name = expr->name()->ToCString();
-      PrintF("%d: t%d = Global(%s)  // last_use = %d\n", expr->num(),
-             expr->num(), *name, expr->var_def()->last_use()->num());
+      PrintF("%d: t%d = Global(%s)\n", expr->num(),
+             expr->num(), *name);
     }
     EmitGlobalVariableLoad(cell);
   }
@@ -857,9 +854,8 @@
     SmartPointer<char> name_string = name->ToCString();
     PrintF("%d: ", expr->num());
     if (!destination().is(no_reg)) PrintF("t%d = ", expr->num());
-    PrintF("Store(this, \"%s\", t%d)  // last_use(this) = %d\n", *name_string,
-           expr->value()->num(),
-           expr->var_def()->last_use()->num());
+    PrintF("Store(this, \"%s\", t%d)\n", *name_string,
+           expr->value()->num());
   }
 
   EmitThisPropertyStore(name);
@@ -882,9 +878,8 @@
     Comment cmnt(masm(), ";; Load from this");
     if (FLAG_print_ir) {
       SmartPointer<char> name_string = name->ToCString();
-      PrintF("%d: t%d = Load(this, \"%s\")  // last_use(this) = %d\n",
-             expr->num(), expr->num(), *name_string,
-             expr->var_def()->last_use()->num());
+      PrintF("%d: t%d = Load(this, \"%s\")\n",
+             expr->num(), expr->num(), *name_string);
     }
     EmitThisPropertyLoad(name);
   }
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 703ca79..3529336 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -351,20 +351,20 @@
 }
 
 
-void MacroAssembler::AbortIfNotNumber(Register object, const char* msg) {
+void MacroAssembler::AbortIfNotNumber(Register object) {
   Label ok;
   test(object, Immediate(kSmiTagMask));
   j(zero, &ok);
   cmp(FieldOperand(object, HeapObject::kMapOffset),
       Factory::heap_number_map());
-  Assert(equal, msg);
+  Assert(equal, "Operand not a number");
   bind(&ok);
 }
 
 
-void MacroAssembler::AbortIfNotSmi(Register object, const char* msg) {
+void MacroAssembler::AbortIfNotSmi(Register object) {
   test(object, Immediate(kSmiTagMask));
-  Assert(equal, msg);
+  Assert(equal, "Operand not a smi");
 }
 
 
@@ -1553,7 +1553,7 @@
 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(
     Register instance_type,
     Register scratch,
-    Label *failure) {
+    Label* failure) {
   if (!scratch.is(instance_type)) {
     mov(scratch, instance_type);
   }
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index 00243d7..caa96da 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -182,17 +182,18 @@
   // Smi tagging support.
   void SmiTag(Register reg) {
     ASSERT(kSmiTag == 0);
-    shl(reg, kSmiTagSize);
+    ASSERT(kSmiTagSize == 1);
+    add(reg, Operand(reg));
   }
   void SmiUntag(Register reg) {
     sar(reg, kSmiTagSize);
   }
 
   // Abort execution if argument is not a number. Used in debug code.
-  void AbortIfNotNumber(Register object, const char* msg);
+  void AbortIfNotNumber(Register object);
 
   // Abort execution if argument is not a smi. Used in debug code.
-  void AbortIfNotSmi(Register object, const char* msg);
+  void AbortIfNotSmi(Register object);
 
   // ---------------------------------------------------------------------------
   // Exception handling
@@ -476,7 +477,7 @@
   // for both instance type and scratch.
   void JumpIfInstanceTypeIsNotSequentialAscii(Register instance_type,
                                               Register scratch,
-                                              Label *on_not_flat_ascii_string);
+                                              Label* on_not_flat_ascii_string);
 
   // Checks if both objects are sequential ASCII strings, and jumps to label
   // if either is not.
@@ -484,7 +485,7 @@
                                            Register object2,
                                            Register scratch1,
                                            Register scratch2,
-                                           Label *on_not_flat_ascii_strings);
+                                           Label* on_not_flat_ascii_strings);
 
  private:
   bool generating_stub_;
diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index 74b9d12..c6accbd 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -653,6 +653,8 @@
   __ j(not_zero, &exit_label_);
 
   __ bind(&stack_ok);
+  // Load start index for later use.
+  __ mov(ebx, Operand(ebp, kStartIndex));
 
   // Allocate space on stack for registers.
   __ sub(Operand(esp), Immediate(num_registers_ * kPointerSize));
@@ -662,17 +664,23 @@
   __ mov(edi, Operand(ebp, kInputStart));
   // Set up edi to be negative offset from string end.
   __ sub(edi, Operand(esi));
-  // Set eax to address of char before start of input
+
+  // Set eax to address of char before start of the string.
   // (effectively string position -1).
-  __ lea(eax, Operand(edi, -char_size()));
+  __ neg(ebx);
+  if (mode_ == UC16) {
+    __ lea(eax, Operand(edi, ebx, times_2, -char_size()));
+  } else {
+    __ lea(eax, Operand(edi, ebx, times_1, -char_size()));
+  }
   // Store this value in a local variable, for use when clearing
   // position registers.
   __ mov(Operand(ebp, kInputStartMinusOne), eax);
 
   // Determine whether the start index is zero, that is at the start of the
   // string, and store that value in a local variable.
-  __ mov(ebx, Operand(ebp, kStartIndex));
   __ xor_(Operand(ecx), ecx);  // setcc only operates on cl (lower byte of ecx).
+  // Register ebx still holds -stringIndex.
   __ test(ebx, Operand(ebx));
   __ setcc(zero, ecx);  // 1 if 0 (start of string), 0 if positive.
   __ mov(Operand(ebp, kAtStart), ecx);
@@ -721,10 +729,17 @@
       // copy captures to output
       __ mov(ebx, Operand(ebp, kRegisterOutput));
       __ mov(ecx, Operand(ebp, kInputEnd));
+      __ mov(edx, Operand(ebp, kStartIndex));
       __ sub(ecx, Operand(ebp, kInputStart));
+      if (mode_ == UC16) {
+        __ lea(ecx, Operand(ecx, edx, times_2, 0));
+      } else {
+        __ add(ecx, Operand(edx));
+      }
       for (int i = 0; i < num_saved_registers_; i++) {
         __ mov(eax, register_location(i));
-        __ add(eax, Operand(ecx));  // Convert to index from start, not end.
+        // Convert to index from start of string, not end.
+        __ add(eax, Operand(ecx));
         if (mode_ == UC16) {
           __ sar(eax, 1);  // Convert byte index to character index.
         }
diff --git a/src/ia32/virtual-frame-ia32.h b/src/ia32/virtual-frame-ia32.h
index 69c3e47..e622cdf 100644
--- a/src/ia32/virtual-frame-ia32.h
+++ b/src/ia32/virtual-frame-ia32.h
@@ -446,8 +446,9 @@
     return true;
   }
 
-  // Update the type information of a local variable frame element directly.
+  // Update the type information of a variable frame element directly.
   inline void SetTypeForLocalAt(int index, NumberInfo info);
+  inline void SetTypeForParamAt(int index, NumberInfo info);
 
  private:
   static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index 505cf03..f3c801c 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -149,7 +149,7 @@
     Handle<String> atom_string = Factory::NewStringFromTwoByte(atom_pattern);
     AtomCompile(re, pattern, flags, atom_string);
   } else {
-    IrregexpPrepare(re, pattern, flags, parse_result.capture_count);
+    IrregexpInitialize(re, pattern, flags, parse_result.capture_count);
   }
   ASSERT(re->data()->IsFixedArray());
   // Compilation succeeded so the data is set on the regexp
@@ -341,10 +341,10 @@
 }
 
 
-void RegExpImpl::IrregexpPrepare(Handle<JSRegExp> re,
-                                 Handle<String> pattern,
-                                 JSRegExp::Flags flags,
-                                 int capture_count) {
+void RegExpImpl::IrregexpInitialize(Handle<JSRegExp> re,
+                                    Handle<String> pattern,
+                                    JSRegExp::Flags flags,
+                                    int capture_count) {
   // Initialize compiled code entries to null.
   Factory::SetRegExpIrregexpData(re,
                                  JSRegExp::IRREGEXP,
@@ -354,6 +354,94 @@
 }
 
 
+int RegExpImpl::IrregexpPrepare(Handle<JSRegExp> regexp,
+                                Handle<String> subject) {
+  if (!subject->IsFlat()) {
+    FlattenString(subject);
+  }
+  bool is_ascii = subject->IsAsciiRepresentation();
+  if (!EnsureCompiledIrregexp(regexp, is_ascii)) {
+    return -1;
+  }
+#ifdef V8_NATIVE_REGEXP
+  // Native regexp only needs room to output captures. Registers are handled
+  // internally.
+  return (IrregexpNumberOfCaptures(FixedArray::cast(regexp->data())) + 1) * 2;
+#else  // !V8_NATIVE_REGEXP
+  // Byte-code regexp needs space allocated for all its registers.
+  return IrregexpNumberOfRegisters(FixedArray::cast(regexp->data()));
+#endif  // V8_NATIVE_REGEXP
+}
+
+
+RegExpImpl::IrregexpResult RegExpImpl::IrregexpExecOnce(Handle<JSRegExp> regexp,
+                                                        Handle<String> subject,
+                                                        int index,
+                                                        Vector<int> output) {
+  Handle<FixedArray> irregexp(FixedArray::cast(regexp->data()));
+
+  ASSERT(index >= 0);
+  ASSERT(index <= subject->length());
+  ASSERT(subject->IsFlat());
+
+#ifdef V8_NATIVE_REGEXP
+  ASSERT(output.length() >=
+      (IrregexpNumberOfCaptures(*irregexp) + 1) * 2);
+  do {
+    bool is_ascii = subject->IsAsciiRepresentation();
+    Handle<Code> code(IrregexpNativeCode(*irregexp, is_ascii));
+    NativeRegExpMacroAssembler::Result res =
+        NativeRegExpMacroAssembler::Match(code,
+                                          subject,
+                                          output.start(),
+                                          output.length(),
+                                          index);
+    if (res != NativeRegExpMacroAssembler::RETRY) {
+      ASSERT(res != NativeRegExpMacroAssembler::EXCEPTION ||
+             Top::has_pending_exception());
+      STATIC_ASSERT(
+          static_cast<int>(NativeRegExpMacroAssembler::SUCCESS) == RE_SUCCESS);
+      STATIC_ASSERT(
+          static_cast<int>(NativeRegExpMacroAssembler::FAILURE) == RE_FAILURE);
+      STATIC_ASSERT(static_cast<int>(NativeRegExpMacroAssembler::EXCEPTION)
+                    == RE_EXCEPTION);
+      return static_cast<IrregexpResult>(res);
+    }
+    // If result is RETRY, the string has changed representation, and we
+    // must restart from scratch.
+    // In this case, it means we must make sure we are prepared to handle
+    // the, potentially, differen subject (the string can switch between
+    // being internal and external, and even between being ASCII and UC16,
+    // but the characters are always the same).
+    IrregexpPrepare(regexp, subject);
+  } while (true);
+  UNREACHABLE();
+  return RE_EXCEPTION;
+#else  // ndef V8_NATIVE_REGEXP
+
+  ASSERT(output.length() >= IrregexpNumberOfRegisters(*irregexp));
+  bool is_ascii = subject->IsAsciiRepresentation();
+  // We must have done EnsureCompiledIrregexp, so we can get the number of
+  // registers.
+  int* register_vector = output.start();
+  int number_of_capture_registers =
+      (IrregexpNumberOfCaptures(*irregexp) + 1) * 2;
+  for (int i = number_of_capture_registers - 1; i >= 0; i--) {
+    register_vector[i] = -1;
+  }
+  Handle<ByteArray> byte_codes(IrregexpByteCode(*irregexp, is_ascii));
+
+  if (IrregexpInterpreter::Match(byte_codes,
+                                 subject,
+                                 register_vector,
+                                 index)) {
+    return RE_SUCCESS;
+  }
+  return RE_FAILURE;
+#endif  // ndef V8_NATIVE_REGEXP
+}
+
+
 Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp,
                                         Handle<String> subject,
                                         int previous_index,
@@ -361,9 +449,6 @@
   ASSERT_EQ(jsregexp->TypeTag(), JSRegExp::IRREGEXP);
 
   // Prepare space for the return values.
-  int number_of_capture_registers =
-      (IrregexpNumberOfCaptures(FixedArray::cast(jsregexp->data())) + 1) * 2;
-
 #ifndef V8_NATIVE_REGEXP
 #ifdef DEBUG
   if (FLAG_trace_regexp_bytecodes) {
@@ -373,101 +458,42 @@
   }
 #endif
 #endif
-
-  if (!subject->IsFlat()) {
-    FlattenString(subject);
-  }
-
-  last_match_info->EnsureSize(number_of_capture_registers + kLastMatchOverhead);
-
-  Handle<FixedArray> array;
-
-  // Dispatch to the correct RegExp implementation.
-  Handle<FixedArray> regexp(FixedArray::cast(jsregexp->data()));
-
-#ifdef V8_NATIVE_REGEXP
-
-  OffsetsVector captures(number_of_capture_registers);
-  int* captures_vector = captures.vector();
-  NativeRegExpMacroAssembler::Result res;
-  do {
-    bool is_ascii = subject->IsAsciiRepresentation();
-    if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
-      return Handle<Object>::null();
-    }
-    Handle<Code> code(RegExpImpl::IrregexpNativeCode(*regexp, is_ascii));
-    res = NativeRegExpMacroAssembler::Match(code,
-                                            subject,
-                                            captures_vector,
-                                            captures.length(),
-                                            previous_index);
-    // If result is RETRY, the string have changed representation, and we
-    // must restart from scratch.
-  } while (res == NativeRegExpMacroAssembler::RETRY);
-  if (res == NativeRegExpMacroAssembler::EXCEPTION) {
+  int required_registers = RegExpImpl::IrregexpPrepare(jsregexp, subject);
+  if (required_registers < 0) {
+    // Compiling failed with an exception.
     ASSERT(Top::has_pending_exception());
     return Handle<Object>::null();
   }
-  ASSERT(res == NativeRegExpMacroAssembler::SUCCESS
-      || res == NativeRegExpMacroAssembler::FAILURE);
 
-  if (res != NativeRegExpMacroAssembler::SUCCESS) return Factory::null_value();
+  OffsetsVector registers(required_registers);
 
-  array = Handle<FixedArray>(FixedArray::cast(last_match_info->elements()));
-  ASSERT(array->length() >= number_of_capture_registers + kLastMatchOverhead);
-  // The captures come in (start, end+1) pairs.
-  for (int i = 0; i < number_of_capture_registers; i += 2) {
-    // Capture values are relative to start_offset only.
-    // Convert them to be relative to start of string.
-    if (captures_vector[i] >= 0) {
-      captures_vector[i] += previous_index;
+  IrregexpResult res = IrregexpExecOnce(jsregexp,
+                                        subject,
+                                        previous_index,
+                                        Vector<int>(registers.vector(),
+                                                    registers.length()));
+  if (res == RE_SUCCESS) {
+    int capture_register_count =
+        (IrregexpNumberOfCaptures(FixedArray::cast(jsregexp->data())) + 1) * 2;
+    last_match_info->EnsureSize(capture_register_count + kLastMatchOverhead);
+    AssertNoAllocation no_gc;
+    int* register_vector = registers.vector();
+    FixedArray* array = FixedArray::cast(last_match_info->elements());
+    for (int i = 0; i < capture_register_count; i += 2) {
+      SetCapture(array, i, register_vector[i]);
+      SetCapture(array, i + 1, register_vector[i + 1]);
     }
-    if (captures_vector[i + 1] >= 0) {
-      captures_vector[i + 1] += previous_index;
-    }
-    SetCapture(*array, i, captures_vector[i]);
-    SetCapture(*array, i + 1, captures_vector[i + 1]);
+    SetLastCaptureCount(array, capture_register_count);
+    SetLastSubject(array, *subject);
+    SetLastInput(array, *subject);
+    return last_match_info;
   }
-
-#else  // ! V8_NATIVE_REGEXP
-
-  bool is_ascii = subject->IsAsciiRepresentation();
-  if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
+  if (res == RE_EXCEPTION) {
+    ASSERT(Top::has_pending_exception());
     return Handle<Object>::null();
   }
-  // Now that we have done EnsureCompiledIrregexp we can get the number of
-  // registers.
-  int number_of_registers =
-      IrregexpNumberOfRegisters(FixedArray::cast(jsregexp->data()));
-  OffsetsVector registers(number_of_registers);
-  int* register_vector = registers.vector();
-  for (int i = number_of_capture_registers - 1; i >= 0; i--) {
-    register_vector[i] = -1;
-  }
-  Handle<ByteArray> byte_codes(IrregexpByteCode(*regexp, is_ascii));
-
-  if (!IrregexpInterpreter::Match(byte_codes,
-                                  subject,
-                                  register_vector,
-                                  previous_index)) {
-    return Factory::null_value();
-  }
-
-  array = Handle<FixedArray>(FixedArray::cast(last_match_info->elements()));
-  ASSERT(array->length() >= number_of_capture_registers + kLastMatchOverhead);
-  // The captures come in (start, end+1) pairs.
-  for (int i = 0; i < number_of_capture_registers; i += 2) {
-    SetCapture(*array, i, register_vector[i]);
-    SetCapture(*array, i + 1, register_vector[i + 1]);
-  }
-
-#endif  // V8_NATIVE_REGEXP
-
-  SetLastCaptureCount(*array, number_of_capture_registers);
-  SetLastSubject(*array, *subject);
-  SetLastInput(*array, *subject);
-
-  return last_match_info;
+  ASSERT(res == RE_FAILURE);
+  return Factory::null_value();
 }
 
 
diff --git a/src/jsregexp.h b/src/jsregexp.h
index 46d53c2..8f01342 100644
--- a/src/jsregexp.h
+++ b/src/jsregexp.h
@@ -77,10 +77,10 @@
                              Handle<JSArray> lastMatchInfo);
 
   // Prepares a JSRegExp object with Irregexp-specific data.
-  static void IrregexpPrepare(Handle<JSRegExp> re,
-                              Handle<String> pattern,
-                              JSRegExp::Flags flags,
-                              int capture_register_count);
+  static void IrregexpInitialize(Handle<JSRegExp> re,
+                                 Handle<String> pattern,
+                                 JSRegExp::Flags flags,
+                                 int capture_register_count);
 
 
   static void AtomCompile(Handle<JSRegExp> re,
@@ -93,6 +93,29 @@
                                  int index,
                                  Handle<JSArray> lastMatchInfo);
 
+  enum IrregexpResult { RE_FAILURE = 0, RE_SUCCESS = 1, RE_EXCEPTION = -1 };
+
+  // Prepare a RegExp for being executed one or more times (using
+  // IrregexpExecOnce) on the subject.
+  // This ensures that the regexp is compiled for the subject, and that
+  // the subject is flat.
+  // Returns the number of integer spaces required by IrregexpExecOnce
+  // as its "registers" argument. If the regexp cannot be compiled,
+  // an exception is set as pending, and this function returns negative.
+  static int IrregexpPrepare(Handle<JSRegExp> regexp,
+                             Handle<String> subject);
+
+  // Execute a regular expression once on the subject, starting from
+  // character "index".
+  // If successful, returns RE_SUCCESS and set the capture positions
+  // in the first registers.
+  // If matching fails, returns RE_FAILURE.
+  // If execution fails, sets a pending exception and returns RE_EXCEPTION.
+  static IrregexpResult IrregexpExecOnce(Handle<JSRegExp> regexp,
+                                         Handle<String> subject,
+                                         int index,
+                                         Vector<int32_t> registers);
+
   // Execute an Irregexp bytecode pattern.
   // On a successful match, the result is a JSArray containing
   // captured positions. On a failure, the result is the null value.
diff --git a/src/liveedit.cc b/src/liveedit.cc
index 4533f9c..55308ab 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -391,6 +391,26 @@
   ZoneList<RelocInfo> reloc_infos_;
 };
 
+
+class FrameCookingThreadVisitor : public ThreadVisitor {
+ public:
+  void VisitThread(ThreadLocalTop* top) {
+    StackFrame::CookFramesForThread(top);
+  }
+};
+
+class FrameUncookingThreadVisitor : public ThreadVisitor {
+ public:
+  void VisitThread(ThreadLocalTop* top) {
+    StackFrame::UncookFramesForThread(top);
+  }
+};
+
+static void IterateAllThreads(ThreadVisitor* visitor) {
+  Top::IterateThread(visitor);
+  ThreadManager::IterateThreads(visitor);
+}
+
 // Finds all references to original and replaces them with substitution.
 static void ReplaceCodeObject(Code* original, Code* substitution) {
   ASSERT(!Heap::InNewSpace(substitution));
@@ -405,9 +425,15 @@
   // Iterate over all roots. Stack frames may have pointer into original code,
   // so temporary replace the pointers with offset numbers
   // in prologue/epilogue.
-  ThreadManager::MarkCompactPrologue(true);
-  Heap::IterateStrongRoots(&visitor, VISIT_ALL);
-  ThreadManager::MarkCompactEpilogue(true);
+  {
+    FrameCookingThreadVisitor cooking_visitor;
+    IterateAllThreads(&cooking_visitor);
+
+    Heap::IterateStrongRoots(&visitor, VISIT_ALL);
+
+    FrameUncookingThreadVisitor uncooking_visitor;
+    IterateAllThreads(&uncooking_visitor);
+  }
 
   // Now iterate over all pointers of all objects, including code_target
   // implicit pointers.
diff --git a/src/math.js b/src/math.js
index 0623cb8..d17a6fd 100644
--- a/src/math.js
+++ b/src/math.js
@@ -171,7 +171,7 @@
 // ECMA 262 - 15.8.2.15
 function MathRound(x) {
   if (!IS_NUMBER(x)) x = ToNumber(x);
-  return %Math_round(x);
+  return %RoundNumber(x);
 }
 
 // ECMA 262 - 15.8.2.16
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 4cc9b9f..e7daa2d 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1121,6 +1121,17 @@
 }
 
 
+int HeapNumber::get_exponent() {
+  return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
+          kExponentShift) - kExponentBias;
+}
+
+
+int HeapNumber::get_sign() {
+  return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
+}
+
+
 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
 
 
diff --git a/src/objects.h b/src/objects.h
index b3fe448..d696570 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1094,6 +1094,9 @@
   void HeapNumberVerify();
 #endif
 
+  inline int get_exponent();
+  inline int get_sign();
+
   // Layout description.
   static const int kValueOffset = HeapObject::kHeaderSize;
   // IEEE doubles are two 32 bit words.  The first is just mantissa, the second
diff --git a/src/parser.cc b/src/parser.cc
index 74f6997..cff56a3 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -1585,13 +1585,15 @@
   }
 
   void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
-    // Check that the property assigned to is a named property.
+    // Check that the property assigned to is a named property, which is not
+    // __proto__.
     Property* property = assignment->target()->AsProperty();
     ASSERT(property != NULL);
     Literal* literal = property->key()->AsLiteral();
     uint32_t dummy;
     if (literal != NULL &&
         literal->handle()->IsString() &&
+        !String::cast(*(literal->handle()))->Equals(Heap::Proto_symbol()) &&
         !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
       Handle<String> key = Handle<String>::cast(literal->handle());
 
diff --git a/src/platform.h b/src/platform.h
index bc2e9d6..f124cf1 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -114,6 +114,10 @@
 namespace v8 {
 namespace internal {
 
+// Use AtomicWord for a machine-sized pointer. It is assumed that
+// reads and writes of naturally aligned values of this type are atomic.
+typedef intptr_t AtomicWord;
+
 class Semaphore;
 
 double ceiling(double x);
@@ -525,7 +529,7 @@
   Address function;  // The last called JS function.
   StateTag state;  // The state of the VM.
   static const int kMaxFramesCount = 100;
-  EmbeddedVector<Address, kMaxFramesCount> stack;  // Call stack.
+  Address stack[kMaxFramesCount];  // Call stack.
   int frames_count;  // Number of captured frames.
 };
 
diff --git a/src/powers-ten.h b/src/powers-ten.h
new file mode 100644
index 0000000..93d92d9
--- /dev/null
+++ b/src/powers-ten.h
@@ -0,0 +1,2461 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// ------------ GENERATED FILE ----------------
+// command used:
+//  tools/generate-ten-powers --from -308 --to 342 --mantissa-size 64 --round round -o src/powers-ten.h  // NOLINT
+
+// This file is intended to be included inside another .h or .cc files
+// with the following defines set:
+//  GRISU_CACHE_STRUCT: should expand to the name of a struct that will
+//   hold the cached powers of ten. Each entry will hold a 64-bit
+//   significand, a 16-bit signed binary exponent, and a 16-bit
+//   signed decimal exponent. Each entry will be constructed as follows:
+//      { significand, binary_exponent, decimal_exponent }.
+//  GRISU_CACHE_NAME(i): generates the name for the different caches.
+//   The parameter i will be a number in the range 1-20. A cache will
+//   hold every i'th element of a full cache. GRISU_CACHE_NAME(1) will
+//   thus hold all elements. The higher i the fewer elements it has.
+//   Ideally the user should only reference one cache and let the
+//   compiler remove the unused ones.
+//  GRISU_CACHE_MAX_DISTANCE(i): generates the name for the maximum
+//   binary exponent distance between all elements of a given cache.
+//  GRISU_CACHE_OFFSET: is used as variable name for the decimal
+//   exponent offset. It is equal to -cache[0].decimal_exponent.
+//  GRISU_UINT64_C: used to construct 64-bit values in a platform
+//   independent way. In order to encode 0x123456789ABCDEF0 the macro
+//   will be invoked as follows: GRISU_UINT64_C(0x12345678,9ABCDEF0).
+
+
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(1)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0x8fd0c162, 06306bac), -1083, -307},
+  {GRISU_UINT64_C(0xb3c4f1ba, 87bc8697), -1080, -306},
+  {GRISU_UINT64_C(0xe0b62e29, 29aba83c), -1077, -305},
+  {GRISU_UINT64_C(0x8c71dcd9, ba0b4926), -1073, -304},
+  {GRISU_UINT64_C(0xaf8e5410, 288e1b6f), -1070, -303},
+  {GRISU_UINT64_C(0xdb71e914, 32b1a24b), -1067, -302},
+  {GRISU_UINT64_C(0x892731ac, 9faf056f), -1063, -301},
+  {GRISU_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
+  {GRISU_UINT64_C(0xd64d3d9d, b981787d), -1057, -299},
+  {GRISU_UINT64_C(0x85f04682, 93f0eb4e), -1053, -298},
+  {GRISU_UINT64_C(0xa76c5823, 38ed2622), -1050, -297},
+  {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
+  {GRISU_UINT64_C(0x82cca4db, 847945ca), -1043, -295},
+  {GRISU_UINT64_C(0xa37fce12, 6597973d), -1040, -294},
+  {GRISU_UINT64_C(0xcc5fc196, fefd7d0c), -1037, -293},
+  {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
+  {GRISU_UINT64_C(0x9faacf3d, f73609b1), -1030, -291},
+  {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
+  {GRISU_UINT64_C(0xf97ae3d0, d2446f25), -1024, -289},
+  {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
+  {GRISU_UINT64_C(0xc2e801fb, 244576d5), -1017, -287},
+  {GRISU_UINT64_C(0xf3a20279, ed56d48a), -1014, -286},
+  {GRISU_UINT64_C(0x9845418c, 345644d7), -1010, -285},
+  {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+  {GRISU_UINT64_C(0xedec366b, 11c6cb8f), -1004, -283},
+  {GRISU_UINT64_C(0x94b3a202, eb1c3f39), -1000, -282},
+  {GRISU_UINT64_C(0xb9e08a83, a5e34f08), -997, -281},
+  {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
+  {GRISU_UINT64_C(0x91376c36, d99995be), -990, -279},
+  {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+  {GRISU_UINT64_C(0xe2e69915, b3fff9f9), -984, -277},
+  {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
+  {GRISU_UINT64_C(0xb1442798, f49ffb4b), -977, -275},
+  {GRISU_UINT64_C(0xdd95317f, 31c7fa1d), -974, -274},
+  {GRISU_UINT64_C(0x8a7d3eef, 7f1cfc52), -970, -273},
+  {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+  {GRISU_UINT64_C(0xd863b256, 369d4a41), -964, -271},
+  {GRISU_UINT64_C(0x873e4f75, e2224e68), -960, -270},
+  {GRISU_UINT64_C(0xa90de353, 5aaae202), -957, -269},
+  {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+  {GRISU_UINT64_C(0x8412d999, 1ed58092), -950, -267},
+  {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
+  {GRISU_UINT64_C(0xce5d73ff, 402d98e4), -944, -265},
+  {GRISU_UINT64_C(0x80fa687f, 881c7f8e), -940, -264},
+  {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
+  {GRISU_UINT64_C(0xc9874347, 44ac874f), -934, -262},
+  {GRISU_UINT64_C(0xfbe91419, 15d7a922), -931, -261},
+  {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+  {GRISU_UINT64_C(0xc4ce17b3, 99107c23), -924, -259},
+  {GRISU_UINT64_C(0xf6019da0, 7f549b2b), -921, -258},
+  {GRISU_UINT64_C(0x99c10284, 4f94e0fb), -917, -257},
+  {GRISU_UINT64_C(0xc0314325, 637a193a), -914, -256},
+  {GRISU_UINT64_C(0xf03d93ee, bc589f88), -911, -255},
+  {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
+  {GRISU_UINT64_C(0xbbb01b92, 83253ca3), -904, -253},
+  {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
+  {GRISU_UINT64_C(0x92a1958a, 7675175f), -897, -251},
+  {GRISU_UINT64_C(0xb749faed, 14125d37), -894, -250},
+  {GRISU_UINT64_C(0xe51c79a8, 5916f485), -891, -249},
+  {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+  {GRISU_UINT64_C(0xb2fe3f0b, 8599ef08), -884, -247},
+  {GRISU_UINT64_C(0xdfbdcece, 67006ac9), -881, -246},
+  {GRISU_UINT64_C(0x8bd6a141, 006042be), -877, -245},
+  {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
+  {GRISU_UINT64_C(0xda7f5bf5, 90966849), -871, -243},
+  {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
+  {GRISU_UINT64_C(0xaab37fd7, d8f58179), -864, -241},
+  {GRISU_UINT64_C(0xd5605fcd, cf32e1d7), -861, -240},
+  {GRISU_UINT64_C(0x855c3be0, a17fcd26), -857, -239},
+  {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
+  {GRISU_UINT64_C(0xd0601d8e, fc57b08c), -851, -237},
+  {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+  {GRISU_UINT64_C(0xa2cb1717, b52481ed), -844, -235},
+  {GRISU_UINT64_C(0xcb7ddcdd, a26da269), -841, -234},
+  {GRISU_UINT64_C(0xfe5d5415, 0b090b03), -838, -233},
+  {GRISU_UINT64_C(0x9efa548d, 26e5a6e2), -834, -232},
+  {GRISU_UINT64_C(0xc6b8e9b0, 709f109a), -831, -231},
+  {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
+  {GRISU_UINT64_C(0x9b407691, d7fc44f8), -824, -229},
+  {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+  {GRISU_UINT64_C(0xf294b943, e17a2bc4), -818, -227},
+  {GRISU_UINT64_C(0x979cf3ca, 6cec5b5b), -814, -226},
+  {GRISU_UINT64_C(0xbd8430bd, 08277231), -811, -225},
+  {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+  {GRISU_UINT64_C(0x940f4613, ae5ed137), -804, -223},
+  {GRISU_UINT64_C(0xb9131798, 99f68584), -801, -222},
+  {GRISU_UINT64_C(0xe757dd7e, c07426e5), -798, -221},
+  {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
+  {GRISU_UINT64_C(0xb4bca50b, 065abe63), -791, -219},
+  {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+  {GRISU_UINT64_C(0x8d3360f0, 9cf6e4bd), -784, -217},
+  {GRISU_UINT64_C(0xb080392c, c4349ded), -781, -216},
+  {GRISU_UINT64_C(0xdca04777, f541c568), -778, -215},
+  {GRISU_UINT64_C(0x89e42caa, f9491b61), -774, -214},
+  {GRISU_UINT64_C(0xac5d37d5, b79b6239), -771, -213},
+  {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+  {GRISU_UINT64_C(0x86a8d39e, f77164bd), -764, -211},
+  {GRISU_UINT64_C(0xa8530886, b54dbdec), -761, -210},
+  {GRISU_UINT64_C(0xd267caa8, 62a12d67), -758, -209},
+  {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
+  {GRISU_UINT64_C(0xa4611653, 8d0deb78), -751, -207},
+  {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
+  {GRISU_UINT64_C(0x806bd971, 4632dff6), -744, -205},
+  {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
+  {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
+  {GRISU_UINT64_C(0xfad2a4b1, 3d1b5d6c), -735, -202},
+  {GRISU_UINT64_C(0x9cc3a6ee, c6311a64), -731, -201},
+  {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+  {GRISU_UINT64_C(0xf4f1b4d5, 15acb93c), -725, -199},
+  {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
+  {GRISU_UINT64_C(0xbf5cd546, 78eef0b7), -718, -197},
+  {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+  {GRISU_UINT64_C(0x9580869f, 0e7aac0f), -711, -195},
+  {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
+  {GRISU_UINT64_C(0xe998d258, 869facd7), -705, -193},
+  {GRISU_UINT64_C(0x91ff8377, 5423cc06), -701, -192},
+  {GRISU_UINT64_C(0xb67f6455, 292cbf08), -698, -191},
+  {GRISU_UINT64_C(0xe41f3d6a, 7377eeca), -695, -190},
+  {GRISU_UINT64_C(0x8e938662, 882af53e), -691, -189},
+  {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+  {GRISU_UINT64_C(0xdec681f9, f4c31f31), -685, -187},
+  {GRISU_UINT64_C(0x8b3c113c, 38f9f37f), -681, -186},
+  {GRISU_UINT64_C(0xae0b158b, 4738705f), -678, -185},
+  {GRISU_UINT64_C(0xd98ddaee, 19068c76), -675, -184},
+  {GRISU_UINT64_C(0x87f8a8d4, cfa417ca), -671, -183},
+  {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+  {GRISU_UINT64_C(0xd47487cc, 8470652b), -665, -181},
+  {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
+  {GRISU_UINT64_C(0xa5fb0a17, c777cf0a), -658, -179},
+  {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
+  {GRISU_UINT64_C(0x81ac1fe2, 93d599c0), -651, -177},
+  {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+  {GRISU_UINT64_C(0xca9cf1d2, 06fdc03c), -645, -175},
+  {GRISU_UINT64_C(0xfd442e46, 88bd304b), -642, -174},
+  {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
+  {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
+  {GRISU_UINT64_C(0xf7549530, e188c129), -632, -171},
+  {GRISU_UINT64_C(0x9a94dd3e, 8cf578ba), -628, -170},
+  {GRISU_UINT64_C(0xc13a148e, 3032d6e8), -625, -169},
+  {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+  {GRISU_UINT64_C(0x96f5600f, 15a7b7e5), -618, -167},
+  {GRISU_UINT64_C(0xbcb2b812, db11a5de), -615, -166},
+  {GRISU_UINT64_C(0xebdf6617, 91d60f56), -612, -165},
+  {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+  {GRISU_UINT64_C(0xb84687c2, 69ef3bfb), -605, -163},
+  {GRISU_UINT64_C(0xe65829b3, 046b0afa), -602, -162},
+  {GRISU_UINT64_C(0x8ff71a0f, e2c2e6dc), -598, -161},
+  {GRISU_UINT64_C(0xb3f4e093, db73a093), -595, -160},
+  {GRISU_UINT64_C(0xe0f218b8, d25088b8), -592, -159},
+  {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+  {GRISU_UINT64_C(0xafbd2350, 644eead0), -585, -157},
+  {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
+  {GRISU_UINT64_C(0x894bc396, ce5da772), -578, -155},
+  {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
+  {GRISU_UINT64_C(0xd686619b, a27255a3), -572, -153},
+  {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+  {GRISU_UINT64_C(0xa798fc41, 96e952e7), -565, -151},
+  {GRISU_UINT64_C(0xd17f3b51, fca3a7a1), -562, -150},
+  {GRISU_UINT64_C(0x82ef8513, 3de648c5), -558, -149},
+  {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+  {GRISU_UINT64_C(0xcc963fee, 10b7d1b3), -552, -147},
+  {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
+  {GRISU_UINT64_C(0x9fd561f1, fd0f9bd4), -545, -145},
+  {GRISU_UINT64_C(0xc7caba6e, 7c5382c9), -542, -144},
+  {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
+  {GRISU_UINT64_C(0x9c1661a6, 51213e2d), -535, -142},
+  {GRISU_UINT64_C(0xc31bfa0f, e5698db8), -532, -141},
+  {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+  {GRISU_UINT64_C(0x986ddb5c, 6b3a76b8), -525, -139},
+  {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
+  {GRISU_UINT64_C(0xee2ba6c0, 678b597f), -519, -137},
+  {GRISU_UINT64_C(0x94db4838, 40b717f0), -515, -136},
+  {GRISU_UINT64_C(0xba121a46, 50e4ddec), -512, -135},
+  {GRISU_UINT64_C(0xe896a0d7, e51e1566), -509, -134},
+  {GRISU_UINT64_C(0x915e2486, ef32cd60), -505, -133},
+  {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
+  {GRISU_UINT64_C(0xe3231912, d5bf60e6), -499, -131},
+  {GRISU_UINT64_C(0x8df5efab, c5979c90), -495, -130},
+  {GRISU_UINT64_C(0xb1736b96, b6fd83b4), -492, -129},
+  {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+  {GRISU_UINT64_C(0x8aa22c0d, bef60ee4), -485, -127},
+  {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
+  {GRISU_UINT64_C(0xd89d64d5, 7a607745), -479, -125},
+  {GRISU_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
+  {GRISU_UINT64_C(0xa93af6c6, c79b5d2e), -472, -123},
+  {GRISU_UINT64_C(0xd389b478, 79823479), -469, -122},
+  {GRISU_UINT64_C(0x843610cb, 4bf160cc), -465, -121},
+  {GRISU_UINT64_C(0xa54394fe, 1eedb8ff), -462, -120},
+  {GRISU_UINT64_C(0xce947a3d, a6a9273e), -459, -119},
+  {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
+  {GRISU_UINT64_C(0xa163ff80, 2a3426a9), -452, -117},
+  {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+  {GRISU_UINT64_C(0xfc2c3f38, 41f17c68), -446, -115},
+  {GRISU_UINT64_C(0x9d9ba783, 2936edc1), -442, -114},
+  {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
+  {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
+  {GRISU_UINT64_C(0x99ea0196, 163fa42e), -432, -111},
+  {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+  {GRISU_UINT64_C(0xf07da27a, 82c37088), -426, -109},
+  {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+  {GRISU_UINT64_C(0xbbe226ef, b628afeb), -419, -107},
+  {GRISU_UINT64_C(0xeadab0ab, a3b2dbe5), -416, -106},
+  {GRISU_UINT64_C(0x92c8ae6b, 464fc96f), -412, -105},
+  {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+  {GRISU_UINT64_C(0xe5599087, 9ddcaabe), -406, -103},
+  {GRISU_UINT64_C(0x8f57fa54, c2a9eab7), -402, -102},
+  {GRISU_UINT64_C(0xb32df8e9, f3546564), -399, -101},
+  {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
+  {GRISU_UINT64_C(0x8bfbea76, c619ef36), -392, -99},
+  {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+  {GRISU_UINT64_C(0xdab99e59, 958885c5), -386, -97},
+  {GRISU_UINT64_C(0x88b402f7, fd75539b), -382, -96},
+  {GRISU_UINT64_C(0xaae103b5, fcd2a882), -379, -95},
+  {GRISU_UINT64_C(0xd59944a3, 7c0752a2), -376, -94},
+  {GRISU_UINT64_C(0x857fcae6, 2d8493a5), -372, -93},
+  {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+  {GRISU_UINT64_C(0xd097ad07, a71f26b2), -366, -91},
+  {GRISU_UINT64_C(0x825ecc24, c8737830), -362, -90},
+  {GRISU_UINT64_C(0xa2f67f2d, fa90563b), -359, -89},
+  {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+  {GRISU_UINT64_C(0xfea126b7, d78186bd), -353, -87},
+  {GRISU_UINT64_C(0x9f24b832, e6b0f436), -349, -86},
+  {GRISU_UINT64_C(0xc6ede63f, a05d3144), -346, -85},
+  {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+  {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
+  {GRISU_UINT64_C(0xc24452da, 229b021c), -336, -82},
+  {GRISU_UINT64_C(0xf2d56790, ab41c2a3), -333, -81},
+  {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+  {GRISU_UINT64_C(0xbdb6b8e9, 05cb600f), -326, -79},
+  {GRISU_UINT64_C(0xed246723, 473e3813), -323, -78},
+  {GRISU_UINT64_C(0x9436c076, 0c86e30c), -319, -77},
+  {GRISU_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
+  {GRISU_UINT64_C(0xe7958cb8, 7392c2c3), -313, -75},
+  {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+  {GRISU_UINT64_C(0xb4ecd5f0, 1a4aa828), -306, -73},
+  {GRISU_UINT64_C(0xe2280b6c, 20dd5232), -303, -72},
+  {GRISU_UINT64_C(0x8d590723, 948a535f), -299, -71},
+  {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
+  {GRISU_UINT64_C(0xdcdb1b27, 98182245), -293, -69},
+  {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+  {GRISU_UINT64_C(0xac8b2d36, eed2dac6), -286, -67},
+  {GRISU_UINT64_C(0xd7adf884, aa879177), -283, -66},
+  {GRISU_UINT64_C(0x86ccbb52, ea94baeb), -279, -65},
+  {GRISU_UINT64_C(0xa87fea27, a539e9a5), -276, -64},
+  {GRISU_UINT64_C(0xd29fe4b1, 8e88640f), -273, -63},
+  {GRISU_UINT64_C(0x83a3eeee, f9153e89), -269, -62},
+  {GRISU_UINT64_C(0xa48ceaaa, b75a8e2b), -266, -61},
+  {GRISU_UINT64_C(0xcdb02555, 653131b6), -263, -60},
+  {GRISU_UINT64_C(0x808e1755, 5f3ebf12), -259, -59},
+  {GRISU_UINT64_C(0xa0b19d2a, b70e6ed6), -256, -58},
+  {GRISU_UINT64_C(0xc8de0475, 64d20a8c), -253, -57},
+  {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+  {GRISU_UINT64_C(0x9ced737b, b6c4183d), -246, -55},
+  {GRISU_UINT64_C(0xc428d05a, a4751e4d), -243, -54},
+  {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
+  {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
+  {GRISU_UINT64_C(0xbf8fdb78, 849a5f97), -233, -51},
+  {GRISU_UINT64_C(0xef73d256, a5c0f77d), -230, -50},
+  {GRISU_UINT64_C(0x95a86376, 27989aae), -226, -49},
+  {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+  {GRISU_UINT64_C(0xe9d71b68, 9dde71b0), -220, -47},
+  {GRISU_UINT64_C(0x92267121, 62ab070e), -216, -46},
+  {GRISU_UINT64_C(0xb6b00d69, bb55c8d1), -213, -45},
+  {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+  {GRISU_UINT64_C(0x8eb98a7a, 9a5b04e3), -206, -43},
+  {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
+  {GRISU_UINT64_C(0xdf01e85f, 912e37a3), -200, -41},
+  {GRISU_UINT64_C(0x8b61313b, babce2c6), -196, -40},
+  {GRISU_UINT64_C(0xae397d8a, a96c1b78), -193, -39},
+  {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+  {GRISU_UINT64_C(0x881cea14, 545c7575), -186, -37},
+  {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
+  {GRISU_UINT64_C(0xd4ad2dbf, c3d07788), -180, -35},
+  {GRISU_UINT64_C(0x84ec3c97, da624ab5), -176, -34},
+  {GRISU_UINT64_C(0xa6274bbd, d0fadd62), -173, -33},
+  {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
+  {GRISU_UINT64_C(0x81ceb32c, 4b43fcf5), -166, -31},
+  {GRISU_UINT64_C(0xa2425ff7, 5e14fc32), -163, -30},
+  {GRISU_UINT64_C(0xcad2f7f5, 359a3b3e), -160, -29},
+  {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+  {GRISU_UINT64_C(0x9e74d1b7, 91e07e48), -153, -27},
+  {GRISU_UINT64_C(0xc6120625, 76589ddb), -150, -26},
+  {GRISU_UINT64_C(0xf79687ae, d3eec551), -147, -25},
+  {GRISU_UINT64_C(0x9abe14cd, 44753b53), -143, -24},
+  {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
+  {GRISU_UINT64_C(0xf1c90080, baf72cb1), -137, -22},
+  {GRISU_UINT64_C(0x971da050, 74da7bef), -133, -21},
+  {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+  {GRISU_UINT64_C(0xec1e4a7d, b69561a5), -127, -19},
+  {GRISU_UINT64_C(0x9392ee8e, 921d5d07), -123, -18},
+  {GRISU_UINT64_C(0xb877aa32, 36a4b449), -120, -17},
+  {GRISU_UINT64_C(0xe69594be, c44de15b), -117, -16},
+  {GRISU_UINT64_C(0x901d7cf7, 3ab0acd9), -113, -15},
+  {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
+  {GRISU_UINT64_C(0xe12e1342, 4bb40e13), -107, -13},
+  {GRISU_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
+  {GRISU_UINT64_C(0xafebff0b, cb24aaff), -100, -11},
+  {GRISU_UINT64_C(0xdbe6fece, bdedd5bf), -97, -10},
+  {GRISU_UINT64_C(0x89705f41, 36b4a597), -93, -9},
+  {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+  {GRISU_UINT64_C(0xd6bf94d5, e57a42bc), -87, -7},
+  {GRISU_UINT64_C(0x8637bd05, af6c69b6), -83, -6},
+  {GRISU_UINT64_C(0xa7c5ac47, 1b478423), -80, -5},
+  {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
+  {GRISU_UINT64_C(0x83126e97, 8d4fdf3b), -73, -3},
+  {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+  {GRISU_UINT64_C(0xcccccccc, cccccccd), -67, -1},
+  {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
+  {GRISU_UINT64_C(0xa0000000, 00000000), -60, 1},
+  {GRISU_UINT64_C(0xc8000000, 00000000), -57, 2},
+  {GRISU_UINT64_C(0xfa000000, 00000000), -54, 3},
+  {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+  {GRISU_UINT64_C(0xc3500000, 00000000), -47, 5},
+  {GRISU_UINT64_C(0xf4240000, 00000000), -44, 6},
+  {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
+  {GRISU_UINT64_C(0xbebc2000, 00000000), -37, 8},
+  {GRISU_UINT64_C(0xee6b2800, 00000000), -34, 9},
+  {GRISU_UINT64_C(0x9502f900, 00000000), -30, 10},
+  {GRISU_UINT64_C(0xba43b740, 00000000), -27, 11},
+  {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+  {GRISU_UINT64_C(0x9184e72a, 00000000), -20, 13},
+  {GRISU_UINT64_C(0xb5e620f4, 80000000), -17, 14},
+  {GRISU_UINT64_C(0xe35fa931, a0000000), -14, 15},
+  {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+  {GRISU_UINT64_C(0xb1a2bc2e, c5000000), -7, 17},
+  {GRISU_UINT64_C(0xde0b6b3a, 76400000), -4, 18},
+  {GRISU_UINT64_C(0x8ac72304, 89e80000), 0, 19},
+  {GRISU_UINT64_C(0xad78ebc5, ac620000), 3, 20},
+  {GRISU_UINT64_C(0xd8d726b7, 177a8000), 6, 21},
+  {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+  {GRISU_UINT64_C(0xa968163f, 0a57b400), 13, 23},
+  {GRISU_UINT64_C(0xd3c21bce, cceda100), 16, 24},
+  {GRISU_UINT64_C(0x84595161, 401484a0), 20, 25},
+  {GRISU_UINT64_C(0xa56fa5b9, 9019a5c8), 23, 26},
+  {GRISU_UINT64_C(0xcecb8f27, f4200f3a), 26, 27},
+  {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+  {GRISU_UINT64_C(0xa18f07d7, 36b90be5), 33, 29},
+  {GRISU_UINT64_C(0xc9f2c9cd, 04674edf), 36, 30},
+  {GRISU_UINT64_C(0xfc6f7c40, 45812296), 39, 31},
+  {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+  {GRISU_UINT64_C(0xc5371912, 364ce305), 46, 33},
+  {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+  {GRISU_UINT64_C(0x9a130b96, 3a6c115c), 53, 35},
+  {GRISU_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
+  {GRISU_UINT64_C(0xf0bdc21a, bb48db20), 59, 37},
+  {GRISU_UINT64_C(0x96769950, b50d88f4), 63, 38},
+  {GRISU_UINT64_C(0xbc143fa4, e250eb31), 66, 39},
+  {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
+  {GRISU_UINT64_C(0x92efd1b8, d0cf37be), 73, 41},
+  {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
+  {GRISU_UINT64_C(0xe596b7b0, c643c719), 79, 43},
+  {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
+  {GRISU_UINT64_C(0xb35dbf82, 1ae4f38c), 86, 45},
+  {GRISU_UINT64_C(0xe0352f62, a19e306f), 89, 46},
+  {GRISU_UINT64_C(0x8c213d9d, a502de45), 93, 47},
+  {GRISU_UINT64_C(0xaf298d05, 0e4395d7), 96, 48},
+  {GRISU_UINT64_C(0xdaf3f046, 51d47b4c), 99, 49},
+  {GRISU_UINT64_C(0x88d8762b, f324cd10), 103, 50},
+  {GRISU_UINT64_C(0xab0e93b6, efee0054), 106, 51},
+  {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+  {GRISU_UINT64_C(0x85a36366, eb71f041), 113, 53},
+  {GRISU_UINT64_C(0xa70c3c40, a64e6c52), 116, 54},
+  {GRISU_UINT64_C(0xd0cf4b50, cfe20766), 119, 55},
+  {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
+  {GRISU_UINT64_C(0xa321f2d7, 226895c8), 126, 57},
+  {GRISU_UINT64_C(0xcbea6f8c, eb02bb3a), 129, 58},
+  {GRISU_UINT64_C(0xfee50b70, 25c36a08), 132, 59},
+  {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
+  {GRISU_UINT64_C(0xc722f0ef, 9d80aad6), 139, 61},
+  {GRISU_UINT64_C(0xf8ebad2b, 84e0d58c), 142, 62},
+  {GRISU_UINT64_C(0x9b934c3b, 330c8577), 146, 63},
+  {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
+  {GRISU_UINT64_C(0xf316271c, 7fc3908b), 152, 65},
+  {GRISU_UINT64_C(0x97edd871, cfda3a57), 156, 66},
+  {GRISU_UINT64_C(0xbde94e8e, 43d0c8ec), 159, 67},
+  {GRISU_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
+  {GRISU_UINT64_C(0x945e455f, 24fb1cf9), 166, 69},
+  {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+  {GRISU_UINT64_C(0xe7d34c64, a9c85d44), 172, 71},
+  {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+  {GRISU_UINT64_C(0xb51d13ae, a4a488dd), 179, 73},
+  {GRISU_UINT64_C(0xe264589a, 4dcdab15), 182, 74},
+  {GRISU_UINT64_C(0x8d7eb760, 70a08aed), 186, 75},
+  {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+  {GRISU_UINT64_C(0xdd15fe86, affad912), 192, 77},
+  {GRISU_UINT64_C(0x8a2dbf14, 2dfcc7ab), 196, 78},
+  {GRISU_UINT64_C(0xacb92ed9, 397bf996), 199, 79},
+  {GRISU_UINT64_C(0xd7e77a8f, 87daf7fc), 202, 80},
+  {GRISU_UINT64_C(0x86f0ac99, b4e8dafd), 206, 81},
+  {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+  {GRISU_UINT64_C(0xd2d80db0, 2aabd62c), 212, 83},
+  {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
+  {GRISU_UINT64_C(0xa4b8cab1, a1563f52), 219, 85},
+  {GRISU_UINT64_C(0xcde6fd5e, 09abcf27), 222, 86},
+  {GRISU_UINT64_C(0x80b05e5a, c60b6178), 226, 87},
+  {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+  {GRISU_UINT64_C(0xc913936d, d571c84c), 232, 89},
+  {GRISU_UINT64_C(0xfb587849, 4ace3a5f), 235, 90},
+  {GRISU_UINT64_C(0x9d174b2d, cec0e47b), 239, 91},
+  {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+  {GRISU_UINT64_C(0xf5746577, 930d6501), 245, 93},
+  {GRISU_UINT64_C(0x9968bf6a, bbe85f20), 249, 94},
+  {GRISU_UINT64_C(0xbfc2ef45, 6ae276e9), 252, 95},
+  {GRISU_UINT64_C(0xefb3ab16, c59b14a3), 255, 96},
+  {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
+  {GRISU_UINT64_C(0xbb445da9, ca61281f), 262, 98},
+  {GRISU_UINT64_C(0xea157514, 3cf97227), 265, 99},
+  {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+  {GRISU_UINT64_C(0xb6e0c377, cfa2e12e), 272, 101},
+  {GRISU_UINT64_C(0xe498f455, c38b997a), 275, 102},
+  {GRISU_UINT64_C(0x8edf98b5, 9a373fec), 279, 103},
+  {GRISU_UINT64_C(0xb2977ee3, 00c50fe7), 282, 104},
+  {GRISU_UINT64_C(0xdf3d5e9b, c0f653e1), 285, 105},
+  {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
+  {GRISU_UINT64_C(0xae67f1e9, aec07188), 292, 107},
+  {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
+  {GRISU_UINT64_C(0x884134fe, 908658b2), 299, 109},
+  {GRISU_UINT64_C(0xaa51823e, 34a7eedf), 302, 110},
+  {GRISU_UINT64_C(0xd4e5e2cd, c1d1ea96), 305, 111},
+  {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+  {GRISU_UINT64_C(0xa6539930, bf6bff46), 312, 113},
+  {GRISU_UINT64_C(0xcfe87f7c, ef46ff17), 315, 114},
+  {GRISU_UINT64_C(0x81f14fae, 158c5f6e), 319, 115},
+  {GRISU_UINT64_C(0xa26da399, 9aef774a), 322, 116},
+  {GRISU_UINT64_C(0xcb090c80, 01ab551c), 325, 117},
+  {GRISU_UINT64_C(0xfdcb4fa0, 02162a63), 328, 118},
+  {GRISU_UINT64_C(0x9e9f11c4, 014dda7e), 332, 119},
+  {GRISU_UINT64_C(0xc646d635, 01a1511e), 335, 120},
+  {GRISU_UINT64_C(0xf7d88bc2, 4209a565), 338, 121},
+  {GRISU_UINT64_C(0x9ae75759, 6946075f), 342, 122},
+  {GRISU_UINT64_C(0xc1a12d2f, c3978937), 345, 123},
+  {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+  {GRISU_UINT64_C(0x9745eb4d, 50ce6333), 352, 125},
+  {GRISU_UINT64_C(0xbd176620, a501fc00), 355, 126},
+  {GRISU_UINT64_C(0xec5d3fa8, ce427b00), 358, 127},
+  {GRISU_UINT64_C(0x93ba47c9, 80e98ce0), 362, 128},
+  {GRISU_UINT64_C(0xb8a8d9bb, e123f018), 365, 129},
+  {GRISU_UINT64_C(0xe6d3102a, d96cec1e), 368, 130},
+  {GRISU_UINT64_C(0x9043ea1a, c7e41393), 372, 131},
+  {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+  {GRISU_UINT64_C(0xe16a1dc9, d8545e95), 378, 133},
+  {GRISU_UINT64_C(0x8ce2529e, 2734bb1d), 382, 134},
+  {GRISU_UINT64_C(0xb01ae745, b101e9e4), 385, 135},
+  {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
+  {GRISU_UINT64_C(0x899504ae, 72497eba), 392, 137},
+  {GRISU_UINT64_C(0xabfa45da, 0edbde69), 395, 138},
+  {GRISU_UINT64_C(0xd6f8d750, 9292d603), 398, 139},
+  {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+  {GRISU_UINT64_C(0xa7f26836, f282b733), 405, 141},
+  {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+  {GRISU_UINT64_C(0x8335616a, ed761f1f), 412, 143},
+  {GRISU_UINT64_C(0xa402b9c5, a8d3a6e7), 415, 144},
+  {GRISU_UINT64_C(0xcd036837, 130890a1), 418, 145},
+  {GRISU_UINT64_C(0x80222122, 6be55a65), 422, 146},
+  {GRISU_UINT64_C(0xa02aa96b, 06deb0fe), 425, 147},
+  {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+  {GRISU_UINT64_C(0xfa42a8b7, 3abbf48d), 431, 149},
+  {GRISU_UINT64_C(0x9c69a972, 84b578d8), 435, 150},
+  {GRISU_UINT64_C(0xc38413cf, 25e2d70e), 438, 151},
+  {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
+  {GRISU_UINT64_C(0x98bf2f79, d5993803), 445, 153},
+  {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+  {GRISU_UINT64_C(0xeeaaba2e, 5dbf6785), 451, 155},
+  {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
+  {GRISU_UINT64_C(0xba756174, 393d88e0), 458, 157},
+  {GRISU_UINT64_C(0xe912b9d1, 478ceb17), 461, 158},
+  {GRISU_UINT64_C(0x91abb422, ccb812ef), 465, 159},
+  {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+  {GRISU_UINT64_C(0xe39c4976, 5fdf9d95), 471, 161},
+  {GRISU_UINT64_C(0x8e41ade9, fbebc27d), 475, 162},
+  {GRISU_UINT64_C(0xb1d21964, 7ae6b31c), 478, 163},
+  {GRISU_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
+  {GRISU_UINT64_C(0x8aec23d6, 80043bee), 485, 165},
+  {GRISU_UINT64_C(0xada72ccc, 20054aea), 488, 166},
+  {GRISU_UINT64_C(0xd910f7ff, 28069da4), 491, 167},
+  {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
+  {GRISU_UINT64_C(0xa99541bf, 57452b28), 498, 169},
+  {GRISU_UINT64_C(0xd3fa922f, 2d1675f2), 501, 170},
+  {GRISU_UINT64_C(0x847c9b5d, 7c2e09b7), 505, 171},
+  {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+  {GRISU_UINT64_C(0xcf02b2c2, 1207ef2f), 511, 173},
+  {GRISU_UINT64_C(0x8161afb9, 4b44f57d), 515, 174},
+  {GRISU_UINT64_C(0xa1ba1ba7, 9e1632dc), 518, 175},
+  {GRISU_UINT64_C(0xca28a291, 859bbf93), 521, 176},
+  {GRISU_UINT64_C(0xfcb2cb35, e702af78), 524, 177},
+  {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
+  {GRISU_UINT64_C(0xc56baec2, 1c7a1916), 531, 179},
+  {GRISU_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
+  {GRISU_UINT64_C(0x9a3c2087, a63f6399), 538, 181},
+  {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
+  {GRISU_UINT64_C(0xf0fdf2d3, f3c30b9f), 544, 183},
+  {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
+  {GRISU_UINT64_C(0xbc4665b5, 96706115), 551, 185},
+  {GRISU_UINT64_C(0xeb57ff22, fc0c795a), 554, 186},
+  {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
+  {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
+  {GRISU_UINT64_C(0xe5d3ef28, 2a242e82), 564, 189},
+  {GRISU_UINT64_C(0x8fa47579, 1a569d11), 568, 190},
+  {GRISU_UINT64_C(0xb38d92d7, 60ec4455), 571, 191},
+  {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
+  {GRISU_UINT64_C(0x8c469ab8, 43b89563), 578, 193},
+  {GRISU_UINT64_C(0xaf584166, 54a6babb), 581, 194},
+  {GRISU_UINT64_C(0xdb2e51bf, e9d0696a), 584, 195},
+  {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+  {GRISU_UINT64_C(0xab3c2fdd, eeaad25b), 591, 197},
+  {GRISU_UINT64_C(0xd60b3bd5, 6a5586f2), 594, 198},
+  {GRISU_UINT64_C(0x85c70565, 62757457), 598, 199},
+  {GRISU_UINT64_C(0xa738c6be, bb12d16d), 601, 200},
+  {GRISU_UINT64_C(0xd106f86e, 69d785c8), 604, 201},
+  {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+  {GRISU_UINT64_C(0xa34d7216, 42b06084), 611, 203},
+  {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
+  {GRISU_UINT64_C(0xff290242, c83396ce), 617, 205},
+  {GRISU_UINT64_C(0x9f79a169, bd203e41), 621, 206},
+  {GRISU_UINT64_C(0xc75809c4, 2c684dd1), 624, 207},
+  {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
+  {GRISU_UINT64_C(0x9bbcc7a1, 42b17ccc), 631, 209},
+  {GRISU_UINT64_C(0xc2abf989, 935ddbfe), 634, 210},
+  {GRISU_UINT64_C(0xf356f7eb, f83552fe), 637, 211},
+  {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+  {GRISU_UINT64_C(0xbe1bf1b0, 59e9a8d6), 644, 213},
+  {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
+  {GRISU_UINT64_C(0x9485d4d1, c63e8be8), 651, 215},
+  {GRISU_UINT64_C(0xb9a74a06, 37ce2ee1), 654, 216},
+  {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
+  {GRISU_UINT64_C(0x910ab1d4, db9914a0), 661, 218},
+  {GRISU_UINT64_C(0xb54d5e4a, 127f59c8), 664, 219},
+  {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+  {GRISU_UINT64_C(0x8da471a9, de737e24), 671, 221},
+  {GRISU_UINT64_C(0xb10d8e14, 56105dad), 674, 222},
+  {GRISU_UINT64_C(0xdd50f199, 6b947519), 677, 223},
+  {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
+  {GRISU_UINT64_C(0xace73cbf, dc0bfb7b), 684, 225},
+  {GRISU_UINT64_C(0xd8210bef, d30efa5a), 687, 226},
+  {GRISU_UINT64_C(0x8714a775, e3e95c78), 691, 227},
+  {GRISU_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
+  {GRISU_UINT64_C(0xd31045a8, 341ca07c), 697, 229},
+  {GRISU_UINT64_C(0x83ea2b89, 2091e44e), 701, 230},
+  {GRISU_UINT64_C(0xa4e4b66b, 68b65d61), 704, 231},
+  {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+  {GRISU_UINT64_C(0x80d2ae83, e9ce78f4), 711, 233},
+  {GRISU_UINT64_C(0xa1075a24, e4421731), 714, 234},
+  {GRISU_UINT64_C(0xc94930ae, 1d529cfd), 717, 235},
+  {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
+  {GRISU_UINT64_C(0x9d412e08, 06e88aa6), 724, 237},
+  {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+  {GRISU_UINT64_C(0xf5b5d7ec, 8acb58a3), 730, 239},
+  {GRISU_UINT64_C(0x9991a6f3, d6bf1766), 734, 240},
+  {GRISU_UINT64_C(0xbff610b0, cc6edd3f), 737, 241},
+  {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
+  {GRISU_UINT64_C(0x95f83d0a, 1fb69cd9), 744, 243},
+  {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+  {GRISU_UINT64_C(0xea53df5f, d18d5514), 750, 245},
+  {GRISU_UINT64_C(0x92746b9b, e2f8552c), 754, 246},
+  {GRISU_UINT64_C(0xb7118682, dbb66a77), 757, 247},
+  {GRISU_UINT64_C(0xe4d5e823, 92a40515), 760, 248},
+  {GRISU_UINT64_C(0x8f05b116, 3ba6832d), 764, 249},
+  {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
+  {GRISU_UINT64_C(0xdf78e4b2, bd342cf7), 770, 251},
+  {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+  {GRISU_UINT64_C(0xae9672ab, a3d0c321), 777, 253},
+  {GRISU_UINT64_C(0xda3c0f56, 8cc4f3e9), 780, 254},
+  {GRISU_UINT64_C(0x88658996, 17fb1871), 784, 255},
+  {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
+  {GRISU_UINT64_C(0xd51ea6fa, 85785631), 790, 257},
+  {GRISU_UINT64_C(0x8533285c, 936b35df), 794, 258},
+  {GRISU_UINT64_C(0xa67ff273, b8460357), 797, 259},
+  {GRISU_UINT64_C(0xd01fef10, a657842c), 800, 260},
+  {GRISU_UINT64_C(0x8213f56a, 67f6b29c), 804, 261},
+  {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+  {GRISU_UINT64_C(0xcb3f2f76, 42717713), 810, 263},
+  {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
+  {GRISU_UINT64_C(0x9ec95d14, 63e8a507), 817, 265},
+  {GRISU_UINT64_C(0xc67bb459, 7ce2ce49), 820, 266},
+  {GRISU_UINT64_C(0xf81aa16f, dc1b81db), 823, 267},
+  {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+  {GRISU_UINT64_C(0xc1d4ce1f, 63f57d73), 830, 269},
+  {GRISU_UINT64_C(0xf24a01a7, 3cf2dcd0), 833, 270},
+  {GRISU_UINT64_C(0x976e4108, 8617ca02), 837, 271},
+  {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
+  {GRISU_UINT64_C(0xec9c459d, 51852ba3), 843, 273},
+  {GRISU_UINT64_C(0x93e1ab82, 52f33b46), 847, 274},
+  {GRISU_UINT64_C(0xb8da1662, e7b00a17), 850, 275},
+  {GRISU_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
+  {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
+  {GRISU_UINT64_C(0xb484f9dc, 9641e9db), 860, 278},
+  {GRISU_UINT64_C(0xe1a63853, bbd26451), 863, 279},
+  {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+  {GRISU_UINT64_C(0xb049dc01, 6abc5e60), 870, 281},
+  {GRISU_UINT64_C(0xdc5c5301, c56b75f7), 873, 282},
+  {GRISU_UINT64_C(0x89b9b3e1, 1b6329bb), 877, 283},
+  {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
+  {GRISU_UINT64_C(0xd732290f, bacaf134), 883, 285},
+  {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+  {GRISU_UINT64_C(0xa81f3014, 49ee8c70), 890, 287},
+  {GRISU_UINT64_C(0xd226fc19, 5c6a2f8c), 893, 288},
+  {GRISU_UINT64_C(0x83585d8f, d9c25db8), 897, 289},
+  {GRISU_UINT64_C(0xa42e74f3, d032f526), 900, 290},
+  {GRISU_UINT64_C(0xcd3a1230, c43fb26f), 903, 291},
+  {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+  {GRISU_UINT64_C(0xa0555e36, 1951c367), 910, 293},
+  {GRISU_UINT64_C(0xc86ab5c3, 9fa63441), 913, 294},
+  {GRISU_UINT64_C(0xfa856334, 878fc151), 916, 295},
+  {GRISU_UINT64_C(0x9c935e00, d4b9d8d2), 920, 296},
+  {GRISU_UINT64_C(0xc3b83581, 09e84f07), 923, 297},
+  {GRISU_UINT64_C(0xf4a642e1, 4c6262c9), 926, 298},
+  {GRISU_UINT64_C(0x98e7e9cc, cfbd7dbe), 930, 299},
+  {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
+  {GRISU_UINT64_C(0xeeea5d50, 04981478), 936, 301},
+  {GRISU_UINT64_C(0x95527a52, 02df0ccb), 940, 302},
+  {GRISU_UINT64_C(0xbaa718e6, 8396cffe), 943, 303},
+  {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+  {GRISU_UINT64_C(0x91d28b74, 16cdd27e), 950, 305},
+  {GRISU_UINT64_C(0xb6472e51, 1c81471e), 953, 306},
+  {GRISU_UINT64_C(0xe3d8f9e5, 63a198e5), 956, 307},
+  {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+  {GRISU_UINT64_C(0xb201833b, 35d63f73), 963, 309},
+  {GRISU_UINT64_C(0xde81e40a, 034bcf50), 966, 310},
+  {GRISU_UINT64_C(0x8b112e86, 420f6192), 970, 311},
+  {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
+  {GRISU_UINT64_C(0xd94ad8b1, c7380874), 976, 313},
+  {GRISU_UINT64_C(0x87cec76f, 1c830549), 980, 314},
+  {GRISU_UINT64_C(0xa9c2794a, e3a3c69b), 983, 315},
+  {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+  {GRISU_UINT64_C(0x849feec2, 81d7f329), 990, 317},
+  {GRISU_UINT64_C(0xa5c7ea73, 224deff3), 993, 318},
+  {GRISU_UINT64_C(0xcf39e50f, eae16bf0), 996, 319},
+  {GRISU_UINT64_C(0x81842f29, f2cce376), 1000, 320},
+  {GRISU_UINT64_C(0xa1e53af4, 6f801c53), 1003, 321},
+  {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+  {GRISU_UINT64_C(0xfcf62c1d, ee382c42), 1009, 323},
+  {GRISU_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
+  {GRISU_UINT64_C(0xc5a05277, 621be294), 1016, 325},
+  {GRISU_UINT64_C(0xf7086715, 3aa2db39), 1019, 326},
+  {GRISU_UINT64_C(0x9a65406d, 44a5c903), 1023, 327},
+  {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
+  {GRISU_UINT64_C(0xf13e34aa, bb430a15), 1029, 329},
+  {GRISU_UINT64_C(0x96c6e0ea, b509e64d), 1033, 330},
+  {GRISU_UINT64_C(0xbc789925, 624c5fe1), 1036, 331},
+  {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+  {GRISU_UINT64_C(0x933e37a5, 34cbaae8), 1043, 333},
+  {GRISU_UINT64_C(0xb80dc58e, 81fe95a1), 1046, 334},
+  {GRISU_UINT64_C(0xe61136f2, 227e3b0a), 1049, 335},
+  {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
+  {GRISU_UINT64_C(0xb3bd72ed, 2af29e20), 1056, 337},
+  {GRISU_UINT64_C(0xe0accfa8, 75af45a8), 1059, 338},
+  {GRISU_UINT64_C(0x8c6c01c9, 498d8b89), 1063, 339},
+  {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+  {GRISU_UINT64_C(0xdb68c2ca, 82ed2a06), 1069, 341},
+  {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(1) = 4;
+// nb elements (1): 651
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(2)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0xb3c4f1ba, 87bc8697), -1080, -306},
+  {GRISU_UINT64_C(0x8c71dcd9, ba0b4926), -1073, -304},
+  {GRISU_UINT64_C(0xdb71e914, 32b1a24b), -1067, -302},
+  {GRISU_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
+  {GRISU_UINT64_C(0x85f04682, 93f0eb4e), -1053, -298},
+  {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
+  {GRISU_UINT64_C(0xa37fce12, 6597973d), -1040, -294},
+  {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
+  {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
+  {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
+  {GRISU_UINT64_C(0xf3a20279, ed56d48a), -1014, -286},
+  {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+  {GRISU_UINT64_C(0x94b3a202, eb1c3f39), -1000, -282},
+  {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
+  {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+  {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
+  {GRISU_UINT64_C(0xdd95317f, 31c7fa1d), -974, -274},
+  {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+  {GRISU_UINT64_C(0x873e4f75, e2224e68), -960, -270},
+  {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+  {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
+  {GRISU_UINT64_C(0x80fa687f, 881c7f8e), -940, -264},
+  {GRISU_UINT64_C(0xc9874347, 44ac874f), -934, -262},
+  {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+  {GRISU_UINT64_C(0xf6019da0, 7f549b2b), -921, -258},
+  {GRISU_UINT64_C(0xc0314325, 637a193a), -914, -256},
+  {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
+  {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
+  {GRISU_UINT64_C(0xb749faed, 14125d37), -894, -250},
+  {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+  {GRISU_UINT64_C(0xdfbdcece, 67006ac9), -881, -246},
+  {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
+  {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
+  {GRISU_UINT64_C(0xd5605fcd, cf32e1d7), -861, -240},
+  {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
+  {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+  {GRISU_UINT64_C(0xcb7ddcdd, a26da269), -841, -234},
+  {GRISU_UINT64_C(0x9efa548d, 26e5a6e2), -834, -232},
+  {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
+  {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+  {GRISU_UINT64_C(0x979cf3ca, 6cec5b5b), -814, -226},
+  {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+  {GRISU_UINT64_C(0xb9131798, 99f68584), -801, -222},
+  {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
+  {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+  {GRISU_UINT64_C(0xb080392c, c4349ded), -781, -216},
+  {GRISU_UINT64_C(0x89e42caa, f9491b61), -774, -214},
+  {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+  {GRISU_UINT64_C(0xa8530886, b54dbdec), -761, -210},
+  {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
+  {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
+  {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
+  {GRISU_UINT64_C(0xfad2a4b1, 3d1b5d6c), -735, -202},
+  {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+  {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
+  {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+  {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
+  {GRISU_UINT64_C(0x91ff8377, 5423cc06), -701, -192},
+  {GRISU_UINT64_C(0xe41f3d6a, 7377eeca), -695, -190},
+  {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+  {GRISU_UINT64_C(0x8b3c113c, 38f9f37f), -681, -186},
+  {GRISU_UINT64_C(0xd98ddaee, 19068c76), -675, -184},
+  {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+  {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
+  {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
+  {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+  {GRISU_UINT64_C(0xfd442e46, 88bd304b), -642, -174},
+  {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
+  {GRISU_UINT64_C(0x9a94dd3e, 8cf578ba), -628, -170},
+  {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+  {GRISU_UINT64_C(0xbcb2b812, db11a5de), -615, -166},
+  {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+  {GRISU_UINT64_C(0xe65829b3, 046b0afa), -602, -162},
+  {GRISU_UINT64_C(0xb3f4e093, db73a093), -595, -160},
+  {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+  {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
+  {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
+  {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+  {GRISU_UINT64_C(0xd17f3b51, fca3a7a1), -562, -150},
+  {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+  {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
+  {GRISU_UINT64_C(0xc7caba6e, 7c5382c9), -542, -144},
+  {GRISU_UINT64_C(0x9c1661a6, 51213e2d), -535, -142},
+  {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+  {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
+  {GRISU_UINT64_C(0x94db4838, 40b717f0), -515, -136},
+  {GRISU_UINT64_C(0xe896a0d7, e51e1566), -509, -134},
+  {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
+  {GRISU_UINT64_C(0x8df5efab, c5979c90), -495, -130},
+  {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+  {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
+  {GRISU_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
+  {GRISU_UINT64_C(0xd389b478, 79823479), -469, -122},
+  {GRISU_UINT64_C(0xa54394fe, 1eedb8ff), -462, -120},
+  {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
+  {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+  {GRISU_UINT64_C(0x9d9ba783, 2936edc1), -442, -114},
+  {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
+  {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+  {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+  {GRISU_UINT64_C(0xeadab0ab, a3b2dbe5), -416, -106},
+  {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+  {GRISU_UINT64_C(0x8f57fa54, c2a9eab7), -402, -102},
+  {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
+  {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+  {GRISU_UINT64_C(0x88b402f7, fd75539b), -382, -96},
+  {GRISU_UINT64_C(0xd59944a3, 7c0752a2), -376, -94},
+  {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+  {GRISU_UINT64_C(0x825ecc24, c8737830), -362, -90},
+  {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+  {GRISU_UINT64_C(0x9f24b832, e6b0f436), -349, -86},
+  {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+  {GRISU_UINT64_C(0xc24452da, 229b021c), -336, -82},
+  {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+  {GRISU_UINT64_C(0xed246723, 473e3813), -323, -78},
+  {GRISU_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
+  {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+  {GRISU_UINT64_C(0xe2280b6c, 20dd5232), -303, -72},
+  {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
+  {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+  {GRISU_UINT64_C(0xd7adf884, aa879177), -283, -66},
+  {GRISU_UINT64_C(0xa87fea27, a539e9a5), -276, -64},
+  {GRISU_UINT64_C(0x83a3eeee, f9153e89), -269, -62},
+  {GRISU_UINT64_C(0xcdb02555, 653131b6), -263, -60},
+  {GRISU_UINT64_C(0xa0b19d2a, b70e6ed6), -256, -58},
+  {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+  {GRISU_UINT64_C(0xc428d05a, a4751e4d), -243, -54},
+  {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
+  {GRISU_UINT64_C(0xef73d256, a5c0f77d), -230, -50},
+  {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+  {GRISU_UINT64_C(0x92267121, 62ab070e), -216, -46},
+  {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+  {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
+  {GRISU_UINT64_C(0x8b61313b, babce2c6), -196, -40},
+  {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+  {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
+  {GRISU_UINT64_C(0x84ec3c97, da624ab5), -176, -34},
+  {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
+  {GRISU_UINT64_C(0xa2425ff7, 5e14fc32), -163, -30},
+  {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+  {GRISU_UINT64_C(0xc6120625, 76589ddb), -150, -26},
+  {GRISU_UINT64_C(0x9abe14cd, 44753b53), -143, -24},
+  {GRISU_UINT64_C(0xf1c90080, baf72cb1), -137, -22},
+  {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+  {GRISU_UINT64_C(0x9392ee8e, 921d5d07), -123, -18},
+  {GRISU_UINT64_C(0xe69594be, c44de15b), -117, -16},
+  {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
+  {GRISU_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
+  {GRISU_UINT64_C(0xdbe6fece, bdedd5bf), -97, -10},
+  {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+  {GRISU_UINT64_C(0x8637bd05, af6c69b6), -83, -6},
+  {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
+  {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+  {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
+  {GRISU_UINT64_C(0xc8000000, 00000000), -57, 2},
+  {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+  {GRISU_UINT64_C(0xf4240000, 00000000), -44, 6},
+  {GRISU_UINT64_C(0xbebc2000, 00000000), -37, 8},
+  {GRISU_UINT64_C(0x9502f900, 00000000), -30, 10},
+  {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+  {GRISU_UINT64_C(0xb5e620f4, 80000000), -17, 14},
+  {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+  {GRISU_UINT64_C(0xde0b6b3a, 76400000), -4, 18},
+  {GRISU_UINT64_C(0xad78ebc5, ac620000), 3, 20},
+  {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+  {GRISU_UINT64_C(0xd3c21bce, cceda100), 16, 24},
+  {GRISU_UINT64_C(0xa56fa5b9, 9019a5c8), 23, 26},
+  {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+  {GRISU_UINT64_C(0xc9f2c9cd, 04674edf), 36, 30},
+  {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+  {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+  {GRISU_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
+  {GRISU_UINT64_C(0x96769950, b50d88f4), 63, 38},
+  {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
+  {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
+  {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
+  {GRISU_UINT64_C(0xe0352f62, a19e306f), 89, 46},
+  {GRISU_UINT64_C(0xaf298d05, 0e4395d7), 96, 48},
+  {GRISU_UINT64_C(0x88d8762b, f324cd10), 103, 50},
+  {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+  {GRISU_UINT64_C(0xa70c3c40, a64e6c52), 116, 54},
+  {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
+  {GRISU_UINT64_C(0xcbea6f8c, eb02bb3a), 129, 58},
+  {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
+  {GRISU_UINT64_C(0xf8ebad2b, 84e0d58c), 142, 62},
+  {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
+  {GRISU_UINT64_C(0x97edd871, cfda3a57), 156, 66},
+  {GRISU_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
+  {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+  {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+  {GRISU_UINT64_C(0xe264589a, 4dcdab15), 182, 74},
+  {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+  {GRISU_UINT64_C(0x8a2dbf14, 2dfcc7ab), 196, 78},
+  {GRISU_UINT64_C(0xd7e77a8f, 87daf7fc), 202, 80},
+  {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+  {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
+  {GRISU_UINT64_C(0xcde6fd5e, 09abcf27), 222, 86},
+  {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+  {GRISU_UINT64_C(0xfb587849, 4ace3a5f), 235, 90},
+  {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+  {GRISU_UINT64_C(0x9968bf6a, bbe85f20), 249, 94},
+  {GRISU_UINT64_C(0xefb3ab16, c59b14a3), 255, 96},
+  {GRISU_UINT64_C(0xbb445da9, ca61281f), 262, 98},
+  {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+  {GRISU_UINT64_C(0xe498f455, c38b997a), 275, 102},
+  {GRISU_UINT64_C(0xb2977ee3, 00c50fe7), 282, 104},
+  {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
+  {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
+  {GRISU_UINT64_C(0xaa51823e, 34a7eedf), 302, 110},
+  {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+  {GRISU_UINT64_C(0xcfe87f7c, ef46ff17), 315, 114},
+  {GRISU_UINT64_C(0xa26da399, 9aef774a), 322, 116},
+  {GRISU_UINT64_C(0xfdcb4fa0, 02162a63), 328, 118},
+  {GRISU_UINT64_C(0xc646d635, 01a1511e), 335, 120},
+  {GRISU_UINT64_C(0x9ae75759, 6946075f), 342, 122},
+  {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+  {GRISU_UINT64_C(0xbd176620, a501fc00), 355, 126},
+  {GRISU_UINT64_C(0x93ba47c9, 80e98ce0), 362, 128},
+  {GRISU_UINT64_C(0xe6d3102a, d96cec1e), 368, 130},
+  {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+  {GRISU_UINT64_C(0x8ce2529e, 2734bb1d), 382, 134},
+  {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
+  {GRISU_UINT64_C(0xabfa45da, 0edbde69), 395, 138},
+  {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+  {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+  {GRISU_UINT64_C(0xa402b9c5, a8d3a6e7), 415, 144},
+  {GRISU_UINT64_C(0x80222122, 6be55a65), 422, 146},
+  {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+  {GRISU_UINT64_C(0x9c69a972, 84b578d8), 435, 150},
+  {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
+  {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+  {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
+  {GRISU_UINT64_C(0xe912b9d1, 478ceb17), 461, 158},
+  {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+  {GRISU_UINT64_C(0x8e41ade9, fbebc27d), 475, 162},
+  {GRISU_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
+  {GRISU_UINT64_C(0xada72ccc, 20054aea), 488, 166},
+  {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
+  {GRISU_UINT64_C(0xd3fa922f, 2d1675f2), 501, 170},
+  {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+  {GRISU_UINT64_C(0x8161afb9, 4b44f57d), 515, 174},
+  {GRISU_UINT64_C(0xca28a291, 859bbf93), 521, 176},
+  {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
+  {GRISU_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
+  {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
+  {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
+  {GRISU_UINT64_C(0xeb57ff22, fc0c795a), 554, 186},
+  {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
+  {GRISU_UINT64_C(0x8fa47579, 1a569d11), 568, 190},
+  {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
+  {GRISU_UINT64_C(0xaf584166, 54a6babb), 581, 194},
+  {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+  {GRISU_UINT64_C(0xd60b3bd5, 6a5586f2), 594, 198},
+  {GRISU_UINT64_C(0xa738c6be, bb12d16d), 601, 200},
+  {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+  {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
+  {GRISU_UINT64_C(0x9f79a169, bd203e41), 621, 206},
+  {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
+  {GRISU_UINT64_C(0xc2abf989, 935ddbfe), 634, 210},
+  {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+  {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
+  {GRISU_UINT64_C(0xb9a74a06, 37ce2ee1), 654, 216},
+  {GRISU_UINT64_C(0x910ab1d4, db9914a0), 661, 218},
+  {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+  {GRISU_UINT64_C(0xb10d8e14, 56105dad), 674, 222},
+  {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
+  {GRISU_UINT64_C(0xd8210bef, d30efa5a), 687, 226},
+  {GRISU_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
+  {GRISU_UINT64_C(0x83ea2b89, 2091e44e), 701, 230},
+  {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+  {GRISU_UINT64_C(0xa1075a24, e4421731), 714, 234},
+  {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
+  {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+  {GRISU_UINT64_C(0x9991a6f3, d6bf1766), 734, 240},
+  {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
+  {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+  {GRISU_UINT64_C(0x92746b9b, e2f8552c), 754, 246},
+  {GRISU_UINT64_C(0xe4d5e823, 92a40515), 760, 248},
+  {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
+  {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+  {GRISU_UINT64_C(0xda3c0f56, 8cc4f3e9), 780, 254},
+  {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
+  {GRISU_UINT64_C(0x8533285c, 936b35df), 794, 258},
+  {GRISU_UINT64_C(0xd01fef10, a657842c), 800, 260},
+  {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+  {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
+  {GRISU_UINT64_C(0xc67bb459, 7ce2ce49), 820, 266},
+  {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+  {GRISU_UINT64_C(0xf24a01a7, 3cf2dcd0), 833, 270},
+  {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
+  {GRISU_UINT64_C(0x93e1ab82, 52f33b46), 847, 274},
+  {GRISU_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
+  {GRISU_UINT64_C(0xb484f9dc, 9641e9db), 860, 278},
+  {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+  {GRISU_UINT64_C(0xdc5c5301, c56b75f7), 873, 282},
+  {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
+  {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+  {GRISU_UINT64_C(0xd226fc19, 5c6a2f8c), 893, 288},
+  {GRISU_UINT64_C(0xa42e74f3, d032f526), 900, 290},
+  {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+  {GRISU_UINT64_C(0xc86ab5c3, 9fa63441), 913, 294},
+  {GRISU_UINT64_C(0x9c935e00, d4b9d8d2), 920, 296},
+  {GRISU_UINT64_C(0xf4a642e1, 4c6262c9), 926, 298},
+  {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
+  {GRISU_UINT64_C(0x95527a52, 02df0ccb), 940, 302},
+  {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+  {GRISU_UINT64_C(0xb6472e51, 1c81471e), 953, 306},
+  {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+  {GRISU_UINT64_C(0xde81e40a, 034bcf50), 966, 310},
+  {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
+  {GRISU_UINT64_C(0x87cec76f, 1c830549), 980, 314},
+  {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+  {GRISU_UINT64_C(0xa5c7ea73, 224deff3), 993, 318},
+  {GRISU_UINT64_C(0x81842f29, f2cce376), 1000, 320},
+  {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+  {GRISU_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
+  {GRISU_UINT64_C(0xf7086715, 3aa2db39), 1019, 326},
+  {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
+  {GRISU_UINT64_C(0x96c6e0ea, b509e64d), 1033, 330},
+  {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+  {GRISU_UINT64_C(0xb80dc58e, 81fe95a1), 1046, 334},
+  {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
+  {GRISU_UINT64_C(0xe0accfa8, 75af45a8), 1059, 338},
+  {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+  {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(2) = 7;
+// nb elements (2): 326
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(3)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0xe0b62e29, 29aba83c), -1077, -305},
+  {GRISU_UINT64_C(0xdb71e914, 32b1a24b), -1067, -302},
+  {GRISU_UINT64_C(0xd64d3d9d, b981787d), -1057, -299},
+  {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
+  {GRISU_UINT64_C(0xcc5fc196, fefd7d0c), -1037, -293},
+  {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
+  {GRISU_UINT64_C(0xc2e801fb, 244576d5), -1017, -287},
+  {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+  {GRISU_UINT64_C(0xb9e08a83, a5e34f08), -997, -281},
+  {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+  {GRISU_UINT64_C(0xb1442798, f49ffb4b), -977, -275},
+  {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+  {GRISU_UINT64_C(0xa90de353, 5aaae202), -957, -269},
+  {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
+  {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
+  {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+  {GRISU_UINT64_C(0x99c10284, 4f94e0fb), -917, -257},
+  {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
+  {GRISU_UINT64_C(0x92a1958a, 7675175f), -897, -251},
+  {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+  {GRISU_UINT64_C(0x8bd6a141, 006042be), -877, -245},
+  {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
+  {GRISU_UINT64_C(0x855c3be0, a17fcd26), -857, -239},
+  {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+  {GRISU_UINT64_C(0xfe5d5415, 0b090b03), -838, -233},
+  {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
+  {GRISU_UINT64_C(0xf294b943, e17a2bc4), -818, -227},
+  {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+  {GRISU_UINT64_C(0xe757dd7e, c07426e5), -798, -221},
+  {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+  {GRISU_UINT64_C(0xdca04777, f541c568), -778, -215},
+  {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+  {GRISU_UINT64_C(0xd267caa8, 62a12d67), -758, -209},
+  {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
+  {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
+  {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+  {GRISU_UINT64_C(0xbf5cd546, 78eef0b7), -718, -197},
+  {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
+  {GRISU_UINT64_C(0xb67f6455, 292cbf08), -698, -191},
+  {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+  {GRISU_UINT64_C(0xae0b158b, 4738705f), -678, -185},
+  {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+  {GRISU_UINT64_C(0xa5fb0a17, c777cf0a), -658, -179},
+  {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+  {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
+  {GRISU_UINT64_C(0x9a94dd3e, 8cf578ba), -628, -170},
+  {GRISU_UINT64_C(0x96f5600f, 15a7b7e5), -618, -167},
+  {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+  {GRISU_UINT64_C(0x8ff71a0f, e2c2e6dc), -598, -161},
+  {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+  {GRISU_UINT64_C(0x894bc396, ce5da772), -578, -155},
+  {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+  {GRISU_UINT64_C(0x82ef8513, 3de648c5), -558, -149},
+  {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
+  {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
+  {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+  {GRISU_UINT64_C(0xee2ba6c0, 678b597f), -519, -137},
+  {GRISU_UINT64_C(0xe896a0d7, e51e1566), -509, -134},
+  {GRISU_UINT64_C(0xe3231912, d5bf60e6), -499, -131},
+  {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+  {GRISU_UINT64_C(0xd89d64d5, 7a607745), -479, -125},
+  {GRISU_UINT64_C(0xd389b478, 79823479), -469, -122},
+  {GRISU_UINT64_C(0xce947a3d, a6a9273e), -459, -119},
+  {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+  {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
+  {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+  {GRISU_UINT64_C(0xbbe226ef, b628afeb), -419, -107},
+  {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+  {GRISU_UINT64_C(0xb32df8e9, f3546564), -399, -101},
+  {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+  {GRISU_UINT64_C(0xaae103b5, fcd2a882), -379, -95},
+  {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+  {GRISU_UINT64_C(0xa2f67f2d, fa90563b), -359, -89},
+  {GRISU_UINT64_C(0x9f24b832, e6b0f436), -349, -86},
+  {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
+  {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+  {GRISU_UINT64_C(0x9436c076, 0c86e30c), -319, -77},
+  {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+  {GRISU_UINT64_C(0x8d590723, 948a535f), -299, -71},
+  {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+  {GRISU_UINT64_C(0x86ccbb52, ea94baeb), -279, -65},
+  {GRISU_UINT64_C(0x83a3eeee, f9153e89), -269, -62},
+  {GRISU_UINT64_C(0x808e1755, 5f3ebf12), -259, -59},
+  {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+  {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
+  {GRISU_UINT64_C(0xef73d256, a5c0f77d), -230, -50},
+  {GRISU_UINT64_C(0xe9d71b68, 9dde71b0), -220, -47},
+  {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+  {GRISU_UINT64_C(0xdf01e85f, 912e37a3), -200, -41},
+  {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+  {GRISU_UINT64_C(0xd4ad2dbf, c3d07788), -180, -35},
+  {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
+  {GRISU_UINT64_C(0xcad2f7f5, 359a3b3e), -160, -29},
+  {GRISU_UINT64_C(0xc6120625, 76589ddb), -150, -26},
+  {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
+  {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+  {GRISU_UINT64_C(0xb877aa32, 36a4b449), -120, -17},
+  {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
+  {GRISU_UINT64_C(0xafebff0b, cb24aaff), -100, -11},
+  {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+  {GRISU_UINT64_C(0xa7c5ac47, 1b478423), -80, -5},
+  {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+  {GRISU_UINT64_C(0xa0000000, 00000000), -60, 1},
+  {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+  {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
+  {GRISU_UINT64_C(0x9502f900, 00000000), -30, 10},
+  {GRISU_UINT64_C(0x9184e72a, 00000000), -20, 13},
+  {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+  {GRISU_UINT64_C(0x8ac72304, 89e80000), 0, 19},
+  {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+  {GRISU_UINT64_C(0x84595161, 401484a0), 20, 25},
+  {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+  {GRISU_UINT64_C(0xfc6f7c40, 45812296), 39, 31},
+  {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+  {GRISU_UINT64_C(0xf0bdc21a, bb48db20), 59, 37},
+  {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
+  {GRISU_UINT64_C(0xe596b7b0, c643c719), 79, 43},
+  {GRISU_UINT64_C(0xe0352f62, a19e306f), 89, 46},
+  {GRISU_UINT64_C(0xdaf3f046, 51d47b4c), 99, 49},
+  {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+  {GRISU_UINT64_C(0xd0cf4b50, cfe20766), 119, 55},
+  {GRISU_UINT64_C(0xcbea6f8c, eb02bb3a), 129, 58},
+  {GRISU_UINT64_C(0xc722f0ef, 9d80aad6), 139, 61},
+  {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
+  {GRISU_UINT64_C(0xbde94e8e, 43d0c8ec), 159, 67},
+  {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+  {GRISU_UINT64_C(0xb51d13ae, a4a488dd), 179, 73},
+  {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+  {GRISU_UINT64_C(0xacb92ed9, 397bf996), 199, 79},
+  {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+  {GRISU_UINT64_C(0xa4b8cab1, a1563f52), 219, 85},
+  {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+  {GRISU_UINT64_C(0x9d174b2d, cec0e47b), 239, 91},
+  {GRISU_UINT64_C(0x9968bf6a, bbe85f20), 249, 94},
+  {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
+  {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+  {GRISU_UINT64_C(0x8edf98b5, 9a373fec), 279, 103},
+  {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
+  {GRISU_UINT64_C(0x884134fe, 908658b2), 299, 109},
+  {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+  {GRISU_UINT64_C(0x81f14fae, 158c5f6e), 319, 115},
+  {GRISU_UINT64_C(0xfdcb4fa0, 02162a63), 328, 118},
+  {GRISU_UINT64_C(0xf7d88bc2, 4209a565), 338, 121},
+  {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+  {GRISU_UINT64_C(0xec5d3fa8, ce427b00), 358, 127},
+  {GRISU_UINT64_C(0xe6d3102a, d96cec1e), 368, 130},
+  {GRISU_UINT64_C(0xe16a1dc9, d8545e95), 378, 133},
+  {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
+  {GRISU_UINT64_C(0xd6f8d750, 9292d603), 398, 139},
+  {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+  {GRISU_UINT64_C(0xcd036837, 130890a1), 418, 145},
+  {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+  {GRISU_UINT64_C(0xc38413cf, 25e2d70e), 438, 151},
+  {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+  {GRISU_UINT64_C(0xba756174, 393d88e0), 458, 157},
+  {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+  {GRISU_UINT64_C(0xb1d21964, 7ae6b31c), 478, 163},
+  {GRISU_UINT64_C(0xada72ccc, 20054aea), 488, 166},
+  {GRISU_UINT64_C(0xa99541bf, 57452b28), 498, 169},
+  {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+  {GRISU_UINT64_C(0xa1ba1ba7, 9e1632dc), 518, 175},
+  {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
+  {GRISU_UINT64_C(0x9a3c2087, a63f6399), 538, 181},
+  {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
+  {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
+  {GRISU_UINT64_C(0x8fa47579, 1a569d11), 568, 190},
+  {GRISU_UINT64_C(0x8c469ab8, 43b89563), 578, 193},
+  {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+  {GRISU_UINT64_C(0x85c70565, 62757457), 598, 199},
+  {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+  {GRISU_UINT64_C(0xff290242, c83396ce), 617, 205},
+  {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
+  {GRISU_UINT64_C(0xf356f7eb, f83552fe), 637, 211},
+  {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
+  {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
+  {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+  {GRISU_UINT64_C(0xdd50f199, 6b947519), 677, 223},
+  {GRISU_UINT64_C(0xd8210bef, d30efa5a), 687, 226},
+  {GRISU_UINT64_C(0xd31045a8, 341ca07c), 697, 229},
+  {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+  {GRISU_UINT64_C(0xc94930ae, 1d529cfd), 717, 235},
+  {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+  {GRISU_UINT64_C(0xbff610b0, cc6edd3f), 737, 241},
+  {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+  {GRISU_UINT64_C(0xb7118682, dbb66a77), 757, 247},
+  {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
+  {GRISU_UINT64_C(0xae9672ab, a3d0c321), 777, 253},
+  {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
+  {GRISU_UINT64_C(0xa67ff273, b8460357), 797, 259},
+  {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+  {GRISU_UINT64_C(0x9ec95d14, 63e8a507), 817, 265},
+  {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+  {GRISU_UINT64_C(0x976e4108, 8617ca02), 837, 271},
+  {GRISU_UINT64_C(0x93e1ab82, 52f33b46), 847, 274},
+  {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
+  {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+  {GRISU_UINT64_C(0x89b9b3e1, 1b6329bb), 877, 283},
+  {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+  {GRISU_UINT64_C(0x83585d8f, d9c25db8), 897, 289},
+  {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+  {GRISU_UINT64_C(0xfa856334, 878fc151), 916, 295},
+  {GRISU_UINT64_C(0xf4a642e1, 4c6262c9), 926, 298},
+  {GRISU_UINT64_C(0xeeea5d50, 04981478), 936, 301},
+  {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+  {GRISU_UINT64_C(0xe3d8f9e5, 63a198e5), 956, 307},
+  {GRISU_UINT64_C(0xde81e40a, 034bcf50), 966, 310},
+  {GRISU_UINT64_C(0xd94ad8b1, c7380874), 976, 313},
+  {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+  {GRISU_UINT64_C(0xcf39e50f, eae16bf0), 996, 319},
+  {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+  {GRISU_UINT64_C(0xc5a05277, 621be294), 1016, 325},
+  {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
+  {GRISU_UINT64_C(0xbc789925, 624c5fe1), 1036, 331},
+  {GRISU_UINT64_C(0xb80dc58e, 81fe95a1), 1046, 334},
+  {GRISU_UINT64_C(0xb3bd72ed, 2af29e20), 1056, 337},
+  {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(3) = 10;
+// nb elements (3): 217
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(4)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0x8c71dcd9, ba0b4926), -1073, -304},
+  {GRISU_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
+  {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
+  {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
+  {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
+  {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+  {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
+  {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
+  {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+  {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+  {GRISU_UINT64_C(0x80fa687f, 881c7f8e), -940, -264},
+  {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+  {GRISU_UINT64_C(0xc0314325, 637a193a), -914, -256},
+  {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
+  {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+  {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
+  {GRISU_UINT64_C(0xd5605fcd, cf32e1d7), -861, -240},
+  {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+  {GRISU_UINT64_C(0x9efa548d, 26e5a6e2), -834, -232},
+  {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+  {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+  {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
+  {GRISU_UINT64_C(0xb080392c, c4349ded), -781, -216},
+  {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+  {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
+  {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
+  {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+  {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+  {GRISU_UINT64_C(0x91ff8377, 5423cc06), -701, -192},
+  {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+  {GRISU_UINT64_C(0xd98ddaee, 19068c76), -675, -184},
+  {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
+  {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+  {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
+  {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+  {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+  {GRISU_UINT64_C(0xb3f4e093, db73a093), -595, -160},
+  {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
+  {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+  {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+  {GRISU_UINT64_C(0xc7caba6e, 7c5382c9), -542, -144},
+  {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+  {GRISU_UINT64_C(0x94db4838, 40b717f0), -515, -136},
+  {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
+  {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+  {GRISU_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
+  {GRISU_UINT64_C(0xa54394fe, 1eedb8ff), -462, -120},
+  {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+  {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
+  {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+  {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+  {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
+  {GRISU_UINT64_C(0x88b402f7, fd75539b), -382, -96},
+  {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+  {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+  {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+  {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+  {GRISU_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
+  {GRISU_UINT64_C(0xe2280b6c, 20dd5232), -303, -72},
+  {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+  {GRISU_UINT64_C(0xa87fea27, a539e9a5), -276, -64},
+  {GRISU_UINT64_C(0xcdb02555, 653131b6), -263, -60},
+  {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+  {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
+  {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+  {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+  {GRISU_UINT64_C(0x8b61313b, babce2c6), -196, -40},
+  {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
+  {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
+  {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+  {GRISU_UINT64_C(0x9abe14cd, 44753b53), -143, -24},
+  {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+  {GRISU_UINT64_C(0xe69594be, c44de15b), -117, -16},
+  {GRISU_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
+  {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+  {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
+  {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
+  {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+  {GRISU_UINT64_C(0xbebc2000, 00000000), -37, 8},
+  {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+  {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+  {GRISU_UINT64_C(0xad78ebc5, ac620000), 3, 20},
+  {GRISU_UINT64_C(0xd3c21bce, cceda100), 16, 24},
+  {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+  {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+  {GRISU_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
+  {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
+  {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
+  {GRISU_UINT64_C(0xaf298d05, 0e4395d7), 96, 48},
+  {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+  {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
+  {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
+  {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
+  {GRISU_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
+  {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+  {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+  {GRISU_UINT64_C(0xd7e77a8f, 87daf7fc), 202, 80},
+  {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
+  {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+  {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+  {GRISU_UINT64_C(0xefb3ab16, c59b14a3), 255, 96},
+  {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+  {GRISU_UINT64_C(0xb2977ee3, 00c50fe7), 282, 104},
+  {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
+  {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+  {GRISU_UINT64_C(0xa26da399, 9aef774a), 322, 116},
+  {GRISU_UINT64_C(0xc646d635, 01a1511e), 335, 120},
+  {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+  {GRISU_UINT64_C(0x93ba47c9, 80e98ce0), 362, 128},
+  {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+  {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
+  {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+  {GRISU_UINT64_C(0xa402b9c5, a8d3a6e7), 415, 144},
+  {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+  {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
+  {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
+  {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+  {GRISU_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
+  {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
+  {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+  {GRISU_UINT64_C(0xca28a291, 859bbf93), 521, 176},
+  {GRISU_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
+  {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
+  {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
+  {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
+  {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+  {GRISU_UINT64_C(0xa738c6be, bb12d16d), 601, 200},
+  {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
+  {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
+  {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+  {GRISU_UINT64_C(0xb9a74a06, 37ce2ee1), 654, 216},
+  {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+  {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
+  {GRISU_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
+  {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+  {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
+  {GRISU_UINT64_C(0x9991a6f3, d6bf1766), 734, 240},
+  {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+  {GRISU_UINT64_C(0xe4d5e823, 92a40515), 760, 248},
+  {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+  {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
+  {GRISU_UINT64_C(0xd01fef10, a657842c), 800, 260},
+  {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
+  {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+  {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
+  {GRISU_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
+  {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+  {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
+  {GRISU_UINT64_C(0xd226fc19, 5c6a2f8c), 893, 288},
+  {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+  {GRISU_UINT64_C(0x9c935e00, d4b9d8d2), 920, 296},
+  {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
+  {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+  {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+  {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
+  {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+  {GRISU_UINT64_C(0x81842f29, f2cce376), 1000, 320},
+  {GRISU_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
+  {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
+  {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+  {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
+  {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(4) = 14;
+// nb elements (4): 163
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(5)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0xaf8e5410, 288e1b6f), -1070, -303},
+  {GRISU_UINT64_C(0x85f04682, 93f0eb4e), -1053, -298},
+  {GRISU_UINT64_C(0xcc5fc196, fefd7d0c), -1037, -293},
+  {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
+  {GRISU_UINT64_C(0xedec366b, 11c6cb8f), -1004, -283},
+  {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+  {GRISU_UINT64_C(0x8a7d3eef, 7f1cfc52), -970, -273},
+  {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+  {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
+  {GRISU_UINT64_C(0xf6019da0, 7f549b2b), -921, -258},
+  {GRISU_UINT64_C(0xbbb01b92, 83253ca3), -904, -253},
+  {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+  {GRISU_UINT64_C(0xda7f5bf5, 90966849), -871, -243},
+  {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
+  {GRISU_UINT64_C(0xfe5d5415, 0b090b03), -838, -233},
+  {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+  {GRISU_UINT64_C(0x940f4613, ae5ed137), -804, -223},
+  {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+  {GRISU_UINT64_C(0xac5d37d5, b79b6239), -771, -213},
+  {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
+  {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
+  {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
+  {GRISU_UINT64_C(0xe998d258, 869facd7), -705, -193},
+  {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+  {GRISU_UINT64_C(0x87f8a8d4, cfa417ca), -671, -183},
+  {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
+  {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
+  {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+  {GRISU_UINT64_C(0xb84687c2, 69ef3bfb), -605, -163},
+  {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+  {GRISU_UINT64_C(0xd686619b, a27255a3), -572, -153},
+  {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+  {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
+  {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
+  {GRISU_UINT64_C(0x915e2486, ef32cd60), -505, -133},
+  {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+  {GRISU_UINT64_C(0xa93af6c6, c79b5d2e), -472, -123},
+  {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
+  {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
+  {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+  {GRISU_UINT64_C(0xe5599087, 9ddcaabe), -406, -103},
+  {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+  {GRISU_UINT64_C(0x857fcae6, 2d8493a5), -372, -93},
+  {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+  {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
+  {GRISU_UINT64_C(0xed246723, 473e3813), -323, -78},
+  {GRISU_UINT64_C(0xb4ecd5f0, 1a4aa828), -306, -73},
+  {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+  {GRISU_UINT64_C(0xd29fe4b1, 8e88640f), -273, -63},
+  {GRISU_UINT64_C(0xa0b19d2a, b70e6ed6), -256, -58},
+  {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
+  {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+  {GRISU_UINT64_C(0x8eb98a7a, 9a5b04e3), -206, -43},
+  {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+  {GRISU_UINT64_C(0xa6274bbd, d0fadd62), -173, -33},
+  {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+  {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
+  {GRISU_UINT64_C(0x9392ee8e, 921d5d07), -123, -18},
+  {GRISU_UINT64_C(0xe12e1342, 4bb40e13), -107, -13},
+  {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+  {GRISU_UINT64_C(0x83126e97, 8d4fdf3b), -73, -3},
+  {GRISU_UINT64_C(0xc8000000, 00000000), -57, 2},
+  {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
+  {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+  {GRISU_UINT64_C(0xb1a2bc2e, c5000000), -7, 17},
+  {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+  {GRISU_UINT64_C(0xcecb8f27, f4200f3a), 26, 27},
+  {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+  {GRISU_UINT64_C(0xf0bdc21a, bb48db20), 59, 37},
+  {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
+  {GRISU_UINT64_C(0x8c213d9d, a502de45), 93, 47},
+  {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+  {GRISU_UINT64_C(0xa321f2d7, 226895c8), 126, 57},
+  {GRISU_UINT64_C(0xf8ebad2b, 84e0d58c), 142, 62},
+  {GRISU_UINT64_C(0xbde94e8e, 43d0c8ec), 159, 67},
+  {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+  {GRISU_UINT64_C(0xdd15fe86, affad912), 192, 77},
+  {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+  {GRISU_UINT64_C(0x80b05e5a, c60b6178), 226, 87},
+  {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+  {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
+  {GRISU_UINT64_C(0xe498f455, c38b997a), 275, 102},
+  {GRISU_UINT64_C(0xae67f1e9, aec07188), 292, 107},
+  {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+  {GRISU_UINT64_C(0xcb090c80, 01ab551c), 325, 117},
+  {GRISU_UINT64_C(0x9ae75759, 6946075f), 342, 122},
+  {GRISU_UINT64_C(0xec5d3fa8, ce427b00), 358, 127},
+  {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+  {GRISU_UINT64_C(0x899504ae, 72497eba), 392, 137},
+  {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+  {GRISU_UINT64_C(0xa02aa96b, 06deb0fe), 425, 147},
+  {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
+  {GRISU_UINT64_C(0xba756174, 393d88e0), 458, 157},
+  {GRISU_UINT64_C(0x8e41ade9, fbebc27d), 475, 162},
+  {GRISU_UINT64_C(0xd910f7ff, 28069da4), 491, 167},
+  {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+  {GRISU_UINT64_C(0xfcb2cb35, e702af78), 524, 177},
+  {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
+  {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
+  {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
+  {GRISU_UINT64_C(0xab3c2fdd, eeaad25b), 591, 197},
+  {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+  {GRISU_UINT64_C(0xc75809c4, 2c684dd1), 624, 207},
+  {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+  {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
+  {GRISU_UINT64_C(0xb10d8e14, 56105dad), 674, 222},
+  {GRISU_UINT64_C(0x8714a775, e3e95c78), 691, 227},
+  {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+  {GRISU_UINT64_C(0x9d412e08, 06e88aa6), 724, 237},
+  {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
+  {GRISU_UINT64_C(0xb7118682, dbb66a77), 757, 247},
+  {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+  {GRISU_UINT64_C(0xd51ea6fa, 85785631), 790, 257},
+  {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+  {GRISU_UINT64_C(0xf81aa16f, dc1b81db), 823, 267},
+  {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
+  {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
+  {GRISU_UINT64_C(0xdc5c5301, c56b75f7), 873, 282},
+  {GRISU_UINT64_C(0xa81f3014, 49ee8c70), 890, 287},
+  {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+  {GRISU_UINT64_C(0xc3b83581, 09e84f07), 923, 297},
+  {GRISU_UINT64_C(0x95527a52, 02df0ccb), 940, 302},
+  {GRISU_UINT64_C(0xe3d8f9e5, 63a198e5), 956, 307},
+  {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
+  {GRISU_UINT64_C(0x849feec2, 81d7f329), 990, 317},
+  {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+  {GRISU_UINT64_C(0x9a65406d, 44a5c903), 1023, 327},
+  {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+  {GRISU_UINT64_C(0xb3bd72ed, 2af29e20), 1056, 337},
+  {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(5) = 17;
+// nb elements (5): 131
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(6)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0xdb71e914, 32b1a24b), -1067, -302},
+  {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
+  {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
+  {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+  {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+  {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+  {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
+  {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+  {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
+  {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+  {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
+  {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+  {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
+  {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+  {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+  {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+  {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
+  {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+  {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
+  {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+  {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+  {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+  {GRISU_UINT64_C(0x9a94dd3e, 8cf578ba), -628, -170},
+  {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+  {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+  {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+  {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
+  {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+  {GRISU_UINT64_C(0xe896a0d7, e51e1566), -509, -134},
+  {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+  {GRISU_UINT64_C(0xd389b478, 79823479), -469, -122},
+  {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+  {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+  {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+  {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+  {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+  {GRISU_UINT64_C(0x9f24b832, e6b0f436), -349, -86},
+  {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+  {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+  {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+  {GRISU_UINT64_C(0x83a3eeee, f9153e89), -269, -62},
+  {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+  {GRISU_UINT64_C(0xef73d256, a5c0f77d), -230, -50},
+  {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+  {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+  {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
+  {GRISU_UINT64_C(0xc6120625, 76589ddb), -150, -26},
+  {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+  {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
+  {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+  {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+  {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+  {GRISU_UINT64_C(0x9502f900, 00000000), -30, 10},
+  {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+  {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+  {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+  {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+  {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
+  {GRISU_UINT64_C(0xe0352f62, a19e306f), 89, 46},
+  {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+  {GRISU_UINT64_C(0xcbea6f8c, eb02bb3a), 129, 58},
+  {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
+  {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+  {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+  {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+  {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+  {GRISU_UINT64_C(0x9968bf6a, bbe85f20), 249, 94},
+  {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+  {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
+  {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+  {GRISU_UINT64_C(0xfdcb4fa0, 02162a63), 328, 118},
+  {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+  {GRISU_UINT64_C(0xe6d3102a, d96cec1e), 368, 130},
+  {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
+  {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+  {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+  {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+  {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+  {GRISU_UINT64_C(0xada72ccc, 20054aea), 488, 166},
+  {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+  {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
+  {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
+  {GRISU_UINT64_C(0x8fa47579, 1a569d11), 568, 190},
+  {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+  {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+  {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
+  {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
+  {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+  {GRISU_UINT64_C(0xd8210bef, d30efa5a), 687, 226},
+  {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+  {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+  {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+  {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
+  {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
+  {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+  {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+  {GRISU_UINT64_C(0x93e1ab82, 52f33b46), 847, 274},
+  {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+  {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+  {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+  {GRISU_UINT64_C(0xf4a642e1, 4c6262c9), 926, 298},
+  {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+  {GRISU_UINT64_C(0xde81e40a, 034bcf50), 966, 310},
+  {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+  {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+  {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
+  {GRISU_UINT64_C(0xb80dc58e, 81fe95a1), 1046, 334},
+  {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(6) = 20;
+// nb elements (6): 109
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(7)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0x892731ac, 9faf056f), -1063, -301},
+  {GRISU_UINT64_C(0xa37fce12, 6597973d), -1040, -294},
+  {GRISU_UINT64_C(0xc2e801fb, 244576d5), -1017, -287},
+  {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
+  {GRISU_UINT64_C(0x8a7d3eef, 7f1cfc52), -970, -273},
+  {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
+  {GRISU_UINT64_C(0xc4ce17b3, 99107c23), -924, -259},
+  {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
+  {GRISU_UINT64_C(0x8bd6a141, 006042be), -877, -245},
+  {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
+  {GRISU_UINT64_C(0xc6b8e9b0, 709f109a), -831, -231},
+  {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+  {GRISU_UINT64_C(0x8d3360f0, 9cf6e4bd), -784, -217},
+  {GRISU_UINT64_C(0xa8530886, b54dbdec), -761, -210},
+  {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
+  {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+  {GRISU_UINT64_C(0x8e938662, 882af53e), -691, -189},
+  {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+  {GRISU_UINT64_C(0xca9cf1d2, 06fdc03c), -645, -175},
+  {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+  {GRISU_UINT64_C(0x8ff71a0f, e2c2e6dc), -598, -161},
+  {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
+  {GRISU_UINT64_C(0xcc963fee, 10b7d1b3), -552, -147},
+  {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+  {GRISU_UINT64_C(0x915e2486, ef32cd60), -505, -133},
+  {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
+  {GRISU_UINT64_C(0xce947a3d, a6a9273e), -459, -119},
+  {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
+  {GRISU_UINT64_C(0x92c8ae6b, 464fc96f), -412, -105},
+  {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+  {GRISU_UINT64_C(0xd097ad07, a71f26b2), -366, -91},
+  {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+  {GRISU_UINT64_C(0x9436c076, 0c86e30c), -319, -77},
+  {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
+  {GRISU_UINT64_C(0xd29fe4b1, 8e88640f), -273, -63},
+  {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+  {GRISU_UINT64_C(0x95a86376, 27989aae), -226, -49},
+  {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
+  {GRISU_UINT64_C(0xd4ad2dbf, c3d07788), -180, -35},
+  {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+  {GRISU_UINT64_C(0x971da050, 74da7bef), -133, -21},
+  {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
+  {GRISU_UINT64_C(0xd6bf94d5, e57a42bc), -87, -7},
+  {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
+  {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
+  {GRISU_UINT64_C(0xb5e620f4, 80000000), -17, 14},
+  {GRISU_UINT64_C(0xd8d726b7, 177a8000), 6, 21},
+  {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+  {GRISU_UINT64_C(0x9a130b96, 3a6c115c), 53, 35},
+  {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
+  {GRISU_UINT64_C(0xdaf3f046, 51d47b4c), 99, 49},
+  {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
+  {GRISU_UINT64_C(0x9b934c3b, 330c8577), 146, 63},
+  {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+  {GRISU_UINT64_C(0xdd15fe86, affad912), 192, 77},
+  {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
+  {GRISU_UINT64_C(0x9d174b2d, cec0e47b), 239, 91},
+  {GRISU_UINT64_C(0xbb445da9, ca61281f), 262, 98},
+  {GRISU_UINT64_C(0xdf3d5e9b, c0f653e1), 285, 105},
+  {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+  {GRISU_UINT64_C(0x9e9f11c4, 014dda7e), 332, 119},
+  {GRISU_UINT64_C(0xbd176620, a501fc00), 355, 126},
+  {GRISU_UINT64_C(0xe16a1dc9, d8545e95), 378, 133},
+  {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+  {GRISU_UINT64_C(0xa02aa96b, 06deb0fe), 425, 147},
+  {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+  {GRISU_UINT64_C(0xe39c4976, 5fdf9d95), 471, 161},
+  {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
+  {GRISU_UINT64_C(0xa1ba1ba7, 9e1632dc), 518, 175},
+  {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
+  {GRISU_UINT64_C(0xe5d3ef28, 2a242e82), 564, 189},
+  {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+  {GRISU_UINT64_C(0xa34d7216, 42b06084), 611, 203},
+  {GRISU_UINT64_C(0xc2abf989, 935ddbfe), 634, 210},
+  {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
+  {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
+  {GRISU_UINT64_C(0xa4e4b66b, 68b65d61), 704, 231},
+  {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+  {GRISU_UINT64_C(0xea53df5f, d18d5514), 750, 245},
+  {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+  {GRISU_UINT64_C(0xa67ff273, b8460357), 797, 259},
+  {GRISU_UINT64_C(0xc67bb459, 7ce2ce49), 820, 266},
+  {GRISU_UINT64_C(0xec9c459d, 51852ba3), 843, 273},
+  {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+  {GRISU_UINT64_C(0xa81f3014, 49ee8c70), 890, 287},
+  {GRISU_UINT64_C(0xc86ab5c3, 9fa63441), 913, 294},
+  {GRISU_UINT64_C(0xeeea5d50, 04981478), 936, 301},
+  {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+  {GRISU_UINT64_C(0xa9c2794a, e3a3c69b), 983, 315},
+  {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+  {GRISU_UINT64_C(0xf13e34aa, bb430a15), 1029, 329},
+  {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(7) = 24;
+// nb elements (7): 93
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(8)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
+  {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
+  {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+  {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
+  {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+  {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+  {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
+  {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
+  {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+  {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+  {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
+  {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+  {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
+  {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+  {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+  {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
+  {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
+  {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+  {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
+  {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+  {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+  {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
+  {GRISU_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
+  {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+  {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+  {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
+  {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+  {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+  {GRISU_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
+  {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+  {GRISU_UINT64_C(0xcdb02555, 653131b6), -263, -60},
+  {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
+  {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+  {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
+  {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+  {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+  {GRISU_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
+  {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
+  {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+  {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+  {GRISU_UINT64_C(0xad78ebc5, ac620000), 3, 20},
+  {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+  {GRISU_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
+  {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
+  {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+  {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
+  {GRISU_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
+  {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+  {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
+  {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+  {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+  {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
+  {GRISU_UINT64_C(0xa26da399, 9aef774a), 322, 116},
+  {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+  {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+  {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+  {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+  {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
+  {GRISU_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
+  {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+  {GRISU_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
+  {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
+  {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+  {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
+  {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+  {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+  {GRISU_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
+  {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
+  {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+  {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+  {GRISU_UINT64_C(0xd01fef10, a657842c), 800, 260},
+  {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+  {GRISU_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
+  {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
+  {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+  {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
+  {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+  {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+  {GRISU_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
+  {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+  {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(8) = 27;
+// nb elements (8): 82
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(9)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0xd64d3d9d, b981787d), -1057, -299},
+  {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
+  {GRISU_UINT64_C(0xb9e08a83, a5e34f08), -997, -281},
+  {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+  {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
+  {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
+  {GRISU_UINT64_C(0x8bd6a141, 006042be), -877, -245},
+  {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+  {GRISU_UINT64_C(0xf294b943, e17a2bc4), -818, -227},
+  {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+  {GRISU_UINT64_C(0xd267caa8, 62a12d67), -758, -209},
+  {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+  {GRISU_UINT64_C(0xb67f6455, 292cbf08), -698, -191},
+  {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+  {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
+  {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+  {GRISU_UINT64_C(0x894bc396, ce5da772), -578, -155},
+  {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
+  {GRISU_UINT64_C(0xee2ba6c0, 678b597f), -519, -137},
+  {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+  {GRISU_UINT64_C(0xce947a3d, a6a9273e), -459, -119},
+  {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+  {GRISU_UINT64_C(0xb32df8e9, f3546564), -399, -101},
+  {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+  {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
+  {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+  {GRISU_UINT64_C(0x86ccbb52, ea94baeb), -279, -65},
+  {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+  {GRISU_UINT64_C(0xe9d71b68, 9dde71b0), -220, -47},
+  {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+  {GRISU_UINT64_C(0xcad2f7f5, 359a3b3e), -160, -29},
+  {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+  {GRISU_UINT64_C(0xafebff0b, cb24aaff), -100, -11},
+  {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+  {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
+  {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+  {GRISU_UINT64_C(0x84595161, 401484a0), 20, 25},
+  {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+  {GRISU_UINT64_C(0xe596b7b0, c643c719), 79, 43},
+  {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+  {GRISU_UINT64_C(0xc722f0ef, 9d80aad6), 139, 61},
+  {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+  {GRISU_UINT64_C(0xacb92ed9, 397bf996), 199, 79},
+  {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+  {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
+  {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
+  {GRISU_UINT64_C(0x81f14fae, 158c5f6e), 319, 115},
+  {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+  {GRISU_UINT64_C(0xe16a1dc9, d8545e95), 378, 133},
+  {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+  {GRISU_UINT64_C(0xc38413cf, 25e2d70e), 438, 151},
+  {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+  {GRISU_UINT64_C(0xa99541bf, 57452b28), 498, 169},
+  {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
+  {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
+  {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+  {GRISU_UINT64_C(0xff290242, c83396ce), 617, 205},
+  {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
+  {GRISU_UINT64_C(0xdd50f199, 6b947519), 677, 223},
+  {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+  {GRISU_UINT64_C(0xbff610b0, cc6edd3f), 737, 241},
+  {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
+  {GRISU_UINT64_C(0xa67ff273, b8460357), 797, 259},
+  {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+  {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
+  {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+  {GRISU_UINT64_C(0xfa856334, 878fc151), 916, 295},
+  {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+  {GRISU_UINT64_C(0xd94ad8b1, c7380874), 976, 313},
+  {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+  {GRISU_UINT64_C(0xbc789925, 624c5fe1), 1036, 331},
+  {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(9) = 30;
+// nb elements (9): 73
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(10)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0x85f04682, 93f0eb4e), -1053, -298},
+  {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
+  {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+  {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+  {GRISU_UINT64_C(0xf6019da0, 7f549b2b), -921, -258},
+  {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+  {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
+  {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+  {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+  {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
+  {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
+  {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+  {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
+  {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+  {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+  {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+  {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
+  {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+  {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
+  {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+  {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+  {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+  {GRISU_UINT64_C(0xed246723, 473e3813), -323, -78},
+  {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+  {GRISU_UINT64_C(0xa0b19d2a, b70e6ed6), -256, -58},
+  {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+  {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+  {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+  {GRISU_UINT64_C(0x9392ee8e, 921d5d07), -123, -18},
+  {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+  {GRISU_UINT64_C(0xc8000000, 00000000), -57, 2},
+  {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+  {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+  {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+  {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
+  {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+  {GRISU_UINT64_C(0xf8ebad2b, 84e0d58c), 142, 62},
+  {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+  {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+  {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+  {GRISU_UINT64_C(0xe498f455, c38b997a), 275, 102},
+  {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+  {GRISU_UINT64_C(0x9ae75759, 6946075f), 342, 122},
+  {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+  {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+  {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
+  {GRISU_UINT64_C(0x8e41ade9, fbebc27d), 475, 162},
+  {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+  {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
+  {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
+  {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+  {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+  {GRISU_UINT64_C(0xb10d8e14, 56105dad), 674, 222},
+  {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+  {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
+  {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+  {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+  {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
+  {GRISU_UINT64_C(0xdc5c5301, c56b75f7), 873, 282},
+  {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+  {GRISU_UINT64_C(0x95527a52, 02df0ccb), 940, 302},
+  {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
+  {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+  {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+  {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(10) = 34;
+// nb elements (10): 66
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(11)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0xa76c5823, 38ed2622), -1050, -297},
+  {GRISU_UINT64_C(0xf3a20279, ed56d48a), -1014, -286},
+  {GRISU_UINT64_C(0xb1442798, f49ffb4b), -977, -275},
+  {GRISU_UINT64_C(0x80fa687f, 881c7f8e), -940, -264},
+  {GRISU_UINT64_C(0xbbb01b92, 83253ca3), -904, -253},
+  {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
+  {GRISU_UINT64_C(0xc6b8e9b0, 709f109a), -831, -231},
+  {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
+  {GRISU_UINT64_C(0xd267caa8, 62a12d67), -758, -209},
+  {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
+  {GRISU_UINT64_C(0xdec681f9, f4c31f31), -685, -187},
+  {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+  {GRISU_UINT64_C(0xebdf6617, 91d60f56), -612, -165},
+  {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
+  {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
+  {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
+  {GRISU_UINT64_C(0x843610cb, 4bf160cc), -465, -121},
+  {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+  {GRISU_UINT64_C(0x8bfbea76, c619ef36), -392, -99},
+  {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+  {GRISU_UINT64_C(0x9436c076, 0c86e30c), -319, -77},
+  {GRISU_UINT64_C(0xd7adf884, aa879177), -283, -66},
+  {GRISU_UINT64_C(0x9ced737b, b6c4183d), -246, -55},
+  {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+  {GRISU_UINT64_C(0xa6274bbd, d0fadd62), -173, -33},
+  {GRISU_UINT64_C(0xf1c90080, baf72cb1), -137, -22},
+  {GRISU_UINT64_C(0xafebff0b, cb24aaff), -100, -11},
+  {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
+  {GRISU_UINT64_C(0xba43b740, 00000000), -27, 11},
+  {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+  {GRISU_UINT64_C(0xc5371912, 364ce305), 46, 33},
+  {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
+  {GRISU_UINT64_C(0xd0cf4b50, cfe20766), 119, 55},
+  {GRISU_UINT64_C(0x97edd871, cfda3a57), 156, 66},
+  {GRISU_UINT64_C(0xdd15fe86, affad912), 192, 77},
+  {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+  {GRISU_UINT64_C(0xea157514, 3cf97227), 265, 99},
+  {GRISU_UINT64_C(0xaa51823e, 34a7eedf), 302, 110},
+  {GRISU_UINT64_C(0xf7d88bc2, 4209a565), 338, 121},
+  {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+  {GRISU_UINT64_C(0x8335616a, ed761f1f), 412, 143},
+  {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+  {GRISU_UINT64_C(0x8aec23d6, 80043bee), 485, 165},
+  {GRISU_UINT64_C(0xca28a291, 859bbf93), 521, 176},
+  {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
+  {GRISU_UINT64_C(0xd60b3bd5, 6a5586f2), 594, 198},
+  {GRISU_UINT64_C(0x9bbcc7a1, 42b17ccc), 631, 209},
+  {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+  {GRISU_UINT64_C(0xa4e4b66b, 68b65d61), 704, 231},
+  {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
+  {GRISU_UINT64_C(0xae9672ab, a3d0c321), 777, 253},
+  {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
+  {GRISU_UINT64_C(0xb8da1662, e7b00a17), 850, 275},
+  {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+  {GRISU_UINT64_C(0xc3b83581, 09e84f07), 923, 297},
+  {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+  {GRISU_UINT64_C(0xcf39e50f, eae16bf0), 996, 319},
+  {GRISU_UINT64_C(0x96c6e0ea, b509e64d), 1033, 330},
+  {GRISU_UINT64_C(0xdb68c2ca, 82ed2a06), 1069, 341},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(11) = 37;
+// nb elements (11): 60
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(12)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
+  {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+  {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+  {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+  {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+  {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+  {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+  {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+  {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+  {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+  {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+  {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+  {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+  {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+  {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+  {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+  {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+  {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+  {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+  {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+  {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+  {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+  {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
+  {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+  {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+  {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+  {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+  {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+  {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
+  {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+  {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
+  {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+  {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+  {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+  {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+  {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+  {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
+  {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+  {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+  {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+  {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
+  {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+  {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
+  {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+  {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+  {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+  {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
+  {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+  {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+  {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+  {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+  {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+  {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
+  {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(12) = 40;
+// nb elements (12): 55
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(13)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0x82cca4db, 847945ca), -1043, -295},
+  {GRISU_UINT64_C(0x94b3a202, eb1c3f39), -1000, -282},
+  {GRISU_UINT64_C(0xa90de353, 5aaae202), -957, -269},
+  {GRISU_UINT64_C(0xc0314325, 637a193a), -914, -256},
+  {GRISU_UINT64_C(0xda7f5bf5, 90966849), -871, -243},
+  {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
+  {GRISU_UINT64_C(0x8d3360f0, 9cf6e4bd), -784, -217},
+  {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
+  {GRISU_UINT64_C(0xb67f6455, 292cbf08), -698, -191},
+  {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
+  {GRISU_UINT64_C(0xebdf6617, 91d60f56), -612, -165},
+  {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+  {GRISU_UINT64_C(0x986ddb5c, 6b3a76b8), -525, -139},
+  {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
+  {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
+  {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
+  {GRISU_UINT64_C(0xfea126b7, d78186bd), -353, -87},
+  {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+  {GRISU_UINT64_C(0xa48ceaaa, b75a8e2b), -266, -61},
+  {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+  {GRISU_UINT64_C(0xd4ad2dbf, c3d07788), -180, -35},
+  {GRISU_UINT64_C(0xf1c90080, baf72cb1), -137, -22},
+  {GRISU_UINT64_C(0x89705f41, 36b4a597), -93, -9},
+  {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+  {GRISU_UINT64_C(0xb1a2bc2e, c5000000), -7, 17},
+  {GRISU_UINT64_C(0xc9f2c9cd, 04674edf), 36, 30},
+  {GRISU_UINT64_C(0xe596b7b0, c643c719), 79, 43},
+  {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
+  {GRISU_UINT64_C(0x945e455f, 24fb1cf9), 166, 69},
+  {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+  {GRISU_UINT64_C(0xbfc2ef45, 6ae276e9), 252, 95},
+  {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
+  {GRISU_UINT64_C(0xf7d88bc2, 4209a565), 338, 121},
+  {GRISU_UINT64_C(0x8ce2529e, 2734bb1d), 382, 134},
+  {GRISU_UINT64_C(0xa02aa96b, 06deb0fe), 425, 147},
+  {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+  {GRISU_UINT64_C(0xcf02b2c2, 1207ef2f), 511, 173},
+  {GRISU_UINT64_C(0xeb57ff22, fc0c795a), 554, 186},
+  {GRISU_UINT64_C(0x85c70565, 62757457), 598, 199},
+  {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+  {GRISU_UINT64_C(0xace73cbf, dc0bfb7b), 684, 225},
+  {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+  {GRISU_UINT64_C(0xdf78e4b2, bd342cf7), 770, 251},
+  {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
+  {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
+  {GRISU_UINT64_C(0xa42e74f3, d032f526), 900, 290},
+  {GRISU_UINT64_C(0xbaa718e6, 8396cffe), 943, 303},
+  {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+  {GRISU_UINT64_C(0xf13e34aa, bb430a15), 1029, 329},
+  {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(13) = 44;
+// nb elements (13): 51
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(14)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0xa37fce12, 6597973d), -1040, -294},
+  {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
+  {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
+  {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
+  {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
+  {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+  {GRISU_UINT64_C(0xa8530886, b54dbdec), -761, -210},
+  {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+  {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+  {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+  {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
+  {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+  {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
+  {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
+  {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+  {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+  {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
+  {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+  {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
+  {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+  {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
+  {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
+  {GRISU_UINT64_C(0xb5e620f4, 80000000), -17, 14},
+  {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+  {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
+  {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
+  {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+  {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
+  {GRISU_UINT64_C(0xbb445da9, ca61281f), 262, 98},
+  {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+  {GRISU_UINT64_C(0xbd176620, a501fc00), 355, 126},
+  {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+  {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+  {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
+  {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
+  {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+  {GRISU_UINT64_C(0xc2abf989, 935ddbfe), 634, 210},
+  {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
+  {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+  {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+  {GRISU_UINT64_C(0xc67bb459, 7ce2ce49), 820, 266},
+  {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+  {GRISU_UINT64_C(0xc86ab5c3, 9fa63441), 913, 294},
+  {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+  {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+  {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(14) = 47;
+// nb elements (14): 47
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(15)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0xcc5fc196, fefd7d0c), -1037, -293},
+  {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+  {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
+  {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+  {GRISU_UINT64_C(0xfe5d5415, 0b090b03), -838, -233},
+  {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+  {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
+  {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+  {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
+  {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+  {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
+  {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+  {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
+  {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+  {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
+  {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+  {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
+  {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+  {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
+  {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+  {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
+  {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+  {GRISU_UINT64_C(0xf0bdc21a, bb48db20), 59, 37},
+  {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+  {GRISU_UINT64_C(0xbde94e8e, 43d0c8ec), 159, 67},
+  {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+  {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
+  {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+  {GRISU_UINT64_C(0xec5d3fa8, ce427b00), 358, 127},
+  {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+  {GRISU_UINT64_C(0xba756174, 393d88e0), 458, 157},
+  {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+  {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
+  {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+  {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
+  {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+  {GRISU_UINT64_C(0xb7118682, dbb66a77), 757, 247},
+  {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+  {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
+  {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+  {GRISU_UINT64_C(0xe3d8f9e5, 63a198e5), 956, 307},
+  {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+  {GRISU_UINT64_C(0xb3bd72ed, 2af29e20), 1056, 337},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(15) = 50;
+// nb elements (15): 44
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(16)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
+  {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
+  {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+  {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
+  {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+  {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+  {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+  {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
+  {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+  {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+  {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
+  {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+  {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
+  {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+  {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+  {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
+  {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
+  {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+  {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
+  {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+  {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+  {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
+  {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
+  {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+  {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+  {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
+  {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+  {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+  {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
+  {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+  {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
+  {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
+  {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+  {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
+  {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+  {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+  {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
+  {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
+  {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+  {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(16) = 54;
+// nb elements (16): 41
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(17)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0x9faacf3d, f73609b1), -1030, -291},
+  {GRISU_UINT64_C(0xdd95317f, 31c7fa1d), -974, -274},
+  {GRISU_UINT64_C(0x99c10284, 4f94e0fb), -917, -257},
+  {GRISU_UINT64_C(0xd5605fcd, cf32e1d7), -861, -240},
+  {GRISU_UINT64_C(0x940f4613, ae5ed137), -804, -223},
+  {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
+  {GRISU_UINT64_C(0x8e938662, 882af53e), -691, -189},
+  {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
+  {GRISU_UINT64_C(0x894bc396, ce5da772), -578, -155},
+  {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
+  {GRISU_UINT64_C(0x843610cb, 4bf160cc), -465, -121},
+  {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+  {GRISU_UINT64_C(0xfea126b7, d78186bd), -353, -87},
+  {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
+  {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
+  {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
+  {GRISU_UINT64_C(0xec1e4a7d, b69561a5), -127, -19},
+  {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+  {GRISU_UINT64_C(0xe35fa931, a0000000), -14, 15},
+  {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+  {GRISU_UINT64_C(0xdaf3f046, 51d47b4c), 99, 49},
+  {GRISU_UINT64_C(0x97edd871, cfda3a57), 156, 66},
+  {GRISU_UINT64_C(0xd2d80db0, 2aabd62c), 212, 83},
+  {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+  {GRISU_UINT64_C(0xcb090c80, 01ab551c), 325, 117},
+  {GRISU_UINT64_C(0x8ce2529e, 2734bb1d), 382, 134},
+  {GRISU_UINT64_C(0xc38413cf, 25e2d70e), 438, 151},
+  {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
+  {GRISU_UINT64_C(0xbc4665b5, 96706115), 551, 185},
+  {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+  {GRISU_UINT64_C(0xb54d5e4a, 127f59c8), 664, 219},
+  {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
+  {GRISU_UINT64_C(0xae9672ab, a3d0c321), 777, 253},
+  {GRISU_UINT64_C(0xf24a01a7, 3cf2dcd0), 833, 270},
+  {GRISU_UINT64_C(0xa81f3014, 49ee8c70), 890, 287},
+  {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+  {GRISU_UINT64_C(0xa1e53af4, 6f801c53), 1003, 321},
+  {GRISU_UINT64_C(0xe0accfa8, 75af45a8), 1059, 338},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(17) = 57;
+// nb elements (17): 39
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(18)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
+  {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+  {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
+  {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+  {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+  {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+  {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+  {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+  {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
+  {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+  {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+  {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+  {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+  {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+  {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+  {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+  {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+  {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+  {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+  {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+  {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+  {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+  {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
+  {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+  {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+  {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+  {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
+  {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+  {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
+  {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+  {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
+  {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+  {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+  {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+  {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+  {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(18) = 60;
+// nb elements (18): 37
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(19)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0xf97ae3d0, d2446f25), -1024, -289},
+  {GRISU_UINT64_C(0x873e4f75, e2224e68), -960, -270},
+  {GRISU_UINT64_C(0x92a1958a, 7675175f), -897, -251},
+  {GRISU_UINT64_C(0x9efa548d, 26e5a6e2), -834, -232},
+  {GRISU_UINT64_C(0xac5d37d5, b79b6239), -771, -213},
+  {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
+  {GRISU_UINT64_C(0xca9cf1d2, 06fdc03c), -645, -175},
+  {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
+  {GRISU_UINT64_C(0xee2ba6c0, 678b597f), -519, -137},
+  {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
+  {GRISU_UINT64_C(0x8bfbea76, c619ef36), -392, -99},
+  {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+  {GRISU_UINT64_C(0xa48ceaaa, b75a8e2b), -266, -61},
+  {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
+  {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
+  {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
+  {GRISU_UINT64_C(0xe35fa931, a0000000), -14, 15},
+  {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+  {GRISU_UINT64_C(0x85a36366, eb71f041), 113, 53},
+  {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+  {GRISU_UINT64_C(0x9d174b2d, cec0e47b), 239, 91},
+  {GRISU_UINT64_C(0xaa51823e, 34a7eedf), 302, 110},
+  {GRISU_UINT64_C(0xb8a8d9bb, e123f018), 365, 129},
+  {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+  {GRISU_UINT64_C(0xd910f7ff, 28069da4), 491, 167},
+  {GRISU_UINT64_C(0xeb57ff22, fc0c795a), 554, 186},
+  {GRISU_UINT64_C(0xff290242, c83396ce), 617, 205},
+  {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
+  {GRISU_UINT64_C(0x95f83d0a, 1fb69cd9), 744, 243},
+  {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+  {GRISU_UINT64_C(0xb049dc01, 6abc5e60), 870, 281},
+  {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
+  {GRISU_UINT64_C(0xcf39e50f, eae16bf0), 996, 319},
+  {GRISU_UINT64_C(0xe0accfa8, 75af45a8), 1059, 338},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(19) = 64;
+// nb elements (19): 35
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(20)[] = {
+  {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+  {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
+  {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+  {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+  {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+  {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
+  {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+  {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+  {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+  {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+  {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+  {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+  {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+  {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+  {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+  {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+  {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+  {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+  {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+  {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+  {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+  {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+  {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+  {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
+  {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+  {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
+  {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+  {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+  {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+  {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
+  {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+  {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
+  {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+  };
+static const int GRISU_CACHE_MAX_DISTANCE(20) = 67;
+// nb elements (20): 33
+static const int GRISU_CACHE_OFFSET = 308;
diff --git a/src/profile-generator-inl.h b/src/profile-generator-inl.h
index 090ad8f..5e92be4 100644
--- a/src/profile-generator-inl.h
+++ b/src/profile-generator-inl.h
@@ -34,6 +34,17 @@
 namespace internal {
 
 
+CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
+                     const char* name,
+                     const char* resource_name,
+                     int line_number)
+    : tag_(tag),
+      name_(name),
+      resource_name_(resource_name),
+      line_number_(line_number) {
+}
+
+
 bool CodeEntry::is_js_function() {
   return tag_ == Logger::FUNCTION_TAG
       || tag_ == Logger::LAZY_COMPILE_TAG
@@ -41,24 +52,6 @@
 }
 
 
-StaticNameCodeEntry::StaticNameCodeEntry(Logger::LogEventsAndTags tag,
-                                         const char* name)
-    : CodeEntry(tag),
-      name_(name) {
-}
-
-
-ManagedNameCodeEntry::ManagedNameCodeEntry(Logger::LogEventsAndTags tag,
-                                           String* name,
-                                           const char* resource_name,
-                                           int line_number)
-    : CodeEntry(tag),
-      name_(name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach()),
-      resource_name_(resource_name),
-      line_number_(line_number) {
-}
-
-
 ProfileNode::ProfileNode(CodeEntry* entry)
     : entry_(entry),
       total_ticks_(0),
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 5c64d36..7f020c5 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -53,6 +53,15 @@
 }
 
 
+void ProfileNode::GetChildren(List<ProfileNode*>* children) {
+  for (HashMap::Entry* p = children_.Start();
+       p != NULL;
+       p = children_.Next(p)) {
+    children->Add(reinterpret_cast<ProfileNode*>(p->value));
+  }
+}
+
+
 void ProfileNode::Print(int indent) {
   OS::Print("%4u %4u %*c %s\n",
             total_ticks_, self_ticks_,
@@ -233,63 +242,143 @@
 }
 
 
-ProfileGenerator::ProfileGenerator()
-    : resource_names_(StringsMatch) {
+CpuProfilesCollection::CpuProfilesCollection()
+    : function_and_resource_names_(StringsMatch) {
 }
 
 
-static void CodeEntriesDeleter(CodeEntry** entry_ptr) {
+static void DeleteArgsCountName(char** name_ptr) {
+  DeleteArray(*name_ptr);
+}
+
+
+static void DeleteCodeEntry(CodeEntry** entry_ptr) {
   delete *entry_ptr;
 }
 
+static void DeleteCpuProfile(CpuProfile** profile_ptr) {
+  delete *profile_ptr;
+}
 
-ProfileGenerator::~ProfileGenerator() {
-  for (HashMap::Entry* p = resource_names_.Start();
+
+CpuProfilesCollection::~CpuProfilesCollection() {
+  profiles_.Iterate(DeleteCpuProfile);
+  code_entries_.Iterate(DeleteCodeEntry);
+  args_count_names_.Iterate(DeleteArgsCountName);
+  for (HashMap::Entry* p = function_and_resource_names_.Start();
        p != NULL;
-       p = resource_names_.Next(p)) {
+       p = function_and_resource_names_.Next(p)) {
     DeleteArray(reinterpret_cast<const char*>(p->value));
   }
-
-  code_entries_.Iterate(CodeEntriesDeleter);
 }
 
 
-CodeEntry* ProfileGenerator::NewCodeEntry(
-    Logger::LogEventsAndTags tag,
-    String* name,
-    String* resource_name, int line_number) {
-  const char* cached_resource_name = NULL;
-  if (resource_name->IsString()) {
-    // As we copy contents of resource names, and usually they are repeated,
-    // we cache names by string hashcode.
+void CpuProfilesCollection::AddProfile(unsigned uid) {
+  profiles_.Add(new CpuProfile());
+}
+
+
+CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
+                                               String* name,
+                                               String* resource_name,
+                                               int line_number) {
+  CodeEntry* entry = new CodeEntry(tag,
+                                   GetName(name),
+                                   GetName(resource_name),
+                                   line_number);
+  code_entries_.Add(entry);
+  return entry;
+}
+
+
+CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
+                                               const char* name) {
+  CodeEntry* entry = new CodeEntry(tag, name, "", 0);
+  code_entries_.Add(entry);
+  return entry;
+}
+
+
+CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
+                                               int args_count) {
+  CodeEntry* entry = new CodeEntry(tag, GetName(args_count), "", 0);
+  code_entries_.Add(entry);
+  return entry;
+}
+
+
+const char* CpuProfilesCollection::GetName(String* name) {
+  if (name->IsString()) {
+    char* c_name =
+        name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach();
     HashMap::Entry* cache_entry =
-        resource_names_.Lookup(resource_name,
-                               StringEntryHash(resource_name),
-                               true);
+        function_and_resource_names_.Lookup(c_name,
+                                            name->Hash(),
+                                            true);
     if (cache_entry->value == NULL) {
       // New entry added.
-      cache_entry->value =
-          resource_name->ToCString(DISALLOW_NULLS,
-                                   ROBUST_STRING_TRAVERSAL).Detach();
+      cache_entry->value = c_name;
+    } else {
+      DeleteArray(c_name);
     }
-    cached_resource_name = reinterpret_cast<const char*>(cache_entry->value);
+    return reinterpret_cast<const char*>(cache_entry->value);
+  } else {
+    return "";
+  }
+}
+
+
+const char* CpuProfilesCollection::GetName(int args_count) {
+  ASSERT(args_count >= 0);
+  if (args_count_names_.length() <= args_count) {
+    args_count_names_.AddBlock(
+        NULL, args_count - args_count_names_.length() + 1);
+  }
+  if (args_count_names_[args_count] == NULL) {
+    const int kMaximumNameLength = 32;
+    char* name = NewArray<char>(kMaximumNameLength);
+    OS::SNPrintF(Vector<char>(name, kMaximumNameLength),
+                 "args_count: %d", args_count);
+    args_count_names_[args_count] = name;
+  }
+  return args_count_names_[args_count];
+}
+
+
+ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
+    : profiles_(profiles) {
+}
+
+
+void ProfileGenerator::RecordTickSample(const TickSample& sample) {
+  // Allocate space for stack frames + pc + function.
+  ScopedVector<CodeEntry*> entries(sample.frames_count + 2);
+  CodeEntry** entry = entries.start();
+  *entry++ = code_map_.FindEntry(sample.pc);
+
+  if (sample.function != NULL) {
+    *entry = code_map_.FindEntry(sample.function);
+    if (*entry != NULL && !(*entry)->is_js_function()) {
+      *entry = NULL;
+    } else {
+      CodeEntry* pc_entry = *entries.start();
+      if (pc_entry == NULL || pc_entry->is_js_function())
+        *entry = NULL;
+    }
+    entry++;
+  } else {
+    *entry++ = NULL;
   }
 
-  CodeEntry* entry = new ManagedNameCodeEntry(tag,
-                                              name,
-                                              cached_resource_name,
-                                              line_number);
-  code_entries_.Add(entry);
-  return entry;
+  for (const Address *stack_pos = sample.stack,
+         *stack_end = stack_pos + sample.frames_count;
+       stack_pos != stack_end;
+       ++stack_pos) {
+    *entry++ = code_map_.FindEntry(*stack_pos);
+  }
+
+  profile()->AddPath(entries);
 }
 
 
-CodeEntry* ProfileGenerator::NewCodeEntry(
-    Logger::LogEventsAndTags tag,
-    const char* name) {
-  CodeEntry* entry = new StaticNameCodeEntry(tag, name);
-  code_entries_.Add(entry);
-  return entry;
-}
-
 } }  // namespace v8::internal
diff --git a/src/profile-generator.h b/src/profile-generator.h
index c3843bf..c0454cb 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -36,50 +36,22 @@
 
 class CodeEntry {
  public:
-  virtual ~CodeEntry() { }
+  // CodeEntry doesn't own name strings, just references them.
+  INLINE(CodeEntry(Logger::LogEventsAndTags tag_,
+                   const char* name_,
+                   const char* resource_name_,
+                   int line_number_));
 
-  virtual const char* name() = 0;
   INLINE(bool is_js_function());
-
- protected:
-  INLINE(explicit CodeEntry(Logger::LogEventsAndTags tag))
-      : tag_(tag) { }
+  INLINE(const char* name()) { return name_; }
 
  private:
   Logger::LogEventsAndTags tag_;
-
-  DISALLOW_COPY_AND_ASSIGN(CodeEntry);
-};
-
-
-class StaticNameCodeEntry : public CodeEntry {
- public:
-  INLINE(StaticNameCodeEntry(Logger::LogEventsAndTags tag,
-                             const char* name));
-
-  INLINE(virtual const char* name()) { return name_ != NULL ? name_ : ""; }
-
- private:
   const char* name_;
-
-  DISALLOW_COPY_AND_ASSIGN(StaticNameCodeEntry);
-};
-
-
-class ManagedNameCodeEntry : public CodeEntry {
- public:
-  INLINE(ManagedNameCodeEntry(Logger::LogEventsAndTags tag,
-                              String* name,
-                              const char* resource_name, int line_number));
-
-  INLINE(virtual const char* name()) { return !name_.is_empty() ? *name_ : ""; }
-
- private:
-  SmartPointer<char> name_;
   const char* resource_name_;
   int line_number_;
 
-  DISALLOW_COPY_AND_ASSIGN(ManagedNameCodeEntry);
+  DISALLOW_COPY_AND_ASSIGN(CodeEntry);
 };
 
 
@@ -92,17 +64,19 @@
   INLINE(void IncrementSelfTicks()) { ++self_ticks_; }
   INLINE(void IncreaseTotalTicks(unsigned amount)) { total_ticks_ += amount; }
 
-  INLINE(unsigned total_ticks()) { return total_ticks_; }
-  INLINE(unsigned self_ticks()) { return self_ticks_; }
+  INLINE(CodeEntry* entry() const) { return entry_; }
+  INLINE(unsigned total_ticks() const) { return total_ticks_; }
+  INLINE(unsigned self_ticks() const) { return self_ticks_; }
+  void GetChildren(List<ProfileNode*>* children);
 
   void Print(int indent);
 
  private:
-  INLINE(static bool CodeEntriesMatch(void* key1, void* key2)) {
-    return key1 == key2;
+  INLINE(static bool CodeEntriesMatch(void* entry1, void* entry2)) {
+    return entry1 == entry2;
   }
 
-  INLINE(static bool CodeEntryHash(CodeEntry* entry)) {
+  INLINE(static uint32_t CodeEntryHash(CodeEntry* entry)) {
     return static_cast<int32_t>(reinterpret_cast<intptr_t>(entry));
   }
 
@@ -144,13 +118,16 @@
 };
 
 
-class CpuProfile BASE_EMBEDDED {
+class CpuProfile {
  public:
   CpuProfile() { }
   // Add pc -> ... -> main() call path to the profile.
   void AddPath(const Vector<CodeEntry*>& path);
   void CalculateTotalTicks();
 
+  INLINE(ProfileTree* top_down()) { return &top_down_; }
+  INLINE(ProfileTree* bottom_up()) { return &bottom_up_; }
+
   void ShortPrint();
   void Print();
 
@@ -196,33 +173,70 @@
 };
 
 
-class ProfileGenerator {
+class CpuProfilesCollection {
  public:
-  ProfileGenerator();
-  ~ProfileGenerator();
+  CpuProfilesCollection();
+  ~CpuProfilesCollection();
+
+  void AddProfile(unsigned uid);
 
   CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
                           String* name, String* resource_name, int line_number);
   CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, const char* name);
+  CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, int args_count);
 
-  INLINE(CpuProfile* profile()) { return &profile_; }
+  INLINE(CpuProfile* profile()) { return profiles_.last(); }
+
+ private:
+  const char* GetName(String* name);
+  const char* GetName(int args_count);
+
+  INLINE(static bool StringsMatch(void* key1, void* key2)) {
+    return strcmp(reinterpret_cast<char*>(key1),
+                  reinterpret_cast<char*>(key2)) == 0;
+  }
+
+  // String::Hash -> const char*
+  HashMap function_and_resource_names_;
+  // args_count -> char*
+  List<char*> args_count_names_;
+  List<CodeEntry*> code_entries_;
+  List<CpuProfile*> profiles_;
+
+  DISALLOW_COPY_AND_ASSIGN(CpuProfilesCollection);
+};
+
+
+class ProfileGenerator {
+ public:
+  explicit ProfileGenerator(CpuProfilesCollection* profiles);
+
+  INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
+                                 String* name,
+                                 String* resource_name,
+                                 int line_number)) {
+    return profiles_->NewCodeEntry(tag, name, resource_name, line_number);
+  }
+
+  INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
+                                 const char* name)) {
+    return profiles_->NewCodeEntry(tag, name);
+  }
+
+  INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
+                                 int args_count)) {
+    return profiles_->NewCodeEntry(tag, args_count);
+  }
+
+  void RecordTickSample(const TickSample& sample);
+
   INLINE(CodeMap* code_map()) { return &code_map_; }
 
  private:
-  INLINE(static bool StringsMatch(void* key1, void* key2)) {
-    return key1 == key2;
-  }
+  INLINE(CpuProfile* profile()) { return profiles_->profile(); }
 
-  INLINE(static bool StringEntryHash(String* entry)) {
-    return entry->Hash();
-  }
-
-  CpuProfile profile_;
+  CpuProfilesCollection* profiles_;
   CodeMap code_map_;
-  typedef List<CodeEntry*> CodeEntryList;
-  CodeEntryList code_entries_;
-  // String::Hash -> const char*
-  HashMap resource_names_;
 
   DISALLOW_COPY_AND_ASSIGN(ProfileGenerator);
 };
diff --git a/src/runtime.cc b/src/runtime.cc
index 4e4856d..0fe2457 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -2353,6 +2353,14 @@
 static inline int SingleCharIndexOf(Vector<const schar> string,
                                     schar pattern_char,
                                     int start_index) {
+  if (sizeof(schar) == 1) {
+    const schar* pos = reinterpret_cast<const schar*>(
+        memchr(string.start() + start_index,
+               pattern_char,
+               string.length() - start_index));
+    if (pos == NULL) return -1;
+    return pos - string.start();
+  }
   for (int i = start_index, n = string.length(); i < n; i++) {
     if (pattern_char == string[i]) {
       return i;
@@ -2400,7 +2408,19 @@
       *complete = false;
       return i;
     }
-    if (subject[i] != pattern_first_char) continue;
+    if (sizeof(schar) == 1 && sizeof(pchar) == 1) {
+      const schar* pos = reinterpret_cast<const schar*>(
+          memchr(subject.start() + i,
+                 pattern_first_char,
+                 n - i + 1));
+      if (pos == NULL) {
+        *complete = true;
+        return -1;
+      }
+      i = pos - subject.start();
+    } else {
+      if (subject[i] != pattern_first_char) continue;
+    }
     int j = 1;
     do {
       if (pattern[j] != subject[i+j]) {
@@ -2425,7 +2445,16 @@
                          int idx) {
   pchar pattern_first_char = pattern[0];
   for (int i = idx, n = subject.length() - pattern.length(); i <= n; i++) {
-    if (subject[i] != pattern_first_char) continue;
+    if (sizeof(schar) == 1 && sizeof(pchar) == 1) {
+      const schar* pos = reinterpret_cast<const schar*>(
+          memchr(subject.start() + i,
+                 pattern_first_char,
+                 n - i + 1));
+      if (pos == NULL) return -1;
+      i = pos - subject.start();
+    } else {
+      if (subject[i] != pattern_first_char) continue;
+    }
     int j = 1;
     do {
       if (pattern[j] != subject[i+j]) {
@@ -5321,16 +5350,38 @@
 }
 
 
-static Object* Runtime_Math_round(Arguments args) {
+static Object* Runtime_RoundNumber(Arguments args) {
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
   Counters::math_round.Increment();
 
-  CONVERT_DOUBLE_CHECKED(x, args[0]);
-  if (signbit(x) && x >= -0.5) return Heap::minus_zero_value();
-  double integer = ceil(x);
-  if (integer - x > 0.5) { integer -= 1.0; }
-  return Heap::NumberFromDouble(integer);
+  if (!args[0]->IsHeapNumber()) {
+    // Must be smi. Return the argument unchanged for all the other types
+    // to make fuzz-natives test happy.
+    return args[0];
+  }
+
+  HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
+
+  double value = number->value();
+  int exponent = number->get_exponent();
+  int sign = number->get_sign();
+
+  // We compare with kSmiValueSize - 3 because (2^30 - 0.1) has exponent 29 and
+  // should be rounded to 2^30, which is not smi.
+  if (!sign && exponent <= kSmiValueSize - 3) {
+    return Smi::FromInt(static_cast<int>(value + 0.5));
+  }
+
+  // If the magnitude is big enough, there's no place for fraction part. If we
+  // try to add 0.5 to this number, 1.0 will be added instead.
+  if (exponent >= 52) {
+    return number;
+  }
+
+  if (sign && value >= -0.5) return Heap::minus_zero_value();
+
+  return Heap::NumberFromDouble(floor(value + 0.5));
 }
 
 
@@ -5635,7 +5686,7 @@
 
 // This function works for dates from 1970 to 2099.
 static inline void DateYMDFromTimeAfter1970(int date,
-                                            int &year, int &month, int &day) {
+                                            int& year, int& month, int& day) {
 #ifdef DEBUG
   int save_date = date;  // Need this for ASSERT in the end.
 #endif
@@ -5651,7 +5702,7 @@
 
 
 static inline void DateYMDFromTimeSlow(int date,
-                                       int &year, int &month, int &day) {
+                                       int& year, int& month, int& day) {
 #ifdef DEBUG
   int save_date = date;  // Need this for ASSERT in the end.
 #endif
@@ -5680,11 +5731,11 @@
   bool is_leap = (!yd1 || yd2) && !yd3;
 
   ASSERT(date >= -1);
-  ASSERT(is_leap || date >= 0);
-  ASSERT(date < 365 || is_leap && date < 366);
-  ASSERT(is_leap == (year % 4 == 0 && (year % 100 || (year % 400 == 0))));
-  ASSERT(is_leap || MakeDay(year, 0, 1) + date == save_date);
-  ASSERT(!is_leap || MakeDay(year, 0, 1) + date + 1 == save_date);
+  ASSERT(is_leap || (date >= 0));
+  ASSERT((date < 365) || (is_leap && (date < 366)));
+  ASSERT(is_leap == ((year % 4 == 0) && (year % 100 || (year % 400 == 0))));
+  ASSERT(is_leap || ((MakeDay(year, 0, 1) + date) == save_date));
+  ASSERT(!is_leap || ((MakeDay(year, 0, 1) + date + 1) == save_date));
 
   if (is_leap) {
     day = kDayInYear[2*365 + 1 + date];
@@ -5699,7 +5750,7 @@
 
 
 static inline void DateYMDFromTime(int date,
-                                   int &year, int &month, int &day) {
+                                   int& year, int& month, int& day) {
   if (date >= 0 && date < 32 * kDaysIn4Years) {
     DateYMDFromTimeAfter1970(date, year, month, day);
   } else {
diff --git a/src/runtime.h b/src/runtime.h
index 05f09f6..4175902 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -145,7 +145,7 @@
   F(Math_log, 1, 1) \
   F(Math_pow, 2, 1) \
   F(Math_pow_cfunction, 2, 1) \
-  F(Math_round, 1, 1) \
+  F(RoundNumber, 1, 1) \
   F(Math_sin, 1, 1) \
   F(Math_sqrt, 1, 1) \
   F(Math_tan, 1, 1) \
diff --git a/src/serialize.cc b/src/serialize.cc
index a95a7d6..0e38151 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -477,7 +477,7 @@
 
 void ExternalReferenceEncoder::Put(Address key, int index) {
   HashMap::Entry* entry = encodings_.Lookup(key, Hash(key), true);
-  entry->value = reinterpret_cast<void *>(index);
+  entry->value = reinterpret_cast<void*>(index);
 }
 
 
@@ -977,7 +977,7 @@
 // the startup snapshot that correspond to the elements of this cache array.  On
 // deserialization we therefore need to visit the cache array.  This fills it up
 // with pointers to deserialized objects.
-void SerializerDeserializer::Iterate(ObjectVisitor *visitor) {
+void SerializerDeserializer::Iterate(ObjectVisitor* visitor) {
   visitor->VisitPointers(
       &partial_snapshot_cache_[0],
       &partial_snapshot_cache_[partial_snapshot_cache_length_]);
diff --git a/src/top.cc b/src/top.cc
index 3efd1fc..0fcf458 100644
--- a/src/top.cc
+++ b/src/top.cc
@@ -88,6 +88,17 @@
 }
 
 
+void Top::IterateThread(ThreadVisitor* v) {
+  v->VisitThread(&thread_local_);
+}
+
+
+void Top::IterateThread(ThreadVisitor* v, char* t) {
+  ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
+  v->VisitThread(thread);
+}
+
+
 void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
   v->VisitPointer(&(thread->pending_exception_));
   v->VisitPointer(&(thread->pending_message_obj_));
diff --git a/src/top.h b/src/top.h
index e20a2a0..d263777 100644
--- a/src/top.h
+++ b/src/top.h
@@ -40,6 +40,7 @@
 // Top has static variables used for JavaScript execution.
 
 class SaveContext;  // Forward declaration.
+class ThreadVisitor;  // Defined in v8threads.h
 
 class ThreadLocalTop BASE_EMBEDDED {
  public:
@@ -319,6 +320,8 @@
   static void Iterate(ObjectVisitor* v);
   static void Iterate(ObjectVisitor* v, ThreadLocalTop* t);
   static char* Iterate(ObjectVisitor* v, char* t);
+  static void IterateThread(ThreadVisitor* v);
+  static void IterateThread(ThreadVisitor* v, char* t);
 
   // Returns the global object of the current context. It could be
   // a builtin object, or a js global object.
diff --git a/src/utils.h b/src/utils.h
index 3c8d873..89cc5ef 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -341,7 +341,6 @@
   // Releases the array underlying this vector. Once disposed the
   // vector is empty.
   void Dispose() {
-    if (is_empty()) return;
     DeleteArray(start_);
     start_ = NULL;
     length_ = 0;
diff --git a/src/v8.cc b/src/v8.cc
index 3953361..395401d 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -43,7 +43,7 @@
 bool V8::has_been_disposed_ = false;
 bool V8::has_fatal_error_ = false;
 
-bool V8::Initialize(Deserializer *des) {
+bool V8::Initialize(Deserializer* des) {
   bool create_heap_objects = des == NULL;
   if (has_been_disposed_ || has_fatal_error_) return false;
   if (IsRunning()) return true;
diff --git a/src/v8threads.cc b/src/v8threads.cc
index 80a7cd9..02292f6 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -331,6 +331,17 @@
 }
 
 
+void ThreadManager::IterateThreads(ThreadVisitor* v) {
+  for (ThreadState* state = ThreadState::FirstInUse();
+       state != NULL;
+       state = state->Next()) {
+    char* data = state->data();
+    data += HandleScopeImplementer::ArchiveSpacePerThread();
+    Top::IterateThread(v, data);
+  }
+}
+
+
 void ThreadManager::MarkCompactPrologue(bool is_compacting) {
   for (ThreadState* state = ThreadState::FirstInUse();
        state != NULL;
diff --git a/src/v8threads.h b/src/v8threads.h
index 0684053..d70aa3c 100644
--- a/src/v8threads.h
+++ b/src/v8threads.h
@@ -79,6 +79,20 @@
 };
 
 
+// Defined in top.h
+class ThreadLocalTop;
+
+
+class ThreadVisitor {
+ public:
+  // ThreadLocalTop may be only available during this call.
+  virtual void VisitThread(ThreadLocalTop* top) = 0;
+
+ protected:
+  virtual ~ThreadVisitor() {}
+};
+
+
 class ThreadManager : public AllStatic {
  public:
   static void Lock();
@@ -90,6 +104,7 @@
   static bool IsArchived();
 
   static void Iterate(ObjectVisitor* v);
+  static void IterateThreads(ThreadVisitor* v);
   static void MarkCompactPrologue(bool is_compacting);
   static void MarkCompactEpilogue(bool is_compacting);
   static bool IsLockedByCurrentThread() { return mutex_owner_.IsSelf(); }
diff --git a/src/version.cc b/src/version.cc
index d45b71e..74bef65 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     2
 #define MINOR_VERSION     1
-#define BUILD_NUMBER      6
-#define PATCH_LEVEL       2
+#define BUILD_NUMBER      7
+#define PATCH_LEVEL       0
 #define CANDIDATE_VERSION false
 
 // Define SONAME to have the SCons build the put a specific SONAME into the
diff --git a/src/virtual-frame-inl.h b/src/virtual-frame-inl.h
index ff599d0..4050d71 100644
--- a/src/virtual-frame-inl.h
+++ b/src/virtual-frame-inl.h
@@ -125,6 +125,11 @@
 }
 
 
+void VirtualFrame::SetTypeForParamAt(int index, NumberInfo info) {
+  elements_[param0_index() + index].set_number_info(info);
+}
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_VIRTUAL_FRAME_INL_H_
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index a994f45..cedb740 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -1030,6 +1030,22 @@
 }
 
 
+void Assembler::imull(Register dst, Register src, Immediate imm) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_optional_rex_32(dst, src);
+  if (is_int8(imm.value_)) {
+    emit(0x6B);
+    emit_modrm(dst, src);
+    emit(imm.value_);
+  } else {
+    emit(0x69);
+    emit_modrm(dst, src);
+    emitl(imm.value_);
+  }
+}
+
+
 void Assembler::incq(Register dst) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
@@ -1190,6 +1206,15 @@
 }
 
 
+void Assembler::leal(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_optional_rex_32(dst, src);
+  emit(0x8D);
+  emit_operand(dst, src);
+}
+
+
 void Assembler::load_rax(void* value, RelocInfo::Mode mode) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
@@ -1219,6 +1244,7 @@
   emit_operand(dst, src);
 }
 
+
 void Assembler::movb(Register dst, Immediate imm) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
@@ -1228,6 +1254,7 @@
   emit(imm.value_);
 }
 
+
 void Assembler::movb(const Operand& dst, Register src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
@@ -1236,6 +1263,7 @@
   emit_operand(src, dst);
 }
 
+
 void Assembler::movw(const Operand& dst, Register src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
@@ -1245,6 +1273,7 @@
   emit_operand(src, dst);
 }
 
+
 void Assembler::movl(Register dst, const Operand& src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
@@ -1600,6 +1629,15 @@
 }
 
 
+void Assembler::notl(Register dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_optional_rex_32(dst);
+  emit(0xF7);
+  emit_modrm(0x2, dst);
+}
+
+
 void Assembler::nop(int n) {
   // The recommended muti-byte sequences of NOP instructions from the Intel 64
   // and IA-32 Architectures Software Developer's Manual.
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index 5019525..e3ad488 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -742,14 +742,16 @@
   void imul(Register dst, Register src);                 // dst = dst * src.
   void imul(Register dst, const Operand& src);           // dst = dst * src.
   void imul(Register dst, Register src, Immediate imm);  // dst = src * imm.
-  // Multiply 32 bit registers
-  void imull(Register dst, Register src);                // dst = dst * src.
+  // Signed 32-bit multiply instructions.
+  void imull(Register dst, Register src);                 // dst = dst * src.
+  void imull(Register dst, Register src, Immediate imm);  // dst = src * imm.
 
   void incq(Register dst);
   void incq(const Operand& dst);
   void incl(const Operand& dst);
 
   void lea(Register dst, const Operand& src);
+  void leal(Register dst, const Operand& src);
 
   // Multiply rax by src, put the result in rdx:rax.
   void mul(Register src);
@@ -760,6 +762,7 @@
 
   void not_(Register dst);
   void not_(const Operand& dst);
+  void notl(Register dst);
 
   void or_(Register dst, Register src) {
     arithmetic_op(0x0B, dst, src);
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index 8ec1c95..a6b0ffc 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -7182,12 +7182,6 @@
   // Read the value from the static offsets vector buffer and make it a smi.
   __ movl(rdi, Operand(rcx, rdx, times_int_size, 0));
   __ Integer32ToSmi(rdi, rdi, &runtime);
-  // Add previous index (from its stack slot) if value is not negative.
-  Label capture_negative;
-  // Negative flag set by smi convertion above.
-  __ j(negative, &capture_negative);
-  __ SmiAdd(rdi, rdi, rax, &runtime);  // Add previous index.
-  __ bind(&capture_negative);
   // Store the smi value in the last match info.
   __ movq(FieldOperand(rbx,
                        rdx,
@@ -8408,14 +8402,15 @@
   }
 
   OS::SNPrintF(Vector<char>(name_, len),
-               "GenericBinaryOpStub_%s_%s%s_%s%s_%s%s",
+               "GenericBinaryOpStub_%s_%s%s_%s%s_%s%s_%s",
                op_name,
                overwrite_name,
                (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "",
                args_in_registers_ ? "RegArgs" : "StackArgs",
                args_reversed_ ? "_R" : "",
                use_sse3_ ? "SSE3" : "SSE2",
-               operands_type_.ToString());
+               static_operands_type_.ToString(),
+               BinaryOpIC::GetName(runtime_operands_type_));
   return name_;
 }
 
@@ -8565,8 +8560,8 @@
 
 
 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) {
-  // 1. Move arguments into edx, eax except for DIV and MOD, which need the
-  // dividend in eax and edx free for the division.  Use eax, ebx for those.
+  // 1. Move arguments into rdx, rax except for DIV and MOD, which need the
+  // dividend in rax and rdx free for the division.  Use rax, rbx for those.
   Comment load_comment(masm, "-- Load arguments");
   Register left = rdx;
   Register right = rax;
@@ -8665,7 +8660,7 @@
       break;
   }
 
-  // 4. Emit return of result in eax.
+  // 4. Emit return of result in rax.
   GenerateReturn(masm);
 
   // 5. For some operations emit inline code to perform floating point
@@ -8726,20 +8721,35 @@
 
 void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
   Label call_runtime;
-  if (HasSmiCodeInStub()) {
+
+  if (ShouldGenerateSmiCode()) {
     GenerateSmiCode(masm, &call_runtime);
   } else if (op_ != Token::MOD) {
-    GenerateLoadArguments(masm);
+    if (!HasArgsInRegisters()) {
+      GenerateLoadArguments(masm);
+    }
   }
   // Floating point case.
-  switch (op_) {
-    case Token::ADD:
-    case Token::SUB:
-    case Token::MUL:
-    case Token::DIV: {
-      // rax: y
-      // rdx: x
-      if (operands_type_.IsNumber()) {
+  if (ShouldGenerateFPCode()) {
+    switch (op_) {
+      case Token::ADD:
+      case Token::SUB:
+      case Token::MUL:
+      case Token::DIV: {
+        if (runtime_operands_type_ == BinaryOpIC::DEFAULT &&
+            HasSmiCodeInStub()) {
+          // Execution reaches this point when the first non-smi argument occurs
+          // (and only if smi code is generated). This is the right moment to
+          // patch to HEAP_NUMBERS state. The transition is attempted only for
+          // the four basic operations. The stub stays in the DEFAULT state
+          // forever for all other operations (also if smi code is skipped).
+          GenerateTypeTransition(masm);
+        }
+
+        Label not_floats;
+        // rax: y
+        // rdx: x
+      if (static_operands_type_.IsNumber()) {
         if (FLAG_debug_code) {
           // Assert at runtime that inputs are only numbers.
           __ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number.");
@@ -8748,118 +8758,132 @@
       } else {
         FloatingPointHelper::CheckNumberOperands(masm, &call_runtime);
       }
-      // Fast-case: Both operands are numbers.
-      // xmm4 and xmm5 are volatile XMM registers.
-      FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5);
+        // Fast-case: Both operands are numbers.
+        // xmm4 and xmm5 are volatile XMM registers.
+        FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5);
 
-      switch (op_) {
-        case Token::ADD: __ addsd(xmm4, xmm5); break;
-        case Token::SUB: __ subsd(xmm4, xmm5); break;
-        case Token::MUL: __ mulsd(xmm4, xmm5); break;
-        case Token::DIV: __ divsd(xmm4, xmm5); break;
-        default: UNREACHABLE();
-      }
-      // Allocate a heap number, if needed.
-      Label skip_allocation;
-      OverwriteMode mode = mode_;
-      if (HasArgsReversed()) {
-        if (mode == OVERWRITE_RIGHT) {
-          mode = OVERWRITE_LEFT;
-        } else if (mode == OVERWRITE_LEFT) {
-          mode = OVERWRITE_RIGHT;
+        switch (op_) {
+          case Token::ADD: __ addsd(xmm4, xmm5); break;
+          case Token::SUB: __ subsd(xmm4, xmm5); break;
+          case Token::MUL: __ mulsd(xmm4, xmm5); break;
+          case Token::DIV: __ divsd(xmm4, xmm5); break;
+          default: UNREACHABLE();
         }
-      }
-      switch (mode) {
-        case OVERWRITE_LEFT:
-          __ JumpIfNotSmi(rdx, &skip_allocation);
-          __ AllocateHeapNumber(rbx, rcx, &call_runtime);
-          __ movq(rdx, rbx);
-          __ bind(&skip_allocation);
-          __ movq(rax, rdx);
-          break;
-        case OVERWRITE_RIGHT:
-          // If the argument in rax is already an object, we skip the
-          // allocation of a heap number.
-          __ JumpIfNotSmi(rax, &skip_allocation);
-          // Fall through!
-        case NO_OVERWRITE:
-          // Allocate a heap number for the result. Keep rax and rdx intact
-          // for the possible runtime call.
-          __ AllocateHeapNumber(rbx, rcx, &call_runtime);
-          __ movq(rax, rbx);
-          __ bind(&skip_allocation);
-          break;
-        default: UNREACHABLE();
-      }
-      __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm4);
-      GenerateReturn(masm);
-    }
-    case Token::MOD: {
-      // For MOD we go directly to runtime in the non-smi case.
-      break;
-    }
-    case Token::BIT_OR:
-    case Token::BIT_AND:
-    case Token::BIT_XOR:
-    case Token::SAR:
-    case Token::SHL:
-    case Token::SHR: {
-      Label skip_allocation, non_smi_result;
-      FloatingPointHelper::LoadAsIntegers(masm, use_sse3_, &call_runtime);
-      switch (op_) {
-        case Token::BIT_OR:  __ orl(rax, rcx); break;
-        case Token::BIT_AND: __ andl(rax, rcx); break;
-        case Token::BIT_XOR: __ xorl(rax, rcx); break;
-        case Token::SAR: __ sarl_cl(rax); break;
-        case Token::SHL: __ shll_cl(rax); break;
-        case Token::SHR: __ shrl_cl(rax); break;
-        default: UNREACHABLE();
-      }
-      if (op_ == Token::SHR) {
-        // Check if result is non-negative. This can only happen for a shift
-        // by zero, which also doesn't update the sign flag.
-        __ testl(rax, rax);
-        __ j(negative, &non_smi_result);
-      }
-      __ JumpIfNotValidSmiValue(rax, &non_smi_result);
-      // Tag smi result, if possible, and return.
-      __ Integer32ToSmi(rax, rax);
-      GenerateReturn(masm);
-
-      // All ops except SHR return a signed int32 that we load in a HeapNumber.
-      if (op_ != Token::SHR && non_smi_result.is_linked()) {
-        __ bind(&non_smi_result);
-        // Allocate a heap number if needed.
-        __ movsxlq(rbx, rax);  // rbx: sign extended 32-bit result
-        switch (mode_) {
+        // Allocate a heap number, if needed.
+        Label skip_allocation;
+        OverwriteMode mode = mode_;
+        if (HasArgsReversed()) {
+          if (mode == OVERWRITE_RIGHT) {
+            mode = OVERWRITE_LEFT;
+          } else if (mode == OVERWRITE_LEFT) {
+            mode = OVERWRITE_RIGHT;
+          }
+        }
+        switch (mode) {
           case OVERWRITE_LEFT:
+            __ JumpIfNotSmi(rdx, &skip_allocation);
+            __ AllocateHeapNumber(rbx, rcx, &call_runtime);
+            __ movq(rdx, rbx);
+            __ bind(&skip_allocation);
+            __ movq(rax, rdx);
+            break;
           case OVERWRITE_RIGHT:
-            // If the operand was an object, we skip the
+            // If the argument in rax is already an object, we skip the
             // allocation of a heap number.
-            __ movq(rax, Operand(rsp, mode_ == OVERWRITE_RIGHT ?
-                                 1 * kPointerSize : 2 * kPointerSize));
             __ JumpIfNotSmi(rax, &skip_allocation);
             // Fall through!
           case NO_OVERWRITE:
-            __ AllocateHeapNumber(rax, rcx, &call_runtime);
+            // Allocate a heap number for the result. Keep rax and rdx intact
+            // for the possible runtime call.
+            __ AllocateHeapNumber(rbx, rcx, &call_runtime);
+            __ movq(rax, rbx);
             __ bind(&skip_allocation);
             break;
           default: UNREACHABLE();
         }
-        // Store the result in the HeapNumber and return.
-        __ movq(Operand(rsp, 1 * kPointerSize), rbx);
-        __ fild_s(Operand(rsp, 1 * kPointerSize));
-        __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
+        __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm4);
         GenerateReturn(masm);
+        __ bind(&not_floats);
+        if (runtime_operands_type_ == BinaryOpIC::DEFAULT &&
+            !HasSmiCodeInStub()) {
+            // Execution reaches this point when the first non-number argument
+            // occurs (and only if smi code is skipped from the stub, otherwise
+            // the patching has already been done earlier in this case branch).
+            // A perfect moment to try patching to STRINGS for ADD operation.
+            if (op_ == Token::ADD) {
+              GenerateTypeTransition(masm);
+            }
+        }
+        break;
       }
+      case Token::MOD: {
+        // For MOD we go directly to runtime in the non-smi case.
+        break;
+      }
+      case Token::BIT_OR:
+      case Token::BIT_AND:
+      case Token::BIT_XOR:
+      case Token::SAR:
+      case Token::SHL:
+      case Token::SHR: {
+        Label skip_allocation, non_smi_result;
+        FloatingPointHelper::LoadAsIntegers(masm, use_sse3_, &call_runtime);
+        switch (op_) {
+          case Token::BIT_OR:  __ orl(rax, rcx); break;
+          case Token::BIT_AND: __ andl(rax, rcx); break;
+          case Token::BIT_XOR: __ xorl(rax, rcx); break;
+          case Token::SAR: __ sarl_cl(rax); break;
+          case Token::SHL: __ shll_cl(rax); break;
+          case Token::SHR: __ shrl_cl(rax); break;
+          default: UNREACHABLE();
+        }
+        if (op_ == Token::SHR) {
+          // Check if result is non-negative. This can only happen for a shift
+          // by zero, which also doesn't update the sign flag.
+          __ testl(rax, rax);
+          __ j(negative, &non_smi_result);
+        }
+        __ JumpIfNotValidSmiValue(rax, &non_smi_result);
+        // Tag smi result, if possible, and return.
+        __ Integer32ToSmi(rax, rax);
+        GenerateReturn(masm);
 
-      // SHR should return uint32 - go to runtime for non-smi/negative result.
-      if (op_ == Token::SHR) {
-        __ bind(&non_smi_result);
+        // All ops except SHR return a signed int32 that we load in
+        // a HeapNumber.
+        if (op_ != Token::SHR && non_smi_result.is_linked()) {
+          __ bind(&non_smi_result);
+          // Allocate a heap number if needed.
+          __ movsxlq(rbx, rax);  // rbx: sign extended 32-bit result
+          switch (mode_) {
+            case OVERWRITE_LEFT:
+            case OVERWRITE_RIGHT:
+              // If the operand was an object, we skip the
+              // allocation of a heap number.
+              __ movq(rax, Operand(rsp, mode_ == OVERWRITE_RIGHT ?
+                                   1 * kPointerSize : 2 * kPointerSize));
+              __ JumpIfNotSmi(rax, &skip_allocation);
+              // Fall through!
+            case NO_OVERWRITE:
+              __ AllocateHeapNumber(rax, rcx, &call_runtime);
+              __ bind(&skip_allocation);
+              break;
+            default: UNREACHABLE();
+          }
+          // Store the result in the HeapNumber and return.
+          __ movq(Operand(rsp, 1 * kPointerSize), rbx);
+          __ fild_s(Operand(rsp, 1 * kPointerSize));
+          __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
+          GenerateReturn(masm);
+        }
+
+        // SHR should return uint32 - go to runtime for non-smi/negative result.
+        if (op_ == Token::SHR) {
+          __ bind(&non_smi_result);
+        }
+        break;
       }
-      break;
+      default: UNREACHABLE(); break;
     }
-    default: UNREACHABLE(); break;
   }
 
   // If all else fails, use the runtime system to get the correct
@@ -8868,15 +8892,7 @@
   __ bind(&call_runtime);
 
   if (HasArgsInRegisters()) {
-    __ pop(rcx);
-    if (HasArgsReversed()) {
-      __ push(rax);
-      __ push(rdx);
-    } else {
-      __ push(rdx);
-      __ push(rax);
-    }
-    __ push(rcx);
+    GenerateRegisterArgsPush(masm);
   }
 
   switch (op_) {
@@ -8894,8 +8910,14 @@
 
       // Test for string arguments before calling runtime.
       Label not_strings, both_strings, not_string1, string1, string1_smi2;
+
+      // If this stub has already generated FP-specific code then the arguments
+      // are already in rdx, rax
+      if (!ShouldGenerateFPCode() && !HasArgsInRegisters()) {
+        GenerateLoadArguments(masm);
+      }
+
       Condition is_smi;
-      Result answer;
       is_smi = masm->CheckSmi(lhs);
       __ j(is_smi, &not_string1);
       __ CmpObjectType(lhs, FIRST_NONSTRING_TYPE, r8);
@@ -8974,15 +8996,22 @@
     default:
       UNREACHABLE();
   }
+
+  // TODO(kaznacheev) Remove this (along with clearing) if it does not harm
+  // performance.
+  // Generate an unreachable reference to the DEFAULT stub so that it can be
+  // found at the end of this stub when clearing ICs at GC.
+  if (runtime_operands_type_ != BinaryOpIC::DEFAULT) {
+    GenericBinaryOpStub uninit(MinorKey(), BinaryOpIC::DEFAULT);
+    __ TailCallStub(&uninit);
+  }
 }
 
 
 void GenericBinaryOpStub::GenerateLoadArguments(MacroAssembler* masm) {
-  // If arguments are not passed in registers read them from the stack.
-  if (!HasArgsInRegisters()) {
-    __ movq(rax, Operand(rsp, 1 * kPointerSize));
-    __ movq(rdx, Operand(rsp, 2 * kPointerSize));
-  }
+  ASSERT(!HasArgsInRegisters());
+  __ movq(rax, Operand(rsp, 1 * kPointerSize));
+  __ movq(rdx, Operand(rsp, 2 * kPointerSize));
 }
 
 
@@ -8997,8 +9026,81 @@
 }
 
 
+void GenericBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
+  ASSERT(HasArgsInRegisters());
+  __ pop(rcx);
+  if (HasArgsReversed()) {
+    __ push(rax);
+    __ push(rdx);
+  } else {
+    __ push(rdx);
+    __ push(rax);
+  }
+  __ push(rcx);
+}
+
+
+void GenericBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
+  Label get_result;
+
+  // Keep a copy of operands on the stack and make sure they are also in
+  // rdx, rax.
+  if (HasArgsInRegisters()) {
+    GenerateRegisterArgsPush(masm);
+  } else {
+    GenerateLoadArguments(masm);
+  }
+
+  // Internal frame is necessary to handle exceptions properly.
+  __ EnterInternalFrame();
+
+  // Push arguments on stack if the stub expects them there.
+  if (!HasArgsInRegisters()) {
+    __ push(rdx);
+    __ push(rax);
+  }
+  // Call the stub proper to get the result in rax.
+  __ call(&get_result);
+  __ LeaveInternalFrame();
+
+  // Left and right arguments are already on stack.
+  __ pop(rcx);
+  // Push the operation result. The tail call to BinaryOp_Patch will
+  // return it to the original caller..
+  __ push(rax);
+
+  // Push this stub's key.
+  __ movq(rax, Immediate(MinorKey()));
+  __ Integer32ToSmi(rax, rax);
+  __ push(rax);
+
+  // Although the operation and the type info are encoded into the key,
+  // the encoding is opaque, so push them too.
+  __ movq(rax, Immediate(op_));
+  __ Integer32ToSmi(rax, rax);
+  __ push(rax);
+
+  __ movq(rax, Immediate(runtime_operands_type_));
+  __ Integer32ToSmi(rax, rax);
+  __ push(rax);
+
+  __ push(rcx);
+
+  // Perform patching to an appropriate fast case and return the result.
+  __ TailCallExternalReference(
+      ExternalReference(IC_Utility(IC::kBinaryOp_Patch)),
+      6,
+      1);
+
+  // The entry point for the result calculation is assumed to be immediately
+  // after this sequence.
+  __ bind(&get_result);
+}
+
+
 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) {
-  return Handle<Code>::null();
+  GenericBinaryOpStub stub(key, type_info);
+  return stub.GetCode();
 }
 
 
diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h
index ce5f6d1..42b4993 100644
--- a/src/x64/codegen-x64.h
+++ b/src/x64/codegen-x64.h
@@ -28,6 +28,8 @@
 #ifndef V8_X64_CODEGEN_X64_H_
 #define V8_X64_CODEGEN_X64_H_
 
+#include "ic-inl.h"
+
 namespace v8 {
 namespace internal {
 
@@ -671,12 +673,26 @@
         flags_(flags),
         args_in_registers_(false),
         args_reversed_(false),
-        name_(NULL),
-        operands_type_(operands_type) {
+        static_operands_type_(operands_type),
+        runtime_operands_type_(BinaryOpIC::DEFAULT),
+        name_(NULL) {
     use_sse3_ = CpuFeatures::IsSupported(SSE3);
     ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
   }
 
+  GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info)
+      : op_(OpBits::decode(key)),
+        mode_(ModeBits::decode(key)),
+        flags_(FlagBits::decode(key)),
+        args_in_registers_(ArgsInRegistersBits::decode(key)),
+        args_reversed_(ArgsReversedBits::decode(key)),
+        use_sse3_(SSE3Bits::decode(key)),
+        static_operands_type_(NumberInfo::ExpandedRepresentation(
+            StaticTypeInfoBits::decode(key))),
+        runtime_operands_type_(type_info),
+        name_(NULL) {
+  }
+
   // Generate code to call the stub with the supplied arguments. This will add
   // code at the call site to prepare arguments either in registers or on the
   // stack together with the actual call.
@@ -696,8 +712,14 @@
   bool args_in_registers_;  // Arguments passed in registers not on the stack.
   bool args_reversed_;  // Left and right argument are swapped.
   bool use_sse3_;
+
+  // Number type information of operands, determined by code generator.
+  NumberInfo static_operands_type_;
+
+  // Operand type information determined at runtime.
+  BinaryOpIC::TypeInfo runtime_operands_type_;
+
   char* name_;
-  NumberInfo operands_type_;
 
   const char* GetName();
 
@@ -711,35 +733,40 @@
            static_cast<int>(flags_),
            static_cast<int>(args_in_registers_),
            static_cast<int>(args_reversed_),
-           operands_type_.ToString());
+           static_operands_type_.ToString());
   }
 #endif
 
-  // Minor key encoding in 16 bits NNNFRASOOOOOOOMM.
+  // Minor key encoding in 18 bits TTNNNFRASOOOOOOOMM.
   class ModeBits: public BitField<OverwriteMode, 0, 2> {};
   class OpBits: public BitField<Token::Value, 2, 7> {};
   class SSE3Bits: public BitField<bool, 9, 1> {};
   class ArgsInRegistersBits: public BitField<bool, 10, 1> {};
   class ArgsReversedBits: public BitField<bool, 11, 1> {};
   class FlagBits: public BitField<GenericBinaryFlags, 12, 1> {};
-  class NumberInfoBits: public BitField<int, 13, 3> {};
+  class StaticTypeInfoBits: public BitField<int, 13, 3> {};
+  class RuntimeTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 16, 2> {};
 
   Major MajorKey() { return GenericBinaryOp; }
   int MinorKey() {
-    // Encode the parameters in a unique 16 bit value.
+    // Encode the parameters in a unique 18 bit value.
     return OpBits::encode(op_)
            | ModeBits::encode(mode_)
            | FlagBits::encode(flags_)
            | SSE3Bits::encode(use_sse3_)
            | ArgsInRegistersBits::encode(args_in_registers_)
            | ArgsReversedBits::encode(args_reversed_)
-           | NumberInfoBits::encode(operands_type_.ThreeBitRepresentation());
+           | StaticTypeInfoBits::encode(
+               static_operands_type_.ThreeBitRepresentation())
+           | RuntimeTypeInfoBits::encode(runtime_operands_type_);
   }
 
   void Generate(MacroAssembler* masm);
   void GenerateSmiCode(MacroAssembler* masm, Label* slow);
   void GenerateLoadArguments(MacroAssembler* masm);
   void GenerateReturn(MacroAssembler* masm);
+  void GenerateRegisterArgsPush(MacroAssembler* masm);
+  void GenerateTypeTransition(MacroAssembler* masm);
 
   bool ArgsInRegistersSupported() {
     return (op_ == Token::ADD) || (op_ == Token::SUB)
@@ -754,6 +781,22 @@
   bool HasSmiCodeInStub() { return (flags_ & NO_SMI_CODE_IN_STUB) == 0; }
   bool HasArgsInRegisters() { return args_in_registers_; }
   bool HasArgsReversed() { return args_reversed_; }
+
+  bool ShouldGenerateSmiCode() {
+    return HasSmiCodeInStub() &&
+        runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS &&
+        runtime_operands_type_ != BinaryOpIC::STRINGS;
+  }
+
+  bool ShouldGenerateFPCode() {
+    return runtime_operands_type_ != BinaryOpIC::STRINGS;
+  }
+
+  virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
+
+  virtual InlineCacheState GetICState() {
+    return BinaryOpIC::ToState(runtime_operands_type_);
+  }
 };
 
 
diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc
index 547daee..9ba364a 100644
--- a/src/x64/disasm-x64.cc
+++ b/src/x64/disasm-x64.cc
@@ -1273,7 +1273,9 @@
         get_modrm(*(data + 1), &mod, &regop, &rm);
         int32_t imm = *data == 0x6B ? *(data + 2)
             : *reinterpret_cast<int32_t*>(data + 2);
-        AppendToBuffer("imul %s,%s,0x%x", NameOfCPURegister(regop),
+        AppendToBuffer("imul%c %s,%s,0x%x",
+                       operand_size_code(),
+                       NameOfCPURegister(regop),
                        NameOfCPURegister(rm), imm);
         data += 2 + (*data == 0x6B ? 1 : 4);
         break;
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index e05f68d..1d28a1f 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -151,6 +151,108 @@
 }
 
 
+static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
+                                         Label* miss,
+                                         Register elements,
+                                         Register key,
+                                         Register r0,
+                                         Register r1,
+                                         Register r2) {
+  // Register use:
+  //
+  // elements - holds the slow-case elements of the receiver and is unchanged.
+  //
+  // key      - holds the smi key on entry and is unchanged if a branch is
+  //            performed to the miss label.
+  //
+  // Scratch registers:
+  //
+  // r0 - holds the untagged key on entry and holds the hash once computed.
+  //      Holds the result on exit if the load succeeded.
+  //
+  // r1 - used to hold the capacity mask of the dictionary
+  //
+  // r2 - used for the index into the dictionary.
+  Label done;
+
+  // Compute the hash code from the untagged key.  This must be kept in sync
+  // with ComputeIntegerHash in utils.h.
+  //
+  // hash = ~hash + (hash << 15);
+  __ movl(r1, r0);
+  __ notl(r0);
+  __ shll(r1, Immediate(15));
+  __ addl(r0, r1);
+  // hash = hash ^ (hash >> 12);
+  __ movl(r1, r0);
+  __ shrl(r1, Immediate(12));
+  __ xorl(r0, r1);
+  // hash = hash + (hash << 2);
+  __ leal(r0, Operand(r0, r0, times_4, 0));
+  // hash = hash ^ (hash >> 4);
+  __ movl(r1, r0);
+  __ shrl(r1, Immediate(4));
+  __ xorl(r0, r1);
+  // hash = hash * 2057;
+  __ imull(r0, r0, Immediate(2057));
+  // hash = hash ^ (hash >> 16);
+  __ movl(r1, r0);
+  __ shrl(r1, Immediate(16));
+  __ xorl(r0, r1);
+
+  // Compute capacity mask.
+  const int kCapacityOffset =
+      StringDictionary::kHeaderSize +
+      StringDictionary::kCapacityIndex * kPointerSize;
+  __ movq(r1, FieldOperand(elements, kCapacityOffset));
+  __ SmiToInteger32(r1, r1);
+  __ decl(r1);
+
+  const int kElementsStartOffset =
+      NumberDictionary::kHeaderSize +
+      NumberDictionary::kElementsStartIndex * kPointerSize;
+
+  // Generate an unrolled loop that performs a few probes before giving up.
+  const int kProbes = 4;
+  for (int i = 0; i < kProbes; i++) {
+    // Use r2 for index calculations and keep the hash intact in r0.
+    __ movq(r2, r0);
+    // Compute the masked index: (hash + i + i * i) & mask.
+    if (i > 0) {
+      __ addl(r2, Immediate(NumberDictionary::GetProbeOffset(i)));
+    }
+    __ and_(r2, r1);
+
+    // Scale the index by multiplying by the entry size.
+    ASSERT(NumberDictionary::kEntrySize == 3);
+    __ lea(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3
+
+    // Check if the key matches.
+    __ cmpq(key, FieldOperand(elements,
+                              r2,
+                              times_pointer_size,
+                              kElementsStartOffset));
+    if (i != (kProbes - 1)) {
+      __ j(equal, &done);
+    } else {
+      __ j(not_equal, miss);
+    }
+  }
+
+  __ bind(&done);
+  // Check that the value is a normal propety.
+  const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
+  ASSERT_EQ(NORMAL, 0);
+  __ Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
+          Smi::FromInt(PropertyDetails::TypeField::mask()));
+  __ j(not_zero, miss);
+
+  // Get the value at the masked, scaled index.
+  const int kValueOffset = kElementsStartOffset + kPointerSize;
+  __ movq(r0, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
+}
+
+
 // Helper function used to check that a value is either not an object
 // or is loaded if it is an object.
 static void GenerateCheckNonObjectOrLoaded(MacroAssembler* masm, Label* miss,
@@ -271,6 +373,7 @@
   // -----------------------------------
   Label slow, check_string, index_int, index_string;
   Label check_pixel_array, probe_dictionary;
+  Label check_number_dictionary;
 
   // Load name and receiver.
   __ movq(rax, Operand(rsp, kPointerSize));
@@ -294,6 +397,9 @@
 
   // Check that the key is a smi.
   __ JumpIfNotSmi(rax, &check_string);
+  // Save key in rbx in case we want it for the number dictionary
+  // case.
+  __ movq(rbx, rax);
   __ SmiToInteger32(rax, rax);
   // Get the elements array of the object.
   __ bind(&index_int);
@@ -321,7 +427,7 @@
   __ bind(&check_pixel_array);
   __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
                  Heap::kPixelArrayMapRootIndex);
-  __ j(not_equal, &slow);
+  __ j(not_equal, &check_number_dictionary);
   __ cmpl(rax, FieldOperand(rcx, PixelArray::kLengthOffset));
   __ j(above_equal, &slow);
   __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset));
@@ -329,6 +435,17 @@
   __ Integer32ToSmi(rax, rax);
   __ ret(0);
 
+  __ bind(&check_number_dictionary);
+  // Check whether the elements is a number dictionary.
+  // rax: untagged index
+  // rbx: key
+  // rcx: elements
+  __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
+                 Heap::kHashTableMapRootIndex);
+  __ j(not_equal, &slow);
+  GenerateNumberDictionaryLoad(masm, &slow, rcx, rbx, rax, rdx, rdi);
+  __ ret(0);
+
   // Slow case: Load name and receiver from stack and jump to runtime.
   __ bind(&slow);
   __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index 6e7d9c9..3fe6be2 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -711,9 +711,15 @@
   __ movq(rdi, Operand(rbp, kInputStart));
   // Set up rdi to be negative offset from string end.
   __ subq(rdi, rsi);
-  // Set rax to address of char before start of input
+  // Set rax to address of char before start of the string
   // (effectively string position -1).
-  __ lea(rax, Operand(rdi, -char_size()));
+  __ movq(rbx, Operand(rbp, kStartIndex));
+  __ neg(rbx);
+  if (mode_ == UC16) {
+    __ lea(rax, Operand(rdi, rbx, times_2, -char_size()));
+  } else {
+    __ lea(rax, Operand(rdi, rbx, times_1, -char_size()));
+  }
   // Store this value in a local variable, for use when clearing
   // position registers.
   __ movq(Operand(rbp, kInputStartMinusOne), rax);
@@ -770,9 +776,15 @@
     __ bind(&success_label_);
     if (num_saved_registers_ > 0) {
       // copy captures to output
+      __ movq(rdx, Operand(rbp, kStartIndex));
       __ movq(rbx, Operand(rbp, kRegisterOutput));
       __ movq(rcx, Operand(rbp, kInputEnd));
       __ subq(rcx, Operand(rbp, kInputStart));
+      if (mode_ == UC16) {
+        __ lea(rcx, Operand(rcx, rdx, times_2, 0));
+      } else {
+        __ addq(rcx, rdx);
+      }
       for (int i = 0; i < num_saved_registers_; i++) {
         __ movq(rax, register_location(i));
         __ addq(rax, rcx);  // Convert to index from start, not end.
diff --git a/src/x64/virtual-frame-x64.h b/src/x64/virtual-frame-x64.h
index e93140e..3e9f6dd 100644
--- a/src/x64/virtual-frame-x64.h
+++ b/src/x64/virtual-frame-x64.h
@@ -417,6 +417,7 @@
   inline void Nip(int num_dropped);
 
   inline void SetTypeForLocalAt(int index, NumberInfo info);
+  inline void SetTypeForParamAt(int index, NumberInfo info);
 
  private:
   static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;