diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2010-03-23 15:19:12 -0700 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2010-03-23 15:19:32 -0700 |
commit | b35d72df760bb7d65382b156de4863738e28c662 (patch) | |
tree | 2d8dbaf477a0a1ebcf92d70b1db30c3085f2c9c2 /deps/v8/src | |
parent | 6e603ccbe2dec3394ea0af86e226bfc9eea7bcd5 (diff) | |
download | node-b35d72df760bb7d65382b156de4863738e28c662.tar.gz |
Upgrade V8 to 2.1.7
Diffstat (limited to 'deps/v8/src')
74 files changed, 5656 insertions, 874 deletions
diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript index f4bba6beb..bf42fd4e6 100755 --- a/deps/v8/src/SConscript +++ b/deps/v8/src/SConscript @@ -43,6 +43,7 @@ SOURCES = { bootstrapper.cc builtins.cc checks.cc + circular-queue.cc code-stubs.cc codegen.cc compilation-cache.cc @@ -50,11 +51,13 @@ SOURCES = { 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 @@ SOURCES = { full-codegen.cc func-name-inferrer.cc global-handles.cc + fast-dtoa.cc handles.cc hashmap.cc heap-profiler.cc diff --git a/deps/v8/src/arm/assembler-arm-inl.h b/deps/v8/src/arm/assembler-arm-inl.h index 354436cb1..3f0854e33 100644 --- a/deps/v8/src/arm/assembler-arm-inl.h +++ b/deps/v8/src/arm/assembler-arm-inl.h @@ -144,12 +144,21 @@ void RelocInfo::set_call_object(Object* target) { 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 @@ Address Assembler::target_address_address_at(Address pc) { 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/deps/v8/src/arm/assembler-arm.cc b/deps/v8/src/arm/assembler-arm.cc index 6b226fd3d..d4cd818c1 100644 --- a/deps/v8/src/arm/assembler-arm.cc +++ b/deps/v8/src/arm/assembler-arm.cc @@ -240,8 +240,14 @@ static const Instr kPopRegPattern = 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/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h index c972c57b5..539a6b899 100644 --- a/deps/v8/src/arm/assembler-arm.h +++ b/deps/v8/src/arm/assembler-arm.h @@ -509,7 +509,10 @@ typedef int32_t Instr; 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 @@ class Assembler : public Malloced { 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/deps/v8/src/arm/constants-arm.h b/deps/v8/src/arm/constants-arm.h index 8a32c95b6..2b883f3b3 100644 --- a/deps/v8/src/arm/constants-arm.h +++ b/deps/v8/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/deps/v8/src/arm/debug-arm.cc b/deps/v8/src/arm/debug-arm.cc index e6b61b4d2..bc81b19d2 100644 --- a/deps/v8/src/arm/debug-arm.cc +++ b/deps/v8/src/arm/debug-arm.cc @@ -46,13 +46,23 @@ void BreakLocationIterator::SetDebugBreakAtReturn() { // 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/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc index bc779eb8d..691c08c4b 100644 --- a/deps/v8/src/arm/macro-assembler-arm.cc +++ b/deps/v8/src/arm/macro-assembler-arm.cc @@ -58,11 +58,6 @@ MacroAssembler::MacroAssembler(void* buffer, int size) #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(Register target, Condition cond) { 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/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h index 5d9e51304..8c70d9587 100644 --- a/deps/v8/src/arm/macro-assembler-arm.h +++ b/deps/v8/src/arm/macro-assembler-arm.h @@ -415,7 +415,7 @@ class MacroAssembler: public Assembler { 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/deps/v8/src/arm/regexp-macro-assembler-arm.cc b/deps/v8/src/arm/regexp-macro-assembler-arm.cc index f621be47b..13d464d17 100644 --- a/deps/v8/src/arm/regexp-macro-assembler-arm.cc +++ b/deps/v8/src/arm/regexp-macro-assembler-arm.cc @@ -648,16 +648,17 @@ Handle<Object> RegExpMacroAssemblerARM::GetCode(Handle<String> source) { __ 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 @@ Handle<Object> RegExpMacroAssemblerARM::GetCode(Handle<String> source) { // 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/deps/v8/src/arm/virtual-frame-arm.h b/deps/v8/src/arm/virtual-frame-arm.h index 7375b3183..9ac7a0548 100644 --- a/deps/v8/src/arm/virtual-frame-arm.h +++ b/deps/v8/src/arm/virtual-frame-arm.h @@ -365,6 +365,7 @@ class VirtualFrame : public ZoneObject { 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/deps/v8/src/array.js b/deps/v8/src/array.js index 914b82a80..a29015a5e 100644 --- a/deps/v8/src/array.js +++ b/deps/v8/src/array.js @@ -994,11 +994,16 @@ function ArrayIndexOf(element, index) { // 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 @@ function ArrayLastIndexOf(element, index) { 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/deps/v8/src/ast.h b/deps/v8/src/ast.h index 262bf17c7..8248f62a8 100644 --- a/deps/v8/src/ast.h +++ b/deps/v8/src/ast.h @@ -196,10 +196,7 @@ class Expression: public AstNode { kTestValue }; - Expression() - : bitfields_(0), - def_(NULL), - defined_vars_(NULL) {} + Expression() : bitfields_(0) {} virtual Expression* AsExpression() { return this; } @@ -233,15 +230,6 @@ class Expression: public AstNode { // 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 @@ class Expression: public AstNode { 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/deps/v8/src/cached-powers.h b/deps/v8/src/cached-powers.h new file mode 100644 index 000000000..314ccca3c --- /dev/null +++ b/deps/v8/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/deps/v8/src/checks.h b/deps/v8/src/checks.h index eeb748b4a..cdcd18ad2 100644 --- a/deps/v8/src/checks.h +++ b/deps/v8/src/checks.h @@ -80,6 +80,7 @@ static inline void CheckEqualsHelper(const char* file, int line, } } + // 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 CheckEqualsHelper(const char* file, } +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/deps/v8/src/circular-queue-inl.h b/deps/v8/src/circular-queue-inl.h new file mode 100644 index 000000000..ffe8fb003 --- /dev/null +++ b/deps/v8/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/deps/v8/src/circular-queue.cc b/deps/v8/src/circular-queue.cc new file mode 100644 index 000000000..5f7a33eb3 --- /dev/null +++ b/deps/v8/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/deps/v8/src/circular-queue.h b/deps/v8/src/circular-queue.h new file mode 100644 index 000000000..11159e038 --- /dev/null +++ b/deps/v8/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/deps/v8/src/conversions.cc b/deps/v8/src/conversions.cc index fd6d38d84..d0abc2b31 100644 --- a/deps/v8/src/conversions.cc +++ b/deps/v8/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 @@ const char* DoubleToCString(double v, Vector<char> buffer) { 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 @@ const char* DoubleToCString(double v, Vector<char> buffer) { builder.AddFormatted("%d", exponent); } - freedtoa(decimal_rep); + if (used_gay_dtoa) freedtoa(decimal_rep); } } return builder.Finalize(); diff --git a/deps/v8/src/counters.h b/deps/v8/src/counters.h index 5f4dca927..aed46cfb3 100644 --- a/deps/v8/src/counters.h +++ b/deps/v8/src/counters.h @@ -65,7 +65,7 @@ class StatsTable : public AllStatic { // 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/deps/v8/src/cpu-profiler-inl.h b/deps/v8/src/cpu-profiler-inl.h new file mode 100644 index 000000000..26ab643c3 --- /dev/null +++ b/deps/v8/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/deps/v8/src/cpu-profiler.cc b/deps/v8/src/cpu-profiler.cc new file mode 100644 index 000000000..d36f51120 --- /dev/null +++ b/deps/v8/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/deps/v8/src/cpu-profiler.h b/deps/v8/src/cpu-profiler.h new file mode 100644 index 000000000..ccfac5c5c --- /dev/null +++ b/deps/v8/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/deps/v8/src/data-flow.cc b/deps/v8/src/data-flow.cc index 278b82bc6..141718dc8 100644 --- a/deps/v8/src/data-flow.cc +++ b/deps/v8/src/data-flow.cc @@ -770,293 +770,6 @@ void AstLabeler::VisitDeclaration(Declaration* decl) { } -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/deps/v8/src/data-flow.h b/deps/v8/src/data-flow.h index 97020137a..74a370c0d 100644 --- a/deps/v8/src/data-flow.h +++ b/deps/v8/src/data-flow.h @@ -550,55 +550,6 @@ class AstLabeler: public AstVisitor { }; -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/deps/v8/src/diy-fp.cc b/deps/v8/src/diy-fp.cc new file mode 100644 index 000000000..c54bd1d32 --- /dev/null +++ b/deps/v8/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/deps/v8/src/diy-fp.h b/deps/v8/src/diy-fp.h new file mode 100644 index 000000000..cfe05ef74 --- /dev/null +++ b/deps/v8/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/deps/v8/src/double.h b/deps/v8/src/double.h new file mode 100644 index 000000000..65f8c9444 --- /dev/null +++ b/deps/v8/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/deps/v8/src/fast-codegen.cc b/deps/v8/src/fast-codegen.cc index 602d6b88c..5d0b9c1db 100644 --- a/deps/v8/src/fast-codegen.cc +++ b/deps/v8/src/fast-codegen.cc @@ -436,9 +436,6 @@ Handle<Code> FastCodeGenerator::MakeCode(CompilationInfo* info) { AstLabeler labeler; labeler.Label(info); - LivenessAnalyzer analyzer; - analyzer.Analyze(info->function()); - CodeGenerator::MakeCodePrologue(info); const int kInitialBufferSize = 4 * KB; @@ -598,8 +595,8 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 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 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { 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 @@ void FastCodeGenerator::VisitProperty(Property* expr) { 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/deps/v8/src/fast-dtoa.cc b/deps/v8/src/fast-dtoa.cc new file mode 100644 index 000000000..029954416 --- /dev/null +++ b/deps/v8/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()), + ÷r, ÷r_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/deps/v8/src/fast-dtoa.h b/deps/v8/src/fast-dtoa.h new file mode 100644 index 000000000..91f6ce76b --- /dev/null +++ b/deps/v8/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/deps/v8/src/frames.cc b/deps/v8/src/frames.cc index 3bf4c93e3..24550a2ed 100644 --- a/deps/v8/src/frames.cc +++ b/deps/v8/src/frames.cc @@ -306,14 +306,12 @@ void SafeStackTraceFrameIterator::Advance() { 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 @@ bool StackFrame::HasHandler() const { 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::CookFramesForThread(ThreadLocalTop* thread) { 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 @@ void JavaScriptFrame::Print(StringStream* accumulator, 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/deps/v8/src/globals.h b/deps/v8/src/globals.h index 0a23f820b..cb7f27ee7 100644 --- a/deps/v8/src/globals.h +++ b/deps/v8/src/globals.h @@ -98,6 +98,11 @@ typedef byte* Address; #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/deps/v8/src/handles.cc b/deps/v8/src/handles.cc index 53c16a499..4ebeaa79c 100644 --- a/deps/v8/src/handles.cc +++ b/deps/v8/src/handles.cc @@ -514,6 +514,30 @@ int GetScriptLineNumber(Handle<Script> script, int code_pos) { } +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/deps/v8/src/handles.h b/deps/v8/src/handles.h index 0c137a4ce..f241da203 100644 --- a/deps/v8/src/handles.h +++ b/deps/v8/src/handles.h @@ -267,6 +267,8 @@ Handle<JSValue> GetScriptWrapper(Handle<Script> script); // 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/deps/v8/src/heap.h b/deps/v8/src/heap.h index 18ab44bf8..1aee8749a 100644 --- a/deps/v8/src/heap.h +++ b/deps/v8/src/heap.h @@ -1165,26 +1165,26 @@ class Heap : public AllStatic { 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/deps/v8/src/ia32/codegen-ia32.cc b/deps/v8/src/ia32/codegen-ia32.cc index 2b3d4d99b..67c9cc130 100644 --- a/deps/v8/src/ia32/codegen-ia32.cc +++ b/deps/v8/src/ia32/codegen-ia32.cc @@ -832,7 +832,7 @@ void CodeGenerator::ToBoolean(ControlDestination* dest) { 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 @@ void CodeGenerator::ToBoolean(ControlDestination* dest) { 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 @@ void DeferredInlineBinaryOperation::Generate() { __ jmp(&load_right); __ bind(&left_smi); + } else { + if (FLAG_debug_code) __ AbortIfNotSmi(left_); } __ SmiUntag(left_); __ cvtsi2sd(xmm0, Operand(left_)); @@ -1070,6 +1072,8 @@ void DeferredInlineBinaryOperation::Generate() { __ jmp(&do_op); __ bind(&right_smi); + } else { + if (FLAG_debug_code) __ AbortIfNotSmi(right_); } __ SmiUntag(right_); __ cvtsi2sd(xmm1, Operand(right_)); @@ -1575,7 +1579,7 @@ Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, 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 @@ Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, 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 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 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 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 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 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, } 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 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 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 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, __ 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 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 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 @@ Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 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 @@ void CodeGenerator::Comparison(AstNode* node, // 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::VisitWhileStatement(WhileStatement* node) { } +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 @@ void CodeGenerator::VisitForStatement(ForStatement* node) { 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,6 +3794,13 @@ void CodeGenerator::VisitForStatement(ForStatement* node) { } } + // 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. + SetTypeForStackSlot(node->loop_variable()->slot(), NumberInfo::Smi()); + } + // Based on the condition analysis, compile the backward jump as // necessary. switch (info) { @@ -6676,9 +6714,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 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)); @@ -6867,15 +6903,18 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) { old_value = allocator_->Allocate(); ASSERT(old_value.is_valid()); __ mov(old_value.reg(), new_value.reg()); + + // The return value for postfix operations is the + // same as the input, and has the same number info. + old_value.set_number_info(new_value.number_info()); } + // Ensure the new value is writable. frame_->Spill(new_value.reg()); 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 @@ -6931,6 +6970,13 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) { } deferred->BindExit(); + // The result of ++ or -- is an Integer32 if the + // input is a smi. Otherwise it is a number. + if (new_value.is_smi()) { + new_value.set_number_info(NumberInfo::Integer32()); + } else { + new_value.set_number_info(NumberInfo::Number()); + } // Postfix: store the old value in the allocated slot under the // reference. @@ -7832,6 +7878,8 @@ Result CodeGenerator::EmitKeyedLoad() { 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 @@ -7985,6 +8033,8 @@ static void CheckTwoForSminess(MacroAssembler* masm, 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()) { @@ -7995,11 +8045,15 @@ static void CheckTwoForSminess(MacroAssembler* masm, } 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); } } } @@ -8506,6 +8560,10 @@ void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) { } if (static_operands_type_.IsSmi()) { + if (FLAG_debug_code) { + __ AbortIfNotSmi(left); + __ AbortIfNotSmi(right); + } if (op_ == Token::BIT_OR) { __ or_(right, Operand(left)); GenerateReturn(masm); @@ -8860,12 +8918,14 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { 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); @@ -8888,10 +8948,8 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { 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); @@ -9621,6 +9679,8 @@ void FloatingPointHelper::LoadNumbersAsIntegers(MacroAssembler* masm, 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); @@ -9639,6 +9699,8 @@ void FloatingPointHelper::LoadNumbersAsIntegers(MacroAssembler* masm, 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); @@ -10526,15 +10588,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { __ 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/deps/v8/src/ia32/codegen-ia32.h b/deps/v8/src/ia32/codegen-ia32.h index 89318ce5e..c7ff2e875 100644 --- a/deps/v8/src/ia32/codegen-ia32.h +++ b/deps/v8/src/ia32/codegen-ia32.h @@ -500,7 +500,7 @@ class CodeGenerator: public AstVisitor { 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 @@ class CodeGenerator: public AstVisitor { // 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 @@ class CodeGenerator: public AstVisitor { 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/deps/v8/src/ia32/fast-codegen-ia32.cc b/deps/v8/src/ia32/fast-codegen-ia32.cc index 4dcf2329a..01190a598 100644 --- a/deps/v8/src/ia32/fast-codegen-ia32.cc +++ b/deps/v8/src/ia32/fast-codegen-ia32.cc @@ -436,9 +436,6 @@ Handle<Code> FastCodeGenerator::MakeCode(CompilationInfo* info) { AstLabeler labeler; labeler.Label(info); - LivenessAnalyzer analyzer; - analyzer.Analyze(info->function()); - CodeGenerator::MakeCodePrologue(info); const int kInitialBufferSize = 4 * KB; @@ -802,8 +799,8 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 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 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { 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 @@ void FastCodeGenerator::VisitProperty(Property* expr) { 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/deps/v8/src/ia32/macro-assembler-ia32.cc b/deps/v8/src/ia32/macro-assembler-ia32.cc index 703ca793a..352933678 100644 --- a/deps/v8/src/ia32/macro-assembler-ia32.cc +++ b/deps/v8/src/ia32/macro-assembler-ia32.cc @@ -351,20 +351,20 @@ void MacroAssembler::FCmp() { } -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::Abort(const char* msg) { void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii( Register instance_type, Register scratch, - Label *failure) { + Label* failure) { if (!scratch.is(instance_type)) { mov(scratch, instance_type); } diff --git a/deps/v8/src/ia32/macro-assembler-ia32.h b/deps/v8/src/ia32/macro-assembler-ia32.h index 00243d76f..caa96da2e 100644 --- a/deps/v8/src/ia32/macro-assembler-ia32.h +++ b/deps/v8/src/ia32/macro-assembler-ia32.h @@ -182,17 +182,18 @@ class MacroAssembler: public Assembler { // 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 @@ class MacroAssembler: public Assembler { // 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 @@ class MacroAssembler: public Assembler { 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/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc b/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc index 74b9d129c..c6accbda9 100644 --- a/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc +++ b/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc @@ -653,6 +653,8 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { __ 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 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { __ 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 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { // 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/deps/v8/src/ia32/virtual-frame-ia32.h b/deps/v8/src/ia32/virtual-frame-ia32.h index 69c3e47d2..e622cdfe0 100644 --- a/deps/v8/src/ia32/virtual-frame-ia32.h +++ b/deps/v8/src/ia32/virtual-frame-ia32.h @@ -446,8 +446,9 @@ class VirtualFrame: public ZoneObject { 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/deps/v8/src/jsregexp.cc b/deps/v8/src/jsregexp.cc index 505cf03e5..f3c801c7e 100644 --- a/deps/v8/src/jsregexp.cc +++ b/deps/v8/src/jsregexp.cc @@ -149,7 +149,7 @@ Handle<Object> RegExpImpl::Compile(Handle<JSRegExp> re, 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 @@ Code* RegExpImpl::IrregexpNativeCode(FixedArray* re, bool is_ascii) { } -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 @@ void RegExpImpl::IrregexpPrepare(Handle<JSRegExp> re, } +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 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp, 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 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp, } #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; - } - if (captures_vector[i + 1] >= 0) { - captures_vector[i + 1] += 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]); } - 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/deps/v8/src/jsregexp.h b/deps/v8/src/jsregexp.h index 46d53c215..8f0134261 100644 --- a/deps/v8/src/jsregexp.h +++ b/deps/v8/src/jsregexp.h @@ -77,10 +77,10 @@ class RegExpImpl { 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 @@ class RegExpImpl { 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/deps/v8/src/liveedit.cc b/deps/v8/src/liveedit.cc index 4533f9c7d..55308ab67 100644 --- a/deps/v8/src/liveedit.cc +++ b/deps/v8/src/liveedit.cc @@ -391,6 +391,26 @@ class ReferenceCollectorVisitor : public ObjectVisitor { 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 @@ static void ReplaceCodeObject(Code* original, Code* substitution) { // 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/deps/v8/src/math.js b/deps/v8/src/math.js index 0623cb82d..d17a6fdf5 100644 --- a/deps/v8/src/math.js +++ b/deps/v8/src/math.js @@ -171,7 +171,7 @@ function MathRandom() { // 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/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h index 4cc9b9f83..e7daa2d68 100644 --- a/deps/v8/src/objects-inl.h +++ b/deps/v8/src/objects-inl.h @@ -1121,6 +1121,17 @@ void HeapNumber::set_value(double value) { } +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/deps/v8/src/objects.h b/deps/v8/src/objects.h index b3fe44846..d69657020 100644 --- a/deps/v8/src/objects.h +++ b/deps/v8/src/objects.h @@ -1094,6 +1094,9 @@ class HeapNumber: public HeapObject { 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/deps/v8/src/parser.cc b/deps/v8/src/parser.cc index 74f69970e..cff56a395 100644 --- a/deps/v8/src/parser.cc +++ b/deps/v8/src/parser.cc @@ -1585,13 +1585,15 @@ class ThisNamedPropertyAssigmentFinder : public ParserFinder { } 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/deps/v8/src/platform.h b/deps/v8/src/platform.h index bc2e9d64f..f124cf157 100644 --- a/deps/v8/src/platform.h +++ b/deps/v8/src/platform.h @@ -114,6 +114,10 @@ int random(); 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 @@ class TickSample { 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/deps/v8/src/powers-ten.h b/deps/v8/src/powers-ten.h new file mode 100644 index 000000000..93d92d917 --- /dev/null +++ b/deps/v8/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/deps/v8/src/profile-generator-inl.h b/deps/v8/src/profile-generator-inl.h index 090ad8f30..5e92be470 100644 --- a/deps/v8/src/profile-generator-inl.h +++ b/deps/v8/src/profile-generator-inl.h @@ -34,6 +34,17 @@ namespace v8 { 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 @@ bool CodeEntry::is_js_function() { } -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/deps/v8/src/profile-generator.cc b/deps/v8/src/profile-generator.cc index 5c64d362c..7f020c5bb 100644 --- a/deps/v8/src/profile-generator.cc +++ b/deps/v8/src/profile-generator.cc @@ -53,6 +53,15 @@ ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) { } +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 @@ CodeEntry* CodeMap::FindEntry(Address addr) { } -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); + +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* 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. +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 ""; } +} - CodeEntry* entry = new ManagedNameCodeEntry(tag, - name, - cached_resource_name, - line_number); - code_entries_.Add(entry); - return entry; + +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]; } -CodeEntry* ProfileGenerator::NewCodeEntry( - Logger::LogEventsAndTags tag, - const char* name) { - CodeEntry* entry = new StaticNameCodeEntry(tag, name); - code_entries_.Add(entry); - return entry; +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; + } + + 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); } + } } // namespace v8::internal diff --git a/deps/v8/src/profile-generator.h b/deps/v8/src/profile-generator.h index c3843bf91..c0454cb82 100644 --- a/deps/v8/src/profile-generator.h +++ b/deps/v8/src/profile-generator.h @@ -36,50 +36,22 @@ namespace internal { 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 @@ class ProfileNode { 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 ProfileTree BASE_EMBEDDED { }; -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 CodeMap BASE_EMBEDDED { }; -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(CodeMap* code_map()) { return &code_map_; } + 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 key1 == key2; + return strcmp(reinterpret_cast<char*>(key1), + reinterpret_cast<char*>(key2)) == 0; } - INLINE(static bool StringEntryHash(String* entry)) { - return entry->Hash(); + // 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); } - CpuProfile profile_; + 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(CpuProfile* profile()) { return profiles_->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/deps/v8/src/rewriter.cc b/deps/v8/src/rewriter.cc index b05b0453a..e87fccec1 100644 --- a/deps/v8/src/rewriter.cc +++ b/deps/v8/src/rewriter.cc @@ -247,7 +247,9 @@ void AstOptimizer::VisitVariableProxy(VariableProxy* node) { } if (FLAG_safe_int32_compiler) { - if (var->IsStackAllocated() && !var->is_arguments()) { + if (var->IsStackAllocated() && + !var->is_arguments() && + var->mode() != Variable::CONST) { node->set_side_effect_free(true); } } diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc index 4e4856dd8..0fe24579b 100644 --- a/deps/v8/src/runtime.cc +++ b/deps/v8/src/runtime.cc @@ -2353,6 +2353,14 @@ template <typename schar> 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 @@ static int SimpleIndexOf(Vector<const schar> subject, *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 @@ static int SimpleIndexOf(Vector<const schar> subject, 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_pow_cfunction(Arguments args) { } -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 @@ static const char kMonthInYear[] = { // 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 DateYMDFromTimeAfter1970(int date, 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 @@ static inline void DateYMDFromTimeSlow(int date, 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 DateYMDFromTimeSlow(int date, 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/deps/v8/src/runtime.h b/deps/v8/src/runtime.h index 05f09f6f3..4175902c4 100644 --- a/deps/v8/src/runtime.h +++ b/deps/v8/src/runtime.h @@ -145,7 +145,7 @@ namespace internal { 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/deps/v8/src/serialize.cc b/deps/v8/src/serialize.cc index a95a7d6aa..0e3815183 100644 --- a/deps/v8/src/serialize.cc +++ b/deps/v8/src/serialize.cc @@ -477,7 +477,7 @@ int ExternalReferenceEncoder::IndexOf(Address key) const { 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 @@ int SerializerDeserializer::partial_snapshot_cache_length_ = 0; // 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/deps/v8/src/top.cc b/deps/v8/src/top.cc index 3efd1fc80..0fcf45866 100644 --- a/deps/v8/src/top.cc +++ b/deps/v8/src/top.cc @@ -88,6 +88,17 @@ char* Top::Iterate(ObjectVisitor* v, char* thread_storage) { } +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/deps/v8/src/top.h b/deps/v8/src/top.h index e20a2a0f1..d263777b9 100644 --- a/deps/v8/src/top.h +++ b/deps/v8/src/top.h @@ -40,6 +40,7 @@ namespace internal { // 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 @@ class Top { 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/deps/v8/src/utils.h b/deps/v8/src/utils.h index 3c8d873ed..89cc5ef4a 100644 --- a/deps/v8/src/utils.h +++ b/deps/v8/src/utils.h @@ -341,7 +341,6 @@ class Vector { // 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/deps/v8/src/v8.cc b/deps/v8/src/v8.cc index 395336117..395401d91 100644 --- a/deps/v8/src/v8.cc +++ b/deps/v8/src/v8.cc @@ -43,7 +43,7 @@ bool V8::has_been_setup_ = false; 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/deps/v8/src/v8threads.cc b/deps/v8/src/v8threads.cc index 80a7cd94f..02292f6d0 100644 --- a/deps/v8/src/v8threads.cc +++ b/deps/v8/src/v8threads.cc @@ -331,6 +331,17 @@ void ThreadManager::Iterate(ObjectVisitor* v) { } +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/deps/v8/src/v8threads.h b/deps/v8/src/v8threads.h index 068405328..d70aa3c89 100644 --- a/deps/v8/src/v8threads.h +++ b/deps/v8/src/v8threads.h @@ -79,6 +79,20 @@ class ThreadState { }; +// 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 @@ class ThreadManager : public AllStatic { 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/deps/v8/src/version.cc b/deps/v8/src/version.cc index f4f539c31..74bef65b6 100644 --- a/deps/v8/src/version.cc +++ b/deps/v8/src/version.cc @@ -34,7 +34,7 @@ // cannot be changed without changing the SCons build script. #define MAJOR_VERSION 2 #define MINOR_VERSION 1 -#define BUILD_NUMBER 6 +#define BUILD_NUMBER 7 #define PATCH_LEVEL 0 #define CANDIDATE_VERSION false diff --git a/deps/v8/src/virtual-frame-inl.h b/deps/v8/src/virtual-frame-inl.h index ff599d08d..4050d715b 100644 --- a/deps/v8/src/virtual-frame-inl.h +++ b/deps/v8/src/virtual-frame-inl.h @@ -125,6 +125,11 @@ void VirtualFrame::SetTypeForLocalAt(int index, NumberInfo info) { } +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/deps/v8/src/x64/assembler-x64.cc b/deps/v8/src/x64/assembler-x64.cc index a994f45b1..cedb7408e 100644 --- a/deps/v8/src/x64/assembler-x64.cc +++ b/deps/v8/src/x64/assembler-x64.cc @@ -1030,6 +1030,22 @@ void Assembler::imull(Register dst, Register src) { } +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::lea(Register dst, const Operand& src) { } +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 @@ void Assembler::movb(Register dst, const Operand& src) { emit_operand(dst, src); } + void Assembler::movb(Register dst, Immediate imm) { EnsureSpace ensure_space(this); last_pc_ = pc_; @@ -1228,6 +1254,7 @@ void Assembler::movb(Register dst, Immediate imm) { emit(imm.value_); } + void Assembler::movb(const Operand& dst, Register src) { EnsureSpace ensure_space(this); last_pc_ = pc_; @@ -1236,6 +1263,7 @@ void Assembler::movb(const Operand& dst, Register src) { emit_operand(src, dst); } + void Assembler::movw(const Operand& dst, Register src) { EnsureSpace ensure_space(this); last_pc_ = pc_; @@ -1245,6 +1273,7 @@ void Assembler::movw(const Operand& dst, Register src) { 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::not_(const Operand& dst) { } +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/deps/v8/src/x64/assembler-x64.h b/deps/v8/src/x64/assembler-x64.h index 501952550..e3ad488d4 100644 --- a/deps/v8/src/x64/assembler-x64.h +++ b/deps/v8/src/x64/assembler-x64.h @@ -742,14 +742,16 @@ class Assembler : public Malloced { 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 @@ class Assembler : public Malloced { 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/deps/v8/src/x64/codegen-x64.cc b/deps/v8/src/x64/codegen-x64.cc index 8ec1c9505..a6b0ffcef 100644 --- a/deps/v8/src/x64/codegen-x64.cc +++ b/deps/v8/src/x64/codegen-x64.cc @@ -7182,12 +7182,6 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { // 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 @@ const char* GenericBinaryOpStub::GetName() { } 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 @@ Result GenericBinaryOpStub::GenerateCall(MacroAssembler* masm, 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 @@ void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) { 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::GenerateSmiCode(MacroAssembler* masm, Label* slow) { 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 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { } else { FloatingPointHelper::CheckNumberOperands(masm, &call_runtime); } - // 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; + // 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(); } - } - 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(¬_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 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { __ 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 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { // 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, ¬_string1); __ CmpObjectType(lhs, FIRST_NONSTRING_TYPE, r8); @@ -8974,15 +8996,22 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { 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::GenerateReturn(MacroAssembler* masm) { } +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/deps/v8/src/x64/codegen-x64.h b/deps/v8/src/x64/codegen-x64.h index ce5f6d1d3..42b499312 100644 --- a/deps/v8/src/x64/codegen-x64.h +++ b/deps/v8/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 @@ class GenericBinaryOpStub: public CodeStub { 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 @@ class GenericBinaryOpStub: public CodeStub { 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 @@ class GenericBinaryOpStub: public CodeStub { 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 @@ class GenericBinaryOpStub: public CodeStub { 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/deps/v8/src/x64/disasm-x64.cc b/deps/v8/src/x64/disasm-x64.cc index 547daeeb1..9ba364a5f 100644 --- a/deps/v8/src/x64/disasm-x64.cc +++ b/deps/v8/src/x64/disasm-x64.cc @@ -1273,7 +1273,9 @@ int DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer, get_modrm(*(data + 1), &mod, ®op, &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/deps/v8/src/x64/ic-x64.cc b/deps/v8/src/x64/ic-x64.cc index e05f68dca..1d28a1f48 100644 --- a/deps/v8/src/x64/ic-x64.cc +++ b/deps/v8/src/x64/ic-x64.cc @@ -151,6 +151,108 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, } +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 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { // ----------------------------------- 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 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { // 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 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { __ 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 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { __ 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/deps/v8/src/x64/regexp-macro-assembler-x64.cc b/deps/v8/src/x64/regexp-macro-assembler-x64.cc index 6e7d9c9e0..3fe6be2b7 100644 --- a/deps/v8/src/x64/regexp-macro-assembler-x64.cc +++ b/deps/v8/src/x64/regexp-macro-assembler-x64.cc @@ -711,9 +711,15 @@ Handle<Object> RegExpMacroAssemblerX64::GetCode(Handle<String> source) { __ 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 @@ Handle<Object> RegExpMacroAssemblerX64::GetCode(Handle<String> source) { __ 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/deps/v8/src/x64/virtual-frame-x64.h b/deps/v8/src/x64/virtual-frame-x64.h index e93140eae..3e9f6dd65 100644 --- a/deps/v8/src/x64/virtual-frame-x64.h +++ b/deps/v8/src/x64/virtual-frame-x64.h @@ -417,6 +417,7 @@ class VirtualFrame : public ZoneObject { 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; |