Version 2.1.4
Fixed code cache lookup for keyed IC's (issue http://crbug.com/37853).
Performance improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@4127 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/SConscript b/src/SConscript
index d61da3e..44b6b5b 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -63,6 +63,7 @@
full-codegen.cc
func-name-inferrer.cc
global-handles.cc
+ grisu3.cc
handles.cc
hashmap.cc
heap-profiler.cc
diff --git a/src/api.cc b/src/api.cc
index 93fce79..af2e7ad 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -3580,6 +3580,7 @@
int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
#ifdef ENABLE_LOGGING_AND_PROFILING
+ ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
#endif
return 0;
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 9e59582..3bf3fb8 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -2709,18 +2709,20 @@
Comment cmnt(masm_, "[ ObjectLiteral");
// Load the function of this activation.
- __ ldr(r2, frame_->Function());
+ __ ldr(r3, frame_->Function());
// Literal array.
- __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset));
+ __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
// Literal index.
- __ mov(r1, Operand(Smi::FromInt(node->literal_index())));
+ __ mov(r2, Operand(Smi::FromInt(node->literal_index())));
// Constant properties.
- __ mov(r0, Operand(node->constant_properties()));
- frame_->EmitPushMultiple(3, r2.bit() | r1.bit() | r0.bit());
+ __ mov(r1, Operand(node->constant_properties()));
+ // Should the object literal have fast elements?
+ __ mov(r0, Operand(Smi::FromInt(node->fast_elements() ? 1 : 0)));
+ frame_->EmitPushMultiple(4, r3.bit() | r2.bit() | r1.bit() | r0.bit());
if (node->depth() > 1) {
- frame_->CallRuntime(Runtime::kCreateObjectLiteral, 3);
+ frame_->CallRuntime(Runtime::kCreateObjectLiteral, 4);
} else {
- frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 3);
+ frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
}
frame_->EmitPush(r0); // save the result
for (int i = 0; i < node->properties()->length(); i++) {
@@ -3597,7 +3599,7 @@
}
-void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
+void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope;
ASSERT(args->length() == 1);
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index bea98b6..9ade70a 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -197,6 +197,10 @@
static const int kUnknownIntValue = -1;
+ // If the name is an inline runtime function call return the number of
+ // expected arguments. Otherwise return -1.
+ static int InlineRuntimeCallArgumentsCount(Handle<String> name);
+
private:
// Construction/Destruction
explicit CodeGenerator(MacroAssembler* masm);
@@ -326,6 +330,7 @@
struct InlineRuntimeLUT {
void (CodeGenerator::*method)(ZoneList<Expression*>*);
const char* name;
+ int nargs;
};
static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
@@ -360,7 +365,7 @@
// Support for arguments.length and arguments[?].
void GenerateArgumentsLength(ZoneList<Expression*>* args);
- void GenerateArgumentsAccess(ZoneList<Expression*>* args);
+ void GenerateArguments(ZoneList<Expression*>* args);
// Support for accessing the class and value fields of an object.
void GenerateClassOf(ZoneList<Expression*>* args);
@@ -396,14 +401,10 @@
// Fast support for number to string.
void GenerateNumberToString(ZoneList<Expression*>* args);
- // Fast support for Math.pow().
+ // Fast call to math functions.
void GenerateMathPow(ZoneList<Expression*>* args);
-
- // Fast call to sine function.
void GenerateMathSin(ZoneList<Expression*>* args);
void GenerateMathCos(ZoneList<Expression*>* args);
-
- // Fast support for Math.pow().
void GenerateMathSqrt(ZoneList<Expression*>* args);
// Simple condition analysis.
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 230818f..a70cf44 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -783,15 +783,16 @@
void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral");
- __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
- __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset));
- __ mov(r1, Operand(Smi::FromInt(expr->literal_index())));
- __ mov(r0, Operand(expr->constant_properties()));
- __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit());
+ __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
+ __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
+ __ mov(r1, Operand(expr->constant_properties()));
+ __ mov(r0, Operand(Smi::FromInt(expr->fast_elements() ? 1 : 0)));
+ __ stm(db_w, sp, r3.bit() | r2.bit() | r1.bit() | r0.bit());
if (expr->depth() > 1) {
- __ CallRuntime(Runtime::kCreateObjectLiteral, 3);
+ __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
} else {
- __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3);
+ __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
}
// If result_saved is true the result is on top of the stack. If
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 36bebdf..bc779eb 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -280,9 +280,9 @@
// Clobber all input registers when running with the debug-code flag
// turned on to provoke errors.
if (FLAG_debug_code) {
- mov(object, Operand(bit_cast<int32_t>(kZapValue)));
- mov(offset, Operand(bit_cast<int32_t>(kZapValue)));
- mov(scratch, Operand(bit_cast<int32_t>(kZapValue)));
+ mov(object, Operand(BitCast<int32_t>(kZapValue)));
+ mov(offset, Operand(BitCast<int32_t>(kZapValue)));
+ mov(scratch, Operand(BitCast<int32_t>(kZapValue)));
}
}
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 5d5b2a5..abf2f64 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -815,6 +815,104 @@
}
+Object* CallStubCompiler::CompileArrayPushCall(Object* object,
+ JSObject* holder,
+ JSFunction* function,
+ String* name,
+ CheckType check) {
+ // ----------- S t a t e -------------
+ // -- r2 : name
+ // -- lr : return address
+ // -----------------------------------
+
+ // TODO(639): faster implementation.
+ ASSERT(check == RECEIVER_MAP_CHECK);
+
+ Label miss;
+
+ // Get the receiver from the stack
+ const int argc = arguments().immediate();
+ __ ldr(r1, MemOperand(sp, argc * kPointerSize));
+
+ // Check that the receiver isn't a smi.
+ __ tst(r1, Operand(kSmiTagMask));
+ __ b(eq, &miss);
+
+ // Check that the maps haven't changed.
+ CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss);
+
+ if (object->IsGlobalObject()) {
+ __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
+ __ str(r3, MemOperand(sp, argc * kPointerSize));
+ }
+
+ __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
+ argc + 1,
+ 1);
+
+ // Handle call cache miss.
+ __ bind(&miss);
+ Handle<Code> ic = ComputeCallMiss(arguments().immediate());
+ __ Jump(ic, RelocInfo::CODE_TARGET);
+
+ // Return the generated code.
+ String* function_name = NULL;
+ if (function->shared()->name()->IsString()) {
+ function_name = String::cast(function->shared()->name());
+ }
+ return GetCode(CONSTANT_FUNCTION, function_name);
+}
+
+
+Object* CallStubCompiler::CompileArrayPopCall(Object* object,
+ JSObject* holder,
+ JSFunction* function,
+ String* name,
+ CheckType check) {
+ // ----------- S t a t e -------------
+ // -- r2 : name
+ // -- lr : return address
+ // -----------------------------------
+
+ // TODO(642): faster implementation.
+ ASSERT(check == RECEIVER_MAP_CHECK);
+
+ Label miss;
+
+ // Get the receiver from the stack
+ const int argc = arguments().immediate();
+ __ ldr(r1, MemOperand(sp, argc * kPointerSize));
+
+ // Check that the receiver isn't a smi.
+ __ tst(r1, Operand(kSmiTagMask));
+ __ b(eq, &miss);
+
+ // Check that the maps haven't changed.
+ CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss);
+
+ if (object->IsGlobalObject()) {
+ __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
+ __ str(r3, MemOperand(sp, argc * kPointerSize));
+ }
+
+ __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop),
+ argc + 1,
+ 1);
+
+ // Handle call cache miss.
+ __ bind(&miss);
+ Handle<Code> ic = ComputeCallMiss(arguments().immediate());
+ __ Jump(ic, RelocInfo::CODE_TARGET);
+
+ // Return the generated code.
+ String* function_name = NULL;
+ if (function->shared()->name()->IsString()) {
+ function_name = String::cast(function->shared()->name());
+ }
+ return GetCode(CONSTANT_FUNCTION, function_name);
+}
+
+
Object* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder,
JSFunction* function,
@@ -824,6 +922,13 @@
// -- r2 : name
// -- lr : return address
// -----------------------------------
+ SharedFunctionInfo* function_info = function->shared();
+ if (function_info->HasCustomCallGenerator()) {
+ CustomCallGenerator generator =
+ ToCData<CustomCallGenerator>(function_info->function_data());
+ return generator(this, object, holder, function, name, check);
+ }
+
Label miss;
// Get the receiver from the stack
@@ -916,18 +1021,6 @@
break;
}
- case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
- CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss);
- // Make sure object->HasFastElements().
- // Get the elements array of the object.
- __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
- // Check that the object is in fast mode (not dictionary).
- __ ldr(r0, FieldMemOperand(r3, HeapObject::kMapOffset));
- __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
- __ cmp(r0, ip);
- __ b(ne, &miss);
- break;
-
default:
UNREACHABLE();
}
diff --git a/src/arm/virtual-frame-arm.h b/src/arm/virtual-frame-arm.h
index 6eb0811..7375b31 100644
--- a/src/arm/virtual-frame-arm.h
+++ b/src/arm/virtual-frame-arm.h
@@ -364,6 +364,8 @@
// the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
inline void Nip(int num_dropped);
+ inline void SetTypeForLocalAt(int index, NumberInfo info);
+
private:
static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;
diff --git a/src/array.js b/src/array.js
index e33c280..95d4ada 100644
--- a/src/array.js
+++ b/src/array.js
@@ -1088,15 +1088,6 @@
return IS_ARRAY(obj);
}
-// -------------------------------------------------------------------
-
-
-function UpdateFunctionLengths(lengths) {
- for (var key in lengths) {
- %FunctionSetLength(this[key], lengths[key]);
- }
-}
-
// -------------------------------------------------------------------
function SetupArray() {
@@ -1109,47 +1100,47 @@
"isArray", ArrayIsArray
));
+ var specialFunctions = %SpecialArrayFunctions({});
+
+ function getFunction(name, jsBuiltin, len) {
+ var f = jsBuiltin;
+ if (specialFunctions.hasOwnProperty(name)) {
+ f = specialFunctions[name];
+ }
+ if (!IS_UNDEFINED(len)) {
+ %FunctionSetLength(f, len);
+ }
+ return f;
+ }
+
// Setup non-enumerable functions of the Array.prototype object and
// set their names.
- InstallFunctionsOnHiddenPrototype($Array.prototype, DONT_ENUM, $Array(
- "toString", ArrayToString,
- "toLocaleString", ArrayToLocaleString,
- "join", ArrayJoin,
- "pop", ArrayPop,
- "push", ArrayPush,
- "concat", ArrayConcat,
- "reverse", ArrayReverse,
- "shift", ArrayShift,
- "unshift", ArrayUnshift,
- "slice", ArraySlice,
- "splice", ArraySplice,
- "sort", ArraySort,
- "filter", ArrayFilter,
- "forEach", ArrayForEach,
- "some", ArraySome,
- "every", ArrayEvery,
- "map", ArrayMap,
- "indexOf", ArrayIndexOf,
- "lastIndexOf", ArrayLastIndexOf,
- "reduce", ArrayReduce,
- "reduceRight", ArrayReduceRight
- ));
-
// Manipulate the length of some of the functions to meet
// expectations set by ECMA-262 or Mozilla.
- UpdateFunctionLengths({
- ArrayFilter: 1,
- ArrayForEach: 1,
- ArraySome: 1,
- ArrayEvery: 1,
- ArrayMap: 1,
- ArrayIndexOf: 1,
- ArrayLastIndexOf: 1,
- ArrayPush: 1,
- ArrayReduce: 1,
- ArrayReduceRight: 1
- });
-
+ InstallFunctionsOnHiddenPrototype($Array.prototype, DONT_ENUM, $Array(
+ "toString", getFunction("toString", ArrayToString),
+ "toLocaleString", getFunction("toLocaleString", ArrayToLocaleString),
+ "join", getFunction("join", ArrayJoin),
+ "pop", getFunction("pop", ArrayPop),
+ "push", getFunction("push", ArrayPush, 1),
+ "concat", getFunction("concat", ArrayConcat),
+ "reverse", getFunction("reverse", ArrayReverse),
+ "shift", getFunction("shift", ArrayShift),
+ "unshift", getFunction("unshift", ArrayUnshift, 1),
+ "slice", getFunction("slice", ArraySlice, 2),
+ "splice", getFunction("splice", ArraySplice, 2),
+ "sort", getFunction("sort", ArraySort),
+ "filter", getFunction("filter", ArrayFilter, 1),
+ "forEach", getFunction("forEach", ArrayForEach, 1),
+ "some", getFunction("some", ArraySome, 1),
+ "every", getFunction("every", ArrayEvery, 1),
+ "map", getFunction("map", ArrayMap, 1),
+ "indexOf", getFunction("indexOf", ArrayIndexOf, 1),
+ "lastIndexOf", getFunction("lastIndexOf", ArrayLastIndexOf, 1),
+ "reduce", getFunction("reduce", ArrayReduce, 1),
+ "reduceRight", getFunction("reduceRight", ArrayReduceRight, 1)
+ ));
+
%FinishArrayPrototypeSetup($Array.prototype);
}
diff --git a/src/ast.cc b/src/ast.cc
index 062a5c6..339cfa1 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -58,13 +58,27 @@
// ----------------------------------------------------------------------------
// Implementation of other node functionality.
+Assignment* ExpressionStatement::StatementAsSimpleAssignment() {
+ return (expression()->AsAssignment() != NULL &&
+ !expression()->AsAssignment()->is_compound())
+ ? expression()->AsAssignment()
+ : NULL;
+}
+
+
+CountOperation* ExpressionStatement::StatementAsCountOperation() {
+ return expression()->AsCountOperation();
+}
+
+
VariableProxy::VariableProxy(Handle<String> name,
bool is_this,
bool inside_with)
: name_(name),
var_(NULL),
is_this_(is_this),
- inside_with_(inside_with) {
+ inside_with_(inside_with),
+ is_trivial_(false) {
// names must be canonicalized for fast equality checks
ASSERT(name->IsSymbol());
}
@@ -484,5 +498,96 @@
}
}
+// IsPrimitive implementation. IsPrimitive is true if the value of an
+// expression is known at compile-time to be any JS type other than Object
+// (e.g, it is Undefined, Null, Boolean, String, or Number).
+
+// The following expression types are never primitive because they express
+// Object values.
+bool FunctionLiteral::IsPrimitive() { return false; }
+bool FunctionBoilerplateLiteral::IsPrimitive() { return false; }
+bool RegExpLiteral::IsPrimitive() { return false; }
+bool ObjectLiteral::IsPrimitive() { return false; }
+bool ArrayLiteral::IsPrimitive() { return false; }
+bool CatchExtensionObject::IsPrimitive() { return false; }
+bool CallNew::IsPrimitive() { return false; }
+bool ThisFunction::IsPrimitive() { return false; }
+
+
+// The following expression types are not always primitive because we do not
+// have enough information to conclude that they are.
+bool VariableProxy::IsPrimitive() { return false; }
+bool Property::IsPrimitive() { return false; }
+bool Call::IsPrimitive() { return false; }
+bool CallRuntime::IsPrimitive() { return false; }
+
+
+// The value of a conditional is the value of one of the alternatives. It's
+// always primitive if both alternatives are always primitive.
+bool Conditional::IsPrimitive() {
+ return then_expression()->IsPrimitive() && else_expression()->IsPrimitive();
+}
+
+
+// A literal is primitive when it is not a JSObject.
+bool Literal::IsPrimitive() { return !handle()->IsJSObject(); }
+
+
+// The value of an assignment is the value of its right-hand side.
+bool Assignment::IsPrimitive() {
+ switch (op()) {
+ case Token::INIT_VAR:
+ case Token::INIT_CONST:
+ case Token::ASSIGN:
+ return value()->IsPrimitive();
+
+ default:
+ // {|=, ^=, &=, <<=, >>=, >>>=, +=, -=, *=, /=, %=}
+ // Arithmetic operations are always primitive. They express Numbers
+ // with the exception of +, which expresses a Number or a String.
+ return true;
+ }
+}
+
+
+// Throw does not express a value, so it's trivially always primitive.
+bool Throw::IsPrimitive() { return true; }
+
+
+// Unary operations always express primitive values. delete and ! express
+// Booleans, void Undefined, typeof String, +, -, and ~ Numbers.
+bool UnaryOperation::IsPrimitive() { return true; }
+
+
+// Count operations (pre- and post-fix increment and decrement) always
+// express primitive values (Numbers). See ECMA-262-3, 11.3.1, 11.3.2,
+// 11.4.4, ane 11.4.5.
+bool CountOperation::IsPrimitive() { return true; }
+
+
+// Binary operations depend on the operator.
+bool BinaryOperation::IsPrimitive() {
+ switch (op()) {
+ case Token::COMMA:
+ // Value is the value of the right subexpression.
+ return right()->IsPrimitive();
+
+ case Token::OR:
+ case Token::AND:
+ // Value is the value one of the subexpressions.
+ return left()->IsPrimitive() && right()->IsPrimitive();
+
+ default:
+ // {|, ^, &, <<, >>, >>>, +, -, *, /, %}
+ // Arithmetic operations are always primitive. They express Numbers
+ // with the exception of +, which expresses a Number or a String.
+ return true;
+ }
+}
+
+
+// Compare operations always express Boolean values.
+bool CompareOperation::IsPrimitive() { return true; }
+
} } // namespace v8::internal
diff --git a/src/ast.h b/src/ast.h
index 13502dc..0d654b1 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -137,6 +137,7 @@
virtual BreakableStatement* AsBreakableStatement() { return NULL; }
virtual IterationStatement* AsIterationStatement() { return NULL; }
virtual UnaryOperation* AsUnaryOperation() { return NULL; }
+ virtual CountOperation* AsCountOperation() { return NULL; }
virtual BinaryOperation* AsBinaryOperation() { return NULL; }
virtual Assignment* AsAssignment() { return NULL; }
virtual FunctionLiteral* AsFunctionLiteral() { return NULL; }
@@ -161,6 +162,9 @@
virtual Statement* AsStatement() { return this; }
virtual ReturnStatement* AsReturnStatement() { return NULL; }
+ virtual Assignment* StatementAsSimpleAssignment() { return NULL; }
+ virtual CountOperation* StatementAsCountOperation() { return NULL; }
+
bool IsEmpty() { return AsEmptyStatement() != NULL; }
void set_statement_pos(int statement_pos) { statement_pos_ = statement_pos; }
@@ -200,6 +204,8 @@
virtual bool IsValidLeftHandSide() { return false; }
+ virtual Variable* AssignedVar() { return NULL; }
+
// Symbols that cannot be parsed as array indices are considered property
// names. We do not treat symbols that can be array indexes as property
// names because [] for string objects is handled only by keyed ICs.
@@ -214,6 +220,10 @@
// evaluate out of order.
virtual bool IsTrivial() { return false; }
+ // True if the expression always has one of the non-Object JS types
+ // (Undefined, Null, Boolean, String, or Number).
+ virtual bool IsPrimitive() = 0;
+
// Mark the expression as being compiled as an expression
// statement. This is used to transform postfix increments to
// (faster) prefix increments.
@@ -274,6 +284,12 @@
virtual bool IsValidLeftHandSide() { return true; }
virtual void Accept(AstVisitor* v) { UNREACHABLE(); }
static ValidLeftHandSideSentinel* instance() { return &instance_; }
+
+ virtual bool IsPrimitive() {
+ UNREACHABLE();
+ return false;
+ }
+
private:
static ValidLeftHandSideSentinel instance_;
};
@@ -321,6 +337,16 @@
virtual void Accept(AstVisitor* v);
+ virtual Assignment* StatementAsSimpleAssignment() {
+ if (statements_.length() != 1) return NULL;
+ return statements_[0]->StatementAsSimpleAssignment();
+ }
+
+ virtual CountOperation* StatementAsCountOperation() {
+ if (statements_.length() != 1) return NULL;
+ return statements_[0]->StatementAsCountOperation();
+ }
+
void AddStatement(Statement* statement) { statements_.Add(statement); }
ZoneList<Statement*>* statements() { return &statements_; }
@@ -442,8 +468,8 @@
init_(NULL),
cond_(NULL),
next_(NULL),
- may_have_function_literal_(true) {
- }
+ may_have_function_literal_(true),
+ loop_variable_(NULL) {}
void Initialize(Statement* init,
Expression* cond,
@@ -464,12 +490,17 @@
return may_have_function_literal_;
}
+ bool is_fast_smi_loop() { return loop_variable_ != NULL; }
+ Variable* loop_variable() { return loop_variable_; }
+ void set_loop_variable(Variable* var) { loop_variable_ = var; }
+
private:
Statement* init_;
Expression* cond_;
Statement* next_;
// True if there is a function literal subexpression in the condition.
bool may_have_function_literal_;
+ Variable* loop_variable_;
friend class AstOptimizer;
};
@@ -507,6 +538,9 @@
// Type testing & conversion.
virtual ExpressionStatement* AsExpressionStatement() { return this; }
+ virtual Assignment* StatementAsSimpleAssignment();
+ virtual CountOperation* StatementAsCountOperation();
+
void set_expression(Expression* e) { expression_ = e; }
Expression* expression() { return expression_; }
@@ -774,6 +808,7 @@
virtual bool IsLeaf() { return true; }
virtual bool IsTrivial() { return true; }
+ virtual bool IsPrimitive();
// Identity testers.
bool IsNull() const { return handle_.is_identical_to(Factory::null_value()); }
@@ -849,24 +884,31 @@
ZoneList<Property*>* properties,
int literal_index,
bool is_simple,
+ bool fast_elements,
int depth)
: MaterializedLiteral(literal_index, is_simple, depth),
constant_properties_(constant_properties),
- properties_(properties) {}
+ properties_(properties),
+ fast_elements_(fast_elements) {}
virtual ObjectLiteral* AsObjectLiteral() { return this; }
virtual void Accept(AstVisitor* v);
virtual bool IsLeaf() { return properties()->is_empty(); }
+ virtual bool IsPrimitive();
+
Handle<FixedArray> constant_properties() const {
return constant_properties_;
}
ZoneList<Property*>* properties() const { return properties_; }
+ bool fast_elements() const { return fast_elements_; }
+
private:
Handle<FixedArray> constant_properties_;
ZoneList<Property*>* properties_;
+ bool fast_elements_;
};
@@ -884,6 +926,8 @@
virtual bool IsLeaf() { return true; }
+ virtual bool IsPrimitive();
+
Handle<String> pattern() const { return pattern_; }
Handle<String> flags() const { return flags_; }
@@ -910,6 +954,8 @@
virtual bool IsLeaf() { return values()->is_empty(); }
+ virtual bool IsPrimitive();
+
Handle<FixedArray> constant_elements() const { return constant_elements_; }
ZoneList<Expression*>* values() const { return values_; }
@@ -930,6 +976,8 @@
virtual void Accept(AstVisitor* v);
+ virtual bool IsPrimitive();
+
Literal* key() const { return key_; }
VariableProxy* value() const { return value_; }
@@ -964,7 +1012,9 @@
// Reading from a mutable variable is a side effect, but 'this' is
// immutable.
- virtual bool IsTrivial() { return is_this(); }
+ virtual bool IsTrivial() { return is_trivial_; }
+
+ virtual bool IsPrimitive();
bool IsVariable(Handle<String> n) {
return !is_this() && name().is_identical_to(n);
@@ -979,6 +1029,8 @@
Variable* var() const { return var_; }
bool is_this() const { return is_this_; }
bool inside_with() const { return inside_with_; }
+ bool is_trivial() { return is_trivial_; }
+ void set_is_trivial(bool b) { is_trivial_ = b; }
// Bind this proxy to the variable var.
void BindTo(Variable* var);
@@ -988,6 +1040,7 @@
Variable* var_; // resolved variable, or NULL
bool is_this_;
bool inside_with_;
+ bool is_trivial_;
VariableProxy(Handle<String> name, bool is_this, bool inside_with);
explicit VariableProxy(bool is_this);
@@ -1004,6 +1057,11 @@
return &identifier_proxy_;
}
+ virtual bool IsPrimitive() {
+ UNREACHABLE();
+ return false;
+ }
+
private:
explicit VariableProxySentinel(bool is_this) : VariableProxy(is_this) { }
static VariableProxySentinel this_proxy_;
@@ -1047,6 +1105,11 @@
virtual bool IsLeaf() { return true; }
+ virtual bool IsPrimitive() {
+ UNREACHABLE();
+ return false;
+ }
+
bool IsStackAllocated() { return type_ == PARAMETER || type_ == LOCAL; }
// Accessors
@@ -1079,6 +1142,8 @@
virtual bool IsValidLeftHandSide() { return true; }
+ virtual bool IsPrimitive();
+
Expression* obj() const { return obj_; }
Expression* key() const { return key_; }
int position() const { return pos_; }
@@ -1109,6 +1174,8 @@
// Type testing and conversion.
virtual Call* AsCall() { return this; }
+ virtual bool IsPrimitive();
+
Expression* expression() const { return expression_; }
ZoneList<Expression*>* arguments() const { return arguments_; }
int position() { return pos_; }
@@ -1131,6 +1198,8 @@
virtual void Accept(AstVisitor* v);
+ virtual bool IsPrimitive();
+
Expression* expression() const { return expression_; }
ZoneList<Expression*>* arguments() const { return arguments_; }
int position() { return pos_; }
@@ -1155,6 +1224,8 @@
virtual void Accept(AstVisitor* v);
+ virtual bool IsPrimitive();
+
Handle<String> name() const { return name_; }
Runtime::Function* function() const { return function_; }
ZoneList<Expression*>* arguments() const { return arguments_; }
@@ -1179,6 +1250,8 @@
// Type testing & conversion
virtual UnaryOperation* AsUnaryOperation() { return this; }
+ virtual bool IsPrimitive();
+
Token::Value op() const { return op_; }
Expression* expression() const { return expression_; }
@@ -1200,6 +1273,8 @@
// Type testing & conversion
virtual BinaryOperation* AsBinaryOperation() { return this; }
+ virtual bool IsPrimitive();
+
// True iff the result can be safely overwritten (to avoid allocation).
// False for operations that can return one of their operands.
bool ResultOverwriteAllowed() {
@@ -1246,6 +1321,14 @@
virtual void Accept(AstVisitor* v);
+ virtual CountOperation* AsCountOperation() { return this; }
+
+ virtual Variable* AssignedVar() {
+ return expression()->AsVariableProxy()->AsVariable();
+ }
+
+ virtual bool IsPrimitive();
+
bool is_prefix() const { return is_prefix_; }
bool is_postfix() const { return !is_prefix_; }
Token::Value op() const { return op_; }
@@ -1272,6 +1355,8 @@
virtual void Accept(AstVisitor* v);
+ virtual bool IsPrimitive();
+
Token::Value op() const { return op_; }
Expression* left() const { return left_; }
Expression* right() const { return right_; }
@@ -1302,6 +1387,8 @@
virtual void Accept(AstVisitor* v);
+ virtual bool IsPrimitive();
+
Expression* condition() const { return condition_; }
Expression* then_expression() const { return then_expression_; }
Expression* else_expression() const { return else_expression_; }
@@ -1324,6 +1411,14 @@
virtual void Accept(AstVisitor* v);
virtual Assignment* AsAssignment() { return this; }
+ virtual bool IsPrimitive();
+
+ Assignment* AsSimpleAssignment() { return !is_compound() ? this : NULL; }
+
+ virtual Variable* AssignedVar() {
+ return target()->AsVariableProxy()->AsVariable();
+ }
+
Token::Value binary_op() const;
Token::Value op() const { return op_; }
@@ -1358,6 +1453,9 @@
: exception_(exception), pos_(pos) {}
virtual void Accept(AstVisitor* v);
+
+ virtual bool IsPrimitive();
+
Expression* exception() const { return exception_; }
int position() const { return pos_; }
@@ -1407,6 +1505,8 @@
virtual bool IsLeaf() { return true; }
+ virtual bool IsPrimitive();
+
Handle<String> name() const { return name_; }
Scope* scope() const { return scope_; }
ZoneList<Statement*>* body() const { return body_; }
@@ -1477,6 +1577,8 @@
virtual void Accept(AstVisitor* v);
+ virtual bool IsPrimitive();
+
private:
Handle<JSFunction> boilerplate_;
};
@@ -1486,6 +1588,7 @@
public:
virtual void Accept(AstVisitor* v);
virtual bool IsLeaf() { return true; }
+ virtual bool IsPrimitive();
};
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 12efbc1..8df37d2 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -55,7 +55,7 @@
}
void Iterate(ObjectVisitor* v) {
- v->VisitPointer(bit_cast<Object**, FixedArray**>(&cache_));
+ v->VisitPointer(BitCast<Object**, FixedArray**>(&cache_));
}
@@ -245,12 +245,6 @@
bool make_prototype_enumerable = false);
void MakeFunctionInstancePrototypeWritable();
- void AddSpecialFunction(Handle<JSObject> prototype,
- const char* name,
- Handle<Code> code);
-
- void BuildSpecialFunctionTable();
-
static bool CompileBuiltin(int index);
static bool CompileNative(Vector<const char> name, Handle<String> source);
static bool CompileScriptCached(Vector<const char> name,
@@ -777,8 +771,6 @@
delegate->shared()->DontAdaptArguments();
}
- global_context()->set_special_function_table(Heap::empty_fixed_array());
-
// Initialize the out of memory slot.
global_context()->set_out_of_memory(Heap::false_value());
@@ -1457,65 +1449,6 @@
}
-void Genesis::AddSpecialFunction(Handle<JSObject> prototype,
- const char* name,
- Handle<Code> code) {
- Handle<String> key = Factory::LookupAsciiSymbol(name);
- Handle<Object> value = Handle<Object>(prototype->GetProperty(*key));
- if (value->IsJSFunction()) {
- Handle<JSFunction> optimized = Factory::NewFunction(key,
- JS_OBJECT_TYPE,
- JSObject::kHeaderSize,
- code,
- false);
- optimized->shared()->DontAdaptArguments();
- int len = global_context()->special_function_table()->length();
- Handle<FixedArray> new_array = Factory::NewFixedArray(len + 3);
- for (int index = 0; index < len; index++) {
- new_array->set(index,
- global_context()->special_function_table()->get(index));
- }
- new_array->set(len+0, *prototype);
- new_array->set(len+1, *value);
- new_array->set(len+2, *optimized);
- global_context()->set_special_function_table(*new_array);
- }
-}
-
-
-void Genesis::BuildSpecialFunctionTable() {
- HandleScope scope;
- Handle<JSObject> global = Handle<JSObject>(global_context()->global());
- // Add special versions for some Array.prototype functions.
- Handle<JSFunction> function =
- Handle<JSFunction>(
- JSFunction::cast(global->GetProperty(Heap::Array_symbol())));
- Handle<JSObject> visible_prototype =
- Handle<JSObject>(JSObject::cast(function->prototype()));
- // Remember to put those specializations on the hidden prototype if present.
- Handle<JSObject> special_prototype;
- Handle<Object> superproto(visible_prototype->GetPrototype());
- if (superproto->IsJSObject() &&
- JSObject::cast(*superproto)->map()->is_hidden_prototype()) {
- special_prototype = Handle<JSObject>::cast(superproto);
- } else {
- special_prototype = visible_prototype;
- }
- AddSpecialFunction(special_prototype, "pop",
- Handle<Code>(Builtins::builtin(Builtins::ArrayPop)));
- AddSpecialFunction(special_prototype, "push",
- Handle<Code>(Builtins::builtin(Builtins::ArrayPush)));
- AddSpecialFunction(special_prototype, "shift",
- Handle<Code>(Builtins::builtin(Builtins::ArrayShift)));
- AddSpecialFunction(special_prototype, "unshift",
- Handle<Code>(Builtins::builtin(Builtins::ArrayUnshift)));
- AddSpecialFunction(special_prototype, "slice",
- Handle<Code>(Builtins::builtin(Builtins::ArraySlice)));
- AddSpecialFunction(special_prototype, "splice",
- Handle<Code>(Builtins::builtin(Builtins::ArraySplice)));
-}
-
-
Genesis::Genesis(Handle<Object> global_object,
v8::Handle<v8::ObjectTemplate> global_template,
v8::ExtensionConfiguration* extensions) {
@@ -1539,7 +1472,6 @@
if (!InstallNatives()) return;
MakeFunctionInstancePrototypeWritable();
- BuildSpecialFunctionTable();
if (!ConfigureGlobalObjects(global_template)) return;
diff --git a/src/builtins.cc b/src/builtins.cc
index a8ba818..e59dbcf 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -319,6 +319,24 @@
}
+static bool IsJSArrayWithFastElements(Object* receiver,
+ FixedArray** elements) {
+ if (!receiver->IsJSArray()) {
+ return false;
+ }
+
+ JSArray* array = JSArray::cast(receiver);
+
+ HeapObject* elms = HeapObject::cast(array->elements());
+ if (elms->map() != Heap::fixed_array_map()) {
+ return false;
+ }
+
+ *elements = FixedArray::cast(elms);
+ return true;
+}
+
+
static Object* CallJsBuiltin(const char* name,
BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
HandleScope handleScope;
@@ -331,7 +349,7 @@
Vector<Object**> argv(Vector<Object**>::New(args.length() - 1));
int n_args = args.length() - 1;
for (int i = 0; i < n_args; i++) {
- argv[i] = &args[i + 1];
+ argv[i] = args.at<Object>(i + 1).location();
}
bool pending_exception = false;
Handle<Object> result = Execution::Call(function,
@@ -346,8 +364,12 @@
BUILTIN(ArrayPush) {
- JSArray* array = JSArray::cast(*args.receiver());
- ASSERT(array->HasFastElements());
+ Object* receiver = *args.receiver();
+ FixedArray* elms = NULL;
+ if (!IsJSArrayWithFastElements(receiver, &elms)) {
+ return CallJsBuiltin("ArrayPush", args);
+ }
+ JSArray* array = JSArray::cast(receiver);
int len = Smi::cast(array->length())->value();
int to_add = args.length() - 1;
@@ -359,7 +381,6 @@
ASSERT(to_add <= (Smi::kMaxValue - len));
int new_length = len + to_add;
- FixedArray* elms = FixedArray::cast(array->elements());
if (new_length > elms->length()) {
// New backing storage is needed.
@@ -390,14 +411,17 @@
BUILTIN(ArrayPop) {
- JSArray* array = JSArray::cast(*args.receiver());
- ASSERT(array->HasFastElements());
+ Object* receiver = *args.receiver();
+ FixedArray* elms = NULL;
+ if (!IsJSArrayWithFastElements(receiver, &elms)) {
+ return CallJsBuiltin("ArrayPop", args);
+ }
+ JSArray* array = JSArray::cast(receiver);
int len = Smi::cast(array->length())->value();
if (len == 0) return Heap::undefined_value();
// Get top element
- FixedArray* elms = FixedArray::cast(array->elements());
Object* top = elms->get(len - 1);
// Set the length.
@@ -420,18 +444,18 @@
BUILTIN(ArrayShift) {
- if (!ArrayPrototypeHasNoElements()) {
+ Object* receiver = *args.receiver();
+ FixedArray* elms = NULL;
+ if (!IsJSArrayWithFastElements(receiver, &elms)
+ || !ArrayPrototypeHasNoElements()) {
return CallJsBuiltin("ArrayShift", args);
}
-
- JSArray* array = JSArray::cast(*args.receiver());
+ JSArray* array = JSArray::cast(receiver);
ASSERT(array->HasFastElements());
int len = Smi::cast(array->length())->value();
if (len == 0) return Heap::undefined_value();
- FixedArray* elms = FixedArray::cast(array->elements());
-
// Get first element
Object* first = elms->get(0);
if (first->IsTheHole()) {
@@ -451,26 +475,22 @@
BUILTIN(ArrayUnshift) {
- if (!ArrayPrototypeHasNoElements()) {
+ Object* receiver = *args.receiver();
+ FixedArray* elms = NULL;
+ if (!IsJSArrayWithFastElements(receiver, &elms)
+ || !ArrayPrototypeHasNoElements()) {
return CallJsBuiltin("ArrayUnshift", args);
}
-
- JSArray* array = JSArray::cast(*args.receiver());
+ JSArray* array = JSArray::cast(receiver);
ASSERT(array->HasFastElements());
int len = Smi::cast(array->length())->value();
int to_add = args.length() - 1;
- // Note that we cannot quit early if to_add == 0 as
- // values should be lifted from prototype into
- // the array.
-
int new_length = len + to_add;
// Currently fixed arrays cannot grow too big, so
// we should never hit this case.
ASSERT(to_add <= (Smi::kMaxValue - len));
- FixedArray* elms = FixedArray::cast(array->elements());
-
if (new_length > elms->length()) {
// New backing storage is needed.
int capacity = new_length + (new_length >> 1) + 16;
@@ -503,11 +523,13 @@
BUILTIN(ArraySlice) {
- if (!ArrayPrototypeHasNoElements()) {
+ Object* receiver = *args.receiver();
+ FixedArray* elms = NULL;
+ if (!IsJSArrayWithFastElements(receiver, &elms)
+ || !ArrayPrototypeHasNoElements()) {
return CallJsBuiltin("ArraySlice", args);
}
-
- JSArray* array = JSArray::cast(*args.receiver());
+ JSArray* array = JSArray::cast(receiver);
ASSERT(array->HasFastElements());
int len = Smi::cast(array->length())->value();
@@ -558,8 +580,6 @@
if (result->IsFailure()) return result;
FixedArray* result_elms = FixedArray::cast(result);
- FixedArray* elms = FixedArray::cast(array->elements());
-
AssertNoAllocation no_gc;
CopyElements(&no_gc, result_elms, 0, elms, k, result_len);
@@ -573,11 +593,13 @@
BUILTIN(ArraySplice) {
- if (!ArrayPrototypeHasNoElements()) {
+ Object* receiver = *args.receiver();
+ FixedArray* elms = NULL;
+ if (!IsJSArrayWithFastElements(receiver, &elms)
+ || !ArrayPrototypeHasNoElements()) {
return CallJsBuiltin("ArraySplice", args);
}
-
- JSArray* array = JSArray::cast(*args.receiver());
+ JSArray* array = JSArray::cast(receiver);
ASSERT(array->HasFastElements());
int len = Smi::cast(array->length())->value();
@@ -618,8 +640,6 @@
}
int actual_delete_count = Min(Max(delete_count, 0), len - actual_start);
- FixedArray* elms = FixedArray::cast(array->elements());
-
JSArray* result_array = NULL;
if (actual_delete_count == 0) {
Object* result = AllocateEmptyJSArray();
@@ -766,20 +786,19 @@
HandleScope scope;
Handle<JSFunction> function = args.called_function();
+ ASSERT(function->shared()->IsApiFunction());
+ FunctionTemplateInfo* fun_data = function->shared()->get_api_func_data();
if (is_construct) {
- Handle<FunctionTemplateInfo> desc =
- Handle<FunctionTemplateInfo>(
- FunctionTemplateInfo::cast(function->shared()->function_data()));
+ Handle<FunctionTemplateInfo> desc(fun_data);
bool pending_exception = false;
Factory::ConfigureInstance(desc, Handle<JSObject>::cast(args.receiver()),
&pending_exception);
ASSERT(Top::has_pending_exception() == pending_exception);
if (pending_exception) return Failure::Exception();
+ fun_data = *desc;
}
- FunctionTemplateInfo* fun_data =
- FunctionTemplateInfo::cast(function->shared()->function_data());
Object* raw_holder = TypeCheck(args.length(), &args[0], fun_data);
if (raw_holder->IsNull()) {
@@ -850,8 +869,8 @@
static void VerifyTypeCheck(Handle<JSObject> object,
Handle<JSFunction> function) {
- FunctionTemplateInfo* info =
- FunctionTemplateInfo::cast(function->shared()->function_data());
+ ASSERT(function->shared()->IsApiFunction());
+ FunctionTemplateInfo* info = function->shared()->get_api_func_data();
if (info->signature()->IsUndefined()) return;
SignatureInfo* signature = SignatureInfo::cast(info->signature());
Object* receiver_type = signature->receiver();
@@ -935,9 +954,9 @@
// used to create the called object.
ASSERT(obj->map()->has_instance_call_handler());
JSFunction* constructor = JSFunction::cast(obj->map()->constructor());
- Object* template_info = constructor->shared()->function_data();
+ ASSERT(constructor->shared()->IsApiFunction());
Object* handler =
- FunctionTemplateInfo::cast(template_info)->instance_call_handler();
+ constructor->shared()->get_api_func_data()->instance_call_handler();
ASSERT(!handler->IsUndefined());
CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
Object* callback_obj = call_data->callback();
diff --git a/src/cached_powers.h b/src/cached_powers.h
new file mode 100644
index 0000000..7c3d234
--- /dev/null
+++ b/src/cached_powers.h
@@ -0,0 +1,119 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_CACHED_POWERS_H_
+#define V8_CACHED_POWERS_H_
+
+#include "diy_fp.h"
+
+namespace v8 {
+namespace internal {
+
+struct CachedPower {
+ uint64_t significand;
+ int16_t binary_exponent;
+ int16_t decimal_exponent;
+};
+
+// The following defines implement the interface between this file and the
+// generated 'powers_ten.h'.
+// GRISU_CACHE_NAME(1) contains all possible cached powers.
+// GRISU_CACHE_NAME(i) contains GRISU_CACHE_NAME(1) where only every 'i'th
+// element is kept. More formally GRISU_CACHE_NAME(i) contains the elements j*i
+// with 0 <= j < k with k such that j*k < the size of GRISU_CACHE_NAME(1).
+// The higher 'i' is the fewer elements we use.
+// Given that there are less elements, the exponent-distance between two
+// elements in the cache grows. The variable GRISU_CACHE_MAX_DISTANCE(i) stores
+// the maximum distance between two elements.
+#define GRISU_CACHE_STRUCT CachedPower
+#define GRISU_CACHE_NAME(i) kCachedPowers##i
+#define GRISU_CACHE_MAX_DISTANCE(i) kCachedPowersMaxDistance##i
+#define GRISU_CACHE_OFFSET kCachedPowerOffset
+#define GRISU_UINT64_C V8_2PART_UINT64_C
+// The following include imports the precompiled cached powers.
+#include "powers_ten.h" // NOLINT
+
+static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
+
+// We can't use a function since we reference variables depending on the 'i'.
+// This way the compiler is able to see at compile time that only one
+// cache-array variable is used and thus can remove all the others.
+#define COMPUTE_FOR_CACHE(i) \
+ if (!found && (gamma - alpha + 1 >= GRISU_CACHE_MAX_DISTANCE(i))) { \
+ int kQ = DiyFp::kSignificandSize; \
+ double k = ceiling((alpha - e + kQ - 1) * kD_1_LOG2_10); \
+ int index = (GRISU_CACHE_OFFSET + static_cast<int>(k) - 1) / i + 1; \
+ cached_power = GRISU_CACHE_NAME(i)[index]; \
+ found = true; \
+ } \
+
+static void GetCachedPower(int e, int alpha, int gamma, int* mk, DiyFp* c_mk) {
+ // The following if statement should be optimized by the compiler so that only
+ // one array is referenced and the others are not included in the object file.
+ bool found = false;
+ CachedPower cached_power;
+ COMPUTE_FOR_CACHE(20);
+ COMPUTE_FOR_CACHE(19);
+ COMPUTE_FOR_CACHE(18);
+ COMPUTE_FOR_CACHE(17);
+ COMPUTE_FOR_CACHE(16);
+ COMPUTE_FOR_CACHE(15);
+ COMPUTE_FOR_CACHE(14);
+ COMPUTE_FOR_CACHE(13);
+ COMPUTE_FOR_CACHE(12);
+ COMPUTE_FOR_CACHE(11);
+ COMPUTE_FOR_CACHE(10);
+ COMPUTE_FOR_CACHE(9);
+ COMPUTE_FOR_CACHE(8);
+ COMPUTE_FOR_CACHE(7);
+ COMPUTE_FOR_CACHE(6);
+ COMPUTE_FOR_CACHE(5);
+ COMPUTE_FOR_CACHE(4);
+ COMPUTE_FOR_CACHE(3);
+ COMPUTE_FOR_CACHE(2);
+ COMPUTE_FOR_CACHE(1);
+ if (!found) {
+ UNIMPLEMENTED();
+ // Silence compiler warnings.
+ cached_power.significand = 0;
+ cached_power.binary_exponent = 0;
+ cached_power.decimal_exponent = 0;
+ }
+ *c_mk = DiyFp(cached_power.significand, cached_power.binary_exponent);
+ *mk = cached_power.decimal_exponent;
+ ASSERT((alpha <= c_mk->e() + e) && (c_mk->e() + e <= gamma));
+}
+#undef GRISU_REDUCTION
+#undef GRISU_CACHE_STRUCT
+#undef GRISU_CACHE_NAME
+#undef GRISU_CACHE_MAX_DISTANCE
+#undef GRISU_CACHE_OFFSET
+#undef GRISU_UINT64_C
+
+} } // namespace v8::internal
+
+#endif // V8_CACHED_POWERS_H_
diff --git a/src/checks.h b/src/checks.h
index eeb748b..cdcd18a 100644
--- a/src/checks.h
+++ b/src/checks.h
@@ -80,6 +80,7 @@
}
}
+
// Helper function used by the CHECK_EQ function when given int64_t
// arguments. Should not be called directly.
static inline void CheckEqualsHelper(const char* file, int line,
@@ -202,6 +203,27 @@
}
+static inline void CheckNonEqualsHelper(const char* file,
+ int line,
+ const char* expected_source,
+ double expected,
+ const char* value_source,
+ double value) {
+ // Force values to 64 bit memory to truncate 80 bit precision on IA32.
+ volatile double* exp = new double[1];
+ *exp = expected;
+ volatile double* val = new double[1];
+ *val = value;
+ if (*exp == *val) {
+ V8_Fatal(file, line,
+ "CHECK_NE(%s, %s) failed\n# Value: %f",
+ expected_source, value_source, *val);
+ }
+ delete[] exp;
+ delete[] val;
+}
+
+
namespace v8 {
class Value;
template <class T> class Handle;
diff --git a/src/codegen.cc b/src/codegen.cc
index 6841c21..f9913b9 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -351,42 +351,18 @@
}
+// List of special runtime calls which are generated inline. For some of these
+// functions the code will be generated inline, and for others a call to a code
+// stub will be inlined.
-// Special cases: These 'runtime calls' manipulate the current
-// frame and are only used 1 or two places, so we generate them
-// inline instead of generating calls to them. They are used
-// for implementing Function.prototype.call() and
-// Function.prototype.apply().
+#define INLINE_RUNTIME_ENTRY(Name, argc, ressize) \
+ {&CodeGenerator::Generate##Name, "_" #Name, argc}, \
+
CodeGenerator::InlineRuntimeLUT CodeGenerator::kInlineRuntimeLUT[] = {
- {&CodeGenerator::GenerateIsSmi, "_IsSmi"},
- {&CodeGenerator::GenerateIsNonNegativeSmi, "_IsNonNegativeSmi"},
- {&CodeGenerator::GenerateIsArray, "_IsArray"},
- {&CodeGenerator::GenerateIsRegExp, "_IsRegExp"},
- {&CodeGenerator::GenerateIsConstructCall, "_IsConstructCall"},
- {&CodeGenerator::GenerateArgumentsLength, "_ArgumentsLength"},
- {&CodeGenerator::GenerateArgumentsAccess, "_Arguments"},
- {&CodeGenerator::GenerateClassOf, "_ClassOf"},
- {&CodeGenerator::GenerateValueOf, "_ValueOf"},
- {&CodeGenerator::GenerateSetValueOf, "_SetValueOf"},
- {&CodeGenerator::GenerateFastCharCodeAt, "_FastCharCodeAt"},
- {&CodeGenerator::GenerateCharFromCode, "_CharFromCode"},
- {&CodeGenerator::GenerateObjectEquals, "_ObjectEquals"},
- {&CodeGenerator::GenerateLog, "_Log"},
- {&CodeGenerator::GenerateRandomPositiveSmi, "_RandomPositiveSmi"},
- {&CodeGenerator::GenerateIsObject, "_IsObject"},
- {&CodeGenerator::GenerateIsFunction, "_IsFunction"},
- {&CodeGenerator::GenerateIsUndetectableObject, "_IsUndetectableObject"},
- {&CodeGenerator::GenerateStringAdd, "_StringAdd"},
- {&CodeGenerator::GenerateSubString, "_SubString"},
- {&CodeGenerator::GenerateStringCompare, "_StringCompare"},
- {&CodeGenerator::GenerateRegExpExec, "_RegExpExec"},
- {&CodeGenerator::GenerateNumberToString, "_NumberToString"},
- {&CodeGenerator::GenerateMathPow, "_Math_pow"},
- {&CodeGenerator::GenerateMathSin, "_Math_sin"},
- {&CodeGenerator::GenerateMathCos, "_Math_cos"},
- {&CodeGenerator::GenerateMathSqrt, "_Math_sqrt"},
+ INLINE_RUNTIME_FUNCTION_LIST(INLINE_RUNTIME_ENTRY)
};
+#undef INLINE_RUNTIME_ENTRY
CodeGenerator::InlineRuntimeLUT* CodeGenerator::FindInlineRuntimeLUT(
Handle<String> name) {
@@ -431,6 +407,14 @@
}
+int CodeGenerator::InlineRuntimeCallArgumentsCount(Handle<String> name) {
+ CodeGenerator::InlineRuntimeLUT* f =
+ CodeGenerator::FindInlineRuntimeLUT(name);
+ if (f != NULL) return f->nargs;
+ return -1;
+}
+
+
// Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
// known result for the test expression, with no side effects.
CodeGenerator::ConditionAnalysis CodeGenerator::AnalyzeCondition(
diff --git a/src/codegen.h b/src/codegen.h
index 8dcde84..40ed6ce 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -99,6 +99,36 @@
namespace internal {
+#define INLINE_RUNTIME_FUNCTION_LIST(F) \
+ F(IsSmi, 1, 1) \
+ F(IsNonNegativeSmi, 1, 1) \
+ F(IsArray, 1, 1) \
+ F(IsRegExp, 1, 1) \
+ F(IsConstructCall, 0, 1) \
+ F(ArgumentsLength, 0, 1) \
+ F(Arguments, 1, 1) \
+ F(ClassOf, 1, 1) \
+ F(ValueOf, 1, 1) \
+ F(SetValueOf, 2, 1) \
+ F(FastCharCodeAt, 2, 1) \
+ F(CharFromCode, 1, 1) \
+ F(ObjectEquals, 2, 1) \
+ F(Log, 3, 1) \
+ F(RandomPositiveSmi, 0, 1) \
+ F(IsObject, 1, 1) \
+ F(IsFunction, 1, 1) \
+ F(IsUndetectableObject, 1, 1) \
+ F(StringAdd, 2, 1) \
+ F(SubString, 3, 1) \
+ F(StringCompare, 2, 1) \
+ F(RegExpExec, 4, 1) \
+ F(NumberToString, 1, 1) \
+ F(MathPow, 2, 1) \
+ F(MathSin, 1, 1) \
+ F(MathCos, 1, 1) \
+ F(MathSqrt, 1, 1)
+
+
// Support for "structured" code comments.
#ifdef DEBUG
diff --git a/src/compilation-cache.cc b/src/compilation-cache.cc
index 9dcbeb5..378a24e 100644
--- a/src/compilation-cache.cc
+++ b/src/compilation-cache.cc
@@ -218,9 +218,7 @@
void CompilationSubCache::Clear() {
- for (int i = 0; i < generations_; i++) {
- tables_[i] = Heap::undefined_value();
- }
+ MemsetPointer(tables_, Heap::undefined_value(), generations_);
}
diff --git a/src/compiler.cc b/src/compiler.cc
index ebb62f1..dce8816 100755
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -79,12 +79,32 @@
return Handle<Code>::null();
}
+ if (function->scope()->num_parameters() > 0 ||
+ function->scope()->num_stack_slots()) {
+ AssignedVariablesAnalyzer ava(function);
+ ava.Analyze();
+ if (ava.HasStackOverflow()) {
+ return Handle<Code>::null();
+ }
+ }
+
if (FLAG_use_flow_graph) {
FlowGraphBuilder builder;
builder.Build(function);
+ if (!builder.HasStackOverflow()) {
+ int variable_count =
+ function->num_parameters() + function->scope()->num_stack_slots();
+ if (variable_count > 0 && builder.definitions()->length() > 0) {
+ ReachingDefinitions rd(builder.postorder(),
+ builder.definitions(),
+ variable_count);
+ rd.Compute();
+ }
+ }
+
#ifdef DEBUG
- if (FLAG_print_graph_text) {
+ if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
builder.graph()->PrintText(builder.postorder());
}
#endif
@@ -463,12 +483,32 @@
return Handle<JSFunction>::null();
}
+ if (literal->scope()->num_parameters() > 0 ||
+ literal->scope()->num_stack_slots()) {
+ AssignedVariablesAnalyzer ava(literal);
+ ava.Analyze();
+ if (ava.HasStackOverflow()) {
+ return Handle<JSFunction>::null();
+ }
+ }
+
if (FLAG_use_flow_graph) {
FlowGraphBuilder builder;
builder.Build(literal);
+ if (!builder.HasStackOverflow()) {
+ int variable_count =
+ literal->num_parameters() + literal->scope()->num_stack_slots();
+ if (variable_count > 0 && builder.definitions()->length() > 0) {
+ ReachingDefinitions rd(builder.postorder(),
+ builder.definitions(),
+ variable_count);
+ rd.Compute();
+ }
+ }
+
#ifdef DEBUG
- if (FLAG_print_graph_text) {
+ if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
builder.graph()->PrintText(builder.postorder());
}
#endif
diff --git a/src/contexts.h b/src/contexts.h
index 98ebc47..4997741 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -50,12 +50,6 @@
// must always be allocated via Heap::AllocateContext() or
// Factory::NewContext.
-// Comment for special_function_table:
-// Table for providing optimized/specialized functions.
-// The array contains triplets [object, general_function, optimized_function].
-// Primarily added to support built-in optimized variants of
-// Array.prototype.{push,pop}.
-
#define GLOBAL_CONTEXT_FIELDS(V) \
V(GLOBAL_PROXY_INDEX, JSObject, global_proxy_object) \
V(SECURITY_TOKEN_INDEX, Object, security_token) \
@@ -82,7 +76,6 @@
V(FUNCTION_MAP_INDEX, Map, function_map) \
V(FUNCTION_INSTANCE_MAP_INDEX, Map, function_instance_map) \
V(JS_ARRAY_MAP_INDEX, Map, js_array_map)\
- V(SPECIAL_FUNCTION_TABLE_INDEX, FixedArray, special_function_table) \
V(ARGUMENTS_BOILERPLATE_INDEX, JSObject, arguments_boilerplate) \
V(MESSAGE_LISTENERS_INDEX, JSObject, message_listeners) \
V(MAKE_MESSAGE_FUN_INDEX, JSFunction, make_message_fun) \
@@ -206,7 +199,6 @@
GLOBAL_EVAL_FUN_INDEX,
INSTANTIATE_FUN_INDEX,
CONFIGURE_INSTANCE_FUN_INDEX,
- SPECIAL_FUNCTION_TABLE_INDEX,
MESSAGE_LISTENERS_INDEX,
MAKE_MESSAGE_FUN_INDEX,
GET_STACK_TRACE_LINE_INDEX,
diff --git a/src/conversions.cc b/src/conversions.cc
index fd6d38d..864b625 100644
--- a/src/conversions.cc
+++ b/src/conversions.cc
@@ -31,6 +31,7 @@
#include "conversions-inl.h"
#include "factory.h"
+#include "grisu3.h"
#include "scanner.h"
namespace v8 {
@@ -382,8 +383,17 @@
int decimal_point;
int sign;
- char* decimal_rep = dtoa(v, 0, 0, &decimal_point, &sign, NULL);
- int length = StrLength(decimal_rep);
+ char* decimal_rep;
+ bool used_dtoa = false;
+ char grisu_buffer[kGrisu3MaximalLength + 1];
+ int length;
+ if (grisu3(v, grisu_buffer, &sign, &length, &decimal_point)) {
+ decimal_rep = grisu_buffer;
+ } else {
+ decimal_rep = dtoa(v, 0, 0, &decimal_point, &sign, NULL);
+ used_dtoa = true;
+ length = StrLength(decimal_rep);
+ }
if (sign) builder.AddCharacter('-');
@@ -418,7 +428,7 @@
builder.AddFormatted("%d", exponent);
}
- freedtoa(decimal_rep);
+ if (used_dtoa) freedtoa(decimal_rep);
}
}
return builder.Finalize();
diff --git a/src/data-flow.cc b/src/data-flow.cc
index 6b45da0..f6ccef1 100644
--- a/src/data-flow.cc
+++ b/src/data-flow.cc
@@ -28,73 +28,76 @@
#include "v8.h"
#include "data-flow.h"
+#include "scopes.h"
namespace v8 {
namespace internal {
void FlowGraph::AppendInstruction(AstNode* instruction) {
+ // Add a (non-null) AstNode to the end of the graph fragment.
ASSERT(instruction != NULL);
- if (is_empty() || !exit()->IsBlockNode()) {
- AppendNode(new BlockNode());
- }
+ if (exit()->IsExitNode()) return;
+ if (!exit()->IsBlockNode()) AppendNode(new BlockNode());
BlockNode::cast(exit())->AddInstruction(instruction);
}
void FlowGraph::AppendNode(Node* node) {
+ // Add a node to the end of the graph. An empty block is added to
+ // maintain edge-split form (that no join nodes or exit nodes as
+ // successors to branch nodes).
ASSERT(node != NULL);
- if (is_empty()) {
- entry_ = exit_ = node;
- } else {
- exit()->AddSuccessor(node);
- node->AddPredecessor(exit());
- exit_ = node;
+ if (exit()->IsExitNode()) return;
+ if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) {
+ AppendNode(new BlockNode());
}
+ exit()->AddSuccessor(node);
+ node->AddPredecessor(exit());
+ exit_ = node;
}
void FlowGraph::AppendGraph(FlowGraph* graph) {
- ASSERT(!graph->is_empty());
- if (is_empty()) {
- entry_ = graph->entry();
- exit_ = graph->exit();
- } else {
- exit()->AddSuccessor(graph->entry());
- graph->entry()->AddPredecessor(exit());
- exit_ = graph->exit();
+ // Add a flow graph fragment to the end of this one. An empty block is
+ // added to maintain edge-split form (that no join nodes or exit nodes as
+ // successors to branch nodes).
+ ASSERT(graph != NULL);
+ if (exit()->IsExitNode()) return;
+ Node* node = graph->entry();
+ if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) {
+ AppendNode(new BlockNode());
}
+ exit()->AddSuccessor(node);
+ node->AddPredecessor(exit());
+ exit_ = graph->exit();
}
void FlowGraph::Split(BranchNode* branch,
FlowGraph* left,
FlowGraph* right,
- JoinNode* merge) {
- // Graphs are in edge split form. Add empty blocks if necessary.
- if (left->is_empty()) left->AppendNode(new BlockNode());
- if (right->is_empty()) right->AppendNode(new BlockNode());
-
- // Add the branch, left flowgraph and merge.
+ JoinNode* join) {
+ // Add the branch node, left flowgraph, join node.
AppendNode(branch);
AppendGraph(left);
- AppendNode(merge);
+ AppendNode(join);
// Splice in the right flowgraph.
- right->AppendNode(merge);
+ right->AppendNode(join);
branch->AddSuccessor(right->entry());
right->entry()->AddPredecessor(branch);
}
-void FlowGraph::Loop(JoinNode* merge,
+void FlowGraph::Loop(JoinNode* join,
FlowGraph* condition,
BranchNode* branch,
FlowGraph* body) {
- // Add the merge, condition and branch. Add merge's predecessors in
+ // Add the join, condition and branch. Add join's predecessors in
// left-to-right order.
- AppendNode(merge);
- body->AppendNode(merge);
+ AppendNode(join);
+ body->AppendNode(join);
AppendGraph(condition);
AppendNode(branch);
@@ -104,19 +107,6 @@
}
-void EntryNode::Traverse(bool mark,
- ZoneList<Node*>* preorder,
- ZoneList<Node*>* postorder) {
- ASSERT(successor_ != NULL);
- preorder->Add(this);
- if (!successor_->IsMarkedWith(mark)) {
- successor_->MarkWith(mark);
- successor_->Traverse(mark, preorder, postorder);
- }
- postorder->Add(this);
-}
-
-
void ExitNode::Traverse(bool mark,
ZoneList<Node*>* preorder,
ZoneList<Node*>* postorder) {
@@ -143,14 +133,14 @@
ZoneList<Node*>* postorder) {
ASSERT(successor0_ != NULL && successor1_ != NULL);
preorder->Add(this);
- if (!successor0_->IsMarkedWith(mark)) {
- successor0_->MarkWith(mark);
- successor0_->Traverse(mark, preorder, postorder);
- }
if (!successor1_->IsMarkedWith(mark)) {
successor1_->MarkWith(mark);
successor1_->Traverse(mark, preorder, postorder);
}
+ if (!successor0_->IsMarkedWith(mark)) {
+ successor0_->MarkWith(mark);
+ successor0_->Traverse(mark, preorder, postorder);
+ }
postorder->Add(this);
}
@@ -169,16 +159,15 @@
void FlowGraphBuilder::Build(FunctionLiteral* lit) {
- graph_ = FlowGraph::Empty();
- graph_.AppendNode(new EntryNode());
global_exit_ = new ExitNode();
VisitStatements(lit->body());
- if (HasStackOverflow()) {
- graph_ = FlowGraph::Empty();
- return;
- }
+ if (HasStackOverflow()) return;
+ // The graph can end with a branch node (if the function ended with a
+ // loop). Maintain edge-split form (no join nodes or exit nodes as
+ // successors to branch nodes).
+ if (graph_.exit()->IsBranchNode()) graph_.AppendNode(new BlockNode());
graph_.AppendNode(global_exit_);
// Build preorder and postorder traversal orders. All the nodes in
@@ -222,6 +211,7 @@
graph_ = FlowGraph::Empty();
Visit(stmt->else_statement());
+ if (HasStackOverflow()) return;
JoinNode* join = new JoinNode();
original.Split(branch, &left, &graph_, join);
graph_ = original;
@@ -239,20 +229,17 @@
void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
- Visit(stmt->expression());
- graph_.AppendInstruction(stmt);
- graph_.AppendNode(global_exit());
+ SetStackOverflow();
}
void FlowGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
- Visit(stmt->expression());
- graph_.AppendInstruction(stmt);
+ SetStackOverflow();
}
void FlowGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
- graph_.AppendInstruction(stmt);
+ SetStackOverflow();
}
@@ -262,44 +249,12 @@
void FlowGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
- JoinNode* join = new JoinNode();
- FlowGraph original = graph_;
- graph_ = FlowGraph::Empty();
- Visit(stmt->body());
-
- FlowGraph body = graph_;
- graph_ = FlowGraph::Empty();
- Visit(stmt->cond());
-
- BranchNode* branch = new BranchNode();
-
- // Add body, condition and branch.
- original.AppendNode(join);
- original.AppendGraph(&body);
- original.AppendGraph(&graph_); // The condition.
- original.AppendNode(branch);
-
- // Tie the knot.
- branch->AddSuccessor(join);
- join->AddPredecessor(branch);
-
- graph_ = original;
+ SetStackOverflow();
}
void FlowGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
- JoinNode* join = new JoinNode();
- FlowGraph original = graph_;
- graph_ = FlowGraph::Empty();
- Visit(stmt->cond());
-
- BranchNode* branch = new BranchNode();
- FlowGraph condition = graph_;
- graph_ = FlowGraph::Empty();
- Visit(stmt->body());
-
- original.Loop(join, &condition, branch, &graph_);
- graph_ = original;
+ SetStackOverflow();
}
@@ -318,23 +273,14 @@
if (stmt->next() != NULL) Visit(stmt->next());
+ if (HasStackOverflow()) return;
original.Loop(join, &condition, branch, &graph_);
graph_ = original;
}
void FlowGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
- Visit(stmt->enumerable());
-
- JoinNode* join = new JoinNode();
- FlowGraph empty;
- BranchNode* branch = new BranchNode();
- FlowGraph original = graph_;
- graph_ = FlowGraph::Empty();
- Visit(stmt->body());
-
- original.Loop(join, &empty, branch, &graph_);
- graph_ = original;
+ SetStackOverflow();
}
@@ -349,36 +295,23 @@
void FlowGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
- graph_.AppendInstruction(stmt);
+ SetStackOverflow();
}
void FlowGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
- graph_.AppendInstruction(expr);
+ SetStackOverflow();
}
void FlowGraphBuilder::VisitFunctionBoilerplateLiteral(
FunctionBoilerplateLiteral* expr) {
- graph_.AppendInstruction(expr);
+ SetStackOverflow();
}
void FlowGraphBuilder::VisitConditional(Conditional* expr) {
- Visit(expr->condition());
-
- BranchNode* branch = new BranchNode();
- FlowGraph original = graph_;
- graph_ = FlowGraph::Empty();
- Visit(expr->then_expression());
-
- FlowGraph left = graph_;
- graph_ = FlowGraph::Empty();
- Visit(expr->else_expression());
-
- JoinNode* join = new JoinNode();
- original.Split(branch, &left, &graph_, join);
- graph_ = original;
+ SetStackOverflow();
}
@@ -398,30 +331,22 @@
void FlowGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
- graph_.AppendInstruction(expr);
+ SetStackOverflow();
}
void FlowGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
- ZoneList<ObjectLiteral::Property*>* properties = expr->properties();
- for (int i = 0, len = properties->length(); i < len; i++) {
- Visit(properties->at(i)->value());
- }
- graph_.AppendInstruction(expr);
+ SetStackOverflow();
}
void FlowGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
- ZoneList<Expression*>* values = expr->values();
- for (int i = 0, len = values->length(); i < len; i++) {
- Visit(values->at(i));
- }
- graph_.AppendInstruction(expr);
+ SetStackOverflow();
}
void FlowGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
- graph_.AppendInstruction(expr);
+ SetStackOverflow();
}
@@ -433,26 +358,32 @@
ASSERT(var == NULL || prop == NULL);
if (var != NULL) {
Visit(expr->value());
- if (var->IsStackAllocated()) definitions_.Add(expr);
+ if (var->IsStackAllocated()) {
+ expr->set_num(definitions_.length());
+ definitions_.Add(expr);
+ }
} else if (prop != NULL) {
Visit(prop->obj());
if (!prop->key()->IsPropertyName()) Visit(prop->key());
Visit(expr->value());
}
+
+ if (HasStackOverflow()) return;
graph_.AppendInstruction(expr);
}
void FlowGraphBuilder::VisitThrow(Throw* expr) {
- Visit(expr->exception());
- graph_.AppendInstruction(expr);
+ SetStackOverflow();
}
void FlowGraphBuilder::VisitProperty(Property* expr) {
Visit(expr->obj());
if (!expr->key()->IsPropertyName()) Visit(expr->key());
+
+ if (HasStackOverflow()) return;
graph_.AppendInstruction(expr);
}
@@ -463,32 +394,42 @@
for (int i = 0, len = arguments->length(); i < len; i++) {
Visit(arguments->at(i));
}
+
+ if (HasStackOverflow()) return;
graph_.AppendInstruction(expr);
}
void FlowGraphBuilder::VisitCallNew(CallNew* expr) {
- Visit(expr->expression());
- ZoneList<Expression*>* arguments = expr->arguments();
- for (int i = 0, len = arguments->length(); i < len; i++) {
- Visit(arguments->at(i));
- }
- graph_.AppendInstruction(expr);
+ SetStackOverflow();
}
void FlowGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
- ZoneList<Expression*>* arguments = expr->arguments();
- for (int i = 0, len = arguments->length(); i < len; i++) {
- Visit(arguments->at(i));
- }
- graph_.AppendInstruction(expr);
+ SetStackOverflow();
}
void FlowGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
- Visit(expr->expression());
- graph_.AppendInstruction(expr);
+ switch (expr->op()) {
+ case Token::NOT:
+ case Token::BIT_NOT:
+ case Token::DELETE:
+ case Token::TYPEOF:
+ case Token::VOID:
+ SetStackOverflow();
+ break;
+
+ case Token::ADD:
+ case Token::SUB:
+ Visit(expr->expression());
+ if (HasStackOverflow()) return;
+ graph_.AppendInstruction(expr);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
}
@@ -496,56 +437,37 @@
Visit(expr->expression());
Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
if (var != NULL && var->IsStackAllocated()) {
+ expr->set_num(definitions_.length());
definitions_.Add(expr);
}
+
+ if (HasStackOverflow()) return;
graph_.AppendInstruction(expr);
}
void FlowGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
- Visit(expr->left());
-
switch (expr->op()) {
case Token::COMMA:
- Visit(expr->right());
+ case Token::OR:
+ case Token::AND:
+ SetStackOverflow();
break;
- case Token::OR: {
- BranchNode* branch = new BranchNode();
- FlowGraph original = graph_;
- graph_ = FlowGraph::Empty();
- Visit(expr->right());
- FlowGraph empty;
- JoinNode* join = new JoinNode();
- original.Split(branch, &empty, &graph_, join);
- graph_ = original;
- break;
- }
-
- case Token::AND: {
- BranchNode* branch = new BranchNode();
- FlowGraph original = graph_;
- graph_ = FlowGraph::Empty();
- Visit(expr->right());
- FlowGraph empty;
- JoinNode* join = new JoinNode();
- original.Split(branch, &graph_, &empty, join);
- graph_ = original;
- break;
- }
-
case Token::BIT_OR:
case Token::BIT_XOR:
case Token::BIT_AND:
case Token::SHL:
- case Token::SAR:
case Token::SHR:
case Token::ADD:
case Token::SUB:
case Token::MUL:
case Token::DIV:
case Token::MOD:
+ case Token::SAR:
+ Visit(expr->left());
Visit(expr->right());
+ if (HasStackOverflow()) return;
graph_.AppendInstruction(expr);
break;
@@ -556,14 +478,34 @@
void FlowGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
- Visit(expr->left());
- Visit(expr->right());
- graph_.AppendInstruction(expr);
+ switch (expr->op()) {
+ case Token::EQ:
+ case Token::NE:
+ case Token::EQ_STRICT:
+ case Token::NE_STRICT:
+ case Token::INSTANCEOF:
+ case Token::IN:
+ SetStackOverflow();
+ break;
+
+ case Token::LT:
+ case Token::GT:
+ case Token::LTE:
+ case Token::GTE:
+ Visit(expr->left());
+ Visit(expr->right());
+ if (HasStackOverflow()) return;
+ graph_.AppendInstruction(expr);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
}
void FlowGraphBuilder::VisitThisFunction(ThisFunction* expr) {
- graph_.AppendInstruction(expr);
+ SetStackOverflow();
}
@@ -1098,6 +1040,451 @@
}
+AssignedVariablesAnalyzer::AssignedVariablesAnalyzer(FunctionLiteral* fun)
+ : fun_(fun),
+ av_(fun->scope()->num_parameters() + fun->scope()->num_stack_slots()) {}
+
+
+void AssignedVariablesAnalyzer::Analyze() {
+ ASSERT(av_.length() > 0);
+ VisitStatements(fun_->body());
+}
+
+
+Variable* AssignedVariablesAnalyzer::FindSmiLoopVariable(ForStatement* stmt) {
+ // The loop must have all necessary parts.
+ if (stmt->init() == NULL || stmt->cond() == NULL || stmt->next() == NULL) {
+ return NULL;
+ }
+ // The initialization statement has to be a simple assignment.
+ Assignment* init = stmt->init()->StatementAsSimpleAssignment();
+ if (init == NULL) return NULL;
+
+ // We only deal with local variables.
+ Variable* loop_var = init->target()->AsVariableProxy()->AsVariable();
+ if (loop_var == NULL || !loop_var->IsStackAllocated()) return NULL;
+
+ // The initial value has to be a smi.
+ Literal* init_lit = init->value()->AsLiteral();
+ if (init_lit == NULL || !init_lit->handle()->IsSmi()) return NULL;
+ int init_value = Smi::cast(*init_lit->handle())->value();
+
+ // The condition must be a compare of variable with <, <=, >, or >=.
+ CompareOperation* cond = stmt->cond()->AsCompareOperation();
+ if (cond == NULL) return NULL;
+ if (cond->op() != Token::LT
+ && cond->op() != Token::LTE
+ && cond->op() != Token::GT
+ && cond->op() != Token::GTE) return NULL;
+
+ // The lhs must be the same variable as in the init expression.
+ if (cond->left()->AsVariableProxy()->AsVariable() != loop_var) return NULL;
+
+ // The rhs must be a smi.
+ Literal* term_lit = cond->right()->AsLiteral();
+ if (term_lit == NULL || !term_lit->handle()->IsSmi()) return NULL;
+ int term_value = Smi::cast(*term_lit->handle())->value();
+
+ // The count operation updates the same variable as in the init expression.
+ CountOperation* update = stmt->next()->StatementAsCountOperation();
+ if (update == NULL) return NULL;
+ if (update->expression()->AsVariableProxy()->AsVariable() != loop_var) {
+ return NULL;
+ }
+
+ // The direction of the count operation must agree with the start and the end
+ // value. We currently do not allow the initial value to be the same as the
+ // terminal value. This _would_ be ok as long as the loop body never executes
+ // or executes exactly one time.
+ if (init_value == term_value) return NULL;
+ if (init_value < term_value && update->op() != Token::INC) return NULL;
+ if (init_value > term_value && update->op() != Token::DEC) return NULL;
+
+ // Found a smi loop variable.
+ return loop_var;
+}
+
+int AssignedVariablesAnalyzer::BitIndex(Variable* var) {
+ ASSERT(var != NULL);
+ ASSERT(var->IsStackAllocated());
+ Slot* slot = var->slot();
+ if (slot->type() == Slot::PARAMETER) {
+ return slot->index();
+ } else {
+ return fun_->scope()->num_parameters() + slot->index();
+ }
+}
+
+
+void AssignedVariablesAnalyzer::RecordAssignedVar(Variable* var) {
+ ASSERT(var != NULL);
+ if (var->IsStackAllocated()) {
+ av_.Add(BitIndex(var));
+ }
+}
+
+
+void AssignedVariablesAnalyzer::MarkIfTrivial(Expression* expr) {
+ Variable* var = expr->AsVariableProxy()->AsVariable();
+ if (var != NULL &&
+ var->IsStackAllocated() &&
+ !var->is_arguments() &&
+ var->mode() != Variable::CONST &&
+ (var->is_this() || !av_.Contains(BitIndex(var)))) {
+ expr->AsVariableProxy()->set_is_trivial(true);
+ }
+}
+
+
+void AssignedVariablesAnalyzer::ProcessExpression(Expression* expr) {
+ BitVector saved_av(av_);
+ av_.Clear();
+ Visit(expr);
+ av_.Union(saved_av);
+}
+
+void AssignedVariablesAnalyzer::VisitBlock(Block* stmt) {
+ VisitStatements(stmt->statements());
+}
+
+
+void AssignedVariablesAnalyzer::VisitExpressionStatement(
+ ExpressionStatement* stmt) {
+ ProcessExpression(stmt->expression());
+}
+
+
+void AssignedVariablesAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) {
+ // Do nothing.
+}
+
+
+void AssignedVariablesAnalyzer::VisitIfStatement(IfStatement* stmt) {
+ ProcessExpression(stmt->condition());
+ Visit(stmt->then_statement());
+ Visit(stmt->else_statement());
+}
+
+
+void AssignedVariablesAnalyzer::VisitContinueStatement(
+ ContinueStatement* stmt) {
+ // Nothing to do.
+}
+
+
+void AssignedVariablesAnalyzer::VisitBreakStatement(BreakStatement* stmt) {
+ // Nothing to do.
+}
+
+
+void AssignedVariablesAnalyzer::VisitReturnStatement(ReturnStatement* stmt) {
+ ProcessExpression(stmt->expression());
+}
+
+
+void AssignedVariablesAnalyzer::VisitWithEnterStatement(
+ WithEnterStatement* stmt) {
+ ProcessExpression(stmt->expression());
+}
+
+
+void AssignedVariablesAnalyzer::VisitWithExitStatement(
+ WithExitStatement* stmt) {
+ // Nothing to do.
+}
+
+
+void AssignedVariablesAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) {
+ BitVector result(av_);
+ av_.Clear();
+ Visit(stmt->tag());
+ result.Union(av_);
+ for (int i = 0; i < stmt->cases()->length(); i++) {
+ CaseClause* clause = stmt->cases()->at(i);
+ if (!clause->is_default()) {
+ av_.Clear();
+ Visit(clause->label());
+ result.Union(av_);
+ }
+ VisitStatements(clause->statements());
+ }
+ av_.Union(result);
+}
+
+
+void AssignedVariablesAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) {
+ ProcessExpression(stmt->cond());
+ Visit(stmt->body());
+}
+
+
+void AssignedVariablesAnalyzer::VisitWhileStatement(WhileStatement* stmt) {
+ ProcessExpression(stmt->cond());
+ Visit(stmt->body());
+}
+
+
+void AssignedVariablesAnalyzer::VisitForStatement(ForStatement* stmt) {
+ if (stmt->init() != NULL) Visit(stmt->init());
+
+ if (stmt->cond() != NULL) ProcessExpression(stmt->cond());
+
+ if (stmt->next() != NULL) Visit(stmt->next());
+
+ // Process loop body. After visiting the loop body av_ contains
+ // the assigned variables of the loop body.
+ BitVector saved_av(av_);
+ av_.Clear();
+ Visit(stmt->body());
+
+ Variable* var = FindSmiLoopVariable(stmt);
+ if (var != NULL && !av_.Contains(BitIndex(var))) {
+ stmt->set_loop_variable(var);
+ }
+
+ av_.Union(saved_av);
+}
+
+
+void AssignedVariablesAnalyzer::VisitForInStatement(ForInStatement* stmt) {
+ ProcessExpression(stmt->each());
+ ProcessExpression(stmt->enumerable());
+ Visit(stmt->body());
+}
+
+
+void AssignedVariablesAnalyzer::VisitTryCatchStatement(
+ TryCatchStatement* stmt) {
+ Visit(stmt->try_block());
+ Visit(stmt->catch_block());
+}
+
+
+void AssignedVariablesAnalyzer::VisitTryFinallyStatement(
+ TryFinallyStatement* stmt) {
+ Visit(stmt->try_block());
+ Visit(stmt->finally_block());
+}
+
+
+void AssignedVariablesAnalyzer::VisitDebuggerStatement(
+ DebuggerStatement* stmt) {
+ // Nothing to do.
+}
+
+
+void AssignedVariablesAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) {
+ // Nothing to do.
+ ASSERT(av_.IsEmpty());
+}
+
+
+void AssignedVariablesAnalyzer::VisitFunctionBoilerplateLiteral(
+ FunctionBoilerplateLiteral* expr) {
+ // Nothing to do.
+ ASSERT(av_.IsEmpty());
+}
+
+
+void AssignedVariablesAnalyzer::VisitConditional(Conditional* expr) {
+ ASSERT(av_.IsEmpty());
+
+ Visit(expr->condition());
+
+ BitVector result(av_);
+ av_.Clear();
+ Visit(expr->then_expression());
+ result.Union(av_);
+
+ av_.Clear();
+ Visit(expr->else_expression());
+ av_.Union(result);
+}
+
+
+void AssignedVariablesAnalyzer::VisitSlot(Slot* expr) {
+ UNREACHABLE();
+}
+
+
+void AssignedVariablesAnalyzer::VisitVariableProxy(VariableProxy* expr) {
+ // Nothing to do.
+ ASSERT(av_.IsEmpty());
+}
+
+
+void AssignedVariablesAnalyzer::VisitLiteral(Literal* expr) {
+ // Nothing to do.
+ ASSERT(av_.IsEmpty());
+}
+
+
+void AssignedVariablesAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) {
+ // Nothing to do.
+ ASSERT(av_.IsEmpty());
+}
+
+
+void AssignedVariablesAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) {
+ ASSERT(av_.IsEmpty());
+ BitVector result(av_.length());
+ for (int i = 0; i < expr->properties()->length(); i++) {
+ Visit(expr->properties()->at(i)->value());
+ result.Union(av_);
+ av_.Clear();
+ }
+ av_.CopyFrom(result);
+}
+
+
+void AssignedVariablesAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) {
+ ASSERT(av_.IsEmpty());
+ BitVector result(av_.length());
+ for (int i = 0; i < expr->values()->length(); i++) {
+ Visit(expr->values()->at(i));
+ result.Union(av_);
+ av_.Clear();
+ }
+ av_.CopyFrom(result);
+}
+
+
+void AssignedVariablesAnalyzer::VisitCatchExtensionObject(
+ CatchExtensionObject* expr) {
+ ASSERT(av_.IsEmpty());
+ Visit(expr->key());
+ ProcessExpression(expr->value());
+}
+
+
+void AssignedVariablesAnalyzer::VisitAssignment(Assignment* expr) {
+ ASSERT(av_.IsEmpty());
+
+ if (expr->target()->AsProperty() != NULL) {
+ // Visit receiver and key of property store and rhs.
+ Visit(expr->target()->AsProperty()->obj());
+ ProcessExpression(expr->target()->AsProperty()->key());
+ ProcessExpression(expr->value());
+
+ // If we have a variable as a receiver in a property store, check if
+ // we can mark it as trivial.
+ MarkIfTrivial(expr->target()->AsProperty()->obj());
+ } else {
+ Visit(expr->target());
+ ProcessExpression(expr->value());
+
+ Variable* var = expr->target()->AsVariableProxy()->AsVariable();
+ if (var != NULL) RecordAssignedVar(var);
+ }
+}
+
+
+void AssignedVariablesAnalyzer::VisitThrow(Throw* expr) {
+ ASSERT(av_.IsEmpty());
+ Visit(expr->exception());
+}
+
+
+void AssignedVariablesAnalyzer::VisitProperty(Property* expr) {
+ ASSERT(av_.IsEmpty());
+ Visit(expr->obj());
+ ProcessExpression(expr->key());
+
+ // In case we have a variable as a receiver, check if we can mark
+ // it as trivial.
+ MarkIfTrivial(expr->obj());
+}
+
+
+void AssignedVariablesAnalyzer::VisitCall(Call* expr) {
+ ASSERT(av_.IsEmpty());
+ Visit(expr->expression());
+ BitVector result(av_);
+ for (int i = 0; i < expr->arguments()->length(); i++) {
+ av_.Clear();
+ Visit(expr->arguments()->at(i));
+ result.Union(av_);
+ }
+ av_.CopyFrom(result);
+}
+
+
+void AssignedVariablesAnalyzer::VisitCallNew(CallNew* expr) {
+ ASSERT(av_.IsEmpty());
+ Visit(expr->expression());
+ BitVector result(av_);
+ for (int i = 0; i < expr->arguments()->length(); i++) {
+ av_.Clear();
+ Visit(expr->arguments()->at(i));
+ result.Union(av_);
+ }
+ av_.CopyFrom(result);
+}
+
+
+void AssignedVariablesAnalyzer::VisitCallRuntime(CallRuntime* expr) {
+ ASSERT(av_.IsEmpty());
+ BitVector result(av_);
+ for (int i = 0; i < expr->arguments()->length(); i++) {
+ av_.Clear();
+ Visit(expr->arguments()->at(i));
+ result.Union(av_);
+ }
+ av_.CopyFrom(result);
+}
+
+
+void AssignedVariablesAnalyzer::VisitUnaryOperation(UnaryOperation* expr) {
+ ASSERT(av_.IsEmpty());
+ Visit(expr->expression());
+}
+
+
+void AssignedVariablesAnalyzer::VisitCountOperation(CountOperation* expr) {
+ ASSERT(av_.IsEmpty());
+
+ Visit(expr->expression());
+
+ Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
+ if (var != NULL) RecordAssignedVar(var);
+}
+
+
+void AssignedVariablesAnalyzer::VisitBinaryOperation(BinaryOperation* expr) {
+ ASSERT(av_.IsEmpty());
+ Visit(expr->left());
+
+ ProcessExpression(expr->right());
+
+ // In case we have a variable on the left side, check if we can mark
+ // it as trivial.
+ MarkIfTrivial(expr->left());
+}
+
+
+void AssignedVariablesAnalyzer::VisitCompareOperation(CompareOperation* expr) {
+ ASSERT(av_.IsEmpty());
+ Visit(expr->left());
+
+ ProcessExpression(expr->right());
+
+ // In case we have a variable on the left side, check if we can mark
+ // it as trivial.
+ MarkIfTrivial(expr->left());
+}
+
+
+void AssignedVariablesAnalyzer::VisitThisFunction(ThisFunction* expr) {
+ // Nothing to do.
+ ASSERT(av_.IsEmpty());
+}
+
+
+void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) {
+ UNREACHABLE();
+}
+
+
#ifdef DEBUG
// Print a textual representation of an instruction in a flow graph. Using
@@ -1105,7 +1492,10 @@
// only used for printing in debug mode.
class TextInstructionPrinter: public AstVisitor {
public:
- TextInstructionPrinter() {}
+ TextInstructionPrinter() : number_(0) {}
+
+ int NextNumber() { return number_; }
+ void AssignNumber(AstNode* node) { node->set_num(number_++); }
private:
// AST node visit functions.
@@ -1113,6 +1503,8 @@
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
+ int number_;
+
DISALLOW_COPY_AND_ASSIGN(TextInstructionPrinter);
};
@@ -1233,8 +1625,7 @@
void TextInstructionPrinter::VisitVariableProxy(VariableProxy* expr) {
Variable* var = expr->AsVariable();
if (var != NULL) {
- SmartPointer<char> name = var->name()->ToCString();
- PrintF("%s", *name);
+ PrintF("%s", *var->name()->ToCString());
} else {
ASSERT(expr->AsProperty() != NULL);
VisitProperty(expr->AsProperty());
@@ -1273,9 +1664,8 @@
Property* prop = expr->target()->AsProperty();
if (var != NULL) {
- SmartPointer<char> name = var->name()->ToCString();
PrintF("%s %s @%d",
- *name,
+ *var->name()->ToCString(),
Token::String(expr->op()),
expr->value()->num());
} else if (prop != NULL) {
@@ -1297,6 +1687,10 @@
// Throw reference error.
Visit(expr->target());
}
+
+ if (expr->num() != AstNode::kNoNumber) {
+ PrintF(" ;; D%d", expr->num());
+ }
}
@@ -1339,8 +1733,7 @@
void TextInstructionPrinter::VisitCallRuntime(CallRuntime* expr) {
- SmartPointer<char> name = expr->name()->ToCString();
- PrintF("%s(", *name);
+ PrintF("%s(", *expr->name()->ToCString());
ZoneList<Expression*>* arguments = expr->arguments();
for (int i = 0, len = arguments->length(); i < len; i++) {
if (i != 0) PrintF(", ");
@@ -1361,6 +1754,10 @@
} else {
PrintF("@%d%s", expr->expression()->num(), Token::String(expr->op()));
}
+
+ if (expr->num() != AstNode::kNoNumber) {
+ PrintF(" ;; D%d", expr->num());
+ }
}
@@ -1392,36 +1789,66 @@
static int instruction_count = 0;
-void Node::AssignNumbers() {
+void Node::AssignNodeNumber() {
set_number(node_count++);
}
-void BlockNode::AssignNumbers() {
- set_number(node_count++);
- for (int i = 0, len = instructions_.length(); i < len; i++) {
- instructions_[i]->set_num(instruction_count++);
+void Node::PrintReachingDefinitions() {
+ if (rd_.rd_in() != NULL) {
+ ASSERT(rd_.kill() != NULL && rd_.gen() != NULL);
+
+ PrintF("RD_in = {");
+ bool first = true;
+ for (int i = 0; i < rd_.rd_in()->length(); i++) {
+ if (rd_.rd_in()->Contains(i)) {
+ if (!first) PrintF(",");
+ PrintF("%d");
+ first = false;
+ }
+ }
+ PrintF("}\n");
+
+ PrintF("RD_kill = {");
+ first = true;
+ for (int i = 0; i < rd_.kill()->length(); i++) {
+ if (rd_.kill()->Contains(i)) {
+ if (!first) PrintF(",");
+ PrintF("%d");
+ first = false;
+ }
+ }
+ PrintF("}\n");
+
+ PrintF("RD_gen = {");
+ first = true;
+ for (int i = 0; i < rd_.gen()->length(); i++) {
+ if (rd_.gen()->Contains(i)) {
+ if (!first) PrintF(",");
+ PrintF("%d");
+ first = false;
+ }
+ }
+ PrintF("}\n");
}
}
-void EntryNode::PrintText() {
- PrintF("L%d: Entry\n", number());
- PrintF("goto L%d\n\n", successor_->number());
-}
-
void ExitNode::PrintText() {
+ PrintReachingDefinitions();
PrintF("L%d: Exit\n\n", number());
}
void BlockNode::PrintText() {
+ PrintReachingDefinitions();
// Print the instructions in the block.
PrintF("L%d: Block\n", number());
TextInstructionPrinter printer;
for (int i = 0, len = instructions_.length(); i < len; i++) {
- PrintF("%d ", instructions_[i]->num());
+ PrintF("%d ", printer.NextNumber());
printer.Visit(instructions_[i]);
+ printer.AssignNumber(instructions_[i]);
PrintF("\n");
}
PrintF("goto L%d\n\n", successor_->number());
@@ -1429,12 +1856,14 @@
void BranchNode::PrintText() {
+ PrintReachingDefinitions();
PrintF("L%d: Branch\n", number());
PrintF("goto (L%d, L%d)\n\n", successor0_->number(), successor1_->number());
}
void JoinNode::PrintText() {
+ PrintReachingDefinitions();
PrintF("L%d: Join(", number());
for (int i = 0, len = predecessors_.length(); i < len; i++) {
if (i != 0) PrintF(", ");
@@ -1451,7 +1880,7 @@
node_count = 0;
instruction_count = 0;
for (int i = postorder->length() - 1; i >= 0; i--) {
- postorder->at(i)->AssignNumbers();
+ postorder->at(i)->AssignNodeNumber();
}
// Print basic blocks in reverse postorder.
@@ -1464,4 +1893,231 @@
#endif // defined(DEBUG)
+int ReachingDefinitions::IndexFor(Variable* var, int variable_count) {
+ // Parameters are numbered left-to-right from the beginning of the bit
+ // set. Stack-allocated locals are allocated right-to-left from the end.
+ ASSERT(var != NULL && var->IsStackAllocated());
+ Slot* slot = var->slot();
+ if (slot->type() == Slot::PARAMETER) {
+ return slot->index();
+ } else {
+ return (variable_count - 1) - slot->index();
+ }
+}
+
+
+void Node::InitializeReachingDefinitions(int definition_count,
+ List<BitVector*>* variables,
+ WorkList<Node>* worklist,
+ bool mark) {
+ ASSERT(!IsMarkedWith(mark));
+ rd_.Initialize(definition_count);
+ MarkWith(mark);
+ worklist->Insert(this);
+}
+
+
+void BlockNode::InitializeReachingDefinitions(int definition_count,
+ List<BitVector*>* variables,
+ WorkList<Node>* worklist,
+ bool mark) {
+ ASSERT(!IsMarkedWith(mark));
+ int instruction_count = instructions_.length();
+ int variable_count = variables->length();
+
+ rd_.Initialize(definition_count);
+
+ for (int i = 0; i < instruction_count; i++) {
+ Expression* expr = instructions_[i]->AsExpression();
+ if (expr == NULL) continue;
+ Variable* var = expr->AssignedVar();
+ if (var == NULL || !var->IsStackAllocated()) continue;
+
+ // All definitions of this variable are killed.
+ BitVector* def_set =
+ variables->at(ReachingDefinitions::IndexFor(var, variable_count));
+ rd_.kill()->Union(*def_set);
+
+ // All previously generated definitions are not generated.
+ rd_.gen()->Subtract(*def_set);
+
+ // This one is generated.
+ rd_.gen()->Add(expr->num());
+ }
+
+ // Add all blocks except the entry node to the worklist.
+ if (predecessor_ != NULL) {
+ MarkWith(mark);
+ worklist->Insert(this);
+ }
+}
+
+
+void ExitNode::ComputeRDOut(BitVector* result) {
+ // Should not be the predecessor of any node.
+ UNREACHABLE();
+}
+
+
+void BlockNode::ComputeRDOut(BitVector* result) {
+ // All definitions reaching this block ...
+ result->CopyFrom(*rd_.rd_in());
+ // ... except those killed by the block ...
+ result->Subtract(*rd_.kill());
+ // ... but including those generated by the block.
+ result->Union(*rd_.gen());
+}
+
+
+void BranchNode::ComputeRDOut(BitVector* result) {
+ // Branch nodes don't kill or generate definitions.
+ result->CopyFrom(*rd_.rd_in());
+}
+
+
+void JoinNode::ComputeRDOut(BitVector* result) {
+ // Join nodes don't kill or generate definitions.
+ result->CopyFrom(*rd_.rd_in());
+}
+
+
+void ExitNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
+ // The exit node has no successors so we can just update in place. New
+ // RD_in is the union over all predecessors.
+ int definition_count = rd_.rd_in()->length();
+ rd_.rd_in()->Clear();
+
+ BitVector temp(definition_count);
+ for (int i = 0, len = predecessors_.length(); i < len; i++) {
+ // Because ComputeRDOut always overwrites temp and its value is
+ // always read out before calling ComputeRDOut again, we do not
+ // have to clear it on each iteration of the loop.
+ predecessors_[i]->ComputeRDOut(&temp);
+ rd_.rd_in()->Union(temp);
+ }
+}
+
+
+void BlockNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
+ // The entry block has no predecessor. Its RD_in does not change.
+ if (predecessor_ == NULL) return;
+
+ BitVector new_rd_in(rd_.rd_in()->length());
+ predecessor_->ComputeRDOut(&new_rd_in);
+
+ if (rd_.rd_in()->Equals(new_rd_in)) return;
+
+ // Update RD_in.
+ rd_.rd_in()->CopyFrom(new_rd_in);
+ // Add the successor to the worklist if not already present.
+ if (!successor_->IsMarkedWith(mark)) {
+ successor_->MarkWith(mark);
+ worklist->Insert(successor_);
+ }
+}
+
+
+void BranchNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
+ BitVector new_rd_in(rd_.rd_in()->length());
+ predecessor_->ComputeRDOut(&new_rd_in);
+
+ if (rd_.rd_in()->Equals(new_rd_in)) return;
+
+ // Update RD_in.
+ rd_.rd_in()->CopyFrom(new_rd_in);
+ // Add the successors to the worklist if not already present.
+ if (!successor0_->IsMarkedWith(mark)) {
+ successor0_->MarkWith(mark);
+ worklist->Insert(successor0_);
+ }
+ if (!successor1_->IsMarkedWith(mark)) {
+ successor1_->MarkWith(mark);
+ worklist->Insert(successor1_);
+ }
+}
+
+
+void JoinNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
+ int definition_count = rd_.rd_in()->length();
+ BitVector new_rd_in(definition_count);
+
+ // New RD_in is the union over all predecessors.
+ BitVector temp(definition_count);
+ for (int i = 0, len = predecessors_.length(); i < len; i++) {
+ predecessors_[i]->ComputeRDOut(&temp);
+ new_rd_in.Union(temp);
+ }
+
+ if (rd_.rd_in()->Equals(new_rd_in)) return;
+
+ // Update RD_in.
+ rd_.rd_in()->CopyFrom(new_rd_in);
+ // Add the successor to the worklist if not already present.
+ if (!successor_->IsMarkedWith(mark)) {
+ successor_->MarkWith(mark);
+ worklist->Insert(successor_);
+ }
+}
+
+
+void ReachingDefinitions::Compute() {
+ ASSERT(!definitions_->is_empty());
+
+ int variable_count = variables_.length();
+ int definition_count = definitions_->length();
+ int node_count = postorder_->length();
+
+ // Step 1: For each variable, identify the set of all its definitions in
+ // the body.
+ for (int i = 0; i < definition_count; i++) {
+ Variable* var = definitions_->at(i)->AssignedVar();
+ variables_[IndexFor(var, variable_count)]->Add(i);
+ }
+
+ if (FLAG_print_graph_text) {
+ for (int i = 0; i < variable_count; i++) {
+ BitVector* def_set = variables_[i];
+ if (!def_set->IsEmpty()) {
+ // At least one definition.
+ bool first = true;
+ for (int j = 0; j < definition_count; j++) {
+ if (def_set->Contains(j)) {
+ if (first) {
+ Variable* var = definitions_->at(j)->AssignedVar();
+ ASSERT(var != NULL);
+ PrintF("Def[%s] = {%d", *var->name()->ToCString(), j);
+ first = false;
+ } else {
+ PrintF(", %d", j);
+ }
+ }
+ }
+ PrintF("}\n");
+ }
+ }
+ }
+
+ // Step 2: Compute KILL and GEN for each block node, initialize RD_in for
+ // all nodes, and mark and add all nodes to the worklist in reverse
+ // postorder. All nodes should currently have the same mark.
+ bool mark = postorder_->at(0)->IsMarkedWith(false); // Negation of current.
+ WorkList<Node> worklist(node_count);
+ for (int i = node_count - 1; i >= 0; i--) {
+ postorder_->at(i)->InitializeReachingDefinitions(definition_count,
+ &variables_,
+ &worklist,
+ mark);
+ }
+
+ // Step 3: Until the worklist is empty, remove an item compute and update
+ // its rd_in based on its predecessor's rd_out. If rd_in has changed, add
+ // all necessary successors to the worklist.
+ while (!worklist.is_empty()) {
+ Node* node = worklist.Remove();
+ node->MarkWith(!mark);
+ node->UpdateRDIn(&worklist, mark);
+ }
+}
+
+
} } // namespace v8::internal
diff --git a/src/data-flow.h b/src/data-flow.h
index 2dc2d73..236d0ad 100644
--- a/src/data-flow.h
+++ b/src/data-flow.h
@@ -100,6 +100,13 @@
}
}
+ void Subtract(const BitVector& other) {
+ ASSERT(other.length() == length());
+ for (int i = 0; i < data_length_; i++) {
+ data_[i] &= ~other.data_[i];
+ }
+ }
+
void Clear() {
for (int i = 0; i < data_length_; i++) {
data_[i] = 0;
@@ -113,6 +120,13 @@
return true;
}
+ bool Equals(const BitVector& other) {
+ for (int i = 0; i < data_length_; i++) {
+ if (data_[i] != other.data_[i]) return false;
+ }
+ return true;
+ }
+
int length() const { return length_; }
private:
@@ -122,56 +136,68 @@
};
-// Forward declarations of Node types.
-class Node;
-class BranchNode;
-class JoinNode;
-
-// Flow graphs have a single entry and single exit. The empty flowgraph is
-// represented by both entry and exit being NULL.
-class FlowGraph BASE_EMBEDDED {
+// Simple fixed-capacity list-based worklist (managed as a queue) of
+// pointers to T.
+template<typename T>
+class WorkList BASE_EMBEDDED {
public:
- FlowGraph() : entry_(NULL), exit_(NULL) {}
+ // The worklist cannot grow bigger than size. We keep one item empty to
+ // distinguish between empty and full.
+ explicit WorkList(int size)
+ : capacity_(size + 1), head_(0), tail_(0), queue_(capacity_) {
+ for (int i = 0; i < capacity_; i++) queue_.Add(NULL);
+ }
- static FlowGraph Empty() { return FlowGraph(); }
+ bool is_empty() { return head_ == tail_; }
- bool is_empty() const { return entry_ == NULL; }
- Node* entry() const { return entry_; }
- Node* exit() const { return exit_; }
+ bool is_full() {
+ // The worklist is full if head is at 0 and tail is at capacity - 1:
+ // head == 0 && tail == capacity-1 ==> tail - head == capacity - 1
+ // or if tail is immediately to the left of head:
+ // tail+1 == head ==> tail - head == -1
+ int diff = tail_ - head_;
+ return (diff == -1 || diff == capacity_ - 1);
+ }
- // Add a single instruction to the end of this flowgraph.
- void AppendInstruction(AstNode* instruction);
+ void Insert(T* item) {
+ ASSERT(!is_full());
+ queue_[tail_++] = item;
+ if (tail_ == capacity_) tail_ = 0;
+ }
- // Add a single node to the end of this flow graph.
- void AppendNode(Node* node);
-
- // Add a flow graph fragment to the end of this one.
- void AppendGraph(FlowGraph* graph);
-
- // Concatenate an if-then-else flow-graph to this one. Control is split
- // and merged, so the graph remains single-entry, single-exit.
- void Split(BranchNode* branch,
- FlowGraph* left,
- FlowGraph* right,
- JoinNode* merge);
-
- // Concatenate a forward loop (e.g., while or for loop) flow-graph to this
- // one. Control is split by the condition and merged back from the back
- // edge at end of the body to the beginning of the condition. The single
- // (free) exit of the result graph is the right (false) arm of the branch
- // node.
- void Loop(JoinNode* merge,
- FlowGraph* condition,
- BranchNode* branch,
- FlowGraph* body);
-
-#ifdef DEBUG
- void PrintText(ZoneList<Node*>* postorder);
-#endif
+ T* Remove() {
+ ASSERT(!is_empty());
+ T* item = queue_[head_++];
+ if (head_ == capacity_) head_ = 0;
+ return item;
+ }
private:
- Node* entry_;
- Node* exit_;
+ int capacity_; // Including one empty slot.
+ int head_; // Where the first item is.
+ int tail_; // Where the next inserted item will go.
+ List<T*> queue_;
+};
+
+
+struct ReachingDefinitionsData BASE_EMBEDDED {
+ public:
+ ReachingDefinitionsData() : rd_in_(NULL), kill_(NULL), gen_(NULL) {}
+
+ void Initialize(int definition_count) {
+ rd_in_ = new BitVector(definition_count);
+ kill_ = new BitVector(definition_count);
+ gen_ = new BitVector(definition_count);
+ }
+
+ BitVector* rd_in() { return rd_in_; }
+ BitVector* kill() { return kill_; }
+ BitVector* gen() { return gen_; }
+
+ private:
+ BitVector* rd_in_;
+ BitVector* kill_;
+ BitVector* gen_;
};
@@ -182,7 +208,9 @@
virtual ~Node() {}
+ virtual bool IsExitNode() { return false; }
virtual bool IsBlockNode() { return false; }
+ virtual bool IsBranchNode() { return false; }
virtual bool IsJoinNode() { return false; }
virtual void AddPredecessor(Node* predecessor) = 0;
@@ -200,11 +228,23 @@
int number() { return number_; }
void set_number(int number) { number_ = number; }
+ // Functions used by data-flow analyses.
+ virtual void InitializeReachingDefinitions(int definition_count,
+ List<BitVector*>* variables,
+ WorkList<Node>* worklist,
+ bool mark);
+ virtual void ComputeRDOut(BitVector* result) = 0;
+ virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark) = 0;
+
#ifdef DEBUG
- virtual void AssignNumbers();
+ void AssignNodeNumber();
+ void PrintReachingDefinitions();
virtual void PrintText() = 0;
#endif
+ protected:
+ ReachingDefinitionsData rd_;
+
private:
int number_;
bool mark_;
@@ -213,49 +253,27 @@
};
-// An entry node has no predecessors and a single successor.
-class EntryNode: public Node {
- public:
- EntryNode() : successor_(NULL) {}
-
- void AddPredecessor(Node* predecessor) { UNREACHABLE(); }
-
- void AddSuccessor(Node* successor) {
- ASSERT(successor_ == NULL && successor != NULL);
- successor_ = successor;
- }
-
- void Traverse(bool mark,
- ZoneList<Node*>* preorder,
- ZoneList<Node*>* postorder);
-
-#ifdef DEBUG
- void PrintText();
-#endif
-
- private:
- Node* successor_;
-
- DISALLOW_COPY_AND_ASSIGN(EntryNode);
-};
-
-
// An exit node has a arbitrarily many predecessors and no successors.
class ExitNode: public Node {
public:
ExitNode() : predecessors_(4) {}
+ bool IsExitNode() { return true; }
+
void AddPredecessor(Node* predecessor) {
ASSERT(predecessor != NULL);
predecessors_.Add(predecessor);
}
- void AddSuccessor(Node* successor) { /* Do nothing. */ }
+ void AddSuccessor(Node* successor) { UNREACHABLE(); }
void Traverse(bool mark,
ZoneList<Node*>* preorder,
ZoneList<Node*>* postorder);
+ void ComputeRDOut(BitVector* result);
+ void UpdateRDIn(WorkList<Node>* worklist, bool mark);
+
#ifdef DEBUG
void PrintText();
#endif
@@ -280,6 +298,8 @@
bool IsBlockNode() { return true; }
+ bool is_empty() { return instructions_.is_empty(); }
+
void AddPredecessor(Node* predecessor) {
ASSERT(predecessor_ == NULL && predecessor != NULL);
predecessor_ = predecessor;
@@ -298,8 +318,14 @@
ZoneList<Node*>* preorder,
ZoneList<Node*>* postorder);
+ void InitializeReachingDefinitions(int definition_count,
+ List<BitVector*>* variables,
+ WorkList<Node>* worklist,
+ bool mark);
+ void ComputeRDOut(BitVector* result);
+ void UpdateRDIn(WorkList<Node>* worklist, bool mark);
+
#ifdef DEBUG
- void AssignNumbers();
void PrintText();
#endif
@@ -317,6 +343,8 @@
public:
BranchNode() : predecessor_(NULL), successor0_(NULL), successor1_(NULL) {}
+ bool IsBranchNode() { return true; }
+
void AddPredecessor(Node* predecessor) {
ASSERT(predecessor_ == NULL && predecessor != NULL);
predecessor_ = predecessor;
@@ -335,6 +363,9 @@
ZoneList<Node*>* preorder,
ZoneList<Node*>* postorder);
+ void ComputeRDOut(BitVector* result);
+ void UpdateRDIn(WorkList<Node>* worklist, bool mark);
+
#ifdef DEBUG
void PrintText();
#endif
@@ -374,6 +405,9 @@
ZoneList<Node*>* preorder,
ZoneList<Node*>* postorder);
+ void ComputeRDOut(BitVector* result);
+ void UpdateRDIn(WorkList<Node>* worklist, bool mark);
+
#ifdef DEBUG
void PrintText();
#endif
@@ -386,12 +420,68 @@
};
+// Flow graphs have a single entry and single exit. The empty flowgraph is
+// represented by both entry and exit being NULL.
+class FlowGraph BASE_EMBEDDED {
+ public:
+ static FlowGraph Empty() {
+ FlowGraph graph;
+ graph.entry_ = new BlockNode();
+ graph.exit_ = graph.entry_;
+ return graph;
+ }
+
+ bool is_empty() const {
+ return entry_ == exit_ && BlockNode::cast(entry_)->is_empty();
+ }
+ Node* entry() const { return entry_; }
+ Node* exit() const { return exit_; }
+
+ // Add a single instruction to the end of this flowgraph.
+ void AppendInstruction(AstNode* instruction);
+
+ // Add a single node to the end of this flow graph.
+ void AppendNode(Node* node);
+
+ // Add a flow graph fragment to the end of this one.
+ void AppendGraph(FlowGraph* graph);
+
+ // Concatenate an if-then-else flow-graph to this one. Control is split
+ // and merged, so the graph remains single-entry, single-exit.
+ void Split(BranchNode* branch,
+ FlowGraph* left,
+ FlowGraph* right,
+ JoinNode* merge);
+
+ // Concatenate a forward loop (e.g., while or for loop) flow-graph to this
+ // one. Control is split by the condition and merged back from the back
+ // edge at end of the body to the beginning of the condition. The single
+ // (free) exit of the result graph is the right (false) arm of the branch
+ // node.
+ void Loop(JoinNode* merge,
+ FlowGraph* condition,
+ BranchNode* branch,
+ FlowGraph* body);
+
+#ifdef DEBUG
+ void PrintText(ZoneList<Node*>* postorder);
+#endif
+
+ private:
+ FlowGraph() : entry_(NULL), exit_(NULL) {}
+
+ Node* entry_;
+ Node* exit_;
+};
+
+
// Construct a flow graph from a function literal. Build pre- and postorder
// traversal orders as a byproduct.
class FlowGraphBuilder: public AstVisitor {
public:
FlowGraphBuilder()
- : global_exit_(NULL),
+ : graph_(FlowGraph::Empty()),
+ global_exit_(NULL),
preorder_(4),
postorder_(4),
definitions_(4) {
@@ -400,8 +490,8 @@
void Build(FunctionLiteral* lit);
FlowGraph* graph() { return &graph_; }
-
ZoneList<Node*>* postorder() { return &postorder_; }
+ ZoneList<Expression*>* definitions() { return &definitions_; }
private:
ExitNode* global_exit() { return global_exit_; }
@@ -418,8 +508,9 @@
// The flow graph builder collects a list of definitions (assignments and
// count operations) to stack-allocated variables to use for reaching
- // definitions analysis.
- ZoneList<AstNode*> definitions_;
+ // definitions analysis. AST node numbers in the AST are used to refer
+ // into this list.
+ ZoneList<Expression*> definitions_;
DISALLOW_COPY_AND_ASSIGN(FlowGraphBuilder);
};
@@ -502,6 +593,74 @@
};
+// 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.
+class AssignedVariablesAnalyzer : public AstVisitor {
+ public:
+ explicit AssignedVariablesAnalyzer(FunctionLiteral* fun);
+
+ void Analyze();
+
+ private:
+ Variable* FindSmiLoopVariable(ForStatement* stmt);
+
+ int BitIndex(Variable* var);
+
+ void RecordAssignedVar(Variable* var);
+
+ void MarkIfTrivial(Expression* expr);
+
+ // Visits an expression saving the accumulator before, clearing
+ // it before visting and restoring it after visiting.
+ void ProcessExpression(Expression* expr);
+
+ // AST node visit functions.
+#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
+ AST_NODE_LIST(DECLARE_VISIT)
+#undef DECLARE_VISIT
+
+ FunctionLiteral* fun_;
+
+ // Accumulator for assigned variables set.
+ BitVector av_;
+
+ DISALLOW_COPY_AND_ASSIGN(AssignedVariablesAnalyzer);
+};
+
+
+class ReachingDefinitions BASE_EMBEDDED {
+ public:
+ ReachingDefinitions(ZoneList<Node*>* postorder,
+ ZoneList<Expression*>* definitions,
+ int variable_count)
+ : postorder_(postorder),
+ definitions_(definitions),
+ variables_(variable_count) {
+ int definition_count = definitions->length();
+ for (int i = 0; i < variable_count; i++) {
+ variables_.Add(new BitVector(definition_count));
+ }
+ }
+
+ static int IndexFor(Variable* var, int variable_count);
+
+ void Compute();
+
+ private:
+ // A (postorder) list of flow-graph nodes in the body.
+ ZoneList<Node*>* postorder_;
+
+ // A list of all the definitions in the body.
+ ZoneList<Expression*>* definitions_;
+
+ // For each variable, the set of all its definitions.
+ List<BitVector*> variables_;
+
+ DISALLOW_COPY_AND_ASSIGN(ReachingDefinitions);
+};
+
+
} } // namespace v8::internal
diff --git a/src/date-delay.js b/src/date-delay.js
index c0180c2..f2ea1ec 100644
--- a/src/date-delay.js
+++ b/src/date-delay.js
@@ -293,55 +293,48 @@
}
-// Constructor for creating objects holding year, month, and date.
-// Introduced to ensure the two return points in FromJulianDay match same map.
-function DayTriplet(year, month, date) {
- this.year = year;
- this.month = month;
- this.date = date;
+var ymd_from_time_cache = [$NaN, $NaN, $NaN];
+var ymd_from_time_cached_time = $NaN;
+
+function YearFromTime(t) {
+ if (t !== ymd_from_time_cached_time) {
+ // Limits according to ECMA 262 15.9.1.1
+ if (!$isFinite(t) || t < -8640000000000000 || t > 8640000000000000) {
+ return $NaN;
+ }
+
+ %DateYMDFromTime(t, ymd_from_time_cache);
+ ymd_from_time_cached_time = t
+ }
+
+ return ymd_from_time_cache[0];
}
-var julian_day_cache_triplet;
-var julian_day_cache_day = $NaN;
+function MonthFromTime(t) {
+ if (t !== ymd_from_time_cached_time) {
+ // Limits according to ECMA 262 15.9.1.1
+ if (!$isFinite(t) || t < -8640000000000000 || t > 8640000000000000) {
+ return $NaN;
+ }
+ %DateYMDFromTime(t, ymd_from_time_cache);
+ ymd_from_time_cached_time = t
+ }
-// Compute year, month, and day from modified Julian day.
-// The missing days in 1582 are ignored for JavaScript compatibility.
-function FromJulianDay(julian) {
- if (julian_day_cache_day == julian) {
- return julian_day_cache_triplet;
+ return ymd_from_time_cache[1];
+}
+
+function DateFromTime(t) {
+ if (t !== ymd_from_time_cached_time) {
+ // Limits according to ECMA 262 15.9.1.1
+ if (!$isFinite(t) || t < -8640000000000000 || t > 8640000000000000) {
+ return $NaN;
+ }
+
+ %DateYMDFromTime(t, ymd_from_time_cache);
+ ymd_from_time_cached_time = t
}
- var result;
- // Avoid floating point and non-Smi maths in common case. This is also a period of
- // time where leap years are very regular. The range is not too large to avoid overflow
- // when doing the multiply-to-divide trick.
- if (julian > kDayZeroInJulianDay &&
- (julian - kDayZeroInJulianDay) < 40177) { // 1970 - 2080
- var jsimple = (julian - kDayZeroInJulianDay) + 731; // Day 0 is 1st January 1968
- var y = 1968;
- // Divide by 1461 by multiplying with 22967 and shifting down by 25!
- var after_1968 = (jsimple * 22967) >> 25;
- y += after_1968 << 2;
- jsimple -= 1461 * after_1968;
- var four_year_cycle = four_year_cycle_table[jsimple];
- result = new DayTriplet(y + (four_year_cycle >> kYearShift),
- (four_year_cycle & kMonthMask) >> kMonthShift,
- four_year_cycle & kDayMask);
- } else {
- var jalpha = FLOOR((julian - 1867216.25) / 36524.25);
- var jb = julian + 1 + jalpha - FLOOR(0.25 * jalpha) + 1524;
- var jc = FLOOR(6680.0 + ((jb-2439870) - 122.1)/365.25);
- var jd = FLOOR(365 * jc + (0.25 * jc));
- var je = FLOOR((jb - jd)/30.6001);
- var m = je - 1;
- if (m > 12) m -= 13;
- var y = jc - 4715;
- if (m > 2) { --y; --m; }
- var d = jb - jd - FLOOR(30.6001 * je);
- result = new DayTriplet(y, m, d);
- }
- julian_day_cache_day = julian;
- julian_day_cache_triplet = result;
- return result;
+
+ return ymd_from_time_cache[2];
}
@@ -577,11 +570,10 @@
function DateString(time) {
- var YMD = FromJulianDay(DAY(time) + kDayZeroInJulianDay);
return WeekDays[WeekDay(time)] + ' '
- + Months[YMD.month] + ' '
- + TwoDigitString(YMD.date) + ' '
- + YMD.year;
+ + Months[MonthFromTime(time)] + ' '
+ + TwoDigitString(DateFromTime(time)) + ' '
+ + YearFromTime(time);
}
@@ -590,11 +582,10 @@
function LongDateString(time) {
- var YMD = FromJulianDay(DAY(time) + kDayZeroInJulianDay);
return LongWeekDays[WeekDay(time)] + ', '
- + LongMonths[YMD.month] + ' '
- + TwoDigitString(YMD.date) + ', '
- + YMD.year;
+ + LongMonths[MonthFromTime(time)] + ' '
+ + TwoDigitString(DateFromTime(time)) + ', '
+ + YearFromTime(time);
}
diff --git a/src/debug.cc b/src/debug.cc
index 959bea1..81752e6 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -803,7 +803,7 @@
void Debug::Iterate(ObjectVisitor* v) {
- v->VisitPointer(bit_cast<Object**, Code**>(&(debug_break_return_)));
+ v->VisitPointer(BitCast<Object**, Code**>(&(debug_break_return_)));
}
diff --git a/src/diy_fp.h b/src/diy_fp.h
new file mode 100644
index 0000000..9cd7003
--- /dev/null
+++ b/src/diy_fp.h
@@ -0,0 +1,136 @@
+// 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) {
+ // 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);
+ tmp += 1U << 31; // round
+ uint64_t result_f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
+ e_ += other.e_ + 64;
+ f_ = result_f;
+ }
+
+ // returns a * b;
+ static DiyFp Times(const DiyFp& a, const DiyFp& b) {
+ DiyFp result = a;
+ result.Multiply(b);
+ return result;
+ }
+
+ void Normalize() {
+ ASSERT(f_ != 0);
+ uint64_t f = f_;
+ int e = e_;
+
+ // This method is mainly called for normalizing boundaries. In general
+ // boundaries need to be shifted by 10 bits. We thus optimize for this case.
+ const uint64_t k10MSBits = V8_2PART_UINT64_C(0xFFC00000, 00000000);
+ while ((f & k10MSBits) == 0) {
+ f <<= 10;
+ e -= 10;
+ }
+ while ((f & kUint64MSB) == 0) {
+ f <<= 1;
+ e--;
+ }
+ f_ = f;
+ e_ = e;
+ }
+
+ static DiyFp Normalize(const DiyFp& a) {
+ DiyFp result = a;
+ result.Normalize();
+ return result;
+ }
+
+ uint64_t f() const { return f_; }
+ int e() const { return e_; }
+
+ void set_f(uint64_t new_value) { f_ = new_value; }
+ void set_e(int new_value) { e_ = new_value; }
+
+ private:
+ static const uint64_t kUint64MSB = V8_2PART_UINT64_C(0x80000000, 00000000);
+
+ uint64_t f_;
+ int e_;
+};
+
+} } // namespace v8::internal
+
+#endif // V8_DIY_FP_H_
diff --git a/src/double.h b/src/double.h
new file mode 100644
index 0000000..f3d17b9
--- /dev/null
+++ b/src/double.h
@@ -0,0 +1,169 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_DOUBLE_H_
+#define V8_DOUBLE_H_
+
+#include "diy_fp.h"
+
+namespace v8 {
+namespace internal {
+
+// We assume that doubles and uint64_t have the same endianness.
+static uint64_t double_to_uint64(double d) { return BitCast<uint64_t>(d); }
+static double uint64_to_double(uint64_t d64) { return BitCast<double>(d64); }
+
+// Helper functions for doubles.
+class Double {
+ public:
+ static const uint64_t kSignMask = V8_2PART_UINT64_C(0x80000000, 00000000);
+ static const uint64_t kExponentMask = V8_2PART_UINT64_C(0x7FF00000, 00000000);
+ static const uint64_t kSignificandMask =
+ V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF);
+ static const uint64_t kHiddenBit = V8_2PART_UINT64_C(0x00100000, 00000000);
+
+ Double() : d64_(0) {}
+ explicit Double(double d) : d64_(double_to_uint64(d)) {}
+ explicit Double(uint64_t d64) : d64_(d64) {}
+
+ DiyFp AsDiyFp() const {
+ ASSERT(!IsSpecial());
+ return DiyFp(Significand(), Exponent());
+ }
+
+ // this->Significand() must not be 0.
+ DiyFp AsNormalizedDiyFp() const {
+ uint64_t f = Significand();
+ int e = Exponent();
+
+ ASSERT(f != 0);
+
+ // The current double could be a denormal.
+ while ((f & kHiddenBit) == 0) {
+ f <<= 1;
+ e--;
+ }
+ // Do the final shifts in one go. Don't forget the hidden bit (the '-1').
+ f <<= DiyFp::kSignificandSize - kSignificandSize - 1;
+ e -= DiyFp::kSignificandSize - kSignificandSize - 1;
+ return DiyFp(f, e);
+ }
+
+ // Returns the double's bit as uint64.
+ uint64_t AsUint64() const {
+ return d64_;
+ }
+
+ int Exponent() const {
+ if (IsDenormal()) return kDenormalExponent;
+
+ uint64_t d64 = AsUint64();
+ int biased_e = static_cast<int>((d64 & kExponentMask) >> kSignificandSize);
+ return biased_e - kExponentBias;
+ }
+
+ uint64_t Significand() const {
+ uint64_t d64 = AsUint64();
+ uint64_t significand = d64 & kSignificandMask;
+ if (!IsDenormal()) {
+ return significand + kHiddenBit;
+ } else {
+ return significand;
+ }
+ }
+
+ // Returns true if the double is a denormal.
+ bool IsDenormal() const {
+ uint64_t d64 = AsUint64();
+ return (d64 & kExponentMask) == 0;
+ }
+
+ // We consider denormals not to be special.
+ // Hence only Infinity and NaN are special.
+ bool IsSpecial() const {
+ uint64_t d64 = AsUint64();
+ return (d64 & kExponentMask) == kExponentMask;
+ }
+
+ bool IsNan() const {
+ uint64_t d64 = AsUint64();
+ return ((d64 & kExponentMask) == kExponentMask) &&
+ ((d64 & kSignificandMask) != 0);
+ }
+
+
+ bool IsInfinite() const {
+ uint64_t d64 = AsUint64();
+ return ((d64 & kExponentMask) == kExponentMask) &&
+ ((d64 & kSignificandMask) == 0);
+ }
+
+
+ int Sign() const {
+ uint64_t d64 = AsUint64();
+ return (d64 & kSignMask) == 0? 1: -1;
+ }
+
+
+ // Returns the two boundaries of this.
+ // The bigger boundary (m_plus) is normalized. The lower boundary has the same
+ // exponent as m_plus.
+ void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
+ DiyFp v = this->AsDiyFp();
+ bool significand_is_zero = (v.f() == kHiddenBit);
+ DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
+ DiyFp m_minus;
+ if (significand_is_zero && v.e() != kDenormalExponent) {
+ // The boundary is closer. Think of v = 1000e10 and v- = 9999e9.
+ // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
+ // at a distance of 1e8.
+ // The only exception is for the smallest normal: the largest denormal is
+ // at the same distance as its successor.
+ // Note: denormals have the same exponent as the smallest normals.
+ m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
+ } else {
+ m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
+ }
+ m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
+ m_minus.set_e(m_plus.e());
+ *out_m_plus = m_plus;
+ *out_m_minus = m_minus;
+ }
+
+ double value() const { return uint64_to_double(d64_); }
+
+ private:
+ static const int kSignificandSize = 52; // Excludes the hidden bit.
+ static const int kExponentBias = 0x3FF + kSignificandSize;
+ static const int kDenormalExponent = -kExponentBias + 1;
+
+ uint64_t d64_;
+};
+
+} } // namespace v8::internal
+
+#endif // V8_DOUBLE_H_
diff --git a/src/factory.cc b/src/factory.cc
index 8d20749..993e2b6 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -866,6 +866,7 @@
map->set_instance_descriptors(*array);
}
+ ASSERT(result->shared()->IsApiFunction());
return result;
}
diff --git a/src/factory.h b/src/factory.h
index 36911da..e08bde4 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -317,7 +317,7 @@
#define ROOT_ACCESSOR(type, name, camel_name) \
static inline Handle<type> name() { \
- return Handle<type>(bit_cast<type**, Object**>( \
+ return Handle<type>(BitCast<type**, Object**>( \
&Heap::roots_[Heap::k##camel_name##RootIndex])); \
}
ROOT_LIST(ROOT_ACCESSOR)
@@ -325,7 +325,7 @@
#define SYMBOL_ACCESSOR(name, str) \
static inline Handle<String> name() { \
- return Handle<String>(bit_cast<String**, Object**>( \
+ return Handle<String>(BitCast<String**, Object**>( \
&Heap::roots_[Heap::k##name##RootIndex])); \
}
SYMBOL_LIST(SYMBOL_ACCESSOR)
diff --git a/src/globals.h b/src/globals.h
index 3840fee..6759a35 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -98,6 +98,11 @@
#define V8_PTR_PREFIX ""
#endif // V8_HOST_ARCH_64_BIT
+// The following macro works on both 32 and 64-bit platforms.
+// Usage: instead of writing 0x1234567890123456
+// write V8_2PART_UINT64_C(0x12345678,90123456);
+#define V8_2PART_UINT64_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
+
#define V8PRIxPTR V8_PTR_PREFIX "x"
#define V8PRIdPTR V8_PTR_PREFIX "d"
@@ -569,42 +574,6 @@
#define INLINE(header) inline header
#endif
-// The type-based aliasing rule allows the compiler to assume that pointers of
-// different types (for some definition of different) never alias each other.
-// Thus the following code does not work:
-//
-// float f = foo();
-// int fbits = *(int*)(&f);
-//
-// The compiler 'knows' that the int pointer can't refer to f since the types
-// don't match, so the compiler may cache f in a register, leaving random data
-// in fbits. Using C++ style casts makes no difference, however a pointer to
-// char data is assumed to alias any other pointer. This is the 'memcpy
-// exception'.
-//
-// Bit_cast uses the memcpy exception to move the bits from a variable of one
-// type of a variable of another type. Of course the end result is likely to
-// be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005)
-// will completely optimize bit_cast away.
-//
-// There is an additional use for bit_cast.
-// Recent gccs will warn when they see casts that may result in breakage due to
-// the type-based aliasing rule. If you have checked that there is no breakage
-// you can use bit_cast to cast one pointer type to another. This confuses gcc
-// enough that it can no longer see that you have cast one pointer type to
-// another thus avoiding the warning.
-template <class Dest, class Source>
-inline Dest bit_cast(const Source& source) {
- // Compile time assertion: sizeof(Dest) == sizeof(Source)
- // A compile error here means your Dest and Source have different sizes.
- typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
-
- Dest dest;
- memcpy(&dest, &source, sizeof(dest));
- return dest;
-}
-
-
// Feature flags bit positions. They are mostly based on the CPUID spec.
// (We assign CPUID itself to one of the currently reserved bits --
// feel free to change this if needed.)
diff --git a/src/grisu3.cc b/src/grisu3.cc
new file mode 100644
index 0000000..13c4932
--- /dev/null
+++ b/src/grisu3.cc
@@ -0,0 +1,494 @@
+// 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 "grisu3.h"
+
+#include "cached_powers.h"
+#include "diy_fp.h"
+#include "double.h"
+
+namespace v8 {
+namespace internal {
+
+template <int alpha = -60, int gamma = -32>
+class Grisu3 {
+ public:
+ // Provides a decimal representation of v.
+ // Returns true if it succeeds, otherwise the result can not 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.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 closest will be
+ // computed.
+ static bool grisu3(double v,
+ char* buffer, int* length, int* decimal_exponent);
+
+ private:
+ // Rounds the buffer according to the rest.
+ // If there is too much imprecision to round then false is returned.
+ // Similarily false is returned when the buffer is not within Delta.
+ static bool RoundWeed(char* buffer, int len, uint64_t wp_W, uint64_t Delta,
+ uint64_t rest, uint64_t ten_kappa, uint64_t ulp);
+ // Dispatches to the a specialized digit-generation routine. The chosen
+ // routine depends on w.e (which in turn depends on alpha and gamma).
+ // Currently there is only one digit-generation routine, but it would be easy
+ // to add others.
+ static bool DigitGen(DiyFp low, DiyFp w, DiyFp high,
+ char* buffer, int* len, int* kappa);
+ // Generates w's digits. The result is the shortest in the interval low-high.
+ // All DiyFp are assumed to be imprecise and this function takes this
+ // imprecision into account. If the function cannot compute the best
+ // representation (due to the imprecision) then false is returned.
+ static bool DigitGen_m60_m32(DiyFp low, DiyFp w, DiyFp high,
+ char* buffer, int* length, int* kappa);
+};
+
+
+template<int alpha, int gamma>
+bool Grisu3<alpha, gamma>::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
+ // neighbors. Any number strictly between boundary_minus and boundary_plus
+ // will round to v when read as 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, alpha, gamma, &mk, &ten_mk);
+ ASSERT(alpha <= w.e() + ten_mk.e() + DiyFp::kSignificandSize &&
+ gamma >= 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;
+}
+
+// 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 alpha and gamma. Typically alpha >= -63
+// and gamma <= 3.
+// 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~
+// * alpha <= w.e() <= gamma
+// 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%).
+template<int alpha, int gamma>
+bool Grisu3<alpha, gamma>::DigitGen(DiyFp low,
+ DiyFp w,
+ DiyFp high,
+ char* buffer,
+ int* len,
+ int* kappa) {
+ ASSERT(low.e() == w.e() && w.e() == high.e());
+ ASSERT(low.f() + 1 <= high.f() - 1);
+ ASSERT(alpha <= w.e() && w.e() <= gamma);
+ // The following tests use alpha and gamma to avoid unnecessary dynamic tests.
+ if ((alpha >= -60 && gamma <= -32) || // -60 <= w.e() <= -32
+ (alpha <= -32 && gamma >= -60 && // Alpha/gamma overlaps -60/-32 region.
+ -60 <= w.e() && w.e() <= -32)) {
+ return DigitGen_m60_m32(low, w, high, buffer, len, kappa);
+ } else {
+ // A simple adaption of the special case -60/-32 would allow greater ranges
+ // of alpha/gamma and thus reduce the number of precomputed cached powers of
+ // ten.
+ UNIMPLEMENTED();
+ return false;
+ }
+}
+
+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 <= 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.
+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();
+ }
+}
+
+
+// Same comments as for DigitGen but with additional precondition:
+// -60 <= w.e() <= -32
+//
+// 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.
+template<int alpha, int gamma>
+bool Grisu3<alpha, gamma>::DigitGen_m60_m32(DiyFp low,
+ DiyFp w,
+ DiyFp high,
+ char* buffer,
+ int* length,
+ int* kappa) {
+ // 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);
+ }
+ }
+}
+
+
+// Rounds the given generated digits in the buffer and weeds out generated
+// digits that are not in the safe interval, or where we cannot find a rounded
+// representation.
+// 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 on success.
+// Modifies the generated digits in the buffer to approach (round towards) w.
+template<int alpha, int gamma>
+bool Grisu3<alpha, gamma>::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- = too_high - big_distance, and
+ // w+ = too_high - small_distance.
+ // Note: w- < w < w+
+ //
+ // The real w (* unit) must lie somewhere inside the interval
+ // ]w-; w+[ (often written as "(w-; w+)")
+
+ // Basically the buffer currently contains a number in the unsafe interval
+ // ]too_low; too_high[ with too_low < w < too_high
+ //
+ // By generating the digits of too_high we got the biggest last digit.
+ // In the case that w+ < 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+
+ // 2) decrementing the buffer would make it leave the unsafe interval
+ // 3) decrementing the buffer would yield a number below w+ and farther away
+ // than the current number. In other words:
+ // (buffer{-1} < w+) && w+ - buffer{-1} > buffer - w+
+ // 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+
+ 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 too
+ // [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);
+}
+
+
+bool grisu3(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<-60, -32>::grisu3(v, buffer, length, &decimal_exponent);
+ *point = *length + decimal_exponent;
+ buffer[*length] = '\0';
+ return result;
+}
+
+} } // namespace v8::internal
diff --git a/src/grisu3.h b/src/grisu3.h
new file mode 100644
index 0000000..b41ca37
--- /dev/null
+++ b/src/grisu3.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_GRISU3_H_
+#define V8_GRISU3_H_
+
+namespace v8 {
+namespace internal {
+
+// Grisu3 will produce at most kGrisu3MaximalLength digits. This does not
+// include the terminating '\0' character.
+static const int kGrisu3MaximalLength = 17;
+
+// Provides a decimal representation of v.
+// v must satisfy v != 0 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^(decimal-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 grisu3(double d, char* buffer, int* sign, int* length, int* decimal_point);
+
+} } // namespace v8::internal
+
+#endif // V8_GRISU3_H_
diff --git a/src/heap.cc b/src/heap.cc
index fbe0464..d666875 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2571,11 +2571,9 @@
reinterpret_cast<Object**>(source->address()),
object_size);
// Update write barrier for all fields that lie beyond the header.
- for (int offset = JSObject::kHeaderSize;
- offset < object_size;
- offset += kPointerSize) {
- RecordWrite(clone_address, offset);
- }
+ RecordWrites(clone_address,
+ JSObject::kHeaderSize,
+ object_size - JSObject::kHeaderSize);
} else {
clone = new_space_.AllocateRaw(object_size);
if (clone->IsFailure()) return clone;
@@ -2906,12 +2904,9 @@
reinterpret_cast<Array*>(result)->set_map(fixed_array_map());
FixedArray* array = FixedArray::cast(result);
array->set_length(length);
- Object* value = undefined_value();
// Initialize body.
- for (int index = 0; index < length; index++) {
- ASSERT(!Heap::InNewSpace(value)); // value = undefined
- array->set(index, value, SKIP_WRITE_BARRIER);
- }
+ ASSERT(!Heap::InNewSpace(undefined_value()));
+ MemsetPointer(array->data_start(), undefined_value(), length);
}
return result;
}
@@ -2963,11 +2958,8 @@
reinterpret_cast<Array*>(result)->set_map(fixed_array_map());
FixedArray* array = FixedArray::cast(result);
array->set_length(length);
- Object* value = undefined_value();
- for (int index = 0; index < length; index++) {
- ASSERT(!Heap::InNewSpace(value)); // value = undefined
- array->set(index, value, SKIP_WRITE_BARRIER);
- }
+ ASSERT(!Heap::InNewSpace(undefined_value()));
+ MemsetPointer(array->data_start(), undefined_value(), length);
return array;
}
@@ -2994,9 +2986,7 @@
array->set_length(length);
// Initialize body.
ASSERT(!Heap::InNewSpace(the_hole_value()));
- MemsetPointer(HeapObject::RawField(array, FixedArray::kHeaderSize),
- the_hole_value(),
- length);
+ MemsetPointer(array->data_start(), the_hole_value(), length);
}
return result;
}
@@ -3409,7 +3399,7 @@
v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]);
v->Synchronize("strong_root_list");
- v->VisitPointer(bit_cast<Object**, String**>(&hidden_symbol_));
+ v->VisitPointer(BitCast<Object**, String**>(&hidden_symbol_));
v->Synchronize("symbol");
Bootstrapper::Iterate(v);
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index f13556b..7f0d5d4 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -2148,6 +2148,17 @@
}
+void Assembler::movmskpd(Register dst, XMMRegister src) {
+ ASSERT(CpuFeatures::IsEnabled(SSE2));
+ EnsureSpace ensure_space(this);
+ last_pc_ = pc_;
+ EMIT(0x66);
+ EMIT(0x0F);
+ EMIT(0x50);
+ emit_sse_operand(dst, src);
+}
+
+
void Assembler::movdqa(const Operand& dst, XMMRegister src ) {
ASSERT(CpuFeatures::IsEnabled(SSE2));
EnsureSpace ensure_space(this);
@@ -2283,6 +2294,11 @@
}
+void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
+ EMIT(0xC0 | dst.code() << 3 | src.code());
+}
+
+
void Assembler::Print() {
Disassembler::Decode(stdout, buffer_, pc_);
}
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index 4497e2a..d8cd57a 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -769,6 +769,7 @@
void comisd(XMMRegister dst, XMMRegister src);
void ucomisd(XMMRegister dst, XMMRegister src);
+ void movmskpd(Register dst, XMMRegister src);
void movdqa(XMMRegister dst, const Operand& src);
void movdqa(const Operand& dst, XMMRegister src);
@@ -828,7 +829,7 @@
void emit_sse_operand(XMMRegister reg, const Operand& adr);
void emit_sse_operand(XMMRegister dst, XMMRegister src);
-
+ void emit_sse_operand(Register dst, XMMRegister src);
private:
byte* addr_at(int pos) { return buffer_ + pos; }
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index bdd1c4a..703fffe 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -2286,61 +2286,69 @@
// a jump target and branching to duplicate the virtual frame at
// the first split. We manually handle the off-frame references
// by reconstituting them on the non-fall-through path.
- JumpTarget is_smi;
- __ test(left_side.reg(), Immediate(kSmiTagMask));
- is_smi.Branch(zero, taken);
- bool is_for_loop_compare = (node->AsCompareOperation() != NULL)
- && node->AsCompareOperation()->is_for_loop_condition();
- if (!is_for_loop_compare
- && CpuFeatures::IsSupported(SSE2)
- && right_val->IsSmi()) {
- // Right side is a constant smi and left side has been checked
- // not to be a smi.
- CpuFeatures::Scope use_sse2(SSE2);
- JumpTarget not_number;
- __ cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
- Immediate(Factory::heap_number_map()));
- not_number.Branch(not_equal, &left_side);
- __ movdbl(xmm1,
- FieldOperand(left_reg, HeapNumber::kValueOffset));
- int value = Smi::cast(*right_val)->value();
- if (value == 0) {
- __ xorpd(xmm0, xmm0);
- } else {
- Result temp = allocator()->Allocate();
- __ mov(temp.reg(), Immediate(value));
- __ cvtsi2sd(xmm0, Operand(temp.reg()));
- temp.Unuse();
+ if (left_side.is_smi()) {
+ if (FLAG_debug_code) {
+ __ AbortIfNotSmi(left_side.reg(), "Argument not a smi");
}
- __ comisd(xmm1, xmm0);
- // Jump to builtin for NaN.
- not_number.Branch(parity_even, &left_side);
- left_side.Unuse();
- Condition double_cc = cc;
- switch (cc) {
- case less: double_cc = below; break;
- case equal: double_cc = equal; break;
- case less_equal: double_cc = below_equal; break;
- case greater: double_cc = above; break;
- case greater_equal: double_cc = above_equal; break;
- default: UNREACHABLE();
+ } else {
+ JumpTarget is_smi;
+ __ test(left_side.reg(), Immediate(kSmiTagMask));
+ is_smi.Branch(zero, taken);
+
+ bool is_for_loop_compare = (node->AsCompareOperation() != NULL)
+ && node->AsCompareOperation()->is_for_loop_condition();
+ if (!is_for_loop_compare
+ && CpuFeatures::IsSupported(SSE2)
+ && right_val->IsSmi()) {
+ // Right side is a constant smi and left side has been checked
+ // not to be a smi.
+ CpuFeatures::Scope use_sse2(SSE2);
+ JumpTarget not_number;
+ __ cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
+ Immediate(Factory::heap_number_map()));
+ not_number.Branch(not_equal, &left_side);
+ __ movdbl(xmm1,
+ FieldOperand(left_reg, HeapNumber::kValueOffset));
+ int value = Smi::cast(*right_val)->value();
+ if (value == 0) {
+ __ xorpd(xmm0, xmm0);
+ } else {
+ Result temp = allocator()->Allocate();
+ __ mov(temp.reg(), Immediate(value));
+ __ cvtsi2sd(xmm0, Operand(temp.reg()));
+ temp.Unuse();
+ }
+ __ comisd(xmm1, xmm0);
+ // Jump to builtin for NaN.
+ not_number.Branch(parity_even, &left_side);
+ left_side.Unuse();
+ Condition double_cc = cc;
+ switch (cc) {
+ case less: double_cc = below; break;
+ case equal: double_cc = equal; break;
+ case less_equal: double_cc = below_equal; break;
+ case greater: double_cc = above; break;
+ case greater_equal: double_cc = above_equal; break;
+ default: UNREACHABLE();
+ }
+ dest->true_target()->Branch(double_cc);
+ dest->false_target()->Jump();
+ not_number.Bind(&left_side);
}
- dest->true_target()->Branch(double_cc);
+
+ // Setup and call the compare stub.
+ CompareStub stub(cc, strict, kCantBothBeNaN);
+ Result result = frame_->CallStub(&stub, &left_side, &right_side);
+ result.ToRegister();
+ __ cmp(result.reg(), 0);
+ result.Unuse();
+ dest->true_target()->Branch(cc);
dest->false_target()->Jump();
- not_number.Bind(&left_side);
+
+ is_smi.Bind();
}
- // Setup and call the compare stub.
- CompareStub stub(cc, strict, kCantBothBeNaN);
- Result result = frame_->CallStub(&stub, &left_side, &right_side);
- result.ToRegister();
- __ cmp(result.reg(), 0);
- result.Unuse();
- dest->true_target()->Branch(cc);
- dest->false_target()->Jump();
-
- is_smi.Bind();
left_side = Result(left_reg);
right_side = Result(right_val);
// Test smi equality and comparison by signed int comparison.
@@ -3579,6 +3587,24 @@
}
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.
+
+ 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.");
+ }
+ }
+
Visit(node->body());
// If there is an update expression, compile it if necessary.
@@ -4754,11 +4780,13 @@
frame_->Push(Smi::FromInt(node->literal_index()));
// Constant properties.
frame_->Push(node->constant_properties());
+ // Should the object literal have fast elements?
+ frame_->Push(Smi::FromInt(node->fast_elements() ? 1 : 0));
Result clone;
if (node->depth() > 1) {
- clone = frame_->CallRuntime(Runtime::kCreateObjectLiteral, 3);
+ clone = frame_->CallRuntime(Runtime::kCreateObjectLiteral, 4);
} else {
- clone = frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 3);
+ clone = frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
}
frame_->Push(&clone);
@@ -5912,7 +5940,7 @@
}
-void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
+void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
// ArgumentsAccessStub expects the key in edx and the formal
@@ -6624,15 +6652,6 @@
__ Set(tmp.reg(), Immediate(0));
}
- DeferredCode* deferred = NULL;
- if (is_postfix) {
- deferred = new DeferredPostfixCountOperation(new_value.reg(),
- old_value.reg(),
- is_increment);
- } else {
- deferred = new DeferredPrefixCountOperation(new_value.reg(),
- is_increment);
- }
if (is_increment) {
__ add(Operand(new_value.reg()), Immediate(Smi::FromInt(1)));
@@ -6640,24 +6659,41 @@
__ sub(Operand(new_value.reg()), Immediate(Smi::FromInt(1)));
}
- // If the count operation didn't overflow and the result is a valid
- // smi, we're done. Otherwise, we jump to the deferred slow-case
- // code.
- if (tmp.is_valid()) {
- // We combine the overflow and the smi tag check if we could
- // successfully allocate a temporary byte register.
- __ setcc(overflow, tmp.reg());
- __ or_(Operand(tmp.reg()), new_value.reg());
- __ test(tmp.reg(), Immediate(kSmiTagMask));
- tmp.Unuse();
- deferred->Branch(not_zero);
+ if (new_value.is_smi()) {
+ if (FLAG_debug_code) {
+ __ AbortIfNotSmi(new_value.reg(), "Argument not a smi");
+ }
+ if (tmp.is_valid()) tmp.Unuse();
} else {
- // Otherwise we test separately for overflow and smi tag.
- deferred->Branch(overflow);
- __ test(new_value.reg(), Immediate(kSmiTagMask));
- deferred->Branch(not_zero);
+ DeferredCode* deferred = NULL;
+ if (is_postfix) {
+ deferred = new DeferredPostfixCountOperation(new_value.reg(),
+ old_value.reg(),
+ is_increment);
+ } else {
+ deferred = new DeferredPrefixCountOperation(new_value.reg(),
+ is_increment);
+ }
+
+ // If the count operation didn't overflow and the result is a valid
+ // smi, we're done. Otherwise, we jump to the deferred slow-case
+ // code.
+ if (tmp.is_valid()) {
+ // We combine the overflow and the smi tag check if we could
+ // successfully allocate a temporary byte register.
+ __ setcc(overflow, tmp.reg());
+ __ or_(Operand(tmp.reg()), new_value.reg());
+ __ test(tmp.reg(), Immediate(kSmiTagMask));
+ tmp.Unuse();
+ deferred->Branch(not_zero);
+ } else {
+ // Otherwise we test separately for overflow and smi tag.
+ deferred->Branch(overflow);
+ __ test(new_value.reg(), Immediate(kSmiTagMask));
+ deferred->Branch(not_zero);
+ }
+ deferred->BindExit();
}
- deferred->BindExit();
// Postfix: store the old value in the allocated slot under the
// reference.
@@ -6823,8 +6859,15 @@
overwrite_mode = OVERWRITE_RIGHT;
}
- Load(node->left());
- Load(node->right());
+ if (node->left()->IsTrivial()) {
+ Load(node->right());
+ Result right = frame_->Pop();
+ frame_->Push(node->left());
+ frame_->Push(&right);
+ } else {
+ Load(node->left());
+ Load(node->right());
+ }
GenericBinaryOperation(node->op(), node->type(), overwrite_mode);
}
}
@@ -7024,8 +7067,20 @@
default:
UNREACHABLE();
}
- if (!left_already_loaded) Load(left);
- Load(right);
+
+ if (left->IsTrivial()) {
+ if (!left_already_loaded) {
+ Load(right);
+ Result right_result = frame_->Pop();
+ frame_->Push(left);
+ frame_->Push(&right_result);
+ } else {
+ Load(right);
+ }
+ } else {
+ if (!left_already_loaded) Load(left);
+ Load(right);
+ }
Comparison(node, cc, strict, destination());
}
@@ -10162,6 +10217,12 @@
}
+void RecordWriteStub::Generate(MacroAssembler* masm) {
+ masm->RecordWriteHelper(object_, addr_, scratch_);
+ masm->ret(0);
+}
+
+
void CompareStub::Generate(MacroAssembler* masm) {
Label call_builtin, done;
diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h
index 79cad72..f7ec0b5 100644
--- a/src/ia32/codegen-ia32.h
+++ b/src/ia32/codegen-ia32.h
@@ -339,6 +339,10 @@
bool in_spilled_code() const { return in_spilled_code_; }
void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; }
+ // If the name is an inline runtime function call return the number of
+ // expected arguments. Otherwise return -1.
+ static int InlineRuntimeCallArgumentsCount(Handle<String> name);
+
private:
// Construction/Destruction
explicit CodeGenerator(MacroAssembler* masm);
@@ -522,6 +526,7 @@
struct InlineRuntimeLUT {
void (CodeGenerator::*method)(ZoneList<Expression*>*);
const char* name;
+ int nargs;
};
static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
@@ -555,7 +560,7 @@
// Support for arguments.length and arguments[?].
void GenerateArgumentsLength(ZoneList<Expression*>* args);
- void GenerateArgumentsAccess(ZoneList<Expression*>* args);
+ void GenerateArguments(ZoneList<Expression*>* args);
// Support for accessing the class and value fields of an object.
void GenerateClassOf(ZoneList<Expression*>* args);
@@ -593,14 +598,10 @@
// Fast support for number to string.
void GenerateNumberToString(ZoneList<Expression*>* args);
- // Fast support for Math.pow().
+ // Fast call to math functions.
void GenerateMathPow(ZoneList<Expression*>* args);
-
- // Fast call to transcendental functions.
void GenerateMathSin(ZoneList<Expression*>* args);
void GenerateMathCos(ZoneList<Expression*>* args);
-
- // Fast case for sqrt
void GenerateMathSqrt(ZoneList<Expression*>* args);
// Simple condition analysis.
@@ -976,6 +977,42 @@
};
+class RecordWriteStub : public CodeStub {
+ public:
+ RecordWriteStub(Register object, Register addr, Register scratch)
+ : object_(object), addr_(addr), scratch_(scratch) { }
+
+ void Generate(MacroAssembler* masm);
+
+ private:
+ Register object_;
+ Register addr_;
+ Register scratch_;
+
+#ifdef DEBUG
+ void Print() {
+ PrintF("RecordWriteStub (object reg %d), (addr reg %d), (scratch reg %d)\n",
+ object_.code(), addr_.code(), scratch_.code());
+ }
+#endif
+
+ // Minor key encoding in 12 bits of three registers (object, address and
+ // scratch) OOOOAAAASSSS.
+ class ScratchBits: public BitField<uint32_t, 0, 4> {};
+ class AddressBits: public BitField<uint32_t, 4, 4> {};
+ class ObjectBits: public BitField<uint32_t, 8, 4> {};
+
+ Major MajorKey() { return RecordWrite; }
+
+ int MinorKey() {
+ // Encode the registers.
+ return ObjectBits::encode(object_.code()) |
+ AddressBits::encode(addr_.code()) |
+ ScratchBits::encode(scratch_.code());
+ }
+};
+
+
} } // namespace v8::internal
#endif // V8_IA32_CODEGEN_IA32_H_
diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc
index 0d85b10..8d342e0 100644
--- a/src/ia32/disasm-ia32.cc
+++ b/src/ia32/disasm-ia32.cc
@@ -1069,12 +1069,26 @@
} else {
UnimplementedInstruction();
}
- } else if (*data == 0x2F) {
+ } else if (*data == 0x2E || *data == 0x2F) {
+ const char* mnem = (*data == 0x2E) ? "ucomisd" : "comisd";
data++;
int mod, regop, rm;
get_modrm(*data, &mod, ®op, &rm);
- AppendToBuffer("comisd %s,%s",
- NameOfXMMRegister(regop),
+ if (mod == 0x3) {
+ AppendToBuffer("%s %s,%s", mnem,
+ NameOfXMMRegister(regop),
+ NameOfXMMRegister(rm));
+ data++;
+ } else {
+ AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
+ data += PrintRightOperand(data);
+ }
+ } else if (*data == 0x50) {
+ data++;
+ int mod, regop, rm;
+ get_modrm(*data, &mod, ®op, &rm);
+ AppendToBuffer("movmskpd %s,%s",
+ NameOfCPURegister(regop),
NameOfXMMRegister(rm));
data++;
} else if (*data == 0x57) {
@@ -1198,6 +1212,7 @@
const char* mnem = "?";
switch (b2) {
case 0x2A: mnem = "cvtsi2sd"; break;
+ case 0x2C: mnem = "cvttsd2si"; break;
case 0x51: mnem = "sqrtsd"; break;
case 0x58: mnem = "addsd"; break;
case 0x59: mnem = "mulsd"; break;
@@ -1208,14 +1223,38 @@
int mod, regop, rm;
get_modrm(*data, &mod, ®op, &rm);
if (b2 == 0x2A) {
- AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
- data += PrintRightOperand(data);
+ if (mod != 0x3) {
+ AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
+ data += PrintRightOperand(data);
+ } else {
+ AppendToBuffer("%s %s,%s",
+ mnem,
+ NameOfXMMRegister(regop),
+ NameOfCPURegister(rm));
+ data++;
+ }
+ } else if (b2 == 0x2C) {
+ if (mod != 0x3) {
+ AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
+ data += PrintRightOperand(data);
+ } else {
+ AppendToBuffer("%s %s,%s",
+ mnem,
+ NameOfCPURegister(regop),
+ NameOfXMMRegister(rm));
+ data++;
+ }
} else {
- AppendToBuffer("%s %s,%s",
- mnem,
- NameOfXMMRegister(regop),
- NameOfXMMRegister(rm));
- data++;
+ if (mod != 0x3) {
+ AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
+ data += PrintRightOperand(data);
+ } else {
+ AppendToBuffer("%s %s,%s",
+ mnem,
+ NameOfXMMRegister(regop),
+ NameOfXMMRegister(rm));
+ data++;
+ }
}
}
} else {
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 6e3ae10..cedf9c9 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -901,10 +901,11 @@
__ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
__ push(Immediate(Smi::FromInt(expr->literal_index())));
__ push(Immediate(expr->constant_properties()));
+ __ push(Immediate(Smi::FromInt(expr->fast_elements() ? 1 : 0)));
if (expr->depth() > 1) {
- __ CallRuntime(Runtime::kCreateObjectLiteral, 3);
+ __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
} else {
- __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3);
+ __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
}
// If result_saved is true the result is on top of the stack. If
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index 555cd1b..3928661 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -152,6 +152,108 @@
}
+static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
+ Label* miss,
+ Register elements,
+ Register key,
+ Register r0,
+ Register r1,
+ Register r2) {
+ // Register use:
+ //
+ // elements - holds the slow-case elements of the receiver and is unchanged.
+ //
+ // key - holds the smi key on entry and is unchanged if a branch is
+ // performed to the miss label. If the load succeeds and we
+ // fall through, key holds the result on exit.
+ //
+ // Scratch registers:
+ //
+ // r0 - holds the untagged key on entry and holds the hash once computed.
+ //
+ // 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);
+ __ mov(r1, r0);
+ __ not_(r0);
+ __ shl(r1, 15);
+ __ add(r0, Operand(r1));
+ // hash = hash ^ (hash >> 12);
+ __ mov(r1, r0);
+ __ shr(r1, 12);
+ __ xor_(r0, Operand(r1));
+ // hash = hash + (hash << 2);
+ __ lea(r0, Operand(r0, r0, times_4, 0));
+ // hash = hash ^ (hash >> 4);
+ __ mov(r1, r0);
+ __ shr(r1, 4);
+ __ xor_(r0, Operand(r1));
+ // hash = hash * 2057;
+ __ imul(r0, r0, 2057);
+ // hash = hash ^ (hash >> 16);
+ __ mov(r1, r0);
+ __ shr(r1, 16);
+ __ xor_(r0, Operand(r1));
+
+ // Compute capacity mask.
+ const int kCapacityOffset =
+ NumberDictionary::kHeaderSize +
+ NumberDictionary::kCapacityIndex * kPointerSize;
+ __ mov(r1, FieldOperand(elements, kCapacityOffset));
+ __ shr(r1, kSmiTagSize); // convert smi to int
+ __ dec(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.
+ __ mov(r2, r0);
+ // Compute the masked index: (hash + i + i * i) & mask.
+ if (i > 0) {
+ __ add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i)));
+ }
+ __ and_(r2, Operand(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.
+ __ cmp(key, FieldOperand(elements,
+ r2,
+ times_pointer_size,
+ kElementsStartOffset));
+ if (i != (kProbes - 1)) {
+ __ j(equal, &done, taken);
+ } else {
+ __ j(not_equal, miss, not_taken);
+ }
+ }
+
+ __ 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),
+ Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
+ __ j(not_zero, miss);
+
+ // Get the value at the masked, scaled index.
+ const int kValueOffset = kElementsStartOffset + kPointerSize;
+ __ mov(key, 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,
@@ -225,6 +327,7 @@
// -----------------------------------
Label slow, check_string, index_int, index_string;
Label check_pixel_array, probe_dictionary;
+ Label check_number_dictionary;
// Check that the object isn't a smi.
__ test(edx, Immediate(kSmiTagMask));
@@ -273,7 +376,7 @@
// ebx: untagged index
// eax: key
// ecx: elements
- __ CheckMap(ecx, Factory::pixel_array_map(), &slow, true);
+ __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true);
__ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset));
__ j(above_equal, &slow);
__ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset));
@@ -281,6 +384,32 @@
__ SmiTag(eax);
__ ret(0);
+ __ bind(&check_number_dictionary);
+ // Check whether the elements is a number dictionary.
+ // edx: receiver
+ // ebx: untagged index
+ // eax: key
+ // ecx: elements
+ __ CheckMap(ecx, Factory::hash_table_map(), &slow, true);
+ Label slow_pop_receiver;
+ // Push receiver on the stack to free up a register for the dictionary
+ // probing.
+ __ push(edx);
+ GenerateNumberDictionaryLoad(masm,
+ &slow_pop_receiver,
+ ecx,
+ eax,
+ ebx,
+ edx,
+ edi);
+ // Pop receiver before returning.
+ __ pop(edx);
+ __ ret(0);
+
+ __ bind(&slow_pop_receiver);
+ // Pop the receiver from the stack and jump to runtime.
+ __ pop(edx);
+
__ bind(&slow);
// Slow case: jump to runtime.
// edx: receiver
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 45e24fa..703ca79 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -47,33 +47,32 @@
}
-static void RecordWriteHelper(MacroAssembler* masm,
- Register object,
- Register addr,
- Register scratch) {
+void MacroAssembler::RecordWriteHelper(Register object,
+ Register addr,
+ Register scratch) {
Label fast;
// Compute the page start address from the heap object pointer, and reuse
// the 'object' register for it.
- masm->and_(object, ~Page::kPageAlignmentMask);
+ and_(object, ~Page::kPageAlignmentMask);
Register page_start = object;
// Compute the bit addr in the remembered set/index of the pointer in the
// page. Reuse 'addr' as pointer_offset.
- masm->sub(addr, Operand(page_start));
- masm->shr(addr, kObjectAlignmentBits);
+ sub(addr, Operand(page_start));
+ shr(addr, kObjectAlignmentBits);
Register pointer_offset = addr;
// If the bit offset lies beyond the normal remembered set range, it is in
// the extra remembered set area of a large object.
- masm->cmp(pointer_offset, Page::kPageSize / kPointerSize);
- masm->j(less, &fast);
+ cmp(pointer_offset, Page::kPageSize / kPointerSize);
+ j(less, &fast);
// Adjust 'page_start' so that addressing using 'pointer_offset' hits the
// extra remembered set after the large object.
// Find the length of the large object (FixedArray).
- masm->mov(scratch, Operand(page_start, Page::kObjectStartOffset
+ mov(scratch, Operand(page_start, Page::kObjectStartOffset
+ FixedArray::kLengthOffset));
Register array_length = scratch;
@@ -83,59 +82,40 @@
// Add the delta between the end of the normal RSet and the start of the
// extra RSet to 'page_start', so that addressing the bit using
// 'pointer_offset' hits the extra RSet words.
- masm->lea(page_start,
- Operand(page_start, array_length, times_pointer_size,
- Page::kObjectStartOffset + FixedArray::kHeaderSize
- - Page::kRSetEndOffset));
+ lea(page_start,
+ Operand(page_start, array_length, times_pointer_size,
+ Page::kObjectStartOffset + FixedArray::kHeaderSize
+ - Page::kRSetEndOffset));
// NOTE: For now, we use the bit-test-and-set (bts) x86 instruction
// to limit code size. We should probably evaluate this decision by
// measuring the performance of an equivalent implementation using
// "simpler" instructions
- masm->bind(&fast);
- masm->bts(Operand(page_start, Page::kRSetOffset), pointer_offset);
+ bind(&fast);
+ bts(Operand(page_start, Page::kRSetOffset), pointer_offset);
}
-class RecordWriteStub : public CodeStub {
- public:
- RecordWriteStub(Register object, Register addr, Register scratch)
- : object_(object), addr_(addr), scratch_(scratch) { }
-
- void Generate(MacroAssembler* masm);
-
- private:
- Register object_;
- Register addr_;
- Register scratch_;
-
-#ifdef DEBUG
- void Print() {
- PrintF("RecordWriteStub (object reg %d), (addr reg %d), (scratch reg %d)\n",
- object_.code(), addr_.code(), scratch_.code());
+void MacroAssembler::InNewSpace(Register object,
+ Register scratch,
+ Condition cc,
+ Label* branch) {
+ if (Serializer::enabled()) {
+ // Can't do arithmetic on external references if it might get serialized.
+ mov(scratch, Operand(object));
+ // The mask isn't really an address. We load it as an external reference in
+ // case the size of the new space is different between the snapshot maker
+ // and the running system.
+ and_(Operand(scratch), Immediate(ExternalReference::new_space_mask()));
+ cmp(Operand(scratch), Immediate(ExternalReference::new_space_start()));
+ j(cc, branch);
+ } else {
+ int32_t new_space_start = reinterpret_cast<int32_t>(
+ ExternalReference::new_space_start().address());
+ lea(scratch, Operand(object, -new_space_start));
+ and_(scratch, Heap::NewSpaceMask());
+ j(cc, branch);
}
-#endif
-
- // Minor key encoding in 12 bits of three registers (object, address and
- // scratch) OOOOAAAASSSS.
- class ScratchBits: public BitField<uint32_t, 0, 4> {};
- class AddressBits: public BitField<uint32_t, 4, 4> {};
- class ObjectBits: public BitField<uint32_t, 8, 4> {};
-
- Major MajorKey() { return RecordWrite; }
-
- int MinorKey() {
- // Encode the registers.
- return ObjectBits::encode(object_.code()) |
- AddressBits::encode(addr_.code()) |
- ScratchBits::encode(scratch_.code());
- }
-};
-
-
-void RecordWriteStub::Generate(MacroAssembler* masm) {
- RecordWriteHelper(masm, object_, addr_, scratch_);
- masm->ret(0);
}
@@ -161,22 +141,7 @@
test(value, Immediate(kSmiTagMask));
j(zero, &done);
- if (Serializer::enabled()) {
- // Can't do arithmetic on external references if it might get serialized.
- mov(value, Operand(object));
- // The mask isn't really an address. We load it as an external reference in
- // case the size of the new space is different between the snapshot maker
- // and the running system.
- and_(Operand(value), Immediate(ExternalReference::new_space_mask()));
- cmp(Operand(value), Immediate(ExternalReference::new_space_start()));
- j(equal, &done);
- } else {
- int32_t new_space_start = reinterpret_cast<int32_t>(
- ExternalReference::new_space_start().address());
- lea(value, Operand(object, -new_space_start));
- and_(value, Heap::NewSpaceMask());
- j(equal, &done);
- }
+ InNewSpace(object, value, equal, &done);
if ((offset > 0) && (offset < Page::kMaxHeapObjectSize)) {
// Compute the bit offset in the remembered set, leave it in 'value'.
@@ -209,7 +174,7 @@
// If we are already generating a shared stub, not inlining the
// record write code isn't going to save us any memory.
if (generating_stub()) {
- RecordWriteHelper(this, object, dst, value);
+ RecordWriteHelper(object, dst, value);
} else {
RecordWriteStub stub(object, dst, value);
CallStub(&stub);
@@ -221,9 +186,9 @@
// Clobber all input registers when running with the debug-code flag
// turned on to provoke errors.
if (FLAG_debug_code) {
- mov(object, Immediate(bit_cast<int32_t>(kZapValue)));
- mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
- mov(scratch, Immediate(bit_cast<int32_t>(kZapValue)));
+ mov(object, Immediate(BitCast<int32_t>(kZapValue)));
+ mov(value, Immediate(BitCast<int32_t>(kZapValue)));
+ mov(scratch, Immediate(BitCast<int32_t>(kZapValue)));
}
}
@@ -397,6 +362,12 @@
}
+void MacroAssembler::AbortIfNotSmi(Register object, const char* msg) {
+ test(object, Immediate(kSmiTagMask));
+ Assert(equal, msg);
+}
+
+
void MacroAssembler::EnterFrame(StackFrame::Type type) {
push(ebp);
mov(ebp, Operand(esp));
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index a284b63..00243d7 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -48,6 +48,18 @@
// ---------------------------------------------------------------------------
// GC Support
+
+ void RecordWriteHelper(Register object,
+ Register addr,
+ Register scratch);
+
+ // Check if object is in new space.
+ // scratch can be object itself, but it will be clobbered.
+ void InNewSpace(Register object,
+ Register scratch,
+ Condition cc, // equal for new space, not_equal otherwise.
+ Label* branch);
+
// Set the remembered set bit for [object+offset].
// object is the object being stored into, value is the object being stored.
// If offset is zero, then the scratch register contains the array index into
@@ -179,6 +191,9 @@
// Abort execution if argument is not a number. Used in debug code.
void AbortIfNotNumber(Register object, const char* msg);
+ // Abort execution if argument is not a smi. Used in debug code.
+ void AbortIfNotSmi(Register object, const char* msg);
+
// ---------------------------------------------------------------------------
// Exception handling
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index a7e9a69..902a5b8 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -549,9 +549,8 @@
// fast api call builtin.
void AnalyzePossibleApiFunction(JSFunction* function) {
SharedFunctionInfo* sfi = function->shared();
- if (sfi->function_data()->IsUndefined()) return;
- FunctionTemplateInfo* info =
- FunctionTemplateInfo::cast(sfi->function_data());
+ if (!sfi->IsApiFunction()) return;
+ FunctionTemplateInfo* info = sfi->get_api_func_data();
// Require a C++ callback.
if (info->call_code()->IsUndefined()) return;
@@ -698,8 +697,7 @@
CallOptimization optimization(lookup);
- if (optimization.is_constant_call() &&
- !Top::CanHaveSpecialFunctions(holder)) {
+ if (optimization.is_constant_call()) {
CompileCacheable(masm,
object,
receiver,
@@ -1211,6 +1209,195 @@
}
+Object* CallStubCompiler::CompileArrayPushCall(Object* object,
+ JSObject* holder,
+ JSFunction* function,
+ String* name,
+ CheckType check) {
+ // ----------- S t a t e -------------
+ // -- ecx : name
+ // -- esp[0] : return address
+ // -- esp[(argc - n) * 4] : arg[n] (zero-based)
+ // -- ...
+ // -- esp[(argc + 1) * 4] : receiver
+ // -----------------------------------
+ ASSERT(check == RECEIVER_MAP_CHECK);
+
+ Label miss;
+
+ // Get the receiver from the stack.
+ const int argc = arguments().immediate();
+ __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+
+ // Check that the receiver isn't a smi.
+ __ test(edx, Immediate(kSmiTagMask));
+ __ j(zero, &miss);
+
+ CheckPrototypes(JSObject::cast(object), edx,
+ holder, ebx,
+ eax, name, &miss);
+
+ if (argc == 0) {
+ // Noop, return the length.
+ __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
+ __ ret((argc + 1) * kPointerSize);
+ } else {
+ // Get the elements array of the object.
+ __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
+
+ // Check that the elements are in fast mode (not dictionary).
+ __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
+ Immediate(Factory::fixed_array_map()));
+ __ j(not_equal, &miss);
+
+ if (argc == 1) { // Otherwise fall through to call builtin.
+ Label call_builtin, exit, with_rset_update;
+
+ // Get the array's length into eax and calculate new length.
+ __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
+ STATIC_ASSERT(kSmiTagSize == 1);
+ STATIC_ASSERT(kSmiTag == 0);
+ __ add(Operand(eax), Immediate(argc << 1));
+
+ // Get the element's length into ecx.
+ __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
+ __ SmiTag(ecx);
+
+ // Check if we could survive without allocation, go to builtin otherwise.
+ __ cmp(eax, Operand(ecx));
+ __ j(greater, &call_builtin);
+
+ // Save new length.
+ __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
+
+ // Push the element.
+ __ lea(edx, FieldOperand(ebx,
+ eax, times_half_pointer_size,
+ FixedArray::kHeaderSize - argc * kPointerSize));
+ __ mov(ecx, Operand(esp, argc * kPointerSize));
+ __ mov(Operand(edx, 0), ecx);
+
+ // Check if value is a smi.
+ __ test(ecx, Immediate(kSmiTagMask));
+ __ j(not_zero, &with_rset_update);
+
+ __ bind(&exit);
+ __ ret((argc + 1) * kPointerSize);
+
+ __ bind(&with_rset_update);
+
+ __ InNewSpace(ebx, ecx, equal, &exit);
+
+ RecordWriteStub stub(ebx, edx, ecx);
+ __ CallStub(&stub);
+ __ ret((argc + 1) * kPointerSize);
+
+ __ bind(&call_builtin);
+ }
+
+ __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
+ argc + 1,
+ 1);
+ }
+
+ __ bind(&miss);
+
+ Handle<Code> ic = ComputeCallMiss(arguments().immediate());
+ __ jmp(ic, RelocInfo::CODE_TARGET);
+
+ // Return the generated code.
+ String* function_name = NULL;
+ if (function->shared()->name()->IsString()) {
+ function_name = String::cast(function->shared()->name());
+ }
+ return GetCode(CONSTANT_FUNCTION, function_name);
+}
+
+
+Object* CallStubCompiler::CompileArrayPopCall(Object* object,
+ JSObject* holder,
+ JSFunction* function,
+ String* name,
+ CheckType check) {
+ // ----------- S t a t e -------------
+ // -- ecx : name
+ // -- esp[0] : return address
+ // -- esp[(argc - n) * 4] : arg[n] (zero-based)
+ // -- ...
+ // -- esp[(argc + 1) * 4] : receiver
+ // -----------------------------------
+ ASSERT(check == RECEIVER_MAP_CHECK);
+
+ Label miss, empty_array, call_builtin;
+
+ // Get the receiver from the stack.
+ const int argc = arguments().immediate();
+ __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+
+ // Check that the receiver isn't a smi.
+ __ test(edx, Immediate(kSmiTagMask));
+ __ j(zero, &miss);
+
+ CheckPrototypes(JSObject::cast(object), edx,
+ holder, ebx,
+ eax, name, &miss);
+
+ // Get the elements array of the object.
+ __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
+
+ // Check that the elements are in fast mode (not dictionary).
+ __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
+ Immediate(Factory::fixed_array_map()));
+ __ j(not_equal, &miss);
+
+ // Get the array's length into ecx and calculate new length.
+ __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset));
+ __ sub(Operand(ecx), Immediate(Smi::FromInt(1)));
+ __ j(negative, &empty_array);
+
+ // Get the last element.
+ STATIC_ASSERT(kSmiTagSize == 1);
+ STATIC_ASSERT(kSmiTag == 0);
+ __ mov(eax, FieldOperand(ebx,
+ ecx, times_half_pointer_size,
+ FixedArray::kHeaderSize));
+ __ cmp(Operand(eax), Immediate(Factory::the_hole_value()));
+ __ j(equal, &call_builtin);
+
+ // Set the array's length.
+ __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx);
+
+ // Fill with the hole.
+ __ mov(FieldOperand(ebx,
+ ecx, times_half_pointer_size,
+ FixedArray::kHeaderSize),
+ Immediate(Factory::the_hole_value()));
+ __ ret((argc + 1) * kPointerSize);
+
+ __ bind(&empty_array);
+ __ mov(eax, Immediate(Factory::undefined_value()));
+ __ ret((argc + 1) * kPointerSize);
+
+ __ bind(&call_builtin);
+
+ __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop),
+ argc + 1,
+ 1);
+
+ __ bind(&miss);
+
+ Handle<Code> ic = ComputeCallMiss(arguments().immediate());
+ __ jmp(ic, RelocInfo::CODE_TARGET);
+
+ // Return the generated code.
+ String* function_name = NULL;
+ if (function->shared()->name()->IsString()) {
+ function_name = String::cast(function->shared()->name());
+ }
+ return GetCode(CONSTANT_FUNCTION, function_name);
+}
+
+
Object* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder,
JSFunction* function,
@@ -1223,6 +1410,14 @@
// -- ...
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
+
+ SharedFunctionInfo* function_info = function->shared();
+ if (function_info->HasCustomCallGenerator()) {
+ CustomCallGenerator generator =
+ ToCData<CustomCallGenerator>(function_info->function_data());
+ return generator(this, object, holder, function, name, check);
+ }
+
Label miss_in_smi_check;
// Get the receiver from the stack.
@@ -1333,18 +1528,6 @@
break;
}
- case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
- CheckPrototypes(JSObject::cast(object), edx, holder,
- ebx, eax, name, &miss);
- // Make sure object->HasFastElements().
- // Get the elements array of the object.
- __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
- // Check that the object is in fast mode (not dictionary).
- __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
- Immediate(Factory::fixed_array_map()));
- __ j(not_equal, &miss, not_taken);
- break;
-
default:
UNREACHABLE();
}
diff --git a/src/ia32/virtual-frame-ia32.cc b/src/ia32/virtual-frame-ia32.cc
index 7b03a5b..a749c78 100644
--- a/src/ia32/virtual-frame-ia32.cc
+++ b/src/ia32/virtual-frame-ia32.cc
@@ -1171,11 +1171,17 @@
}
VariableProxy* proxy = expr->AsVariableProxy();
- if (proxy != NULL && proxy->is_this()) {
- PushParameterAt(-1);
- return;
+ if (proxy != NULL) {
+ Slot* slot = proxy->var()->slot();
+ if (slot->type() == Slot::LOCAL) {
+ PushLocalAt(slot->index());
+ return;
+ }
+ if (slot->type() == Slot::PARAMETER) {
+ PushParameterAt(slot->index());
+ return;
+ }
}
-
UNREACHABLE();
}
diff --git a/src/ia32/virtual-frame-ia32.h b/src/ia32/virtual-frame-ia32.h
index cd2d18f..042f9b7 100644
--- a/src/ia32/virtual-frame-ia32.h
+++ b/src/ia32/virtual-frame-ia32.h
@@ -422,6 +422,9 @@
// the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
inline void Nip(int num_dropped);
+ // Update the type information of a local variable frame element directly.
+ inline void SetTypeForLocalAt(int index, NumberInfo info);
+
private:
static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;
diff --git a/src/ic.cc b/src/ic.cc
index 31154b7..2b97a8b 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -458,17 +458,6 @@
ASSERT(result != Heap::the_hole_value());
if (result->IsJSFunction()) {
- // Check if there is an optimized (builtin) version of the function.
- // Ignored this will degrade performance for some Array functions.
- // Please note we only return the optimized function iff
- // the JSObject has FastElements.
- if (object->IsJSObject() && JSObject::cast(*object)->HasFastElements()) {
- Object* opt = Top::LookupSpecialFunction(JSObject::cast(*object),
- lookup.holder(),
- JSFunction::cast(result));
- if (opt->IsJSFunction()) return opt;
- }
-
#ifdef ENABLE_DEBUGGER_SUPPORT
// Handle stepping into a function if step into is active.
if (Debug::StepInActive()) {
diff --git a/src/log-utils.cc b/src/log-utils.cc
index 722e0fc..62f0ca6 100644
--- a/src/log-utils.cc
+++ b/src/log-utils.cc
@@ -196,6 +196,9 @@
char* end_pos = dest_buf + actual_size - 1;
while (end_pos >= dest_buf && *end_pos != '\n') --end_pos;
actual_size = static_cast<int>(end_pos - dest_buf + 1);
+ // If the assertion below is hit, it means that there was no line end
+ // found --- something wrong has happened.
+ ASSERT(actual_size > 0);
ASSERT(actual_size <= max_size);
return actual_size;
}
diff --git a/src/log-utils.h b/src/log-utils.h
index b769e90..8889f1b 100644
--- a/src/log-utils.h
+++ b/src/log-utils.h
@@ -115,7 +115,7 @@
}
// Size of buffer used for formatting log messages.
- static const int kMessageBufferSize = 2048;
+ static const int kMessageBufferSize = v8::V8::kMinimumSizeForLogLinesBuffer;
private:
typedef int (*WritePtr)(const char* msg, int length);
diff --git a/src/log.cc b/src/log.cc
index 588d345..4441875 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -1346,10 +1346,9 @@
LOG(CodeCreateEvent(
Logger::LAZY_COMPILE_TAG, shared->code(), *func_name));
}
- } else if (shared->function_data()->IsFunctionTemplateInfo()) {
+ } else if (shared->IsApiFunction()) {
// API function.
- FunctionTemplateInfo* fun_data =
- FunctionTemplateInfo::cast(shared->function_data());
+ FunctionTemplateInfo* fun_data = shared->get_api_func_data();
Object* raw_call_data = fun_data->call_code();
if (!raw_call_data->IsUndefined()) {
CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
diff --git a/src/macros.py b/src/macros.py
index 9da2552..122b057 100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -136,9 +136,9 @@
# a type error is thrown.
macro DATE_VALUE(arg) = (%_ClassOf(arg) === 'Date' ? %_ValueOf(arg) : ThrowDateTypeError());
macro DAY(time) = ($floor(time / 86400000));
-macro MONTH_FROM_TIME(time) = (FromJulianDay(($floor(time / 86400000)) + 2440588).month);
-macro DATE_FROM_TIME(time) = (FromJulianDay(($floor(time / 86400000)) + 2440588).date);
-macro YEAR_FROM_TIME(time) = (FromJulianDay(($floor(time / 86400000)) + 2440588).year);
+macro MONTH_FROM_TIME(time) = (MonthFromTime(time));
+macro DATE_FROM_TIME(time) = (DateFromTime(time));
+macro YEAR_FROM_TIME(time) = (YearFromTime(time));
macro HOUR_FROM_TIME(time) = (Modulo($floor(time / 3600000), 24));
macro MIN_FROM_TIME(time) = (Modulo($floor(time / 60000), 60));
macro SEC_FROM_TIME(time) = (Modulo($floor(time / 1000), 60));
diff --git a/src/math.js b/src/math.js
index 034f32d..0623cb8 100644
--- a/src/math.js
+++ b/src/math.js
@@ -45,7 +45,8 @@
function MathAbs(x) {
if (%_IsSmi(x)) return x >= 0 ? x : -x;
if (!IS_NUMBER(x)) x = ToNumber(x);
- return %Math_abs(x);
+ if (x === 0) return 0; // To handle -0.
+ return x > 0 ? x : -x;
}
// ECMA 262 - 15.8.2.2
@@ -84,7 +85,7 @@
// ECMA 262 - 15.8.2.7
function MathCos(x) {
if (!IS_NUMBER(x)) x = ToNumber(x);
- return %_Math_cos(x);
+ return %_MathCos(x);
}
// ECMA 262 - 15.8.2.8
@@ -159,7 +160,7 @@
function MathPow(x, y) {
if (!IS_NUMBER(x)) x = ToNumber(x);
if (!IS_NUMBER(y)) y = ToNumber(y);
- return %_Math_pow(x, y);
+ return %_MathPow(x, y);
}
// ECMA 262 - 15.8.2.14
@@ -176,13 +177,13 @@
// ECMA 262 - 15.8.2.16
function MathSin(x) {
if (!IS_NUMBER(x)) x = ToNumber(x);
- return %_Math_sin(x);
+ return %_MathSin(x);
}
// ECMA 262 - 15.8.2.17
function MathSqrt(x) {
if (!IS_NUMBER(x)) x = ToNumber(x);
- return %_Math_sqrt(x);
+ return %_MathSqrt(x);
}
// ECMA 262 - 15.8.2.18
diff --git a/src/messages.js b/src/messages.js
index 5848115..cb392ff 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -182,7 +182,8 @@
invalid_json: "String '%0' is not valid JSON",
circular_structure: "Converting circular structure to JSON",
obj_ctor_property_non_object: "Object.%0 called on non-object",
- array_indexof_not_defined: "Array.getIndexOf: Argument undefined"
+ array_indexof_not_defined: "Array.getIndexOf: Argument undefined",
+ illegal_access: "illegal access"
};
}
var format = kMessages[message.type];
diff --git a/src/mips/codegen-mips-inl.h b/src/mips/codegen-mips-inl.h
index 2a77715..904dd74 100644
--- a/src/mips/codegen-mips-inl.h
+++ b/src/mips/codegen-mips-inl.h
@@ -38,16 +38,6 @@
void DeferredCode::Jump() { __ b(&entry_label_); }
-void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
- UNIMPLEMENTED_MIPS();
-}
-
-
-void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
- UNIMPLEMENTED_MIPS();
-}
-
-
#undef __
} } // namespace v8::internal
diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc
index facccc2..7b32180 100644
--- a/src/mips/codegen-mips.cc
+++ b/src/mips/codegen-mips.cc
@@ -31,6 +31,7 @@
#include "bootstrapper.h"
#include "codegen-inl.h"
#include "debug.h"
+#include "ic-inl.h"
#include "parser.h"
#include "register-allocator-inl.h"
#include "runtime.h"
@@ -297,6 +298,16 @@
}
+void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
+ UNIMPLEMENTED_MIPS();
+}
+
+
+void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
+ UNIMPLEMENTED_MIPS();
+}
+
+
void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) {
UNIMPLEMENTED_MIPS();
}
@@ -335,7 +346,7 @@
}
-void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
+void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) {
UNIMPLEMENTED_MIPS();
}
@@ -429,6 +440,11 @@
#define __ ACCESS_MASM(masm)
+Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) {
+ return Handle<Code>::null();
+}
+
+
// On entry a0 and a1 are the things to be compared. On exit v0 is 0,
// positive or negative to indicate the result of the comparison.
void CompareStub::Generate(MacroAssembler* masm) {
diff --git a/src/mips/codegen-mips.h b/src/mips/codegen-mips.h
index 987dcca..3f78fcd 100644
--- a/src/mips/codegen-mips.h
+++ b/src/mips/codegen-mips.h
@@ -154,6 +154,10 @@
// used by the debugger to patch the JS return sequence.
static const int kJSReturnSequenceLength = 6;
+ // If the name is an inline runtime function call return the number of
+ // expected arguments. Otherwise return -1.
+ static int InlineRuntimeCallArgumentsCount(Handle<String> name);
+
private:
// Construction/Destruction.
explicit CodeGenerator(MacroAssembler* masm);
@@ -188,6 +192,7 @@
struct InlineRuntimeLUT {
void (CodeGenerator::*method)(ZoneList<Expression*>*);
const char* name;
+ int nargs;
};
static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
@@ -216,7 +221,7 @@
// Support for arguments.length and arguments[?].
void GenerateArgumentsLength(ZoneList<Expression*>* args);
- void GenerateArgumentsAccess(ZoneList<Expression*>* args);
+ void GenerateArguments(ZoneList<Expression*>* args);
// Support for accessing the class and value fields of an object.
void GenerateClassOf(ZoneList<Expression*>* args);
@@ -246,15 +251,11 @@
void GenerateRegExpExec(ZoneList<Expression*>* args);
void GenerateNumberToString(ZoneList<Expression*>* args);
- // Fast support for Math.pow().
+ // Fast call to math functions.
void GenerateMathPow(ZoneList<Expression*>* args);
- // Fast support for Math.sqrt().
- void GenerateMathPow(ZoneList<Expression*>* args);
-
-
- // Fast support for Math.sin and Math.cos.
- inline void GenerateMathSin(ZoneList<Expression*>* args);
- inline void GenerateMathCos(ZoneList<Expression*>* args);
+ void GenerateMathSin(ZoneList<Expression*>* args);
+ void GenerateMathCos(ZoneList<Expression*>* args);
+ void GenerateMathSqrt(ZoneList<Expression*>* args);
// Simple condition analysis.
enum ConditionAnalysis {
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
index 2e2dc86..e2280d3 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -31,7 +31,7 @@
#include "disasm.h"
#include "assembler.h"
-#include "globals.h" // Need the bit_cast
+#include "globals.h" // Need the BitCast
#include "mips/constants-mips.h"
#include "mips/simulator-mips.h"
@@ -604,7 +604,7 @@
void Simulator::set_fpu_register_double(int fpureg, double value) {
ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
- *v8i::bit_cast<double*, int32_t*>(&FPUregisters_[fpureg]) = value;
+ *v8i::BitCast<double*, int32_t*>(&FPUregisters_[fpureg]) = value;
}
@@ -625,7 +625,7 @@
double Simulator::get_fpu_register_double(int fpureg) const {
ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
- return *v8i::bit_cast<double*, int32_t*>(
+ return *v8i::BitCast<double*, int32_t*>(
const_cast<int32_t*>(&FPUregisters_[fpureg]));
}
@@ -901,7 +901,7 @@
break;
case MFHC1:
fp_out = get_fpu_register_double(fs_reg);
- alu_out = *v8i::bit_cast<int32_t*, double*>(&fp_out);
+ alu_out = *v8i::BitCast<int32_t*, double*>(&fp_out);
break;
case MTC1:
case MTHC1:
diff --git a/src/mips/virtual-frame-mips.h b/src/mips/virtual-frame-mips.h
index e5bc93f..77c795c 100644
--- a/src/mips/virtual-frame-mips.h
+++ b/src/mips/virtual-frame-mips.h
@@ -71,7 +71,7 @@
// Create a duplicate of an existing valid frame element.
FrameElement CopyElementAt(int index,
- NumberInfo::Type info = NumberInfo::kUnknown);
+ NumberInfo info = NumberInfo::Unknown());
// The number of elements on the virtual frame.
int element_count() { return elements_.length(); }
@@ -367,7 +367,7 @@
void EmitMultiPushReversed(RegList regs); // higher first
// Push an element on the virtual frame.
- inline void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown);
+ inline void Push(Register reg, NumberInfo info = NumberInfo::Unknown());
inline void Push(Handle<Object> value);
inline void Push(Smi* value);
@@ -391,6 +391,8 @@
// 'a' registers are arguments register a0 to a3.
void EmitArgumentSlots(RegList reglist);
+ inline void SetTypeForLocalAt(int index, NumberInfo info);
+
private:
static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 492b492..44a3b1a 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -789,7 +789,7 @@
VerifyObjectField(kNameOffset);
VerifyObjectField(kCodeOffset);
VerifyObjectField(kInstanceClassNameOffset);
- VerifyObjectField(kExternalReferenceDataOffset);
+ VerifyObjectField(kFunctionDataOffset);
VerifyObjectField(kScriptOffset);
VerifyObjectField(kDebugInfoOffset);
}
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 18f45f3..4cc9b9f 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -2361,8 +2361,7 @@
ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
kInstanceClassNameOffset)
-ACCESSORS(SharedFunctionInfo, function_data, Object,
- kExternalReferenceDataOffset)
+ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
@@ -2453,6 +2452,22 @@
}
+bool SharedFunctionInfo::IsApiFunction() {
+ return function_data()->IsFunctionTemplateInfo();
+}
+
+
+FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
+ ASSERT(IsApiFunction());
+ return FunctionTemplateInfo::cast(function_data());
+}
+
+
+bool SharedFunctionInfo::HasCustomCallGenerator() {
+ return function_data()->IsProxy();
+}
+
+
bool JSFunction::IsBoilerplate() {
return map() == Heap::boilerplate_function_map();
}
diff --git a/src/objects.cc b/src/objects.cc
index 5457678..132aa9e 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -480,7 +480,7 @@
if (!cons_obj->IsJSFunction())
return true;
JSFunction* fun = JSFunction::cast(cons_obj);
- if (!fun->shared()->function_data()->IsFunctionTemplateInfo())
+ if (!fun->shared()->IsApiFunction())
return true;
// If the object is fully fast case and has the same map it was
// created with then no changes can have been made to it.
@@ -6433,9 +6433,9 @@
InterceptorInfo* JSObject::GetNamedInterceptor() {
ASSERT(map()->has_named_interceptor());
JSFunction* constructor = JSFunction::cast(map()->constructor());
- Object* template_info = constructor->shared()->function_data();
+ ASSERT(constructor->shared()->IsApiFunction());
Object* result =
- FunctionTemplateInfo::cast(template_info)->named_property_handler();
+ constructor->shared()->get_api_func_data()->named_property_handler();
return InterceptorInfo::cast(result);
}
@@ -6443,9 +6443,9 @@
InterceptorInfo* JSObject::GetIndexedInterceptor() {
ASSERT(map()->has_indexed_interceptor());
JSFunction* constructor = JSFunction::cast(map()->constructor());
- Object* template_info = constructor->shared()->function_data();
+ ASSERT(constructor->shared()->IsApiFunction());
Object* result =
- FunctionTemplateInfo::cast(template_info)->indexed_property_handler();
+ constructor->shared()->get_api_func_data()->indexed_property_handler();
return InterceptorInfo::cast(result);
}
diff --git a/src/objects.h b/src/objects.h
index 2004d50..b3fe448 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -2154,24 +2154,24 @@
// Returns the value at entry.
Object* ValueAt(int entry) {
- return get(HashTable<Shape, Key>::EntryToIndex(entry)+1);
+ return this->get(HashTable<Shape, Key>::EntryToIndex(entry)+1);
}
// Set the value for entry.
void ValueAtPut(int entry, Object* value) {
- set(HashTable<Shape, Key>::EntryToIndex(entry)+1, value);
+ this->set(HashTable<Shape, Key>::EntryToIndex(entry)+1, value);
}
// Returns the property details for the property at entry.
PropertyDetails DetailsAt(int entry) {
ASSERT(entry >= 0); // Not found is -1, which is not caught by get().
return PropertyDetails(
- Smi::cast(get(HashTable<Shape, Key>::EntryToIndex(entry) + 2)));
+ Smi::cast(this->get(HashTable<Shape, Key>::EntryToIndex(entry) + 2)));
}
// Set the details for entry.
void DetailsAtPut(int entry, PropertyDetails value) {
- set(HashTable<Shape, Key>::EntryToIndex(entry) + 2, value.AsSmi());
+ this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 2, value.AsSmi());
}
// Sorting support
@@ -2194,7 +2194,7 @@
// Accessors for next enumeration index.
void SetNextEnumerationIndex(int index) {
- fast_set(this, kNextEnumerationIndexIndex, Smi::FromInt(index));
+ this->fast_set(this, kNextEnumerationIndexIndex, Smi::FromInt(index));
}
int NextEnumerationIndex() {
@@ -3186,12 +3186,18 @@
// [instance class name]: class name for instances.
DECL_ACCESSORS(instance_class_name, Object)
- // [function data]: This field has been added for make benefit the API.
+ // [function data]: This field holds some additional data for function.
+ // Currently it either has FunctionTemplateInfo to make benefit the API
+ // or Proxy wrapping CustomCallGenerator.
// In the long run we don't want all functions to have this field but
// we can fix that when we have a better model for storing hidden data
// on objects.
DECL_ACCESSORS(function_data, Object)
+ inline bool IsApiFunction();
+ inline FunctionTemplateInfo* get_api_func_data();
+ inline bool HasCustomCallGenerator();
+
// [script info]: Script from which the function originates.
DECL_ACCESSORS(script, Object)
@@ -3299,9 +3305,9 @@
static const int kConstructStubOffset = kCodeOffset + kPointerSize;
static const int kInstanceClassNameOffset =
kConstructStubOffset + kPointerSize;
- static const int kExternalReferenceDataOffset =
+ static const int kFunctionDataOffset =
kInstanceClassNameOffset + kPointerSize;
- static const int kScriptOffset = kExternalReferenceDataOffset + kPointerSize;
+ static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
static const int kThisPropertyAssignmentsOffset =
diff --git a/src/parser.cc b/src/parser.cc
index dd72669..74f6997 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -30,6 +30,7 @@
#include "api.h"
#include "ast.h"
#include "bootstrapper.h"
+#include "codegen.h"
#include "compiler.h"
#include "messages.h"
#include "platform.h"
@@ -211,6 +212,7 @@
ZoneList<ObjectLiteral::Property*>* properties,
Handle<FixedArray> constants,
bool* is_simple,
+ bool* fast_elements,
int* depth);
// Populate the literals fixed array for a materialized array literal.
@@ -1962,9 +1964,7 @@
Factory::NewFunctionBoilerplate(name, literals, code);
boilerplate->shared()->set_construct_stub(*construct_stub);
- // Copy the function data to the boilerplate. Used by
- // builtins.cc:HandleApiCall to perform argument type checks and to
- // find the right native code to call.
+ // Copy the function data to the boilerplate.
boilerplate->shared()->set_function_data(fun->shared()->function_data());
int parameters = fun->shared()->formal_parameter_count();
boilerplate->shared()->set_formal_parameter_count(parameters);
@@ -3445,7 +3445,11 @@
ObjectLiteral* object_literal = expression->AsObjectLiteral();
if (object_literal != NULL) {
ASSERT(object_literal->is_simple());
- result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL));
+ if (object_literal->fast_elements()) {
+ result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
+ } else {
+ result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
+ }
result->set(kElementsSlot, *object_literal->constant_properties());
} else {
ArrayLiteral* array_literal = expression->AsArrayLiteral();
@@ -3483,11 +3487,14 @@
ZoneList<ObjectLiteral::Property*>* properties,
Handle<FixedArray> constant_properties,
bool* is_simple,
+ bool* fast_elements,
int* depth) {
int position = 0;
// Accumulate the value in local variables and store it at the end.
bool is_simple_acc = true;
int depth_acc = 1;
+ uint32_t max_element_index = 0;
+ uint32_t elements = 0;
for (int i = 0; i < properties->length(); i++) {
ObjectLiteral::Property* property = properties->at(i);
if (!IsBoilerplateProperty(property)) {
@@ -3506,11 +3513,31 @@
Handle<Object> value = GetBoilerplateValue(property->value());
is_simple_acc = is_simple_acc && !value->IsUndefined();
+ // Keep track of the number of elements in the object literal and
+ // the largest element index. If the largest element index is
+ // much larger than the number of elements, creating an object
+ // literal with fast elements will be a waste of space.
+ uint32_t element_index = 0;
+ if (key->IsString()
+ && Handle<String>::cast(key)->AsArrayIndex(&element_index)
+ && element_index > max_element_index) {
+ max_element_index = element_index;
+ elements++;
+ } else if (key->IsSmi()) {
+ int key_value = Smi::cast(*key)->value();
+ if (key_value > 0
+ && static_cast<uint32_t>(key_value) > max_element_index) {
+ max_element_index = key_value;
+ }
+ elements++;
+ }
+
// Add name, value pair to the fixed array.
constant_properties->set(position++, *key);
constant_properties->set(position++, *value);
}
-
+ *fast_elements =
+ (max_element_index <= 32) || ((2 * elements) >= max_element_index);
*is_simple = is_simple_acc;
*depth = depth_acc;
}
@@ -3608,15 +3635,18 @@
Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED);
bool is_simple = true;
+ bool fast_elements = true;
int depth = 1;
BuildObjectLiteralConstantProperties(properties.elements(),
constant_properties,
&is_simple,
+ &fast_elements,
&depth);
return new ObjectLiteral(constant_properties,
properties.elements(),
literal_index,
is_simple,
+ fast_elements,
depth);
}
@@ -3832,7 +3862,27 @@
}
}
- // Otherwise we have a runtime call.
+ // Check that the expected number arguments are passed to runtime functions.
+ if (!is_pre_parsing_) {
+ if (function != NULL
+ && function->nargs != -1
+ && function->nargs != args->length()) {
+ ReportMessage("illegal_access", Vector<const char*>::empty());
+ *ok = false;
+ return NULL;
+ } else if (function == NULL && !name.is_null()) {
+ // If this is not a runtime function implemented in C++ it might be an
+ // inlined runtime function.
+ int argc = CodeGenerator::InlineRuntimeCallArgumentsCount(name);
+ if (argc != -1 && argc != args->length()) {
+ ReportMessage("illegal_access", Vector<const char*>::empty());
+ *ok = false;
+ return NULL;
+ }
+ }
+ }
+
+ // Otherwise we have a valid runtime call.
return NEW(CallRuntime(name, function, args));
}
@@ -4123,15 +4173,18 @@
Handle<FixedArray> constant_properties =
Factory::NewFixedArray(boilerplate_properties * 2, TENURED);
bool is_simple = true;
+ bool fast_elements = true;
int depth = 1;
BuildObjectLiteralConstantProperties(properties.elements(),
constant_properties,
&is_simple,
+ &fast_elements,
&depth);
return new ObjectLiteral(constant_properties,
properties.elements(),
literal_index,
is_simple,
+ fast_elements,
depth);
}
diff --git a/src/parser.h b/src/parser.h
index 0f808d7..2e5daf9 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -168,7 +168,8 @@
class CompileTimeValue: public AllStatic {
public:
enum Type {
- OBJECT_LITERAL,
+ OBJECT_LITERAL_FAST_ELEMENTS,
+ OBJECT_LITERAL_SLOW_ELEMENTS,
ARRAY_LITERAL
};
diff --git a/src/powers_ten.h b/src/powers_ten.h
new file mode 100644
index 0000000..7e88c51
--- /dev/null
+++ b/src/powers_ten.h
@@ -0,0 +1,2461 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// ------------ GENERATED FILE ----------------
+// command used:
+// tools/generate-ten-powers --from -308 --to 342 --mantissa-size 64 --round round -o src/powers_ten.h // NOLINT
+
+// This file is intended to be included inside another .h or .cc files
+// with the following defines set:
+// GRISU_CACHE_STRUCT: should expand to the name of a struct that will
+// hold the cached powers of ten. Each entry will hold a 64-bit
+// significand, a 16-bit signed binary exponent, and a 16-bit
+// signed decimal exponent. Each entry will be constructed as follows:
+// { significand, binary_exponent, decimal_exponent }.
+// GRISU_CACHE_NAME(i): generates the name for the different caches.
+// The parameter i will be a number in the range 1-20. A cache will
+// hold every i'th element of a full cache. GRISU_CACHE_NAME(1) will
+// thus hold all elements. The higher i the fewer elements it has.
+// Ideally the user should only reference one cache and let the
+// compiler remove the unused ones.
+// GRISU_CACHE_MAX_DISTANCE(i): generates the name for the maximum
+// binary exponent distance between all elements of a given cache.
+// GRISU_CACHE_OFFSET: is used as variable name for the decimal
+// exponent offset. It is equal to -cache[0].decimal_exponent.
+// GRISU_UINT64_C: used to construct 64-bit values in a platform
+// independent way. In order to encode 0x123456789ABCDEF0 the macro
+// will be invoked as follows: GRISU_UINT64_C(0x12345678,9ABCDEF0).
+
+
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(1)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0x8fd0c162, 06306bac), -1083, -307},
+ {GRISU_UINT64_C(0xb3c4f1ba, 87bc8697), -1080, -306},
+ {GRISU_UINT64_C(0xe0b62e29, 29aba83c), -1077, -305},
+ {GRISU_UINT64_C(0x8c71dcd9, ba0b4926), -1073, -304},
+ {GRISU_UINT64_C(0xaf8e5410, 288e1b6f), -1070, -303},
+ {GRISU_UINT64_C(0xdb71e914, 32b1a24b), -1067, -302},
+ {GRISU_UINT64_C(0x892731ac, 9faf056f), -1063, -301},
+ {GRISU_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
+ {GRISU_UINT64_C(0xd64d3d9d, b981787d), -1057, -299},
+ {GRISU_UINT64_C(0x85f04682, 93f0eb4e), -1053, -298},
+ {GRISU_UINT64_C(0xa76c5823, 38ed2622), -1050, -297},
+ {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
+ {GRISU_UINT64_C(0x82cca4db, 847945ca), -1043, -295},
+ {GRISU_UINT64_C(0xa37fce12, 6597973d), -1040, -294},
+ {GRISU_UINT64_C(0xcc5fc196, fefd7d0c), -1037, -293},
+ {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
+ {GRISU_UINT64_C(0x9faacf3d, f73609b1), -1030, -291},
+ {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
+ {GRISU_UINT64_C(0xf97ae3d0, d2446f25), -1024, -289},
+ {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
+ {GRISU_UINT64_C(0xc2e801fb, 244576d5), -1017, -287},
+ {GRISU_UINT64_C(0xf3a20279, ed56d48a), -1014, -286},
+ {GRISU_UINT64_C(0x9845418c, 345644d7), -1010, -285},
+ {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+ {GRISU_UINT64_C(0xedec366b, 11c6cb8f), -1004, -283},
+ {GRISU_UINT64_C(0x94b3a202, eb1c3f39), -1000, -282},
+ {GRISU_UINT64_C(0xb9e08a83, a5e34f08), -997, -281},
+ {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
+ {GRISU_UINT64_C(0x91376c36, d99995be), -990, -279},
+ {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+ {GRISU_UINT64_C(0xe2e69915, b3fff9f9), -984, -277},
+ {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
+ {GRISU_UINT64_C(0xb1442798, f49ffb4b), -977, -275},
+ {GRISU_UINT64_C(0xdd95317f, 31c7fa1d), -974, -274},
+ {GRISU_UINT64_C(0x8a7d3eef, 7f1cfc52), -970, -273},
+ {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+ {GRISU_UINT64_C(0xd863b256, 369d4a41), -964, -271},
+ {GRISU_UINT64_C(0x873e4f75, e2224e68), -960, -270},
+ {GRISU_UINT64_C(0xa90de353, 5aaae202), -957, -269},
+ {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+ {GRISU_UINT64_C(0x8412d999, 1ed58092), -950, -267},
+ {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
+ {GRISU_UINT64_C(0xce5d73ff, 402d98e4), -944, -265},
+ {GRISU_UINT64_C(0x80fa687f, 881c7f8e), -940, -264},
+ {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
+ {GRISU_UINT64_C(0xc9874347, 44ac874f), -934, -262},
+ {GRISU_UINT64_C(0xfbe91419, 15d7a922), -931, -261},
+ {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+ {GRISU_UINT64_C(0xc4ce17b3, 99107c23), -924, -259},
+ {GRISU_UINT64_C(0xf6019da0, 7f549b2b), -921, -258},
+ {GRISU_UINT64_C(0x99c10284, 4f94e0fb), -917, -257},
+ {GRISU_UINT64_C(0xc0314325, 637a193a), -914, -256},
+ {GRISU_UINT64_C(0xf03d93ee, bc589f88), -911, -255},
+ {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
+ {GRISU_UINT64_C(0xbbb01b92, 83253ca3), -904, -253},
+ {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
+ {GRISU_UINT64_C(0x92a1958a, 7675175f), -897, -251},
+ {GRISU_UINT64_C(0xb749faed, 14125d37), -894, -250},
+ {GRISU_UINT64_C(0xe51c79a8, 5916f485), -891, -249},
+ {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+ {GRISU_UINT64_C(0xb2fe3f0b, 8599ef08), -884, -247},
+ {GRISU_UINT64_C(0xdfbdcece, 67006ac9), -881, -246},
+ {GRISU_UINT64_C(0x8bd6a141, 006042be), -877, -245},
+ {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
+ {GRISU_UINT64_C(0xda7f5bf5, 90966849), -871, -243},
+ {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
+ {GRISU_UINT64_C(0xaab37fd7, d8f58179), -864, -241},
+ {GRISU_UINT64_C(0xd5605fcd, cf32e1d7), -861, -240},
+ {GRISU_UINT64_C(0x855c3be0, a17fcd26), -857, -239},
+ {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
+ {GRISU_UINT64_C(0xd0601d8e, fc57b08c), -851, -237},
+ {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+ {GRISU_UINT64_C(0xa2cb1717, b52481ed), -844, -235},
+ {GRISU_UINT64_C(0xcb7ddcdd, a26da269), -841, -234},
+ {GRISU_UINT64_C(0xfe5d5415, 0b090b03), -838, -233},
+ {GRISU_UINT64_C(0x9efa548d, 26e5a6e2), -834, -232},
+ {GRISU_UINT64_C(0xc6b8e9b0, 709f109a), -831, -231},
+ {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
+ {GRISU_UINT64_C(0x9b407691, d7fc44f8), -824, -229},
+ {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+ {GRISU_UINT64_C(0xf294b943, e17a2bc4), -818, -227},
+ {GRISU_UINT64_C(0x979cf3ca, 6cec5b5b), -814, -226},
+ {GRISU_UINT64_C(0xbd8430bd, 08277231), -811, -225},
+ {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+ {GRISU_UINT64_C(0x940f4613, ae5ed137), -804, -223},
+ {GRISU_UINT64_C(0xb9131798, 99f68584), -801, -222},
+ {GRISU_UINT64_C(0xe757dd7e, c07426e5), -798, -221},
+ {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
+ {GRISU_UINT64_C(0xb4bca50b, 065abe63), -791, -219},
+ {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+ {GRISU_UINT64_C(0x8d3360f0, 9cf6e4bd), -784, -217},
+ {GRISU_UINT64_C(0xb080392c, c4349ded), -781, -216},
+ {GRISU_UINT64_C(0xdca04777, f541c568), -778, -215},
+ {GRISU_UINT64_C(0x89e42caa, f9491b61), -774, -214},
+ {GRISU_UINT64_C(0xac5d37d5, b79b6239), -771, -213},
+ {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+ {GRISU_UINT64_C(0x86a8d39e, f77164bd), -764, -211},
+ {GRISU_UINT64_C(0xa8530886, b54dbdec), -761, -210},
+ {GRISU_UINT64_C(0xd267caa8, 62a12d67), -758, -209},
+ {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
+ {GRISU_UINT64_C(0xa4611653, 8d0deb78), -751, -207},
+ {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
+ {GRISU_UINT64_C(0x806bd971, 4632dff6), -744, -205},
+ {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
+ {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
+ {GRISU_UINT64_C(0xfad2a4b1, 3d1b5d6c), -735, -202},
+ {GRISU_UINT64_C(0x9cc3a6ee, c6311a64), -731, -201},
+ {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+ {GRISU_UINT64_C(0xf4f1b4d5, 15acb93c), -725, -199},
+ {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
+ {GRISU_UINT64_C(0xbf5cd546, 78eef0b7), -718, -197},
+ {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+ {GRISU_UINT64_C(0x9580869f, 0e7aac0f), -711, -195},
+ {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
+ {GRISU_UINT64_C(0xe998d258, 869facd7), -705, -193},
+ {GRISU_UINT64_C(0x91ff8377, 5423cc06), -701, -192},
+ {GRISU_UINT64_C(0xb67f6455, 292cbf08), -698, -191},
+ {GRISU_UINT64_C(0xe41f3d6a, 7377eeca), -695, -190},
+ {GRISU_UINT64_C(0x8e938662, 882af53e), -691, -189},
+ {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+ {GRISU_UINT64_C(0xdec681f9, f4c31f31), -685, -187},
+ {GRISU_UINT64_C(0x8b3c113c, 38f9f37f), -681, -186},
+ {GRISU_UINT64_C(0xae0b158b, 4738705f), -678, -185},
+ {GRISU_UINT64_C(0xd98ddaee, 19068c76), -675, -184},
+ {GRISU_UINT64_C(0x87f8a8d4, cfa417ca), -671, -183},
+ {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+ {GRISU_UINT64_C(0xd47487cc, 8470652b), -665, -181},
+ {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
+ {GRISU_UINT64_C(0xa5fb0a17, c777cf0a), -658, -179},
+ {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
+ {GRISU_UINT64_C(0x81ac1fe2, 93d599c0), -651, -177},
+ {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+ {GRISU_UINT64_C(0xca9cf1d2, 06fdc03c), -645, -175},
+ {GRISU_UINT64_C(0xfd442e46, 88bd304b), -642, -174},
+ {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
+ {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
+ {GRISU_UINT64_C(0xf7549530, e188c129), -632, -171},
+ {GRISU_UINT64_C(0x9a94dd3e, 8cf578ba), -628, -170},
+ {GRISU_UINT64_C(0xc13a148e, 3032d6e8), -625, -169},
+ {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+ {GRISU_UINT64_C(0x96f5600f, 15a7b7e5), -618, -167},
+ {GRISU_UINT64_C(0xbcb2b812, db11a5de), -615, -166},
+ {GRISU_UINT64_C(0xebdf6617, 91d60f56), -612, -165},
+ {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+ {GRISU_UINT64_C(0xb84687c2, 69ef3bfb), -605, -163},
+ {GRISU_UINT64_C(0xe65829b3, 046b0afa), -602, -162},
+ {GRISU_UINT64_C(0x8ff71a0f, e2c2e6dc), -598, -161},
+ {GRISU_UINT64_C(0xb3f4e093, db73a093), -595, -160},
+ {GRISU_UINT64_C(0xe0f218b8, d25088b8), -592, -159},
+ {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+ {GRISU_UINT64_C(0xafbd2350, 644eead0), -585, -157},
+ {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
+ {GRISU_UINT64_C(0x894bc396, ce5da772), -578, -155},
+ {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
+ {GRISU_UINT64_C(0xd686619b, a27255a3), -572, -153},
+ {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+ {GRISU_UINT64_C(0xa798fc41, 96e952e7), -565, -151},
+ {GRISU_UINT64_C(0xd17f3b51, fca3a7a1), -562, -150},
+ {GRISU_UINT64_C(0x82ef8513, 3de648c5), -558, -149},
+ {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+ {GRISU_UINT64_C(0xcc963fee, 10b7d1b3), -552, -147},
+ {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
+ {GRISU_UINT64_C(0x9fd561f1, fd0f9bd4), -545, -145},
+ {GRISU_UINT64_C(0xc7caba6e, 7c5382c9), -542, -144},
+ {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
+ {GRISU_UINT64_C(0x9c1661a6, 51213e2d), -535, -142},
+ {GRISU_UINT64_C(0xc31bfa0f, e5698db8), -532, -141},
+ {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+ {GRISU_UINT64_C(0x986ddb5c, 6b3a76b8), -525, -139},
+ {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
+ {GRISU_UINT64_C(0xee2ba6c0, 678b597f), -519, -137},
+ {GRISU_UINT64_C(0x94db4838, 40b717f0), -515, -136},
+ {GRISU_UINT64_C(0xba121a46, 50e4ddec), -512, -135},
+ {GRISU_UINT64_C(0xe896a0d7, e51e1566), -509, -134},
+ {GRISU_UINT64_C(0x915e2486, ef32cd60), -505, -133},
+ {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
+ {GRISU_UINT64_C(0xe3231912, d5bf60e6), -499, -131},
+ {GRISU_UINT64_C(0x8df5efab, c5979c90), -495, -130},
+ {GRISU_UINT64_C(0xb1736b96, b6fd83b4), -492, -129},
+ {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+ {GRISU_UINT64_C(0x8aa22c0d, bef60ee4), -485, -127},
+ {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
+ {GRISU_UINT64_C(0xd89d64d5, 7a607745), -479, -125},
+ {GRISU_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
+ {GRISU_UINT64_C(0xa93af6c6, c79b5d2e), -472, -123},
+ {GRISU_UINT64_C(0xd389b478, 79823479), -469, -122},
+ {GRISU_UINT64_C(0x843610cb, 4bf160cc), -465, -121},
+ {GRISU_UINT64_C(0xa54394fe, 1eedb8ff), -462, -120},
+ {GRISU_UINT64_C(0xce947a3d, a6a9273e), -459, -119},
+ {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
+ {GRISU_UINT64_C(0xa163ff80, 2a3426a9), -452, -117},
+ {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+ {GRISU_UINT64_C(0xfc2c3f38, 41f17c68), -446, -115},
+ {GRISU_UINT64_C(0x9d9ba783, 2936edc1), -442, -114},
+ {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
+ {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
+ {GRISU_UINT64_C(0x99ea0196, 163fa42e), -432, -111},
+ {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+ {GRISU_UINT64_C(0xf07da27a, 82c37088), -426, -109},
+ {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+ {GRISU_UINT64_C(0xbbe226ef, b628afeb), -419, -107},
+ {GRISU_UINT64_C(0xeadab0ab, a3b2dbe5), -416, -106},
+ {GRISU_UINT64_C(0x92c8ae6b, 464fc96f), -412, -105},
+ {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+ {GRISU_UINT64_C(0xe5599087, 9ddcaabe), -406, -103},
+ {GRISU_UINT64_C(0x8f57fa54, c2a9eab7), -402, -102},
+ {GRISU_UINT64_C(0xb32df8e9, f3546564), -399, -101},
+ {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
+ {GRISU_UINT64_C(0x8bfbea76, c619ef36), -392, -99},
+ {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+ {GRISU_UINT64_C(0xdab99e59, 958885c5), -386, -97},
+ {GRISU_UINT64_C(0x88b402f7, fd75539b), -382, -96},
+ {GRISU_UINT64_C(0xaae103b5, fcd2a882), -379, -95},
+ {GRISU_UINT64_C(0xd59944a3, 7c0752a2), -376, -94},
+ {GRISU_UINT64_C(0x857fcae6, 2d8493a5), -372, -93},
+ {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+ {GRISU_UINT64_C(0xd097ad07, a71f26b2), -366, -91},
+ {GRISU_UINT64_C(0x825ecc24, c8737830), -362, -90},
+ {GRISU_UINT64_C(0xa2f67f2d, fa90563b), -359, -89},
+ {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+ {GRISU_UINT64_C(0xfea126b7, d78186bd), -353, -87},
+ {GRISU_UINT64_C(0x9f24b832, e6b0f436), -349, -86},
+ {GRISU_UINT64_C(0xc6ede63f, a05d3144), -346, -85},
+ {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+ {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
+ {GRISU_UINT64_C(0xc24452da, 229b021c), -336, -82},
+ {GRISU_UINT64_C(0xf2d56790, ab41c2a3), -333, -81},
+ {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+ {GRISU_UINT64_C(0xbdb6b8e9, 05cb600f), -326, -79},
+ {GRISU_UINT64_C(0xed246723, 473e3813), -323, -78},
+ {GRISU_UINT64_C(0x9436c076, 0c86e30c), -319, -77},
+ {GRISU_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
+ {GRISU_UINT64_C(0xe7958cb8, 7392c2c3), -313, -75},
+ {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+ {GRISU_UINT64_C(0xb4ecd5f0, 1a4aa828), -306, -73},
+ {GRISU_UINT64_C(0xe2280b6c, 20dd5232), -303, -72},
+ {GRISU_UINT64_C(0x8d590723, 948a535f), -299, -71},
+ {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
+ {GRISU_UINT64_C(0xdcdb1b27, 98182245), -293, -69},
+ {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {GRISU_UINT64_C(0xac8b2d36, eed2dac6), -286, -67},
+ {GRISU_UINT64_C(0xd7adf884, aa879177), -283, -66},
+ {GRISU_UINT64_C(0x86ccbb52, ea94baeb), -279, -65},
+ {GRISU_UINT64_C(0xa87fea27, a539e9a5), -276, -64},
+ {GRISU_UINT64_C(0xd29fe4b1, 8e88640f), -273, -63},
+ {GRISU_UINT64_C(0x83a3eeee, f9153e89), -269, -62},
+ {GRISU_UINT64_C(0xa48ceaaa, b75a8e2b), -266, -61},
+ {GRISU_UINT64_C(0xcdb02555, 653131b6), -263, -60},
+ {GRISU_UINT64_C(0x808e1755, 5f3ebf12), -259, -59},
+ {GRISU_UINT64_C(0xa0b19d2a, b70e6ed6), -256, -58},
+ {GRISU_UINT64_C(0xc8de0475, 64d20a8c), -253, -57},
+ {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+ {GRISU_UINT64_C(0x9ced737b, b6c4183d), -246, -55},
+ {GRISU_UINT64_C(0xc428d05a, a4751e4d), -243, -54},
+ {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
+ {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
+ {GRISU_UINT64_C(0xbf8fdb78, 849a5f97), -233, -51},
+ {GRISU_UINT64_C(0xef73d256, a5c0f77d), -230, -50},
+ {GRISU_UINT64_C(0x95a86376, 27989aae), -226, -49},
+ {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+ {GRISU_UINT64_C(0xe9d71b68, 9dde71b0), -220, -47},
+ {GRISU_UINT64_C(0x92267121, 62ab070e), -216, -46},
+ {GRISU_UINT64_C(0xb6b00d69, bb55c8d1), -213, -45},
+ {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+ {GRISU_UINT64_C(0x8eb98a7a, 9a5b04e3), -206, -43},
+ {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
+ {GRISU_UINT64_C(0xdf01e85f, 912e37a3), -200, -41},
+ {GRISU_UINT64_C(0x8b61313b, babce2c6), -196, -40},
+ {GRISU_UINT64_C(0xae397d8a, a96c1b78), -193, -39},
+ {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+ {GRISU_UINT64_C(0x881cea14, 545c7575), -186, -37},
+ {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
+ {GRISU_UINT64_C(0xd4ad2dbf, c3d07788), -180, -35},
+ {GRISU_UINT64_C(0x84ec3c97, da624ab5), -176, -34},
+ {GRISU_UINT64_C(0xa6274bbd, d0fadd62), -173, -33},
+ {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
+ {GRISU_UINT64_C(0x81ceb32c, 4b43fcf5), -166, -31},
+ {GRISU_UINT64_C(0xa2425ff7, 5e14fc32), -163, -30},
+ {GRISU_UINT64_C(0xcad2f7f5, 359a3b3e), -160, -29},
+ {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+ {GRISU_UINT64_C(0x9e74d1b7, 91e07e48), -153, -27},
+ {GRISU_UINT64_C(0xc6120625, 76589ddb), -150, -26},
+ {GRISU_UINT64_C(0xf79687ae, d3eec551), -147, -25},
+ {GRISU_UINT64_C(0x9abe14cd, 44753b53), -143, -24},
+ {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
+ {GRISU_UINT64_C(0xf1c90080, baf72cb1), -137, -22},
+ {GRISU_UINT64_C(0x971da050, 74da7bef), -133, -21},
+ {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+ {GRISU_UINT64_C(0xec1e4a7d, b69561a5), -127, -19},
+ {GRISU_UINT64_C(0x9392ee8e, 921d5d07), -123, -18},
+ {GRISU_UINT64_C(0xb877aa32, 36a4b449), -120, -17},
+ {GRISU_UINT64_C(0xe69594be, c44de15b), -117, -16},
+ {GRISU_UINT64_C(0x901d7cf7, 3ab0acd9), -113, -15},
+ {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
+ {GRISU_UINT64_C(0xe12e1342, 4bb40e13), -107, -13},
+ {GRISU_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
+ {GRISU_UINT64_C(0xafebff0b, cb24aaff), -100, -11},
+ {GRISU_UINT64_C(0xdbe6fece, bdedd5bf), -97, -10},
+ {GRISU_UINT64_C(0x89705f41, 36b4a597), -93, -9},
+ {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+ {GRISU_UINT64_C(0xd6bf94d5, e57a42bc), -87, -7},
+ {GRISU_UINT64_C(0x8637bd05, af6c69b6), -83, -6},
+ {GRISU_UINT64_C(0xa7c5ac47, 1b478423), -80, -5},
+ {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
+ {GRISU_UINT64_C(0x83126e97, 8d4fdf3b), -73, -3},
+ {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+ {GRISU_UINT64_C(0xcccccccc, cccccccd), -67, -1},
+ {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
+ {GRISU_UINT64_C(0xa0000000, 00000000), -60, 1},
+ {GRISU_UINT64_C(0xc8000000, 00000000), -57, 2},
+ {GRISU_UINT64_C(0xfa000000, 00000000), -54, 3},
+ {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+ {GRISU_UINT64_C(0xc3500000, 00000000), -47, 5},
+ {GRISU_UINT64_C(0xf4240000, 00000000), -44, 6},
+ {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
+ {GRISU_UINT64_C(0xbebc2000, 00000000), -37, 8},
+ {GRISU_UINT64_C(0xee6b2800, 00000000), -34, 9},
+ {GRISU_UINT64_C(0x9502f900, 00000000), -30, 10},
+ {GRISU_UINT64_C(0xba43b740, 00000000), -27, 11},
+ {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+ {GRISU_UINT64_C(0x9184e72a, 00000000), -20, 13},
+ {GRISU_UINT64_C(0xb5e620f4, 80000000), -17, 14},
+ {GRISU_UINT64_C(0xe35fa931, a0000000), -14, 15},
+ {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+ {GRISU_UINT64_C(0xb1a2bc2e, c5000000), -7, 17},
+ {GRISU_UINT64_C(0xde0b6b3a, 76400000), -4, 18},
+ {GRISU_UINT64_C(0x8ac72304, 89e80000), 0, 19},
+ {GRISU_UINT64_C(0xad78ebc5, ac620000), 3, 20},
+ {GRISU_UINT64_C(0xd8d726b7, 177a8000), 6, 21},
+ {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+ {GRISU_UINT64_C(0xa968163f, 0a57b400), 13, 23},
+ {GRISU_UINT64_C(0xd3c21bce, cceda100), 16, 24},
+ {GRISU_UINT64_C(0x84595161, 401484a0), 20, 25},
+ {GRISU_UINT64_C(0xa56fa5b9, 9019a5c8), 23, 26},
+ {GRISU_UINT64_C(0xcecb8f27, f4200f3a), 26, 27},
+ {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+ {GRISU_UINT64_C(0xa18f07d7, 36b90be5), 33, 29},
+ {GRISU_UINT64_C(0xc9f2c9cd, 04674edf), 36, 30},
+ {GRISU_UINT64_C(0xfc6f7c40, 45812296), 39, 31},
+ {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+ {GRISU_UINT64_C(0xc5371912, 364ce305), 46, 33},
+ {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+ {GRISU_UINT64_C(0x9a130b96, 3a6c115c), 53, 35},
+ {GRISU_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
+ {GRISU_UINT64_C(0xf0bdc21a, bb48db20), 59, 37},
+ {GRISU_UINT64_C(0x96769950, b50d88f4), 63, 38},
+ {GRISU_UINT64_C(0xbc143fa4, e250eb31), 66, 39},
+ {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
+ {GRISU_UINT64_C(0x92efd1b8, d0cf37be), 73, 41},
+ {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
+ {GRISU_UINT64_C(0xe596b7b0, c643c719), 79, 43},
+ {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
+ {GRISU_UINT64_C(0xb35dbf82, 1ae4f38c), 86, 45},
+ {GRISU_UINT64_C(0xe0352f62, a19e306f), 89, 46},
+ {GRISU_UINT64_C(0x8c213d9d, a502de45), 93, 47},
+ {GRISU_UINT64_C(0xaf298d05, 0e4395d7), 96, 48},
+ {GRISU_UINT64_C(0xdaf3f046, 51d47b4c), 99, 49},
+ {GRISU_UINT64_C(0x88d8762b, f324cd10), 103, 50},
+ {GRISU_UINT64_C(0xab0e93b6, efee0054), 106, 51},
+ {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {GRISU_UINT64_C(0x85a36366, eb71f041), 113, 53},
+ {GRISU_UINT64_C(0xa70c3c40, a64e6c52), 116, 54},
+ {GRISU_UINT64_C(0xd0cf4b50, cfe20766), 119, 55},
+ {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
+ {GRISU_UINT64_C(0xa321f2d7, 226895c8), 126, 57},
+ {GRISU_UINT64_C(0xcbea6f8c, eb02bb3a), 129, 58},
+ {GRISU_UINT64_C(0xfee50b70, 25c36a08), 132, 59},
+ {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
+ {GRISU_UINT64_C(0xc722f0ef, 9d80aad6), 139, 61},
+ {GRISU_UINT64_C(0xf8ebad2b, 84e0d58c), 142, 62},
+ {GRISU_UINT64_C(0x9b934c3b, 330c8577), 146, 63},
+ {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
+ {GRISU_UINT64_C(0xf316271c, 7fc3908b), 152, 65},
+ {GRISU_UINT64_C(0x97edd871, cfda3a57), 156, 66},
+ {GRISU_UINT64_C(0xbde94e8e, 43d0c8ec), 159, 67},
+ {GRISU_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
+ {GRISU_UINT64_C(0x945e455f, 24fb1cf9), 166, 69},
+ {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+ {GRISU_UINT64_C(0xe7d34c64, a9c85d44), 172, 71},
+ {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+ {GRISU_UINT64_C(0xb51d13ae, a4a488dd), 179, 73},
+ {GRISU_UINT64_C(0xe264589a, 4dcdab15), 182, 74},
+ {GRISU_UINT64_C(0x8d7eb760, 70a08aed), 186, 75},
+ {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+ {GRISU_UINT64_C(0xdd15fe86, affad912), 192, 77},
+ {GRISU_UINT64_C(0x8a2dbf14, 2dfcc7ab), 196, 78},
+ {GRISU_UINT64_C(0xacb92ed9, 397bf996), 199, 79},
+ {GRISU_UINT64_C(0xd7e77a8f, 87daf7fc), 202, 80},
+ {GRISU_UINT64_C(0x86f0ac99, b4e8dafd), 206, 81},
+ {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+ {GRISU_UINT64_C(0xd2d80db0, 2aabd62c), 212, 83},
+ {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
+ {GRISU_UINT64_C(0xa4b8cab1, a1563f52), 219, 85},
+ {GRISU_UINT64_C(0xcde6fd5e, 09abcf27), 222, 86},
+ {GRISU_UINT64_C(0x80b05e5a, c60b6178), 226, 87},
+ {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+ {GRISU_UINT64_C(0xc913936d, d571c84c), 232, 89},
+ {GRISU_UINT64_C(0xfb587849, 4ace3a5f), 235, 90},
+ {GRISU_UINT64_C(0x9d174b2d, cec0e47b), 239, 91},
+ {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+ {GRISU_UINT64_C(0xf5746577, 930d6501), 245, 93},
+ {GRISU_UINT64_C(0x9968bf6a, bbe85f20), 249, 94},
+ {GRISU_UINT64_C(0xbfc2ef45, 6ae276e9), 252, 95},
+ {GRISU_UINT64_C(0xefb3ab16, c59b14a3), 255, 96},
+ {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
+ {GRISU_UINT64_C(0xbb445da9, ca61281f), 262, 98},
+ {GRISU_UINT64_C(0xea157514, 3cf97227), 265, 99},
+ {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+ {GRISU_UINT64_C(0xb6e0c377, cfa2e12e), 272, 101},
+ {GRISU_UINT64_C(0xe498f455, c38b997a), 275, 102},
+ {GRISU_UINT64_C(0x8edf98b5, 9a373fec), 279, 103},
+ {GRISU_UINT64_C(0xb2977ee3, 00c50fe7), 282, 104},
+ {GRISU_UINT64_C(0xdf3d5e9b, c0f653e1), 285, 105},
+ {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
+ {GRISU_UINT64_C(0xae67f1e9, aec07188), 292, 107},
+ {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
+ {GRISU_UINT64_C(0x884134fe, 908658b2), 299, 109},
+ {GRISU_UINT64_C(0xaa51823e, 34a7eedf), 302, 110},
+ {GRISU_UINT64_C(0xd4e5e2cd, c1d1ea96), 305, 111},
+ {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+ {GRISU_UINT64_C(0xa6539930, bf6bff46), 312, 113},
+ {GRISU_UINT64_C(0xcfe87f7c, ef46ff17), 315, 114},
+ {GRISU_UINT64_C(0x81f14fae, 158c5f6e), 319, 115},
+ {GRISU_UINT64_C(0xa26da399, 9aef774a), 322, 116},
+ {GRISU_UINT64_C(0xcb090c80, 01ab551c), 325, 117},
+ {GRISU_UINT64_C(0xfdcb4fa0, 02162a63), 328, 118},
+ {GRISU_UINT64_C(0x9e9f11c4, 014dda7e), 332, 119},
+ {GRISU_UINT64_C(0xc646d635, 01a1511e), 335, 120},
+ {GRISU_UINT64_C(0xf7d88bc2, 4209a565), 338, 121},
+ {GRISU_UINT64_C(0x9ae75759, 6946075f), 342, 122},
+ {GRISU_UINT64_C(0xc1a12d2f, c3978937), 345, 123},
+ {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+ {GRISU_UINT64_C(0x9745eb4d, 50ce6333), 352, 125},
+ {GRISU_UINT64_C(0xbd176620, a501fc00), 355, 126},
+ {GRISU_UINT64_C(0xec5d3fa8, ce427b00), 358, 127},
+ {GRISU_UINT64_C(0x93ba47c9, 80e98ce0), 362, 128},
+ {GRISU_UINT64_C(0xb8a8d9bb, e123f018), 365, 129},
+ {GRISU_UINT64_C(0xe6d3102a, d96cec1e), 368, 130},
+ {GRISU_UINT64_C(0x9043ea1a, c7e41393), 372, 131},
+ {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+ {GRISU_UINT64_C(0xe16a1dc9, d8545e95), 378, 133},
+ {GRISU_UINT64_C(0x8ce2529e, 2734bb1d), 382, 134},
+ {GRISU_UINT64_C(0xb01ae745, b101e9e4), 385, 135},
+ {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
+ {GRISU_UINT64_C(0x899504ae, 72497eba), 392, 137},
+ {GRISU_UINT64_C(0xabfa45da, 0edbde69), 395, 138},
+ {GRISU_UINT64_C(0xd6f8d750, 9292d603), 398, 139},
+ {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+ {GRISU_UINT64_C(0xa7f26836, f282b733), 405, 141},
+ {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+ {GRISU_UINT64_C(0x8335616a, ed761f1f), 412, 143},
+ {GRISU_UINT64_C(0xa402b9c5, a8d3a6e7), 415, 144},
+ {GRISU_UINT64_C(0xcd036837, 130890a1), 418, 145},
+ {GRISU_UINT64_C(0x80222122, 6be55a65), 422, 146},
+ {GRISU_UINT64_C(0xa02aa96b, 06deb0fe), 425, 147},
+ {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+ {GRISU_UINT64_C(0xfa42a8b7, 3abbf48d), 431, 149},
+ {GRISU_UINT64_C(0x9c69a972, 84b578d8), 435, 150},
+ {GRISU_UINT64_C(0xc38413cf, 25e2d70e), 438, 151},
+ {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
+ {GRISU_UINT64_C(0x98bf2f79, d5993803), 445, 153},
+ {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+ {GRISU_UINT64_C(0xeeaaba2e, 5dbf6785), 451, 155},
+ {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
+ {GRISU_UINT64_C(0xba756174, 393d88e0), 458, 157},
+ {GRISU_UINT64_C(0xe912b9d1, 478ceb17), 461, 158},
+ {GRISU_UINT64_C(0x91abb422, ccb812ef), 465, 159},
+ {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+ {GRISU_UINT64_C(0xe39c4976, 5fdf9d95), 471, 161},
+ {GRISU_UINT64_C(0x8e41ade9, fbebc27d), 475, 162},
+ {GRISU_UINT64_C(0xb1d21964, 7ae6b31c), 478, 163},
+ {GRISU_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
+ {GRISU_UINT64_C(0x8aec23d6, 80043bee), 485, 165},
+ {GRISU_UINT64_C(0xada72ccc, 20054aea), 488, 166},
+ {GRISU_UINT64_C(0xd910f7ff, 28069da4), 491, 167},
+ {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
+ {GRISU_UINT64_C(0xa99541bf, 57452b28), 498, 169},
+ {GRISU_UINT64_C(0xd3fa922f, 2d1675f2), 501, 170},
+ {GRISU_UINT64_C(0x847c9b5d, 7c2e09b7), 505, 171},
+ {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+ {GRISU_UINT64_C(0xcf02b2c2, 1207ef2f), 511, 173},
+ {GRISU_UINT64_C(0x8161afb9, 4b44f57d), 515, 174},
+ {GRISU_UINT64_C(0xa1ba1ba7, 9e1632dc), 518, 175},
+ {GRISU_UINT64_C(0xca28a291, 859bbf93), 521, 176},
+ {GRISU_UINT64_C(0xfcb2cb35, e702af78), 524, 177},
+ {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
+ {GRISU_UINT64_C(0xc56baec2, 1c7a1916), 531, 179},
+ {GRISU_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
+ {GRISU_UINT64_C(0x9a3c2087, a63f6399), 538, 181},
+ {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
+ {GRISU_UINT64_C(0xf0fdf2d3, f3c30b9f), 544, 183},
+ {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
+ {GRISU_UINT64_C(0xbc4665b5, 96706115), 551, 185},
+ {GRISU_UINT64_C(0xeb57ff22, fc0c795a), 554, 186},
+ {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
+ {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
+ {GRISU_UINT64_C(0xe5d3ef28, 2a242e82), 564, 189},
+ {GRISU_UINT64_C(0x8fa47579, 1a569d11), 568, 190},
+ {GRISU_UINT64_C(0xb38d92d7, 60ec4455), 571, 191},
+ {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
+ {GRISU_UINT64_C(0x8c469ab8, 43b89563), 578, 193},
+ {GRISU_UINT64_C(0xaf584166, 54a6babb), 581, 194},
+ {GRISU_UINT64_C(0xdb2e51bf, e9d0696a), 584, 195},
+ {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+ {GRISU_UINT64_C(0xab3c2fdd, eeaad25b), 591, 197},
+ {GRISU_UINT64_C(0xd60b3bd5, 6a5586f2), 594, 198},
+ {GRISU_UINT64_C(0x85c70565, 62757457), 598, 199},
+ {GRISU_UINT64_C(0xa738c6be, bb12d16d), 601, 200},
+ {GRISU_UINT64_C(0xd106f86e, 69d785c8), 604, 201},
+ {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+ {GRISU_UINT64_C(0xa34d7216, 42b06084), 611, 203},
+ {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
+ {GRISU_UINT64_C(0xff290242, c83396ce), 617, 205},
+ {GRISU_UINT64_C(0x9f79a169, bd203e41), 621, 206},
+ {GRISU_UINT64_C(0xc75809c4, 2c684dd1), 624, 207},
+ {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
+ {GRISU_UINT64_C(0x9bbcc7a1, 42b17ccc), 631, 209},
+ {GRISU_UINT64_C(0xc2abf989, 935ddbfe), 634, 210},
+ {GRISU_UINT64_C(0xf356f7eb, f83552fe), 637, 211},
+ {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+ {GRISU_UINT64_C(0xbe1bf1b0, 59e9a8d6), 644, 213},
+ {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
+ {GRISU_UINT64_C(0x9485d4d1, c63e8be8), 651, 215},
+ {GRISU_UINT64_C(0xb9a74a06, 37ce2ee1), 654, 216},
+ {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
+ {GRISU_UINT64_C(0x910ab1d4, db9914a0), 661, 218},
+ {GRISU_UINT64_C(0xb54d5e4a, 127f59c8), 664, 219},
+ {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+ {GRISU_UINT64_C(0x8da471a9, de737e24), 671, 221},
+ {GRISU_UINT64_C(0xb10d8e14, 56105dad), 674, 222},
+ {GRISU_UINT64_C(0xdd50f199, 6b947519), 677, 223},
+ {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
+ {GRISU_UINT64_C(0xace73cbf, dc0bfb7b), 684, 225},
+ {GRISU_UINT64_C(0xd8210bef, d30efa5a), 687, 226},
+ {GRISU_UINT64_C(0x8714a775, e3e95c78), 691, 227},
+ {GRISU_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
+ {GRISU_UINT64_C(0xd31045a8, 341ca07c), 697, 229},
+ {GRISU_UINT64_C(0x83ea2b89, 2091e44e), 701, 230},
+ {GRISU_UINT64_C(0xa4e4b66b, 68b65d61), 704, 231},
+ {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+ {GRISU_UINT64_C(0x80d2ae83, e9ce78f4), 711, 233},
+ {GRISU_UINT64_C(0xa1075a24, e4421731), 714, 234},
+ {GRISU_UINT64_C(0xc94930ae, 1d529cfd), 717, 235},
+ {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
+ {GRISU_UINT64_C(0x9d412e08, 06e88aa6), 724, 237},
+ {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+ {GRISU_UINT64_C(0xf5b5d7ec, 8acb58a3), 730, 239},
+ {GRISU_UINT64_C(0x9991a6f3, d6bf1766), 734, 240},
+ {GRISU_UINT64_C(0xbff610b0, cc6edd3f), 737, 241},
+ {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
+ {GRISU_UINT64_C(0x95f83d0a, 1fb69cd9), 744, 243},
+ {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+ {GRISU_UINT64_C(0xea53df5f, d18d5514), 750, 245},
+ {GRISU_UINT64_C(0x92746b9b, e2f8552c), 754, 246},
+ {GRISU_UINT64_C(0xb7118682, dbb66a77), 757, 247},
+ {GRISU_UINT64_C(0xe4d5e823, 92a40515), 760, 248},
+ {GRISU_UINT64_C(0x8f05b116, 3ba6832d), 764, 249},
+ {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
+ {GRISU_UINT64_C(0xdf78e4b2, bd342cf7), 770, 251},
+ {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+ {GRISU_UINT64_C(0xae9672ab, a3d0c321), 777, 253},
+ {GRISU_UINT64_C(0xda3c0f56, 8cc4f3e9), 780, 254},
+ {GRISU_UINT64_C(0x88658996, 17fb1871), 784, 255},
+ {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
+ {GRISU_UINT64_C(0xd51ea6fa, 85785631), 790, 257},
+ {GRISU_UINT64_C(0x8533285c, 936b35df), 794, 258},
+ {GRISU_UINT64_C(0xa67ff273, b8460357), 797, 259},
+ {GRISU_UINT64_C(0xd01fef10, a657842c), 800, 260},
+ {GRISU_UINT64_C(0x8213f56a, 67f6b29c), 804, 261},
+ {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+ {GRISU_UINT64_C(0xcb3f2f76, 42717713), 810, 263},
+ {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
+ {GRISU_UINT64_C(0x9ec95d14, 63e8a507), 817, 265},
+ {GRISU_UINT64_C(0xc67bb459, 7ce2ce49), 820, 266},
+ {GRISU_UINT64_C(0xf81aa16f, dc1b81db), 823, 267},
+ {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+ {GRISU_UINT64_C(0xc1d4ce1f, 63f57d73), 830, 269},
+ {GRISU_UINT64_C(0xf24a01a7, 3cf2dcd0), 833, 270},
+ {GRISU_UINT64_C(0x976e4108, 8617ca02), 837, 271},
+ {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
+ {GRISU_UINT64_C(0xec9c459d, 51852ba3), 843, 273},
+ {GRISU_UINT64_C(0x93e1ab82, 52f33b46), 847, 274},
+ {GRISU_UINT64_C(0xb8da1662, e7b00a17), 850, 275},
+ {GRISU_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
+ {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
+ {GRISU_UINT64_C(0xb484f9dc, 9641e9db), 860, 278},
+ {GRISU_UINT64_C(0xe1a63853, bbd26451), 863, 279},
+ {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+ {GRISU_UINT64_C(0xb049dc01, 6abc5e60), 870, 281},
+ {GRISU_UINT64_C(0xdc5c5301, c56b75f7), 873, 282},
+ {GRISU_UINT64_C(0x89b9b3e1, 1b6329bb), 877, 283},
+ {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
+ {GRISU_UINT64_C(0xd732290f, bacaf134), 883, 285},
+ {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+ {GRISU_UINT64_C(0xa81f3014, 49ee8c70), 890, 287},
+ {GRISU_UINT64_C(0xd226fc19, 5c6a2f8c), 893, 288},
+ {GRISU_UINT64_C(0x83585d8f, d9c25db8), 897, 289},
+ {GRISU_UINT64_C(0xa42e74f3, d032f526), 900, 290},
+ {GRISU_UINT64_C(0xcd3a1230, c43fb26f), 903, 291},
+ {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {GRISU_UINT64_C(0xa0555e36, 1951c367), 910, 293},
+ {GRISU_UINT64_C(0xc86ab5c3, 9fa63441), 913, 294},
+ {GRISU_UINT64_C(0xfa856334, 878fc151), 916, 295},
+ {GRISU_UINT64_C(0x9c935e00, d4b9d8d2), 920, 296},
+ {GRISU_UINT64_C(0xc3b83581, 09e84f07), 923, 297},
+ {GRISU_UINT64_C(0xf4a642e1, 4c6262c9), 926, 298},
+ {GRISU_UINT64_C(0x98e7e9cc, cfbd7dbe), 930, 299},
+ {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
+ {GRISU_UINT64_C(0xeeea5d50, 04981478), 936, 301},
+ {GRISU_UINT64_C(0x95527a52, 02df0ccb), 940, 302},
+ {GRISU_UINT64_C(0xbaa718e6, 8396cffe), 943, 303},
+ {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+ {GRISU_UINT64_C(0x91d28b74, 16cdd27e), 950, 305},
+ {GRISU_UINT64_C(0xb6472e51, 1c81471e), 953, 306},
+ {GRISU_UINT64_C(0xe3d8f9e5, 63a198e5), 956, 307},
+ {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+ {GRISU_UINT64_C(0xb201833b, 35d63f73), 963, 309},
+ {GRISU_UINT64_C(0xde81e40a, 034bcf50), 966, 310},
+ {GRISU_UINT64_C(0x8b112e86, 420f6192), 970, 311},
+ {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
+ {GRISU_UINT64_C(0xd94ad8b1, c7380874), 976, 313},
+ {GRISU_UINT64_C(0x87cec76f, 1c830549), 980, 314},
+ {GRISU_UINT64_C(0xa9c2794a, e3a3c69b), 983, 315},
+ {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+ {GRISU_UINT64_C(0x849feec2, 81d7f329), 990, 317},
+ {GRISU_UINT64_C(0xa5c7ea73, 224deff3), 993, 318},
+ {GRISU_UINT64_C(0xcf39e50f, eae16bf0), 996, 319},
+ {GRISU_UINT64_C(0x81842f29, f2cce376), 1000, 320},
+ {GRISU_UINT64_C(0xa1e53af4, 6f801c53), 1003, 321},
+ {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+ {GRISU_UINT64_C(0xfcf62c1d, ee382c42), 1009, 323},
+ {GRISU_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
+ {GRISU_UINT64_C(0xc5a05277, 621be294), 1016, 325},
+ {GRISU_UINT64_C(0xf7086715, 3aa2db39), 1019, 326},
+ {GRISU_UINT64_C(0x9a65406d, 44a5c903), 1023, 327},
+ {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
+ {GRISU_UINT64_C(0xf13e34aa, bb430a15), 1029, 329},
+ {GRISU_UINT64_C(0x96c6e0ea, b509e64d), 1033, 330},
+ {GRISU_UINT64_C(0xbc789925, 624c5fe1), 1036, 331},
+ {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+ {GRISU_UINT64_C(0x933e37a5, 34cbaae8), 1043, 333},
+ {GRISU_UINT64_C(0xb80dc58e, 81fe95a1), 1046, 334},
+ {GRISU_UINT64_C(0xe61136f2, 227e3b0a), 1049, 335},
+ {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
+ {GRISU_UINT64_C(0xb3bd72ed, 2af29e20), 1056, 337},
+ {GRISU_UINT64_C(0xe0accfa8, 75af45a8), 1059, 338},
+ {GRISU_UINT64_C(0x8c6c01c9, 498d8b89), 1063, 339},
+ {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+ {GRISU_UINT64_C(0xdb68c2ca, 82ed2a06), 1069, 341},
+ {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(1) = 4;
+// nb elements (1): 651
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(2)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0xb3c4f1ba, 87bc8697), -1080, -306},
+ {GRISU_UINT64_C(0x8c71dcd9, ba0b4926), -1073, -304},
+ {GRISU_UINT64_C(0xdb71e914, 32b1a24b), -1067, -302},
+ {GRISU_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
+ {GRISU_UINT64_C(0x85f04682, 93f0eb4e), -1053, -298},
+ {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
+ {GRISU_UINT64_C(0xa37fce12, 6597973d), -1040, -294},
+ {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
+ {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
+ {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
+ {GRISU_UINT64_C(0xf3a20279, ed56d48a), -1014, -286},
+ {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+ {GRISU_UINT64_C(0x94b3a202, eb1c3f39), -1000, -282},
+ {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
+ {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+ {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
+ {GRISU_UINT64_C(0xdd95317f, 31c7fa1d), -974, -274},
+ {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+ {GRISU_UINT64_C(0x873e4f75, e2224e68), -960, -270},
+ {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+ {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
+ {GRISU_UINT64_C(0x80fa687f, 881c7f8e), -940, -264},
+ {GRISU_UINT64_C(0xc9874347, 44ac874f), -934, -262},
+ {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+ {GRISU_UINT64_C(0xf6019da0, 7f549b2b), -921, -258},
+ {GRISU_UINT64_C(0xc0314325, 637a193a), -914, -256},
+ {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
+ {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
+ {GRISU_UINT64_C(0xb749faed, 14125d37), -894, -250},
+ {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+ {GRISU_UINT64_C(0xdfbdcece, 67006ac9), -881, -246},
+ {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
+ {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
+ {GRISU_UINT64_C(0xd5605fcd, cf32e1d7), -861, -240},
+ {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
+ {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+ {GRISU_UINT64_C(0xcb7ddcdd, a26da269), -841, -234},
+ {GRISU_UINT64_C(0x9efa548d, 26e5a6e2), -834, -232},
+ {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
+ {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+ {GRISU_UINT64_C(0x979cf3ca, 6cec5b5b), -814, -226},
+ {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+ {GRISU_UINT64_C(0xb9131798, 99f68584), -801, -222},
+ {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
+ {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+ {GRISU_UINT64_C(0xb080392c, c4349ded), -781, -216},
+ {GRISU_UINT64_C(0x89e42caa, f9491b61), -774, -214},
+ {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+ {GRISU_UINT64_C(0xa8530886, b54dbdec), -761, -210},
+ {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
+ {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
+ {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
+ {GRISU_UINT64_C(0xfad2a4b1, 3d1b5d6c), -735, -202},
+ {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+ {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
+ {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+ {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
+ {GRISU_UINT64_C(0x91ff8377, 5423cc06), -701, -192},
+ {GRISU_UINT64_C(0xe41f3d6a, 7377eeca), -695, -190},
+ {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+ {GRISU_UINT64_C(0x8b3c113c, 38f9f37f), -681, -186},
+ {GRISU_UINT64_C(0xd98ddaee, 19068c76), -675, -184},
+ {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+ {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
+ {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
+ {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+ {GRISU_UINT64_C(0xfd442e46, 88bd304b), -642, -174},
+ {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
+ {GRISU_UINT64_C(0x9a94dd3e, 8cf578ba), -628, -170},
+ {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+ {GRISU_UINT64_C(0xbcb2b812, db11a5de), -615, -166},
+ {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+ {GRISU_UINT64_C(0xe65829b3, 046b0afa), -602, -162},
+ {GRISU_UINT64_C(0xb3f4e093, db73a093), -595, -160},
+ {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+ {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
+ {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
+ {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+ {GRISU_UINT64_C(0xd17f3b51, fca3a7a1), -562, -150},
+ {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+ {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
+ {GRISU_UINT64_C(0xc7caba6e, 7c5382c9), -542, -144},
+ {GRISU_UINT64_C(0x9c1661a6, 51213e2d), -535, -142},
+ {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+ {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
+ {GRISU_UINT64_C(0x94db4838, 40b717f0), -515, -136},
+ {GRISU_UINT64_C(0xe896a0d7, e51e1566), -509, -134},
+ {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
+ {GRISU_UINT64_C(0x8df5efab, c5979c90), -495, -130},
+ {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+ {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
+ {GRISU_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
+ {GRISU_UINT64_C(0xd389b478, 79823479), -469, -122},
+ {GRISU_UINT64_C(0xa54394fe, 1eedb8ff), -462, -120},
+ {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
+ {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+ {GRISU_UINT64_C(0x9d9ba783, 2936edc1), -442, -114},
+ {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
+ {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+ {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+ {GRISU_UINT64_C(0xeadab0ab, a3b2dbe5), -416, -106},
+ {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+ {GRISU_UINT64_C(0x8f57fa54, c2a9eab7), -402, -102},
+ {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
+ {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+ {GRISU_UINT64_C(0x88b402f7, fd75539b), -382, -96},
+ {GRISU_UINT64_C(0xd59944a3, 7c0752a2), -376, -94},
+ {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+ {GRISU_UINT64_C(0x825ecc24, c8737830), -362, -90},
+ {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+ {GRISU_UINT64_C(0x9f24b832, e6b0f436), -349, -86},
+ {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+ {GRISU_UINT64_C(0xc24452da, 229b021c), -336, -82},
+ {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+ {GRISU_UINT64_C(0xed246723, 473e3813), -323, -78},
+ {GRISU_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
+ {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+ {GRISU_UINT64_C(0xe2280b6c, 20dd5232), -303, -72},
+ {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
+ {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {GRISU_UINT64_C(0xd7adf884, aa879177), -283, -66},
+ {GRISU_UINT64_C(0xa87fea27, a539e9a5), -276, -64},
+ {GRISU_UINT64_C(0x83a3eeee, f9153e89), -269, -62},
+ {GRISU_UINT64_C(0xcdb02555, 653131b6), -263, -60},
+ {GRISU_UINT64_C(0xa0b19d2a, b70e6ed6), -256, -58},
+ {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+ {GRISU_UINT64_C(0xc428d05a, a4751e4d), -243, -54},
+ {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
+ {GRISU_UINT64_C(0xef73d256, a5c0f77d), -230, -50},
+ {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+ {GRISU_UINT64_C(0x92267121, 62ab070e), -216, -46},
+ {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+ {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
+ {GRISU_UINT64_C(0x8b61313b, babce2c6), -196, -40},
+ {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+ {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
+ {GRISU_UINT64_C(0x84ec3c97, da624ab5), -176, -34},
+ {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
+ {GRISU_UINT64_C(0xa2425ff7, 5e14fc32), -163, -30},
+ {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+ {GRISU_UINT64_C(0xc6120625, 76589ddb), -150, -26},
+ {GRISU_UINT64_C(0x9abe14cd, 44753b53), -143, -24},
+ {GRISU_UINT64_C(0xf1c90080, baf72cb1), -137, -22},
+ {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+ {GRISU_UINT64_C(0x9392ee8e, 921d5d07), -123, -18},
+ {GRISU_UINT64_C(0xe69594be, c44de15b), -117, -16},
+ {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
+ {GRISU_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
+ {GRISU_UINT64_C(0xdbe6fece, bdedd5bf), -97, -10},
+ {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+ {GRISU_UINT64_C(0x8637bd05, af6c69b6), -83, -6},
+ {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
+ {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+ {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
+ {GRISU_UINT64_C(0xc8000000, 00000000), -57, 2},
+ {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+ {GRISU_UINT64_C(0xf4240000, 00000000), -44, 6},
+ {GRISU_UINT64_C(0xbebc2000, 00000000), -37, 8},
+ {GRISU_UINT64_C(0x9502f900, 00000000), -30, 10},
+ {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+ {GRISU_UINT64_C(0xb5e620f4, 80000000), -17, 14},
+ {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+ {GRISU_UINT64_C(0xde0b6b3a, 76400000), -4, 18},
+ {GRISU_UINT64_C(0xad78ebc5, ac620000), 3, 20},
+ {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+ {GRISU_UINT64_C(0xd3c21bce, cceda100), 16, 24},
+ {GRISU_UINT64_C(0xa56fa5b9, 9019a5c8), 23, 26},
+ {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+ {GRISU_UINT64_C(0xc9f2c9cd, 04674edf), 36, 30},
+ {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+ {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+ {GRISU_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
+ {GRISU_UINT64_C(0x96769950, b50d88f4), 63, 38},
+ {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
+ {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
+ {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
+ {GRISU_UINT64_C(0xe0352f62, a19e306f), 89, 46},
+ {GRISU_UINT64_C(0xaf298d05, 0e4395d7), 96, 48},
+ {GRISU_UINT64_C(0x88d8762b, f324cd10), 103, 50},
+ {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {GRISU_UINT64_C(0xa70c3c40, a64e6c52), 116, 54},
+ {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
+ {GRISU_UINT64_C(0xcbea6f8c, eb02bb3a), 129, 58},
+ {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
+ {GRISU_UINT64_C(0xf8ebad2b, 84e0d58c), 142, 62},
+ {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
+ {GRISU_UINT64_C(0x97edd871, cfda3a57), 156, 66},
+ {GRISU_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
+ {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+ {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+ {GRISU_UINT64_C(0xe264589a, 4dcdab15), 182, 74},
+ {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+ {GRISU_UINT64_C(0x8a2dbf14, 2dfcc7ab), 196, 78},
+ {GRISU_UINT64_C(0xd7e77a8f, 87daf7fc), 202, 80},
+ {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+ {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
+ {GRISU_UINT64_C(0xcde6fd5e, 09abcf27), 222, 86},
+ {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+ {GRISU_UINT64_C(0xfb587849, 4ace3a5f), 235, 90},
+ {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+ {GRISU_UINT64_C(0x9968bf6a, bbe85f20), 249, 94},
+ {GRISU_UINT64_C(0xefb3ab16, c59b14a3), 255, 96},
+ {GRISU_UINT64_C(0xbb445da9, ca61281f), 262, 98},
+ {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+ {GRISU_UINT64_C(0xe498f455, c38b997a), 275, 102},
+ {GRISU_UINT64_C(0xb2977ee3, 00c50fe7), 282, 104},
+ {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
+ {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
+ {GRISU_UINT64_C(0xaa51823e, 34a7eedf), 302, 110},
+ {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+ {GRISU_UINT64_C(0xcfe87f7c, ef46ff17), 315, 114},
+ {GRISU_UINT64_C(0xa26da399, 9aef774a), 322, 116},
+ {GRISU_UINT64_C(0xfdcb4fa0, 02162a63), 328, 118},
+ {GRISU_UINT64_C(0xc646d635, 01a1511e), 335, 120},
+ {GRISU_UINT64_C(0x9ae75759, 6946075f), 342, 122},
+ {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+ {GRISU_UINT64_C(0xbd176620, a501fc00), 355, 126},
+ {GRISU_UINT64_C(0x93ba47c9, 80e98ce0), 362, 128},
+ {GRISU_UINT64_C(0xe6d3102a, d96cec1e), 368, 130},
+ {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+ {GRISU_UINT64_C(0x8ce2529e, 2734bb1d), 382, 134},
+ {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
+ {GRISU_UINT64_C(0xabfa45da, 0edbde69), 395, 138},
+ {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+ {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+ {GRISU_UINT64_C(0xa402b9c5, a8d3a6e7), 415, 144},
+ {GRISU_UINT64_C(0x80222122, 6be55a65), 422, 146},
+ {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+ {GRISU_UINT64_C(0x9c69a972, 84b578d8), 435, 150},
+ {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
+ {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+ {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
+ {GRISU_UINT64_C(0xe912b9d1, 478ceb17), 461, 158},
+ {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+ {GRISU_UINT64_C(0x8e41ade9, fbebc27d), 475, 162},
+ {GRISU_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
+ {GRISU_UINT64_C(0xada72ccc, 20054aea), 488, 166},
+ {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
+ {GRISU_UINT64_C(0xd3fa922f, 2d1675f2), 501, 170},
+ {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+ {GRISU_UINT64_C(0x8161afb9, 4b44f57d), 515, 174},
+ {GRISU_UINT64_C(0xca28a291, 859bbf93), 521, 176},
+ {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
+ {GRISU_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
+ {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
+ {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
+ {GRISU_UINT64_C(0xeb57ff22, fc0c795a), 554, 186},
+ {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
+ {GRISU_UINT64_C(0x8fa47579, 1a569d11), 568, 190},
+ {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
+ {GRISU_UINT64_C(0xaf584166, 54a6babb), 581, 194},
+ {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+ {GRISU_UINT64_C(0xd60b3bd5, 6a5586f2), 594, 198},
+ {GRISU_UINT64_C(0xa738c6be, bb12d16d), 601, 200},
+ {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+ {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
+ {GRISU_UINT64_C(0x9f79a169, bd203e41), 621, 206},
+ {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
+ {GRISU_UINT64_C(0xc2abf989, 935ddbfe), 634, 210},
+ {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+ {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
+ {GRISU_UINT64_C(0xb9a74a06, 37ce2ee1), 654, 216},
+ {GRISU_UINT64_C(0x910ab1d4, db9914a0), 661, 218},
+ {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+ {GRISU_UINT64_C(0xb10d8e14, 56105dad), 674, 222},
+ {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
+ {GRISU_UINT64_C(0xd8210bef, d30efa5a), 687, 226},
+ {GRISU_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
+ {GRISU_UINT64_C(0x83ea2b89, 2091e44e), 701, 230},
+ {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+ {GRISU_UINT64_C(0xa1075a24, e4421731), 714, 234},
+ {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
+ {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+ {GRISU_UINT64_C(0x9991a6f3, d6bf1766), 734, 240},
+ {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
+ {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+ {GRISU_UINT64_C(0x92746b9b, e2f8552c), 754, 246},
+ {GRISU_UINT64_C(0xe4d5e823, 92a40515), 760, 248},
+ {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
+ {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+ {GRISU_UINT64_C(0xda3c0f56, 8cc4f3e9), 780, 254},
+ {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
+ {GRISU_UINT64_C(0x8533285c, 936b35df), 794, 258},
+ {GRISU_UINT64_C(0xd01fef10, a657842c), 800, 260},
+ {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+ {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
+ {GRISU_UINT64_C(0xc67bb459, 7ce2ce49), 820, 266},
+ {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+ {GRISU_UINT64_C(0xf24a01a7, 3cf2dcd0), 833, 270},
+ {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
+ {GRISU_UINT64_C(0x93e1ab82, 52f33b46), 847, 274},
+ {GRISU_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
+ {GRISU_UINT64_C(0xb484f9dc, 9641e9db), 860, 278},
+ {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+ {GRISU_UINT64_C(0xdc5c5301, c56b75f7), 873, 282},
+ {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
+ {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+ {GRISU_UINT64_C(0xd226fc19, 5c6a2f8c), 893, 288},
+ {GRISU_UINT64_C(0xa42e74f3, d032f526), 900, 290},
+ {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {GRISU_UINT64_C(0xc86ab5c3, 9fa63441), 913, 294},
+ {GRISU_UINT64_C(0x9c935e00, d4b9d8d2), 920, 296},
+ {GRISU_UINT64_C(0xf4a642e1, 4c6262c9), 926, 298},
+ {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
+ {GRISU_UINT64_C(0x95527a52, 02df0ccb), 940, 302},
+ {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+ {GRISU_UINT64_C(0xb6472e51, 1c81471e), 953, 306},
+ {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+ {GRISU_UINT64_C(0xde81e40a, 034bcf50), 966, 310},
+ {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
+ {GRISU_UINT64_C(0x87cec76f, 1c830549), 980, 314},
+ {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+ {GRISU_UINT64_C(0xa5c7ea73, 224deff3), 993, 318},
+ {GRISU_UINT64_C(0x81842f29, f2cce376), 1000, 320},
+ {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+ {GRISU_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
+ {GRISU_UINT64_C(0xf7086715, 3aa2db39), 1019, 326},
+ {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
+ {GRISU_UINT64_C(0x96c6e0ea, b509e64d), 1033, 330},
+ {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+ {GRISU_UINT64_C(0xb80dc58e, 81fe95a1), 1046, 334},
+ {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
+ {GRISU_UINT64_C(0xe0accfa8, 75af45a8), 1059, 338},
+ {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+ {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(2) = 7;
+// nb elements (2): 326
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(3)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0xe0b62e29, 29aba83c), -1077, -305},
+ {GRISU_UINT64_C(0xdb71e914, 32b1a24b), -1067, -302},
+ {GRISU_UINT64_C(0xd64d3d9d, b981787d), -1057, -299},
+ {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
+ {GRISU_UINT64_C(0xcc5fc196, fefd7d0c), -1037, -293},
+ {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
+ {GRISU_UINT64_C(0xc2e801fb, 244576d5), -1017, -287},
+ {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+ {GRISU_UINT64_C(0xb9e08a83, a5e34f08), -997, -281},
+ {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+ {GRISU_UINT64_C(0xb1442798, f49ffb4b), -977, -275},
+ {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+ {GRISU_UINT64_C(0xa90de353, 5aaae202), -957, -269},
+ {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
+ {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
+ {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+ {GRISU_UINT64_C(0x99c10284, 4f94e0fb), -917, -257},
+ {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
+ {GRISU_UINT64_C(0x92a1958a, 7675175f), -897, -251},
+ {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+ {GRISU_UINT64_C(0x8bd6a141, 006042be), -877, -245},
+ {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
+ {GRISU_UINT64_C(0x855c3be0, a17fcd26), -857, -239},
+ {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+ {GRISU_UINT64_C(0xfe5d5415, 0b090b03), -838, -233},
+ {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
+ {GRISU_UINT64_C(0xf294b943, e17a2bc4), -818, -227},
+ {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+ {GRISU_UINT64_C(0xe757dd7e, c07426e5), -798, -221},
+ {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+ {GRISU_UINT64_C(0xdca04777, f541c568), -778, -215},
+ {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+ {GRISU_UINT64_C(0xd267caa8, 62a12d67), -758, -209},
+ {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
+ {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
+ {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+ {GRISU_UINT64_C(0xbf5cd546, 78eef0b7), -718, -197},
+ {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
+ {GRISU_UINT64_C(0xb67f6455, 292cbf08), -698, -191},
+ {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+ {GRISU_UINT64_C(0xae0b158b, 4738705f), -678, -185},
+ {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+ {GRISU_UINT64_C(0xa5fb0a17, c777cf0a), -658, -179},
+ {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+ {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
+ {GRISU_UINT64_C(0x9a94dd3e, 8cf578ba), -628, -170},
+ {GRISU_UINT64_C(0x96f5600f, 15a7b7e5), -618, -167},
+ {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+ {GRISU_UINT64_C(0x8ff71a0f, e2c2e6dc), -598, -161},
+ {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+ {GRISU_UINT64_C(0x894bc396, ce5da772), -578, -155},
+ {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+ {GRISU_UINT64_C(0x82ef8513, 3de648c5), -558, -149},
+ {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
+ {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
+ {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+ {GRISU_UINT64_C(0xee2ba6c0, 678b597f), -519, -137},
+ {GRISU_UINT64_C(0xe896a0d7, e51e1566), -509, -134},
+ {GRISU_UINT64_C(0xe3231912, d5bf60e6), -499, -131},
+ {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+ {GRISU_UINT64_C(0xd89d64d5, 7a607745), -479, -125},
+ {GRISU_UINT64_C(0xd389b478, 79823479), -469, -122},
+ {GRISU_UINT64_C(0xce947a3d, a6a9273e), -459, -119},
+ {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+ {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
+ {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+ {GRISU_UINT64_C(0xbbe226ef, b628afeb), -419, -107},
+ {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+ {GRISU_UINT64_C(0xb32df8e9, f3546564), -399, -101},
+ {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+ {GRISU_UINT64_C(0xaae103b5, fcd2a882), -379, -95},
+ {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+ {GRISU_UINT64_C(0xa2f67f2d, fa90563b), -359, -89},
+ {GRISU_UINT64_C(0x9f24b832, e6b0f436), -349, -86},
+ {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
+ {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+ {GRISU_UINT64_C(0x9436c076, 0c86e30c), -319, -77},
+ {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+ {GRISU_UINT64_C(0x8d590723, 948a535f), -299, -71},
+ {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {GRISU_UINT64_C(0x86ccbb52, ea94baeb), -279, -65},
+ {GRISU_UINT64_C(0x83a3eeee, f9153e89), -269, -62},
+ {GRISU_UINT64_C(0x808e1755, 5f3ebf12), -259, -59},
+ {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+ {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
+ {GRISU_UINT64_C(0xef73d256, a5c0f77d), -230, -50},
+ {GRISU_UINT64_C(0xe9d71b68, 9dde71b0), -220, -47},
+ {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+ {GRISU_UINT64_C(0xdf01e85f, 912e37a3), -200, -41},
+ {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+ {GRISU_UINT64_C(0xd4ad2dbf, c3d07788), -180, -35},
+ {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
+ {GRISU_UINT64_C(0xcad2f7f5, 359a3b3e), -160, -29},
+ {GRISU_UINT64_C(0xc6120625, 76589ddb), -150, -26},
+ {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
+ {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+ {GRISU_UINT64_C(0xb877aa32, 36a4b449), -120, -17},
+ {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
+ {GRISU_UINT64_C(0xafebff0b, cb24aaff), -100, -11},
+ {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+ {GRISU_UINT64_C(0xa7c5ac47, 1b478423), -80, -5},
+ {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+ {GRISU_UINT64_C(0xa0000000, 00000000), -60, 1},
+ {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+ {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
+ {GRISU_UINT64_C(0x9502f900, 00000000), -30, 10},
+ {GRISU_UINT64_C(0x9184e72a, 00000000), -20, 13},
+ {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+ {GRISU_UINT64_C(0x8ac72304, 89e80000), 0, 19},
+ {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+ {GRISU_UINT64_C(0x84595161, 401484a0), 20, 25},
+ {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+ {GRISU_UINT64_C(0xfc6f7c40, 45812296), 39, 31},
+ {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+ {GRISU_UINT64_C(0xf0bdc21a, bb48db20), 59, 37},
+ {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
+ {GRISU_UINT64_C(0xe596b7b0, c643c719), 79, 43},
+ {GRISU_UINT64_C(0xe0352f62, a19e306f), 89, 46},
+ {GRISU_UINT64_C(0xdaf3f046, 51d47b4c), 99, 49},
+ {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {GRISU_UINT64_C(0xd0cf4b50, cfe20766), 119, 55},
+ {GRISU_UINT64_C(0xcbea6f8c, eb02bb3a), 129, 58},
+ {GRISU_UINT64_C(0xc722f0ef, 9d80aad6), 139, 61},
+ {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
+ {GRISU_UINT64_C(0xbde94e8e, 43d0c8ec), 159, 67},
+ {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+ {GRISU_UINT64_C(0xb51d13ae, a4a488dd), 179, 73},
+ {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+ {GRISU_UINT64_C(0xacb92ed9, 397bf996), 199, 79},
+ {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+ {GRISU_UINT64_C(0xa4b8cab1, a1563f52), 219, 85},
+ {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+ {GRISU_UINT64_C(0x9d174b2d, cec0e47b), 239, 91},
+ {GRISU_UINT64_C(0x9968bf6a, bbe85f20), 249, 94},
+ {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
+ {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+ {GRISU_UINT64_C(0x8edf98b5, 9a373fec), 279, 103},
+ {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
+ {GRISU_UINT64_C(0x884134fe, 908658b2), 299, 109},
+ {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+ {GRISU_UINT64_C(0x81f14fae, 158c5f6e), 319, 115},
+ {GRISU_UINT64_C(0xfdcb4fa0, 02162a63), 328, 118},
+ {GRISU_UINT64_C(0xf7d88bc2, 4209a565), 338, 121},
+ {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+ {GRISU_UINT64_C(0xec5d3fa8, ce427b00), 358, 127},
+ {GRISU_UINT64_C(0xe6d3102a, d96cec1e), 368, 130},
+ {GRISU_UINT64_C(0xe16a1dc9, d8545e95), 378, 133},
+ {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
+ {GRISU_UINT64_C(0xd6f8d750, 9292d603), 398, 139},
+ {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+ {GRISU_UINT64_C(0xcd036837, 130890a1), 418, 145},
+ {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+ {GRISU_UINT64_C(0xc38413cf, 25e2d70e), 438, 151},
+ {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+ {GRISU_UINT64_C(0xba756174, 393d88e0), 458, 157},
+ {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+ {GRISU_UINT64_C(0xb1d21964, 7ae6b31c), 478, 163},
+ {GRISU_UINT64_C(0xada72ccc, 20054aea), 488, 166},
+ {GRISU_UINT64_C(0xa99541bf, 57452b28), 498, 169},
+ {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+ {GRISU_UINT64_C(0xa1ba1ba7, 9e1632dc), 518, 175},
+ {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
+ {GRISU_UINT64_C(0x9a3c2087, a63f6399), 538, 181},
+ {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
+ {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
+ {GRISU_UINT64_C(0x8fa47579, 1a569d11), 568, 190},
+ {GRISU_UINT64_C(0x8c469ab8, 43b89563), 578, 193},
+ {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+ {GRISU_UINT64_C(0x85c70565, 62757457), 598, 199},
+ {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+ {GRISU_UINT64_C(0xff290242, c83396ce), 617, 205},
+ {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
+ {GRISU_UINT64_C(0xf356f7eb, f83552fe), 637, 211},
+ {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
+ {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
+ {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+ {GRISU_UINT64_C(0xdd50f199, 6b947519), 677, 223},
+ {GRISU_UINT64_C(0xd8210bef, d30efa5a), 687, 226},
+ {GRISU_UINT64_C(0xd31045a8, 341ca07c), 697, 229},
+ {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+ {GRISU_UINT64_C(0xc94930ae, 1d529cfd), 717, 235},
+ {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+ {GRISU_UINT64_C(0xbff610b0, cc6edd3f), 737, 241},
+ {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+ {GRISU_UINT64_C(0xb7118682, dbb66a77), 757, 247},
+ {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
+ {GRISU_UINT64_C(0xae9672ab, a3d0c321), 777, 253},
+ {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
+ {GRISU_UINT64_C(0xa67ff273, b8460357), 797, 259},
+ {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+ {GRISU_UINT64_C(0x9ec95d14, 63e8a507), 817, 265},
+ {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+ {GRISU_UINT64_C(0x976e4108, 8617ca02), 837, 271},
+ {GRISU_UINT64_C(0x93e1ab82, 52f33b46), 847, 274},
+ {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
+ {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+ {GRISU_UINT64_C(0x89b9b3e1, 1b6329bb), 877, 283},
+ {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+ {GRISU_UINT64_C(0x83585d8f, d9c25db8), 897, 289},
+ {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {GRISU_UINT64_C(0xfa856334, 878fc151), 916, 295},
+ {GRISU_UINT64_C(0xf4a642e1, 4c6262c9), 926, 298},
+ {GRISU_UINT64_C(0xeeea5d50, 04981478), 936, 301},
+ {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+ {GRISU_UINT64_C(0xe3d8f9e5, 63a198e5), 956, 307},
+ {GRISU_UINT64_C(0xde81e40a, 034bcf50), 966, 310},
+ {GRISU_UINT64_C(0xd94ad8b1, c7380874), 976, 313},
+ {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+ {GRISU_UINT64_C(0xcf39e50f, eae16bf0), 996, 319},
+ {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+ {GRISU_UINT64_C(0xc5a05277, 621be294), 1016, 325},
+ {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
+ {GRISU_UINT64_C(0xbc789925, 624c5fe1), 1036, 331},
+ {GRISU_UINT64_C(0xb80dc58e, 81fe95a1), 1046, 334},
+ {GRISU_UINT64_C(0xb3bd72ed, 2af29e20), 1056, 337},
+ {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(3) = 10;
+// nb elements (3): 217
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(4)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0x8c71dcd9, ba0b4926), -1073, -304},
+ {GRISU_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
+ {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
+ {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
+ {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
+ {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+ {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
+ {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
+ {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+ {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+ {GRISU_UINT64_C(0x80fa687f, 881c7f8e), -940, -264},
+ {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+ {GRISU_UINT64_C(0xc0314325, 637a193a), -914, -256},
+ {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
+ {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+ {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
+ {GRISU_UINT64_C(0xd5605fcd, cf32e1d7), -861, -240},
+ {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+ {GRISU_UINT64_C(0x9efa548d, 26e5a6e2), -834, -232},
+ {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+ {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+ {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
+ {GRISU_UINT64_C(0xb080392c, c4349ded), -781, -216},
+ {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+ {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
+ {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
+ {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+ {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+ {GRISU_UINT64_C(0x91ff8377, 5423cc06), -701, -192},
+ {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+ {GRISU_UINT64_C(0xd98ddaee, 19068c76), -675, -184},
+ {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
+ {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+ {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
+ {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+ {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+ {GRISU_UINT64_C(0xb3f4e093, db73a093), -595, -160},
+ {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
+ {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+ {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+ {GRISU_UINT64_C(0xc7caba6e, 7c5382c9), -542, -144},
+ {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+ {GRISU_UINT64_C(0x94db4838, 40b717f0), -515, -136},
+ {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
+ {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+ {GRISU_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
+ {GRISU_UINT64_C(0xa54394fe, 1eedb8ff), -462, -120},
+ {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+ {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
+ {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+ {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+ {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
+ {GRISU_UINT64_C(0x88b402f7, fd75539b), -382, -96},
+ {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+ {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+ {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+ {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+ {GRISU_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
+ {GRISU_UINT64_C(0xe2280b6c, 20dd5232), -303, -72},
+ {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {GRISU_UINT64_C(0xa87fea27, a539e9a5), -276, -64},
+ {GRISU_UINT64_C(0xcdb02555, 653131b6), -263, -60},
+ {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+ {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
+ {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+ {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+ {GRISU_UINT64_C(0x8b61313b, babce2c6), -196, -40},
+ {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
+ {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
+ {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+ {GRISU_UINT64_C(0x9abe14cd, 44753b53), -143, -24},
+ {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+ {GRISU_UINT64_C(0xe69594be, c44de15b), -117, -16},
+ {GRISU_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
+ {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+ {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
+ {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
+ {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+ {GRISU_UINT64_C(0xbebc2000, 00000000), -37, 8},
+ {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+ {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+ {GRISU_UINT64_C(0xad78ebc5, ac620000), 3, 20},
+ {GRISU_UINT64_C(0xd3c21bce, cceda100), 16, 24},
+ {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+ {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+ {GRISU_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
+ {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
+ {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
+ {GRISU_UINT64_C(0xaf298d05, 0e4395d7), 96, 48},
+ {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
+ {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
+ {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
+ {GRISU_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
+ {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+ {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+ {GRISU_UINT64_C(0xd7e77a8f, 87daf7fc), 202, 80},
+ {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
+ {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+ {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+ {GRISU_UINT64_C(0xefb3ab16, c59b14a3), 255, 96},
+ {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+ {GRISU_UINT64_C(0xb2977ee3, 00c50fe7), 282, 104},
+ {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
+ {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+ {GRISU_UINT64_C(0xa26da399, 9aef774a), 322, 116},
+ {GRISU_UINT64_C(0xc646d635, 01a1511e), 335, 120},
+ {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+ {GRISU_UINT64_C(0x93ba47c9, 80e98ce0), 362, 128},
+ {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+ {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
+ {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+ {GRISU_UINT64_C(0xa402b9c5, a8d3a6e7), 415, 144},
+ {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+ {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
+ {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
+ {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+ {GRISU_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
+ {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
+ {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+ {GRISU_UINT64_C(0xca28a291, 859bbf93), 521, 176},
+ {GRISU_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
+ {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
+ {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
+ {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
+ {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+ {GRISU_UINT64_C(0xa738c6be, bb12d16d), 601, 200},
+ {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
+ {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
+ {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+ {GRISU_UINT64_C(0xb9a74a06, 37ce2ee1), 654, 216},
+ {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+ {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
+ {GRISU_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
+ {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+ {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
+ {GRISU_UINT64_C(0x9991a6f3, d6bf1766), 734, 240},
+ {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+ {GRISU_UINT64_C(0xe4d5e823, 92a40515), 760, 248},
+ {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+ {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
+ {GRISU_UINT64_C(0xd01fef10, a657842c), 800, 260},
+ {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
+ {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+ {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
+ {GRISU_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
+ {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+ {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
+ {GRISU_UINT64_C(0xd226fc19, 5c6a2f8c), 893, 288},
+ {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {GRISU_UINT64_C(0x9c935e00, d4b9d8d2), 920, 296},
+ {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
+ {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+ {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+ {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
+ {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+ {GRISU_UINT64_C(0x81842f29, f2cce376), 1000, 320},
+ {GRISU_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
+ {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
+ {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+ {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
+ {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(4) = 14;
+// nb elements (4): 163
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(5)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0xaf8e5410, 288e1b6f), -1070, -303},
+ {GRISU_UINT64_C(0x85f04682, 93f0eb4e), -1053, -298},
+ {GRISU_UINT64_C(0xcc5fc196, fefd7d0c), -1037, -293},
+ {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
+ {GRISU_UINT64_C(0xedec366b, 11c6cb8f), -1004, -283},
+ {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+ {GRISU_UINT64_C(0x8a7d3eef, 7f1cfc52), -970, -273},
+ {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+ {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
+ {GRISU_UINT64_C(0xf6019da0, 7f549b2b), -921, -258},
+ {GRISU_UINT64_C(0xbbb01b92, 83253ca3), -904, -253},
+ {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+ {GRISU_UINT64_C(0xda7f5bf5, 90966849), -871, -243},
+ {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
+ {GRISU_UINT64_C(0xfe5d5415, 0b090b03), -838, -233},
+ {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+ {GRISU_UINT64_C(0x940f4613, ae5ed137), -804, -223},
+ {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+ {GRISU_UINT64_C(0xac5d37d5, b79b6239), -771, -213},
+ {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
+ {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
+ {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
+ {GRISU_UINT64_C(0xe998d258, 869facd7), -705, -193},
+ {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+ {GRISU_UINT64_C(0x87f8a8d4, cfa417ca), -671, -183},
+ {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
+ {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
+ {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+ {GRISU_UINT64_C(0xb84687c2, 69ef3bfb), -605, -163},
+ {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+ {GRISU_UINT64_C(0xd686619b, a27255a3), -572, -153},
+ {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+ {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
+ {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
+ {GRISU_UINT64_C(0x915e2486, ef32cd60), -505, -133},
+ {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+ {GRISU_UINT64_C(0xa93af6c6, c79b5d2e), -472, -123},
+ {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
+ {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
+ {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+ {GRISU_UINT64_C(0xe5599087, 9ddcaabe), -406, -103},
+ {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+ {GRISU_UINT64_C(0x857fcae6, 2d8493a5), -372, -93},
+ {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+ {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
+ {GRISU_UINT64_C(0xed246723, 473e3813), -323, -78},
+ {GRISU_UINT64_C(0xb4ecd5f0, 1a4aa828), -306, -73},
+ {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {GRISU_UINT64_C(0xd29fe4b1, 8e88640f), -273, -63},
+ {GRISU_UINT64_C(0xa0b19d2a, b70e6ed6), -256, -58},
+ {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
+ {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+ {GRISU_UINT64_C(0x8eb98a7a, 9a5b04e3), -206, -43},
+ {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+ {GRISU_UINT64_C(0xa6274bbd, d0fadd62), -173, -33},
+ {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+ {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
+ {GRISU_UINT64_C(0x9392ee8e, 921d5d07), -123, -18},
+ {GRISU_UINT64_C(0xe12e1342, 4bb40e13), -107, -13},
+ {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+ {GRISU_UINT64_C(0x83126e97, 8d4fdf3b), -73, -3},
+ {GRISU_UINT64_C(0xc8000000, 00000000), -57, 2},
+ {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
+ {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+ {GRISU_UINT64_C(0xb1a2bc2e, c5000000), -7, 17},
+ {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+ {GRISU_UINT64_C(0xcecb8f27, f4200f3a), 26, 27},
+ {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+ {GRISU_UINT64_C(0xf0bdc21a, bb48db20), 59, 37},
+ {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
+ {GRISU_UINT64_C(0x8c213d9d, a502de45), 93, 47},
+ {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {GRISU_UINT64_C(0xa321f2d7, 226895c8), 126, 57},
+ {GRISU_UINT64_C(0xf8ebad2b, 84e0d58c), 142, 62},
+ {GRISU_UINT64_C(0xbde94e8e, 43d0c8ec), 159, 67},
+ {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+ {GRISU_UINT64_C(0xdd15fe86, affad912), 192, 77},
+ {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+ {GRISU_UINT64_C(0x80b05e5a, c60b6178), 226, 87},
+ {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+ {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
+ {GRISU_UINT64_C(0xe498f455, c38b997a), 275, 102},
+ {GRISU_UINT64_C(0xae67f1e9, aec07188), 292, 107},
+ {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+ {GRISU_UINT64_C(0xcb090c80, 01ab551c), 325, 117},
+ {GRISU_UINT64_C(0x9ae75759, 6946075f), 342, 122},
+ {GRISU_UINT64_C(0xec5d3fa8, ce427b00), 358, 127},
+ {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+ {GRISU_UINT64_C(0x899504ae, 72497eba), 392, 137},
+ {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+ {GRISU_UINT64_C(0xa02aa96b, 06deb0fe), 425, 147},
+ {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
+ {GRISU_UINT64_C(0xba756174, 393d88e0), 458, 157},
+ {GRISU_UINT64_C(0x8e41ade9, fbebc27d), 475, 162},
+ {GRISU_UINT64_C(0xd910f7ff, 28069da4), 491, 167},
+ {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+ {GRISU_UINT64_C(0xfcb2cb35, e702af78), 524, 177},
+ {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
+ {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
+ {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
+ {GRISU_UINT64_C(0xab3c2fdd, eeaad25b), 591, 197},
+ {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+ {GRISU_UINT64_C(0xc75809c4, 2c684dd1), 624, 207},
+ {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+ {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
+ {GRISU_UINT64_C(0xb10d8e14, 56105dad), 674, 222},
+ {GRISU_UINT64_C(0x8714a775, e3e95c78), 691, 227},
+ {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+ {GRISU_UINT64_C(0x9d412e08, 06e88aa6), 724, 237},
+ {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
+ {GRISU_UINT64_C(0xb7118682, dbb66a77), 757, 247},
+ {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+ {GRISU_UINT64_C(0xd51ea6fa, 85785631), 790, 257},
+ {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+ {GRISU_UINT64_C(0xf81aa16f, dc1b81db), 823, 267},
+ {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
+ {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
+ {GRISU_UINT64_C(0xdc5c5301, c56b75f7), 873, 282},
+ {GRISU_UINT64_C(0xa81f3014, 49ee8c70), 890, 287},
+ {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {GRISU_UINT64_C(0xc3b83581, 09e84f07), 923, 297},
+ {GRISU_UINT64_C(0x95527a52, 02df0ccb), 940, 302},
+ {GRISU_UINT64_C(0xe3d8f9e5, 63a198e5), 956, 307},
+ {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
+ {GRISU_UINT64_C(0x849feec2, 81d7f329), 990, 317},
+ {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+ {GRISU_UINT64_C(0x9a65406d, 44a5c903), 1023, 327},
+ {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+ {GRISU_UINT64_C(0xb3bd72ed, 2af29e20), 1056, 337},
+ {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(5) = 17;
+// nb elements (5): 131
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(6)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0xdb71e914, 32b1a24b), -1067, -302},
+ {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
+ {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
+ {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+ {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+ {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+ {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
+ {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+ {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
+ {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+ {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
+ {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+ {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
+ {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+ {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+ {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+ {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
+ {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+ {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
+ {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+ {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+ {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+ {GRISU_UINT64_C(0x9a94dd3e, 8cf578ba), -628, -170},
+ {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+ {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+ {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+ {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
+ {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+ {GRISU_UINT64_C(0xe896a0d7, e51e1566), -509, -134},
+ {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+ {GRISU_UINT64_C(0xd389b478, 79823479), -469, -122},
+ {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+ {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+ {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+ {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+ {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+ {GRISU_UINT64_C(0x9f24b832, e6b0f436), -349, -86},
+ {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+ {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+ {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {GRISU_UINT64_C(0x83a3eeee, f9153e89), -269, -62},
+ {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+ {GRISU_UINT64_C(0xef73d256, a5c0f77d), -230, -50},
+ {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+ {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+ {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
+ {GRISU_UINT64_C(0xc6120625, 76589ddb), -150, -26},
+ {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+ {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
+ {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+ {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+ {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+ {GRISU_UINT64_C(0x9502f900, 00000000), -30, 10},
+ {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+ {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+ {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+ {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+ {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
+ {GRISU_UINT64_C(0xe0352f62, a19e306f), 89, 46},
+ {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {GRISU_UINT64_C(0xcbea6f8c, eb02bb3a), 129, 58},
+ {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
+ {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+ {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+ {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+ {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+ {GRISU_UINT64_C(0x9968bf6a, bbe85f20), 249, 94},
+ {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+ {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
+ {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+ {GRISU_UINT64_C(0xfdcb4fa0, 02162a63), 328, 118},
+ {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+ {GRISU_UINT64_C(0xe6d3102a, d96cec1e), 368, 130},
+ {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
+ {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+ {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+ {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+ {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+ {GRISU_UINT64_C(0xada72ccc, 20054aea), 488, 166},
+ {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+ {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
+ {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
+ {GRISU_UINT64_C(0x8fa47579, 1a569d11), 568, 190},
+ {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+ {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+ {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
+ {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
+ {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+ {GRISU_UINT64_C(0xd8210bef, d30efa5a), 687, 226},
+ {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+ {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+ {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+ {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
+ {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
+ {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+ {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+ {GRISU_UINT64_C(0x93e1ab82, 52f33b46), 847, 274},
+ {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+ {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+ {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {GRISU_UINT64_C(0xf4a642e1, 4c6262c9), 926, 298},
+ {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+ {GRISU_UINT64_C(0xde81e40a, 034bcf50), 966, 310},
+ {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+ {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+ {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
+ {GRISU_UINT64_C(0xb80dc58e, 81fe95a1), 1046, 334},
+ {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(6) = 20;
+// nb elements (6): 109
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(7)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0x892731ac, 9faf056f), -1063, -301},
+ {GRISU_UINT64_C(0xa37fce12, 6597973d), -1040, -294},
+ {GRISU_UINT64_C(0xc2e801fb, 244576d5), -1017, -287},
+ {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
+ {GRISU_UINT64_C(0x8a7d3eef, 7f1cfc52), -970, -273},
+ {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
+ {GRISU_UINT64_C(0xc4ce17b3, 99107c23), -924, -259},
+ {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
+ {GRISU_UINT64_C(0x8bd6a141, 006042be), -877, -245},
+ {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
+ {GRISU_UINT64_C(0xc6b8e9b0, 709f109a), -831, -231},
+ {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+ {GRISU_UINT64_C(0x8d3360f0, 9cf6e4bd), -784, -217},
+ {GRISU_UINT64_C(0xa8530886, b54dbdec), -761, -210},
+ {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
+ {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+ {GRISU_UINT64_C(0x8e938662, 882af53e), -691, -189},
+ {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+ {GRISU_UINT64_C(0xca9cf1d2, 06fdc03c), -645, -175},
+ {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+ {GRISU_UINT64_C(0x8ff71a0f, e2c2e6dc), -598, -161},
+ {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
+ {GRISU_UINT64_C(0xcc963fee, 10b7d1b3), -552, -147},
+ {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+ {GRISU_UINT64_C(0x915e2486, ef32cd60), -505, -133},
+ {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
+ {GRISU_UINT64_C(0xce947a3d, a6a9273e), -459, -119},
+ {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
+ {GRISU_UINT64_C(0x92c8ae6b, 464fc96f), -412, -105},
+ {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+ {GRISU_UINT64_C(0xd097ad07, a71f26b2), -366, -91},
+ {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+ {GRISU_UINT64_C(0x9436c076, 0c86e30c), -319, -77},
+ {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
+ {GRISU_UINT64_C(0xd29fe4b1, 8e88640f), -273, -63},
+ {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+ {GRISU_UINT64_C(0x95a86376, 27989aae), -226, -49},
+ {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
+ {GRISU_UINT64_C(0xd4ad2dbf, c3d07788), -180, -35},
+ {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+ {GRISU_UINT64_C(0x971da050, 74da7bef), -133, -21},
+ {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
+ {GRISU_UINT64_C(0xd6bf94d5, e57a42bc), -87, -7},
+ {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
+ {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
+ {GRISU_UINT64_C(0xb5e620f4, 80000000), -17, 14},
+ {GRISU_UINT64_C(0xd8d726b7, 177a8000), 6, 21},
+ {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+ {GRISU_UINT64_C(0x9a130b96, 3a6c115c), 53, 35},
+ {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
+ {GRISU_UINT64_C(0xdaf3f046, 51d47b4c), 99, 49},
+ {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
+ {GRISU_UINT64_C(0x9b934c3b, 330c8577), 146, 63},
+ {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+ {GRISU_UINT64_C(0xdd15fe86, affad912), 192, 77},
+ {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
+ {GRISU_UINT64_C(0x9d174b2d, cec0e47b), 239, 91},
+ {GRISU_UINT64_C(0xbb445da9, ca61281f), 262, 98},
+ {GRISU_UINT64_C(0xdf3d5e9b, c0f653e1), 285, 105},
+ {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+ {GRISU_UINT64_C(0x9e9f11c4, 014dda7e), 332, 119},
+ {GRISU_UINT64_C(0xbd176620, a501fc00), 355, 126},
+ {GRISU_UINT64_C(0xe16a1dc9, d8545e95), 378, 133},
+ {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+ {GRISU_UINT64_C(0xa02aa96b, 06deb0fe), 425, 147},
+ {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+ {GRISU_UINT64_C(0xe39c4976, 5fdf9d95), 471, 161},
+ {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
+ {GRISU_UINT64_C(0xa1ba1ba7, 9e1632dc), 518, 175},
+ {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
+ {GRISU_UINT64_C(0xe5d3ef28, 2a242e82), 564, 189},
+ {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+ {GRISU_UINT64_C(0xa34d7216, 42b06084), 611, 203},
+ {GRISU_UINT64_C(0xc2abf989, 935ddbfe), 634, 210},
+ {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
+ {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
+ {GRISU_UINT64_C(0xa4e4b66b, 68b65d61), 704, 231},
+ {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+ {GRISU_UINT64_C(0xea53df5f, d18d5514), 750, 245},
+ {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+ {GRISU_UINT64_C(0xa67ff273, b8460357), 797, 259},
+ {GRISU_UINT64_C(0xc67bb459, 7ce2ce49), 820, 266},
+ {GRISU_UINT64_C(0xec9c459d, 51852ba3), 843, 273},
+ {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+ {GRISU_UINT64_C(0xa81f3014, 49ee8c70), 890, 287},
+ {GRISU_UINT64_C(0xc86ab5c3, 9fa63441), 913, 294},
+ {GRISU_UINT64_C(0xeeea5d50, 04981478), 936, 301},
+ {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+ {GRISU_UINT64_C(0xa9c2794a, e3a3c69b), 983, 315},
+ {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+ {GRISU_UINT64_C(0xf13e34aa, bb430a15), 1029, 329},
+ {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(7) = 24;
+// nb elements (7): 93
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(8)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
+ {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
+ {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+ {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
+ {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+ {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+ {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
+ {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
+ {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+ {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+ {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
+ {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+ {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
+ {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+ {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+ {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
+ {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
+ {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+ {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
+ {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+ {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+ {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
+ {GRISU_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
+ {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+ {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+ {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
+ {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+ {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+ {GRISU_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
+ {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {GRISU_UINT64_C(0xcdb02555, 653131b6), -263, -60},
+ {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
+ {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+ {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
+ {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+ {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+ {GRISU_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
+ {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
+ {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+ {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+ {GRISU_UINT64_C(0xad78ebc5, ac620000), 3, 20},
+ {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+ {GRISU_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
+ {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
+ {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
+ {GRISU_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
+ {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+ {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
+ {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+ {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+ {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
+ {GRISU_UINT64_C(0xa26da399, 9aef774a), 322, 116},
+ {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+ {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+ {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+ {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+ {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
+ {GRISU_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
+ {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+ {GRISU_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
+ {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
+ {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+ {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
+ {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+ {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+ {GRISU_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
+ {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
+ {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+ {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+ {GRISU_UINT64_C(0xd01fef10, a657842c), 800, 260},
+ {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+ {GRISU_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
+ {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
+ {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
+ {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+ {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+ {GRISU_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
+ {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+ {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(8) = 27;
+// nb elements (8): 82
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(9)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0xd64d3d9d, b981787d), -1057, -299},
+ {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
+ {GRISU_UINT64_C(0xb9e08a83, a5e34f08), -997, -281},
+ {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+ {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
+ {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
+ {GRISU_UINT64_C(0x8bd6a141, 006042be), -877, -245},
+ {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+ {GRISU_UINT64_C(0xf294b943, e17a2bc4), -818, -227},
+ {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+ {GRISU_UINT64_C(0xd267caa8, 62a12d67), -758, -209},
+ {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+ {GRISU_UINT64_C(0xb67f6455, 292cbf08), -698, -191},
+ {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+ {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
+ {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+ {GRISU_UINT64_C(0x894bc396, ce5da772), -578, -155},
+ {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
+ {GRISU_UINT64_C(0xee2ba6c0, 678b597f), -519, -137},
+ {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+ {GRISU_UINT64_C(0xce947a3d, a6a9273e), -459, -119},
+ {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+ {GRISU_UINT64_C(0xb32df8e9, f3546564), -399, -101},
+ {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+ {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
+ {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+ {GRISU_UINT64_C(0x86ccbb52, ea94baeb), -279, -65},
+ {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+ {GRISU_UINT64_C(0xe9d71b68, 9dde71b0), -220, -47},
+ {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+ {GRISU_UINT64_C(0xcad2f7f5, 359a3b3e), -160, -29},
+ {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+ {GRISU_UINT64_C(0xafebff0b, cb24aaff), -100, -11},
+ {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+ {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
+ {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+ {GRISU_UINT64_C(0x84595161, 401484a0), 20, 25},
+ {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+ {GRISU_UINT64_C(0xe596b7b0, c643c719), 79, 43},
+ {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {GRISU_UINT64_C(0xc722f0ef, 9d80aad6), 139, 61},
+ {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+ {GRISU_UINT64_C(0xacb92ed9, 397bf996), 199, 79},
+ {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+ {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
+ {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
+ {GRISU_UINT64_C(0x81f14fae, 158c5f6e), 319, 115},
+ {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+ {GRISU_UINT64_C(0xe16a1dc9, d8545e95), 378, 133},
+ {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+ {GRISU_UINT64_C(0xc38413cf, 25e2d70e), 438, 151},
+ {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+ {GRISU_UINT64_C(0xa99541bf, 57452b28), 498, 169},
+ {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
+ {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
+ {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+ {GRISU_UINT64_C(0xff290242, c83396ce), 617, 205},
+ {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
+ {GRISU_UINT64_C(0xdd50f199, 6b947519), 677, 223},
+ {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+ {GRISU_UINT64_C(0xbff610b0, cc6edd3f), 737, 241},
+ {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
+ {GRISU_UINT64_C(0xa67ff273, b8460357), 797, 259},
+ {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+ {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
+ {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+ {GRISU_UINT64_C(0xfa856334, 878fc151), 916, 295},
+ {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+ {GRISU_UINT64_C(0xd94ad8b1, c7380874), 976, 313},
+ {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+ {GRISU_UINT64_C(0xbc789925, 624c5fe1), 1036, 331},
+ {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(9) = 30;
+// nb elements (9): 73
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(10)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0x85f04682, 93f0eb4e), -1053, -298},
+ {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
+ {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+ {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+ {GRISU_UINT64_C(0xf6019da0, 7f549b2b), -921, -258},
+ {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+ {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
+ {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+ {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+ {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
+ {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
+ {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+ {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
+ {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+ {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+ {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+ {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
+ {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+ {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
+ {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+ {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+ {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+ {GRISU_UINT64_C(0xed246723, 473e3813), -323, -78},
+ {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {GRISU_UINT64_C(0xa0b19d2a, b70e6ed6), -256, -58},
+ {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+ {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+ {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+ {GRISU_UINT64_C(0x9392ee8e, 921d5d07), -123, -18},
+ {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+ {GRISU_UINT64_C(0xc8000000, 00000000), -57, 2},
+ {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+ {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+ {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+ {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
+ {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {GRISU_UINT64_C(0xf8ebad2b, 84e0d58c), 142, 62},
+ {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+ {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+ {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+ {GRISU_UINT64_C(0xe498f455, c38b997a), 275, 102},
+ {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+ {GRISU_UINT64_C(0x9ae75759, 6946075f), 342, 122},
+ {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+ {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+ {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
+ {GRISU_UINT64_C(0x8e41ade9, fbebc27d), 475, 162},
+ {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+ {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
+ {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
+ {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+ {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+ {GRISU_UINT64_C(0xb10d8e14, 56105dad), 674, 222},
+ {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+ {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
+ {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+ {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+ {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
+ {GRISU_UINT64_C(0xdc5c5301, c56b75f7), 873, 282},
+ {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {GRISU_UINT64_C(0x95527a52, 02df0ccb), 940, 302},
+ {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
+ {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+ {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+ {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(10) = 34;
+// nb elements (10): 66
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(11)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0xa76c5823, 38ed2622), -1050, -297},
+ {GRISU_UINT64_C(0xf3a20279, ed56d48a), -1014, -286},
+ {GRISU_UINT64_C(0xb1442798, f49ffb4b), -977, -275},
+ {GRISU_UINT64_C(0x80fa687f, 881c7f8e), -940, -264},
+ {GRISU_UINT64_C(0xbbb01b92, 83253ca3), -904, -253},
+ {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
+ {GRISU_UINT64_C(0xc6b8e9b0, 709f109a), -831, -231},
+ {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
+ {GRISU_UINT64_C(0xd267caa8, 62a12d67), -758, -209},
+ {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
+ {GRISU_UINT64_C(0xdec681f9, f4c31f31), -685, -187},
+ {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+ {GRISU_UINT64_C(0xebdf6617, 91d60f56), -612, -165},
+ {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
+ {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
+ {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
+ {GRISU_UINT64_C(0x843610cb, 4bf160cc), -465, -121},
+ {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+ {GRISU_UINT64_C(0x8bfbea76, c619ef36), -392, -99},
+ {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+ {GRISU_UINT64_C(0x9436c076, 0c86e30c), -319, -77},
+ {GRISU_UINT64_C(0xd7adf884, aa879177), -283, -66},
+ {GRISU_UINT64_C(0x9ced737b, b6c4183d), -246, -55},
+ {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+ {GRISU_UINT64_C(0xa6274bbd, d0fadd62), -173, -33},
+ {GRISU_UINT64_C(0xf1c90080, baf72cb1), -137, -22},
+ {GRISU_UINT64_C(0xafebff0b, cb24aaff), -100, -11},
+ {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
+ {GRISU_UINT64_C(0xba43b740, 00000000), -27, 11},
+ {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+ {GRISU_UINT64_C(0xc5371912, 364ce305), 46, 33},
+ {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
+ {GRISU_UINT64_C(0xd0cf4b50, cfe20766), 119, 55},
+ {GRISU_UINT64_C(0x97edd871, cfda3a57), 156, 66},
+ {GRISU_UINT64_C(0xdd15fe86, affad912), 192, 77},
+ {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+ {GRISU_UINT64_C(0xea157514, 3cf97227), 265, 99},
+ {GRISU_UINT64_C(0xaa51823e, 34a7eedf), 302, 110},
+ {GRISU_UINT64_C(0xf7d88bc2, 4209a565), 338, 121},
+ {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+ {GRISU_UINT64_C(0x8335616a, ed761f1f), 412, 143},
+ {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+ {GRISU_UINT64_C(0x8aec23d6, 80043bee), 485, 165},
+ {GRISU_UINT64_C(0xca28a291, 859bbf93), 521, 176},
+ {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
+ {GRISU_UINT64_C(0xd60b3bd5, 6a5586f2), 594, 198},
+ {GRISU_UINT64_C(0x9bbcc7a1, 42b17ccc), 631, 209},
+ {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+ {GRISU_UINT64_C(0xa4e4b66b, 68b65d61), 704, 231},
+ {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
+ {GRISU_UINT64_C(0xae9672ab, a3d0c321), 777, 253},
+ {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
+ {GRISU_UINT64_C(0xb8da1662, e7b00a17), 850, 275},
+ {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+ {GRISU_UINT64_C(0xc3b83581, 09e84f07), 923, 297},
+ {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+ {GRISU_UINT64_C(0xcf39e50f, eae16bf0), 996, 319},
+ {GRISU_UINT64_C(0x96c6e0ea, b509e64d), 1033, 330},
+ {GRISU_UINT64_C(0xdb68c2ca, 82ed2a06), 1069, 341},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(11) = 37;
+// nb elements (11): 60
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(12)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
+ {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+ {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+ {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+ {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+ {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+ {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+ {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+ {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+ {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+ {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
+ {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+ {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+ {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+ {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+ {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+ {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+ {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+ {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+ {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+ {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+ {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
+ {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+ {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+ {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+ {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+ {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+ {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
+ {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
+ {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+ {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+ {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+ {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+ {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+ {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
+ {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+ {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+ {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+ {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
+ {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+ {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
+ {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+ {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+ {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+ {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
+ {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+ {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+ {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+ {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+ {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
+ {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(12) = 40;
+// nb elements (12): 55
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(13)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0x82cca4db, 847945ca), -1043, -295},
+ {GRISU_UINT64_C(0x94b3a202, eb1c3f39), -1000, -282},
+ {GRISU_UINT64_C(0xa90de353, 5aaae202), -957, -269},
+ {GRISU_UINT64_C(0xc0314325, 637a193a), -914, -256},
+ {GRISU_UINT64_C(0xda7f5bf5, 90966849), -871, -243},
+ {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
+ {GRISU_UINT64_C(0x8d3360f0, 9cf6e4bd), -784, -217},
+ {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
+ {GRISU_UINT64_C(0xb67f6455, 292cbf08), -698, -191},
+ {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
+ {GRISU_UINT64_C(0xebdf6617, 91d60f56), -612, -165},
+ {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
+ {GRISU_UINT64_C(0x986ddb5c, 6b3a76b8), -525, -139},
+ {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
+ {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
+ {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
+ {GRISU_UINT64_C(0xfea126b7, d78186bd), -353, -87},
+ {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+ {GRISU_UINT64_C(0xa48ceaaa, b75a8e2b), -266, -61},
+ {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+ {GRISU_UINT64_C(0xd4ad2dbf, c3d07788), -180, -35},
+ {GRISU_UINT64_C(0xf1c90080, baf72cb1), -137, -22},
+ {GRISU_UINT64_C(0x89705f41, 36b4a597), -93, -9},
+ {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
+ {GRISU_UINT64_C(0xb1a2bc2e, c5000000), -7, 17},
+ {GRISU_UINT64_C(0xc9f2c9cd, 04674edf), 36, 30},
+ {GRISU_UINT64_C(0xe596b7b0, c643c719), 79, 43},
+ {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
+ {GRISU_UINT64_C(0x945e455f, 24fb1cf9), 166, 69},
+ {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+ {GRISU_UINT64_C(0xbfc2ef45, 6ae276e9), 252, 95},
+ {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
+ {GRISU_UINT64_C(0xf7d88bc2, 4209a565), 338, 121},
+ {GRISU_UINT64_C(0x8ce2529e, 2734bb1d), 382, 134},
+ {GRISU_UINT64_C(0xa02aa96b, 06deb0fe), 425, 147},
+ {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+ {GRISU_UINT64_C(0xcf02b2c2, 1207ef2f), 511, 173},
+ {GRISU_UINT64_C(0xeb57ff22, fc0c795a), 554, 186},
+ {GRISU_UINT64_C(0x85c70565, 62757457), 598, 199},
+ {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+ {GRISU_UINT64_C(0xace73cbf, dc0bfb7b), 684, 225},
+ {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+ {GRISU_UINT64_C(0xdf78e4b2, bd342cf7), 770, 251},
+ {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
+ {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
+ {GRISU_UINT64_C(0xa42e74f3, d032f526), 900, 290},
+ {GRISU_UINT64_C(0xbaa718e6, 8396cffe), 943, 303},
+ {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+ {GRISU_UINT64_C(0xf13e34aa, bb430a15), 1029, 329},
+ {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(13) = 44;
+// nb elements (13): 51
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(14)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0xa37fce12, 6597973d), -1040, -294},
+ {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
+ {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
+ {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
+ {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
+ {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
+ {GRISU_UINT64_C(0xa8530886, b54dbdec), -761, -210},
+ {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+ {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+ {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+ {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
+ {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+ {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
+ {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
+ {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+ {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+ {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
+ {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+ {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
+ {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+ {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
+ {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
+ {GRISU_UINT64_C(0xb5e620f4, 80000000), -17, 14},
+ {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+ {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
+ {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
+ {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+ {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
+ {GRISU_UINT64_C(0xbb445da9, ca61281f), 262, 98},
+ {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+ {GRISU_UINT64_C(0xbd176620, a501fc00), 355, 126},
+ {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+ {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
+ {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
+ {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
+ {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+ {GRISU_UINT64_C(0xc2abf989, 935ddbfe), 634, 210},
+ {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
+ {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
+ {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+ {GRISU_UINT64_C(0xc67bb459, 7ce2ce49), 820, 266},
+ {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
+ {GRISU_UINT64_C(0xc86ab5c3, 9fa63441), 913, 294},
+ {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+ {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+ {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(14) = 47;
+// nb elements (14): 47
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(15)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0xcc5fc196, fefd7d0c), -1037, -293},
+ {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
+ {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
+ {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+ {GRISU_UINT64_C(0xfe5d5415, 0b090b03), -838, -233},
+ {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+ {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
+ {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+ {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
+ {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
+ {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
+ {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+ {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
+ {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
+ {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
+ {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
+ {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+ {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
+ {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+ {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
+ {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
+ {GRISU_UINT64_C(0xf0bdc21a, bb48db20), 59, 37},
+ {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {GRISU_UINT64_C(0xbde94e8e, 43d0c8ec), 159, 67},
+ {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
+ {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
+ {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+ {GRISU_UINT64_C(0xec5d3fa8, ce427b00), 358, 127},
+ {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+ {GRISU_UINT64_C(0xba756174, 393d88e0), 458, 157},
+ {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+ {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
+ {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+ {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
+ {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+ {GRISU_UINT64_C(0xb7118682, dbb66a77), 757, 247},
+ {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+ {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
+ {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {GRISU_UINT64_C(0xe3d8f9e5, 63a198e5), 956, 307},
+ {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+ {GRISU_UINT64_C(0xb3bd72ed, 2af29e20), 1056, 337},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(15) = 50;
+// nb elements (15): 44
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(16)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
+ {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
+ {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+ {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
+ {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+ {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+ {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
+ {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
+ {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+ {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+ {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
+ {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+ {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
+ {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+ {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
+ {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
+ {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+ {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
+ {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+ {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
+ {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
+ {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
+ {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+ {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+ {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
+ {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+ {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+ {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
+ {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+ {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
+ {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
+ {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+ {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
+ {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+ {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+ {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
+ {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
+ {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+ {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(16) = 54;
+// nb elements (16): 41
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(17)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0x9faacf3d, f73609b1), -1030, -291},
+ {GRISU_UINT64_C(0xdd95317f, 31c7fa1d), -974, -274},
+ {GRISU_UINT64_C(0x99c10284, 4f94e0fb), -917, -257},
+ {GRISU_UINT64_C(0xd5605fcd, cf32e1d7), -861, -240},
+ {GRISU_UINT64_C(0x940f4613, ae5ed137), -804, -223},
+ {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
+ {GRISU_UINT64_C(0x8e938662, 882af53e), -691, -189},
+ {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
+ {GRISU_UINT64_C(0x894bc396, ce5da772), -578, -155},
+ {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
+ {GRISU_UINT64_C(0x843610cb, 4bf160cc), -465, -121},
+ {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
+ {GRISU_UINT64_C(0xfea126b7, d78186bd), -353, -87},
+ {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
+ {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
+ {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
+ {GRISU_UINT64_C(0xec1e4a7d, b69561a5), -127, -19},
+ {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+ {GRISU_UINT64_C(0xe35fa931, a0000000), -14, 15},
+ {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+ {GRISU_UINT64_C(0xdaf3f046, 51d47b4c), 99, 49},
+ {GRISU_UINT64_C(0x97edd871, cfda3a57), 156, 66},
+ {GRISU_UINT64_C(0xd2d80db0, 2aabd62c), 212, 83},
+ {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
+ {GRISU_UINT64_C(0xcb090c80, 01ab551c), 325, 117},
+ {GRISU_UINT64_C(0x8ce2529e, 2734bb1d), 382, 134},
+ {GRISU_UINT64_C(0xc38413cf, 25e2d70e), 438, 151},
+ {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
+ {GRISU_UINT64_C(0xbc4665b5, 96706115), 551, 185},
+ {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
+ {GRISU_UINT64_C(0xb54d5e4a, 127f59c8), 664, 219},
+ {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
+ {GRISU_UINT64_C(0xae9672ab, a3d0c321), 777, 253},
+ {GRISU_UINT64_C(0xf24a01a7, 3cf2dcd0), 833, 270},
+ {GRISU_UINT64_C(0xa81f3014, 49ee8c70), 890, 287},
+ {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+ {GRISU_UINT64_C(0xa1e53af4, 6f801c53), 1003, 321},
+ {GRISU_UINT64_C(0xe0accfa8, 75af45a8), 1059, 338},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(17) = 57;
+// nb elements (17): 39
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(18)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
+ {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
+ {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
+ {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+ {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
+ {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
+ {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
+ {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+ {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
+ {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+ {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
+ {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+ {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
+ {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
+ {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
+ {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+ {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
+ {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
+ {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+ {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
+ {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
+ {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
+ {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+ {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
+ {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
+ {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
+ {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+ {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
+ {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+ {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
+ {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+ {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
+ {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
+ {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
+ {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(18) = 60;
+// nb elements (18): 37
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(19)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0xf97ae3d0, d2446f25), -1024, -289},
+ {GRISU_UINT64_C(0x873e4f75, e2224e68), -960, -270},
+ {GRISU_UINT64_C(0x92a1958a, 7675175f), -897, -251},
+ {GRISU_UINT64_C(0x9efa548d, 26e5a6e2), -834, -232},
+ {GRISU_UINT64_C(0xac5d37d5, b79b6239), -771, -213},
+ {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
+ {GRISU_UINT64_C(0xca9cf1d2, 06fdc03c), -645, -175},
+ {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
+ {GRISU_UINT64_C(0xee2ba6c0, 678b597f), -519, -137},
+ {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
+ {GRISU_UINT64_C(0x8bfbea76, c619ef36), -392, -99},
+ {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
+ {GRISU_UINT64_C(0xa48ceaaa, b75a8e2b), -266, -61},
+ {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
+ {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
+ {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
+ {GRISU_UINT64_C(0xe35fa931, a0000000), -14, 15},
+ {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
+ {GRISU_UINT64_C(0x85a36366, eb71f041), 113, 53},
+ {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+ {GRISU_UINT64_C(0x9d174b2d, cec0e47b), 239, 91},
+ {GRISU_UINT64_C(0xaa51823e, 34a7eedf), 302, 110},
+ {GRISU_UINT64_C(0xb8a8d9bb, e123f018), 365, 129},
+ {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+ {GRISU_UINT64_C(0xd910f7ff, 28069da4), 491, 167},
+ {GRISU_UINT64_C(0xeb57ff22, fc0c795a), 554, 186},
+ {GRISU_UINT64_C(0xff290242, c83396ce), 617, 205},
+ {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
+ {GRISU_UINT64_C(0x95f83d0a, 1fb69cd9), 744, 243},
+ {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
+ {GRISU_UINT64_C(0xb049dc01, 6abc5e60), 870, 281},
+ {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
+ {GRISU_UINT64_C(0xcf39e50f, eae16bf0), 996, 319},
+ {GRISU_UINT64_C(0xe0accfa8, 75af45a8), 1059, 338},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(19) = 64;
+// nb elements (19): 35
+static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(20)[] = {
+ {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
+ {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+ {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
+ {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+ {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
+ {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+ {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
+ {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+ {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
+ {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+ {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
+ {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
+ {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+ {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
+ {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+ {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
+ {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
+ {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+ {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
+ {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+ {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
+ {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
+ {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
+ {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+ {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
+ {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+ {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
+ {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
+ {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+ };
+static const int GRISU_CACHE_MAX_DISTANCE(20) = 67;
+// nb elements (20): 33
+static const int GRISU_CACHE_OFFSET = 308;
diff --git a/src/regexp-delay.js b/src/regexp-delay.js
index 843d0aa..3031799 100644
--- a/src/regexp-delay.js
+++ b/src/regexp-delay.js
@@ -95,6 +95,16 @@
%IgnoreAttributesAndSetProperty(object, 'ignoreCase', ignoreCase);
%IgnoreAttributesAndSetProperty(object, 'multiline', multiline);
%IgnoreAttributesAndSetProperty(object, 'lastIndex', 0);
+ // Clear the regexp result cache.
+ cachedRegexp = 0;
+ cachedSubject = 0;
+ cachedLastIndex = 0;
+ cachedAnswer = 0;
+ // These are from string.js.
+ cachedReplaceSubject = 0;
+ cachedReplaceRegexp = 0;
+ cachedReplaceReplacement = 0;
+ cachedReplaceAnswer = 0;
}
// Call internal function to compile the pattern.
@@ -140,7 +150,36 @@
}
+var cachedRegexp;
+var cachedSubject;
+var cachedLastIndex;
+var cachedAnswer;
+
+
+function CloneRegexpAnswer(array) {
+ var len = array.length;
+ var answer = new $Array(len);
+ for (var i = 0; i < len; i++) {
+ answer[i] = array[i];
+ }
+ answer.index = array.index;
+ answer.input = array.input;
+ return answer;
+}
+
+
function RegExpExec(string) {
+ if (%_ObjectEquals(cachedLastIndex, this.lastIndex) &&
+ %_ObjectEquals(cachedRegexp, this) &&
+ %_ObjectEquals(cachedSubject, string)) {
+ var last = cachedAnswer;
+ if (last == null) {
+ return last;
+ } else {
+ return CloneRegexpAnswer(last);
+ }
+ }
+
if (!IS_REGEXP(this)) {
throw MakeTypeError('incompatible_method_receiver',
['RegExp.prototype.exec', this]);
@@ -159,6 +198,7 @@
s = ToString(string);
}
var lastIndex = this.lastIndex;
+
var i = this.global ? TO_INTEGER(lastIndex) : 0;
if (i < 0 || i > s.length) {
@@ -172,7 +212,11 @@
if (matchIndices == null) {
if (this.global) this.lastIndex = 0;
- return matchIndices; // no match
+ cachedLastIndex = lastIndex;
+ cachedRegexp = this;
+ cachedSubject = s;
+ cachedAnswer = matchIndices; // Null.
+ return matchIndices; // No match.
}
var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1;
@@ -196,11 +240,18 @@
}
}
- if (this.global)
- this.lastIndex = lastMatchInfo[CAPTURE1];
result.index = lastMatchInfo[CAPTURE0];
result.input = s;
- return result;
+ if (this.global) {
+ this.lastIndex = lastMatchInfo[CAPTURE1];
+ return result;
+ } else {
+ cachedRegexp = this;
+ cachedSubject = s;
+ cachedLastIndex = lastIndex;
+ cachedAnswer = result;
+ return CloneRegexpAnswer(result);
+ }
}
diff --git a/src/runtime.cc b/src/runtime.cc
index 6d3a158..61534d3 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -32,6 +32,7 @@
#include "accessors.h"
#include "api.h"
#include "arguments.h"
+#include "codegen.h"
#include "compiler.h"
#include "cpu.h"
#include "dateparser-inl.h"
@@ -247,7 +248,8 @@
static Handle<Object> CreateObjectLiteralBoilerplate(
Handle<FixedArray> literals,
- Handle<FixedArray> constant_properties) {
+ Handle<FixedArray> constant_properties,
+ bool should_have_fast_elements) {
// Get the global context from the literals array. This is the
// context in which the function was created and we use the object
// function from this context to create the object literal. We do
@@ -263,6 +265,10 @@
&is_result_from_cache);
Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map);
+
+ // Normalize the elements of the boilerplate to save space if needed.
+ if (!should_have_fast_elements) NormalizeElements(boilerplate);
+
{ // Add the constant properties to the boilerplate.
int length = constant_properties->length();
OptimizedObjectForAddingMultipleProperties opt(boilerplate,
@@ -344,8 +350,10 @@
Handle<FixedArray> array) {
Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
switch (CompileTimeValue::GetType(array)) {
- case CompileTimeValue::OBJECT_LITERAL:
- return CreateObjectLiteralBoilerplate(literals, elements);
+ case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
+ return CreateObjectLiteralBoilerplate(literals, elements, true);
+ case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
+ return CreateObjectLiteralBoilerplate(literals, elements, false);
case CompileTimeValue::ARRAY_LITERAL:
return CreateArrayLiteralBoilerplate(literals, elements);
default:
@@ -355,26 +363,6 @@
}
-static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
- HandleScope scope;
- ASSERT(args.length() == 3);
- // Copy the arguments.
- CONVERT_ARG_CHECKED(FixedArray, literals, 0);
- CONVERT_SMI_CHECKED(literals_index, args[1]);
- CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
-
- Handle<Object> result =
- CreateObjectLiteralBoilerplate(literals, constant_properties);
-
- if (result.is_null()) return Failure::Exception();
-
- // Update the functions literal and return the boilerplate.
- literals->set(literals_index, *result);
-
- return *result;
-}
-
-
static Object* Runtime_CreateArrayLiteralBoilerplate(Arguments args) {
// Takes a FixedArray of elements containing the literal elements of
// the array literal and produces JSArray with those elements.
@@ -398,15 +386,19 @@
static Object* Runtime_CreateObjectLiteral(Arguments args) {
HandleScope scope;
- ASSERT(args.length() == 3);
+ ASSERT(args.length() == 4);
CONVERT_ARG_CHECKED(FixedArray, literals, 0);
CONVERT_SMI_CHECKED(literals_index, args[1]);
CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
+ CONVERT_SMI_CHECKED(fast_elements, args[3]);
+ bool should_have_fast_elements = fast_elements == 1;
// Check if boilerplate exists. If not, create it first.
Handle<Object> boilerplate(literals->get(literals_index));
if (*boilerplate == Heap::undefined_value()) {
- boilerplate = CreateObjectLiteralBoilerplate(literals, constant_properties);
+ boilerplate = CreateObjectLiteralBoilerplate(literals,
+ constant_properties,
+ should_have_fast_elements);
if (boilerplate.is_null()) return Failure::Exception();
// Update the functions literal and return the boilerplate.
literals->set(literals_index, *boilerplate);
@@ -417,15 +409,19 @@
static Object* Runtime_CreateObjectLiteralShallow(Arguments args) {
HandleScope scope;
- ASSERT(args.length() == 3);
+ ASSERT(args.length() == 4);
CONVERT_ARG_CHECKED(FixedArray, literals, 0);
CONVERT_SMI_CHECKED(literals_index, args[1]);
CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
+ CONVERT_SMI_CHECKED(fast_elements, args[3]);
+ bool should_have_fast_elements = fast_elements == 1;
// Check if boilerplate exists. If not, create it first.
Handle<Object> boilerplate(literals->get(literals_index));
if (*boilerplate == Heap::undefined_value()) {
- boilerplate = CreateObjectLiteralBoilerplate(literals, constant_properties);
+ boilerplate = CreateObjectLiteralBoilerplate(literals,
+ constant_properties,
+ should_have_fast_elements);
if (boilerplate.is_null()) return Failure::Exception();
// Update the functions literal and return the boilerplate.
literals->set(literals_index, *boilerplate);
@@ -1242,6 +1238,70 @@
}
+static void SetCustomCallGenerator(Handle<JSFunction> function,
+ CustomCallGenerator generator) {
+ if (function->shared()->function_data()->IsUndefined()) {
+ function->shared()->set_function_data(*FromCData(generator));
+ }
+}
+
+
+static Handle<JSFunction> InstallBuiltin(Handle<JSObject> holder,
+ const char* name,
+ Builtins::Name builtin_name,
+ CustomCallGenerator generator = NULL) {
+ Handle<String> key = Factory::LookupAsciiSymbol(name);
+ Handle<Code> code(Builtins::builtin(builtin_name));
+ Handle<JSFunction> optimized = Factory::NewFunction(key,
+ JS_OBJECT_TYPE,
+ JSObject::kHeaderSize,
+ code,
+ false);
+ optimized->shared()->DontAdaptArguments();
+ if (generator != NULL) {
+ SetCustomCallGenerator(optimized, generator);
+ }
+ SetProperty(holder, key, optimized, NONE);
+ return optimized;
+}
+
+
+static Object* CompileArrayPushCall(CallStubCompiler* compiler,
+ Object* object,
+ JSObject* holder,
+ JSFunction* function,
+ String* name,
+ StubCompiler::CheckType check) {
+ return compiler->CompileArrayPushCall(object, holder, function, name, check);
+}
+
+
+static Object* CompileArrayPopCall(CallStubCompiler* compiler,
+ Object* object,
+ JSObject* holder,
+ JSFunction* function,
+ String* name,
+ StubCompiler::CheckType check) {
+ return compiler->CompileArrayPopCall(object, holder, function, name, check);
+}
+
+
+static Object* Runtime_SpecialArrayFunctions(Arguments args) {
+ HandleScope scope;
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_CHECKED(JSObject, holder, 0);
+
+ InstallBuiltin(holder, "pop", Builtins::ArrayPop, CompileArrayPopCall);
+ InstallBuiltin(holder, "push", Builtins::ArrayPush, CompileArrayPushCall);
+ InstallBuiltin(holder, "shift", Builtins::ArrayShift);
+ InstallBuiltin(holder, "unshift", Builtins::ArrayUnshift);
+ InstallBuiltin(holder, "slice", Builtins::ArraySlice);
+ InstallBuiltin(holder, "splice", Builtins::ArraySplice);
+
+ return *holder;
+}
+
+
static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 4);
@@ -1376,10 +1436,8 @@
ASSERT(args.length() == 1);
CONVERT_CHECKED(JSFunction, f, args[0]);
- // The function_data field of the shared function info is used exclusively by
- // the API.
- return !f->shared()->function_data()->IsUndefined() ? Heap::true_value()
- : Heap::false_value();
+ return f->shared()->IsApiFunction() ? Heap::true_value()
+ : Heap::false_value();
}
static Object* Runtime_FunctionIsBuiltin(Arguments args) {
@@ -4847,16 +4905,6 @@
}
-static Object* Runtime_Math_abs(Arguments args) {
- NoHandleAllocation ha;
- ASSERT(args.length() == 1);
- Counters::math_abs.Increment();
-
- CONVERT_DOUBLE_CHECKED(x, args[0]);
- return Heap::AllocateHeapNumber(fabs(x));
-}
-
-
static Object* Runtime_Math_acos(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
@@ -5090,14 +5138,7 @@
}
-static Object* Runtime_DateMakeDay(Arguments args) {
- NoHandleAllocation ha;
- ASSERT(args.length() == 3);
-
- CONVERT_SMI_CHECKED(year, args[0]);
- CONVERT_SMI_CHECKED(month, args[1]);
- CONVERT_SMI_CHECKED(date, args[2]);
-
+static int MakeDay(int year, int month, int day) {
static const int day_from_month[] = {0, 31, 59, 90, 120, 151,
181, 212, 243, 273, 304, 334};
static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152,
@@ -5119,7 +5160,7 @@
// ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
// Jan 1 1970. This is required so that we don't run into integer
// division of negative numbers.
- // c) there shouldn't be overflow for 32-bit integers in the following
+ // c) there shouldn't be an overflow for 32-bit integers in the following
// operations.
static const int year_delta = 399999;
static const int base_day = 365 * (1970 + year_delta) +
@@ -5135,10 +5176,327 @@
base_day;
if (year % 4 || (year % 100 == 0 && year % 400 != 0)) {
- return Smi::FromInt(day_from_year + day_from_month[month] + date - 1);
+ return day_from_year + day_from_month[month] + day - 1;
}
- return Smi::FromInt(day_from_year + day_from_month_leap[month] + date - 1);
+ return day_from_year + day_from_month_leap[month] + day - 1;
+}
+
+
+static Object* Runtime_DateMakeDay(Arguments args) {
+ NoHandleAllocation ha;
+ ASSERT(args.length() == 3);
+
+ CONVERT_SMI_CHECKED(year, args[0]);
+ CONVERT_SMI_CHECKED(month, args[1]);
+ CONVERT_SMI_CHECKED(date, args[2]);
+
+ return Smi::FromInt(MakeDay(year, month, date));
+}
+
+
+static const int kDays4Years[] = {0, 365, 2 * 365, 3 * 365 + 1};
+static const int kDaysIn4Years = 4 * 365 + 1;
+static const int kDaysIn100Years = 25 * kDaysIn4Years - 1;
+static const int kDaysIn400Years = 4 * kDaysIn100Years + 1;
+static const int kDays1970to2000 = 30 * 365 + 7;
+static const int kDaysOffset = 1000 * kDaysIn400Years + 5 * kDaysIn400Years -
+ kDays1970to2000;
+static const int kYearsOffset = 400000;
+
+static const char kDayInYear[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
+
+static const char kMonthInYear[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11};
+
+
+// This function works for dates from 1970 to 2099.
+static inline void DateYMDFromTimeAfter1970(int date,
+ int &year, int &month, int &day) {
+#ifdef DEBUG
+ int save_date = date; // Need this for ASSERT in the end.
+#endif
+
+ year = 1970 + (4 * date + 2) / kDaysIn4Years;
+ date %= kDaysIn4Years;
+
+ month = kMonthInYear[date];
+ day = kDayInYear[date];
+
+ ASSERT(MakeDay(year, month, day) == save_date);
+}
+
+
+static inline void DateYMDFromTimeSlow(int date,
+ int &year, int &month, int &day) {
+#ifdef DEBUG
+ int save_date = date; // Need this for ASSERT in the end.
+#endif
+
+ date += kDaysOffset;
+ year = 400 * (date / kDaysIn400Years) - kYearsOffset;
+ date %= kDaysIn400Years;
+
+ ASSERT(MakeDay(year, 0, 1) + date == save_date);
+
+ date--;
+ int yd1 = date / kDaysIn100Years;
+ date %= kDaysIn100Years;
+ year += 100 * yd1;
+
+ date++;
+ int yd2 = date / kDaysIn4Years;
+ date %= kDaysIn4Years;
+ year += 4 * yd2;
+
+ date--;
+ int yd3 = date / 365;
+ date %= 365;
+ year += yd3;
+
+ 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);
+
+ if (is_leap) {
+ day = kDayInYear[2*365 + 1 + date];
+ month = kMonthInYear[2*365 + 1 + date];
+ } else {
+ day = kDayInYear[date];
+ month = kMonthInYear[date];
+ }
+
+ ASSERT(MakeDay(year, month, day) == save_date);
+}
+
+
+static inline void DateYMDFromTime(int date,
+ int &year, int &month, int &day) {
+ if (date >= 0 && date < 32 * kDaysIn4Years) {
+ DateYMDFromTimeAfter1970(date, year, month, day);
+ } else {
+ DateYMDFromTimeSlow(date, year, month, day);
+ }
+}
+
+
+static Object* Runtime_DateYMDFromTime(Arguments args) {
+ NoHandleAllocation ha;
+ ASSERT(args.length() == 2);
+
+ CONVERT_DOUBLE_CHECKED(t, args[0]);
+ CONVERT_CHECKED(JSArray, res_array, args[1]);
+
+ int year, month, day;
+ DateYMDFromTime(static_cast<int>(floor(t / 86400000)), year, month, day);
+
+ res_array->SetElement(0, Smi::FromInt(year));
+ res_array->SetElement(1, Smi::FromInt(month));
+ res_array->SetElement(2, Smi::FromInt(day));
+
+ return Heap::undefined_value();
}
@@ -8675,18 +9033,28 @@
HandleScope scope;
Handle<JSArray> result = Factory::NewJSArray(0);
int index = 0;
+ bool inline_runtime_functions = false;
#define ADD_ENTRY(Name, argc, ressize) \
{ \
HandleScope inner; \
- Handle<String> name = \
- Factory::NewStringFromAscii( \
- Vector<const char>(#Name, StrLength(#Name))); \
+ Handle<String> name; \
+ /* Inline runtime functions have an underscore in front of the name. */ \
+ if (inline_runtime_functions) { \
+ name = Factory::NewStringFromAscii( \
+ Vector<const char>("_" #Name, StrLength("_" #Name))); \
+ } else { \
+ name = Factory::NewStringFromAscii( \
+ Vector<const char>(#Name, StrLength(#Name))); \
+ } \
Handle<JSArray> pair = Factory::NewJSArray(0); \
SetElement(pair, 0, name); \
SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc))); \
SetElement(result, index++, pair); \
}
+ inline_runtime_functions = false;
RUNTIME_FUNCTION_LIST(ADD_ENTRY)
+ inline_runtime_functions = true;
+ INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
#undef ADD_ENTRY
return *result;
}
diff --git a/src/runtime.h b/src/runtime.h
index 8c2f86d..143f636 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -61,6 +61,7 @@
F(ToFastProperties, 1, 1) \
F(ToSlowProperties, 1, 1) \
F(FinishArrayPrototypeSetup, 1, 1) \
+ F(SpecialArrayFunctions, 1, 1) \
\
F(IsInPrototypeChain, 2, 1) \
F(SetHiddenPrototype, 2, 1) \
@@ -132,7 +133,6 @@
F(StringCompare, 2, 1) \
\
/* Math */ \
- F(Math_abs, 1, 1) \
F(Math_acos, 1, 1) \
F(Math_asin, 1, 1) \
F(Math_atan, 1, 1) \
@@ -204,6 +204,7 @@
F(DateLocalTimeOffset, 0, 1) \
F(DateDaylightSavingsOffset, 1, 1) \
F(DateMakeDay, 3, 1) \
+ F(DateYMDFromTime, 2, 1) \
\
/* Numbers */ \
F(NumberIsFinite, 1, 1) \
@@ -234,11 +235,10 @@
/* Literals */ \
F(MaterializeRegExpLiteral, 4, 1)\
F(CreateArrayLiteralBoilerplate, 3, 1) \
- F(CreateObjectLiteralBoilerplate, 3, 1) \
F(CloneLiteralBoilerplate, 1, 1) \
F(CloneShallowLiteralBoilerplate, 1, 1) \
- F(CreateObjectLiteral, 3, 1) \
- F(CreateObjectLiteralShallow, 3, 1) \
+ F(CreateObjectLiteral, 4, 1) \
+ F(CreateObjectLiteralShallow, 4, 1) \
F(CreateArrayLiteral, 3, 1) \
F(CreateArrayLiteralShallow, 3, 1) \
\
diff --git a/src/scopes.h b/src/scopes.h
index 9b506d9..c2354b2 100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -277,7 +277,6 @@
// The number of contexts between this and scope; zero if this == scope.
int ContextChainLength(Scope* scope);
-
// ---------------------------------------------------------------------------
// Debugging.
diff --git a/src/string.js b/src/string.js
index 067578c..e22c93b 100644
--- a/src/string.js
+++ b/src/string.js
@@ -239,14 +239,29 @@
}
+var cachedReplaceSubject;
+var cachedReplaceRegexp;
+var cachedReplaceReplacement;
+var cachedReplaceAnswer;
+
// Helper function for regular expressions in String.prototype.replace.
function StringReplaceRegExp(subject, regexp, replace) {
+ if (%_ObjectEquals(replace, cachedReplaceReplacement) &&
+ %_ObjectEquals(subject, cachedReplaceSubject) &&
+ %_ObjectEquals(regexp, cachedReplaceRegexp)) {
+ return cachedReplaceAnswer;
+ }
replace = TO_STRING_INLINE(replace);
- return %StringReplaceRegExpWithString(subject,
- regexp,
- replace,
- lastMatchInfo);
-};
+ var answer = %StringReplaceRegExpWithString(subject,
+ regexp,
+ replace,
+ lastMatchInfo);
+ cachedReplaceSubject = subject;
+ cachedReplaceRegexp = regexp;
+ cachedReplaceReplacement = replace;
+ cachedReplaceAnswer = answer;
+ return answer;
+}
// Expand the $-expressions in the string and return a new string with
@@ -387,43 +402,68 @@
// Unfortunately, that means this code is nearly duplicated, here and in
// jsregexp.cc.
if (regexp.global) {
- var numberOfCaptures = NUMBER_OF_CAPTURES(matchInfo) >> 1;
var previous = 0;
- do {
- var startOfMatch = matchInfo[CAPTURE0];
- result.addSpecialSlice(previous, startOfMatch);
- previous = matchInfo[CAPTURE1];
- if (numberOfCaptures == 1) {
+ var startOfMatch;
+ if (NUMBER_OF_CAPTURES(matchInfo) == 2) {
+ // Both branches contain essentially the same loop except for the call
+ // to the replace function. The branch is put outside of the loop for
+ // speed
+ do {
+ startOfMatch = matchInfo[CAPTURE0];
+ result.addSpecialSlice(previous, startOfMatch);
+ previous = matchInfo[CAPTURE1];
var match = SubString(subject, startOfMatch, previous);
// Don't call directly to avoid exposing the built-in global object.
result.add(replace.call(null, match, startOfMatch, subject));
- } else {
- result.add(ApplyReplacementFunction(replace, matchInfo, subject));
- }
- // Can't use matchInfo any more from here, since the function could
- // overwrite it.
- // Continue with the next match.
- // Increment previous if we matched an empty string, as per ECMA-262
- // 15.5.4.10.
- if (previous == startOfMatch) {
- // Add the skipped character to the output, if any.
- if (previous < subject.length) {
- result.addSpecialSlice(previous, previous + 1);
+ // Can't use matchInfo any more from here, since the function could
+ // overwrite it.
+ // Continue with the next match.
+ // Increment previous if we matched an empty string, as per ECMA-262
+ // 15.5.4.10.
+ if (previous == startOfMatch) {
+ // Add the skipped character to the output, if any.
+ if (previous < subject.length) {
+ result.addSpecialSlice(previous, previous + 1);
+ }
+ previous++;
+ // Per ECMA-262 15.10.6.2, if the previous index is greater than the
+ // string length, there is no match
+ if (previous > subject.length) {
+ return result.generate();
+ }
}
- previous++;
- }
-
- // Per ECMA-262 15.10.6.2, if the previous index is greater than the
- // string length, there is no match
- matchInfo = (previous > subject.length)
- ? null
- : DoRegExpExec(regexp, subject, previous);
- } while (!IS_NULL(matchInfo));
-
- // Tack on the final right substring after the last match, if necessary.
- if (previous < subject.length) {
- result.addSpecialSlice(previous, subject.length);
+ matchInfo = DoRegExpExec(regexp, subject, previous);
+ } while (!IS_NULL(matchInfo));
+ } else {
+ do {
+ startOfMatch = matchInfo[CAPTURE0];
+ result.addSpecialSlice(previous, startOfMatch);
+ previous = matchInfo[CAPTURE1];
+ result.add(ApplyReplacementFunction(replace, matchInfo, subject));
+ // Can't use matchInfo any more from here, since the function could
+ // overwrite it.
+ // Continue with the next match.
+ // Increment previous if we matched an empty string, as per ECMA-262
+ // 15.5.4.10.
+ if (previous == startOfMatch) {
+ // Add the skipped character to the output, if any.
+ if (previous < subject.length) {
+ result.addSpecialSlice(previous, previous + 1);
+ }
+ previous++;
+ // Per ECMA-262 15.10.6.2, if the previous index is greater than the
+ // string length, there is no match
+ if (previous > subject.length) {
+ return result.generate();
+ }
+ }
+ matchInfo = DoRegExpExec(regexp, subject, previous);
+ } while (!IS_NULL(matchInfo));
}
+
+ // Tack on the final right substring after the last match.
+ result.addSpecialSlice(previous, subject.length);
+
} else { // Not a global regexp, no need to loop.
result.addSpecialSlice(0, matchInfo[CAPTURE0]);
var endOfMatch = matchInfo[CAPTURE1];
@@ -719,16 +759,26 @@
return %StringTrim(TO_STRING_INLINE(this), false, true);
}
+var static_charcode_array = new $Array(4);
+
// ECMA-262, section 15.5.3.2
function StringFromCharCode(code) {
var n = %_ArgumentsLength();
- if (n == 1) return %_CharFromCode(ToNumber(code) & 0xffff)
+ if (n == 1) {
+ if (!%_IsSmi(code)) code = ToNumber(code);
+ return %_CharFromCode(code & 0xffff);
+ }
// NOTE: This is not super-efficient, but it is necessary because we
// want to avoid converting to numbers from within the virtual
// machine. Maybe we can find another way of doing this?
- var codes = new $Array(n);
- for (var i = 0; i < n; i++) codes[i] = ToNumber(%_Arguments(i));
+ var codes = static_charcode_array;
+ for (var i = 0; i < n; i++) {
+ var code = %_Arguments(i);
+ if (!%_IsSmi(code)) code = ToNumber(code);
+ codes[i] = code;
+ }
+ codes.length = n;
return %StringFromCharCodeArray(codes);
}
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 577c2d7..c942d9d 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -435,14 +435,6 @@
argc);
Object* code = map->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
- if (object->IsJSObject()) {
- Object* opt =
- Top::LookupSpecialFunction(JSObject::cast(object), holder, function);
- if (opt->IsJSFunction()) {
- check = StubCompiler::JSARRAY_HAS_FAST_ELEMENTS_CHECK;
- function = JSFunction::cast(opt);
- }
- }
// If the function hasn't been compiled yet, we cannot do it now
// because it may cause GC. To avoid this issue, we return an
// internal error which will make sure we do not update any
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 43354db..0e986dd 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -326,8 +326,7 @@
RECEIVER_MAP_CHECK,
STRING_CHECK,
NUMBER_CHECK,
- BOOLEAN_CHECK,
- JSARRAY_HAS_FAST_ELEMENTS_CHECK
+ BOOLEAN_CHECK
};
StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
@@ -549,7 +548,7 @@
class CallStubCompiler: public StubCompiler {
public:
- explicit CallStubCompiler(int argc, InLoopFlag in_loop)
+ CallStubCompiler(int argc, InLoopFlag in_loop)
: arguments_(argc), in_loop_(in_loop) { }
Object* CompileCallField(JSObject* object,
@@ -570,6 +569,18 @@
JSFunction* function,
String* name);
+ Object* CompileArrayPushCall(Object* object,
+ JSObject* holder,
+ JSFunction* function,
+ String* name,
+ CheckType check);
+
+ Object* CompileArrayPopCall(Object* object,
+ JSObject* holder,
+ JSFunction* function,
+ String* name,
+ CheckType check);
+
private:
const ParameterCount arguments_;
const InLoopFlag in_loop_;
@@ -591,6 +602,14 @@
};
+typedef Object* (*CustomCallGenerator)(CallStubCompiler* compiler,
+ Object* object,
+ JSObject* holder,
+ JSFunction* function,
+ String* name,
+ StubCompiler::CheckType check);
+
+
} } // namespace v8::internal
#endif // V8_STUB_CACHE_H_
diff --git a/src/top.cc b/src/top.cc
index 7c8a1c9..3efd1fc 100644
--- a/src/top.cc
+++ b/src/top.cc
@@ -92,15 +92,15 @@
v->VisitPointer(&(thread->pending_exception_));
v->VisitPointer(&(thread->pending_message_obj_));
v->VisitPointer(
- bit_cast<Object**, Script**>(&(thread->pending_message_script_)));
- v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_)));
+ BitCast<Object**, Script**>(&(thread->pending_message_script_)));
+ v->VisitPointer(BitCast<Object**, Context**>(&(thread->context_)));
v->VisitPointer(&(thread->scheduled_exception_));
for (v8::TryCatch* block = thread->TryCatchHandler();
block != NULL;
block = TRY_CATCH_FROM_ADDRESS(block->next_)) {
- v->VisitPointer(bit_cast<Object**, void**>(&(block->exception_)));
- v->VisitPointer(bit_cast<Object**, void**>(&(block->message_)));
+ v->VisitPointer(BitCast<Object**, void**>(&(block->exception_)));
+ v->VisitPointer(BitCast<Object**, void**>(&(block->message_)));
}
// Iterate over pointers on native execution stack.
@@ -439,10 +439,9 @@
// Get the data object from access check info.
JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
- Object* info = constructor->shared()->function_data();
- if (info == Heap::undefined_value()) return;
-
- Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info();
+ if (!constructor->shared()->IsApiFunction()) return;
+ Object* data_obj =
+ constructor->shared()->get_api_func_data()->access_check_info();
if (data_obj == Heap::undefined_value()) return;
HandleScope scope;
@@ -502,10 +501,10 @@
// Get named access check callback
JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
- Object* info = constructor->shared()->function_data();
- if (info == Heap::undefined_value()) return false;
+ if (!constructor->shared()->IsApiFunction()) return false;
- Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info();
+ Object* data_obj =
+ constructor->shared()->get_api_func_data()->access_check_info();
if (data_obj == Heap::undefined_value()) return false;
Object* fun_obj = AccessCheckInfo::cast(data_obj)->named_callback();
@@ -547,10 +546,10 @@
// Get indexed access check callback
JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
- Object* info = constructor->shared()->function_data();
- if (info == Heap::undefined_value()) return false;
+ if (!constructor->shared()->IsApiFunction()) return false;
- Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info();
+ Object* data_obj =
+ constructor->shared()->get_api_func_data()->access_check_info();
if (data_obj == Heap::undefined_value()) return false;
Object* fun_obj = AccessCheckInfo::cast(data_obj)->indexed_callback();
@@ -950,27 +949,6 @@
}
-bool Top::CanHaveSpecialFunctions(JSObject* object) {
- return object->IsJSArray();
-}
-
-
-Object* Top::LookupSpecialFunction(JSObject* receiver,
- JSObject* prototype,
- JSFunction* function) {
- if (CanHaveSpecialFunctions(receiver)) {
- FixedArray* table = context()->global_context()->special_function_table();
- for (int index = 0; index < table->length(); index +=3) {
- if ((prototype == table->get(index)) &&
- (function == table->get(index+1))) {
- return table->get(index+2);
- }
- }
- }
- return Heap::undefined_value();
-}
-
-
char* Top::ArchiveThread(char* to) {
memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(thread_local_));
InitializeThreadLocal();
diff --git a/src/top.h b/src/top.h
index ddc73ba..e20a2a0 100644
--- a/src/top.h
+++ b/src/top.h
@@ -342,11 +342,6 @@
return Handle<JSBuiltinsObject>(thread_local_.context_->builtins());
}
- static bool CanHaveSpecialFunctions(JSObject* object);
- static Object* LookupSpecialFunction(JSObject* receiver,
- JSObject* prototype,
- JSFunction* value);
-
static void RegisterTryCatchHandler(v8::TryCatch* that);
static void UnregisterTryCatchHandler(v8::TryCatch* that);
diff --git a/src/utils.h b/src/utils.h
index deab09f..3c8d873 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -29,6 +29,7 @@
#define V8_UTILS_H_
#include <stdlib.h>
+#include <string.h>
namespace v8 {
namespace internal {
@@ -396,7 +397,7 @@
if (this == &rhs) return *this;
Vector<T>::operator=(rhs);
memcpy(buffer_, rhs.buffer_, sizeof(T) * kSize);
- set_start(buffer_);
+ this->set_start(buffer_);
return *this;
}
@@ -599,6 +600,43 @@
// Calculate 10^exponent.
int TenToThe(int exponent);
+
+// The type-based aliasing rule allows the compiler to assume that pointers of
+// different types (for some definition of different) never alias each other.
+// Thus the following code does not work:
+//
+// float f = foo();
+// int fbits = *(int*)(&f);
+//
+// The compiler 'knows' that the int pointer can't refer to f since the types
+// don't match, so the compiler may cache f in a register, leaving random data
+// in fbits. Using C++ style casts makes no difference, however a pointer to
+// char data is assumed to alias any other pointer. This is the 'memcpy
+// exception'.
+//
+// Bit_cast uses the memcpy exception to move the bits from a variable of one
+// type of a variable of another type. Of course the end result is likely to
+// be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005)
+// will completely optimize BitCast away.
+//
+// There is an additional use for BitCast.
+// Recent gccs will warn when they see casts that may result in breakage due to
+// the type-based aliasing rule. If you have checked that there is no breakage
+// you can use BitCast to cast one pointer type to another. This confuses gcc
+// enough that it can no longer see that you have cast one pointer type to
+// another thus avoiding the warning.
+template <class Dest, class Source>
+inline Dest BitCast(const Source& source) {
+ // Compile time assertion: sizeof(Dest) == sizeof(Source)
+ // A compile error here means your Dest and Source have different sizes.
+ typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
+
+ Dest dest;
+ memcpy(&dest, &source, sizeof(dest));
+ return dest;
+}
+
+
} } // namespace v8::internal
#endif // V8_UTILS_H_
diff --git a/src/v8-counters.h b/src/v8-counters.h
index 2b493fb..b595cd4 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -170,7 +170,6 @@
SC(regexp_entry_native, V8.RegExpEntryNative) \
SC(number_to_string_native, V8.NumberToStringNative) \
SC(number_to_string_runtime, V8.NumberToStringRuntime) \
- SC(math_abs, V8.MathAbs) \
SC(math_acos, V8.MathAcos) \
SC(math_asin, V8.MathAsin) \
SC(math_atan, V8.MathAtan) \
diff --git a/src/version.cc b/src/version.cc
index 3562e1d..83382de 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 2
#define MINOR_VERSION 1
-#define BUILD_NUMBER 3
-#define PATCH_LEVEL 1
+#define BUILD_NUMBER 4
+#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the
diff --git a/src/virtual-frame-inl.h b/src/virtual-frame-inl.h
index 9aa88fe..ff599d0 100644
--- a/src/virtual-frame-inl.h
+++ b/src/virtual-frame-inl.h
@@ -119,6 +119,12 @@
return true;
}
+
+void VirtualFrame::SetTypeForLocalAt(int index, NumberInfo info) {
+ elements_[local0_index() + index].set_number_info(info);
+}
+
+
} } // namespace v8::internal
#endif // V8_VIRTUAL_FRAME_INL_H_
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index b10c3f9..f5a8d3c 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -2424,11 +2424,13 @@
frame_->Push(Smi::FromInt(node->literal_index()));
// Constant properties.
frame_->Push(node->constant_properties());
+ // Should the object literal have fast elements?
+ frame_->Push(Smi::FromInt(node->fast_elements() ? 1 : 0));
Result clone;
if (node->depth() > 1) {
- clone = frame_->CallRuntime(Runtime::kCreateObjectLiteral, 3);
+ clone = frame_->CallRuntime(Runtime::kCreateObjectLiteral, 4);
} else {
- clone = frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 3);
+ clone = frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
}
frame_->Push(&clone);
@@ -3600,7 +3602,7 @@
}
-void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
+void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
// ArgumentsAccessStub expects the key in rdx and the formal
diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h
index 8f5fdc1..3256cb2 100644
--- a/src/x64/codegen-x64.h
+++ b/src/x64/codegen-x64.h
@@ -337,6 +337,10 @@
bool in_spilled_code() const { return in_spilled_code_; }
void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; }
+ // If the name is an inline runtime function call return the number of
+ // expected arguments. Otherwise return -1.
+ static int InlineRuntimeCallArgumentsCount(Handle<String> name);
+
private:
// Construction/Destruction
explicit CodeGenerator(MacroAssembler* masm);
@@ -506,6 +510,7 @@
struct InlineRuntimeLUT {
void (CodeGenerator::*method)(ZoneList<Expression*>*);
const char* name;
+ int nargs;
};
static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
bool CheckForInlineRuntimeCall(CallRuntime* node);
@@ -537,7 +542,7 @@
// Support for arguments.length and arguments[?].
void GenerateArgumentsLength(ZoneList<Expression*>* args);
- void GenerateArgumentsAccess(ZoneList<Expression*>* args);
+ void GenerateArguments(ZoneList<Expression*>* args);
// Support for accessing the class and value fields of an object.
void GenerateClassOf(ZoneList<Expression*>* args);
@@ -575,14 +580,10 @@
// Fast support for number to string.
void GenerateNumberToString(ZoneList<Expression*>* args);
- // Fast support for Math.pow().
- void GenerateMathPow(ZoneList<Expression*>* args);
-
// Fast call to math functions.
+ void GenerateMathPow(ZoneList<Expression*>* args);
void GenerateMathSin(ZoneList<Expression*>* args);
void GenerateMathCos(ZoneList<Expression*>* args);
-
- // Fast case for sqrt
void GenerateMathSqrt(ZoneList<Expression*>* args);
// Simple condition analysis.
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index bfa1a44..65f99a3 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -903,10 +903,11 @@
__ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
__ Push(Smi::FromInt(expr->literal_index()));
__ Push(expr->constant_properties());
+ __ Push(Smi::FromInt(expr->fast_elements() ? 1 : 0));
if (expr->depth() > 1) {
- __ CallRuntime(Runtime::kCreateObjectLiteral, 3);
+ __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
} else {
- __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3);
+ __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
}
// If result_saved is true the result is on top of the stack. If
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index dca2780..a8e2fdf 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -197,9 +197,9 @@
// avoid having the fast case for smis leave the registers
// unchanged.
if (FLAG_debug_code) {
- movq(object, bit_cast<int64_t>(kZapValue), RelocInfo::NONE);
- movq(value, bit_cast<int64_t>(kZapValue), RelocInfo::NONE);
- movq(smi_index, bit_cast<int64_t>(kZapValue), RelocInfo::NONE);
+ movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
+ movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
+ movq(smi_index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
}
}
@@ -270,9 +270,9 @@
// Clobber all input registers when running with the debug-code flag
// turned on to provoke errors.
if (FLAG_debug_code) {
- movq(object, bit_cast<int64_t>(kZapValue), RelocInfo::NONE);
- movq(scratch, bit_cast<int64_t>(kZapValue), RelocInfo::NONE);
- movq(smi_index, bit_cast<int64_t>(kZapValue), RelocInfo::NONE);
+ movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
+ movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
+ movq(smi_index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
}
}
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 5d73b5f..aa620fc 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -655,6 +655,118 @@
#define __ ACCESS_MASM((masm()))
+Object* CallStubCompiler::CompileArrayPushCall(Object* object,
+ JSObject* holder,
+ JSFunction* function,
+ String* name,
+ CheckType check) {
+ // ----------- S t a t e -------------
+ // rcx : function name
+ // rsp[0] : return address
+ // rsp[8] : argument argc
+ // rsp[16] : argument argc - 1
+ // ...
+ // rsp[argc * 8] : argument 1
+ // rsp[(argc + 1) * 8] : argument 0 = receiver
+ // -----------------------------------
+
+ // TODO(639): faster implementation.
+ ASSERT(check == RECEIVER_MAP_CHECK);
+
+ Label miss;
+
+ // Get the receiver from the stack.
+ const int argc = arguments().immediate();
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
+
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(rdx, &miss);
+
+ // Check that the maps haven't changed.
+ CheckPrototypes(JSObject::cast(object), rdx, holder,
+ rbx, rax, name, &miss);
+
+ // Patch the receiver on the stack with the global proxy if
+ // necessary.
+ if (object->IsGlobalObject()) {
+ __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
+ __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
+ }
+
+ __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
+ argc + 1,
+ 1);
+
+ // Handle call cache miss.
+ __ bind(&miss);
+ Handle<Code> ic = ComputeCallMiss(arguments().immediate());
+ __ Jump(ic, RelocInfo::CODE_TARGET);
+
+ // Return the generated code.
+ String* function_name = NULL;
+ if (function->shared()->name()->IsString()) {
+ function_name = String::cast(function->shared()->name());
+ }
+ return GetCode(CONSTANT_FUNCTION, function_name);
+}
+
+
+Object* CallStubCompiler::CompileArrayPopCall(Object* object,
+ JSObject* holder,
+ JSFunction* function,
+ String* name,
+ CheckType check) {
+ // ----------- S t a t e -------------
+ // rcx : function name
+ // rsp[0] : return address
+ // rsp[8] : argument argc
+ // rsp[16] : argument argc - 1
+ // ...
+ // rsp[argc * 8] : argument 1
+ // rsp[(argc + 1) * 8] : argument 0 = receiver
+ // -----------------------------------
+
+ // TODO(642): faster implementation.
+ ASSERT(check == RECEIVER_MAP_CHECK);
+
+ Label miss;
+
+ // Get the receiver from the stack.
+ const int argc = arguments().immediate();
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
+
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(rdx, &miss);
+
+ // Check that the maps haven't changed.
+ CheckPrototypes(JSObject::cast(object), rdx, holder,
+ rbx, rax, name, &miss);
+
+ // Patch the receiver on the stack with the global proxy if
+ // necessary.
+ if (object->IsGlobalObject()) {
+ __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
+ __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
+ }
+
+ __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop),
+ argc + 1,
+ 1);
+
+ // Handle call cache miss.
+ __ bind(&miss);
+ Handle<Code> ic = ComputeCallMiss(arguments().immediate());
+ __ Jump(ic, RelocInfo::CODE_TARGET);
+
+ // Return the generated code.
+ String* function_name = NULL;
+ if (function->shared()->name()->IsString()) {
+ function_name = String::cast(function->shared()->name());
+ }
+ return GetCode(CONSTANT_FUNCTION, function_name);
+}
+
+
Object* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder,
JSFunction* function,
@@ -670,6 +782,13 @@
// rsp[(argc + 1) * 8] : argument 0 = receiver
// -----------------------------------
+ SharedFunctionInfo* function_info = function->shared();
+ if (function_info->HasCustomCallGenerator()) {
+ CustomCallGenerator generator =
+ ToCData<CustomCallGenerator>(function_info->function_data());
+ return generator(this, object, holder, function, name, check);
+ }
+
Label miss;
// Get the receiver from the stack.
@@ -759,18 +878,6 @@
break;
}
- case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
- CheckPrototypes(JSObject::cast(object), rdx, holder,
- rbx, rax, name, &miss);
- // Make sure object->HasFastElements().
- // Get the elements array of the object.
- __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
- // Check that the object is in fast mode (not dictionary).
- __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
- Factory::fixed_array_map());
- __ j(not_equal, &miss);
- break;
-
default:
UNREACHABLE();
}
diff --git a/src/x64/virtual-frame-x64.h b/src/x64/virtual-frame-x64.h
index ddd606b..e93140e 100644
--- a/src/x64/virtual-frame-x64.h
+++ b/src/x64/virtual-frame-x64.h
@@ -416,6 +416,8 @@
// the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
inline void Nip(int num_dropped);
+ inline void SetTypeForLocalAt(int index, NumberInfo info);
+
private:
static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;