summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-10-22 12:50:53 +0100
committerBen Murdoch <benm@google.com>2010-10-22 20:03:06 +0100
commitf87a203d89e1bbb6708282e0b64dbd13d59b723d (patch)
treed7658572059125113d4052a87e2e2c1251419c64 /src
parent0d5e116f6aee03185f237311a943491bb079a768 (diff)
downloadandroid_external_v8-f87a203d89e1bbb6708282e0b64dbd13d59b723d.tar.gz
android_external_v8-f87a203d89e1bbb6708282e0b64dbd13d59b723d.tar.bz2
android_external_v8-f87a203d89e1bbb6708282e0b64dbd13d59b723d.zip
Update V8 to r5675 as required by WebKit r70209
Change-Id: Ib10adb470d41ca8c109ead5fc893b880e18d489f
Diffstat (limited to 'src')
-rwxr-xr-xsrc/SConscript4
-rw-r--r--src/api.cc114
-rw-r--r--src/api.h6
-rw-r--r--src/arm/code-stubs-arm.cc15
-rw-r--r--src/arm/codegen-arm.cc10
-rw-r--r--src/arm/codegen-arm.h7
-rw-r--r--src/arm/full-codegen-arm.cc7
-rw-r--r--src/arm/ic-arm.cc8
-rw-r--r--src/arm/regexp-macro-assembler-arm.cc14
-rw-r--r--src/arm/regexp-macro-assembler-arm.h1
-rw-r--r--src/arm/simulator-arm.cc16
-rw-r--r--src/arm/simulator-arm.h6
-rw-r--r--src/arm/stub-cache-arm.cc102
-rw-r--r--src/assembler.cc4
-rw-r--r--src/ast.cc49
-rw-r--r--src/ast.h207
-rw-r--r--src/bootstrapper.cc5
-rw-r--r--src/bytecodes-irregexp.h3
-rw-r--r--src/cached-powers.cc152
-rw-r--r--src/cached-powers.h84
-rw-r--r--src/codegen.cc43
-rw-r--r--src/codegen.h1
-rwxr-xr-xsrc/compiler.cc472
-rw-r--r--src/compiler.h214
-rw-r--r--src/contexts.cc5
-rw-r--r--src/contexts.h21
-rw-r--r--src/conversions.cc68
-rw-r--r--src/cpu-profiler.cc44
-rw-r--r--src/cpu-profiler.h8
-rw-r--r--src/d8.js4
-rw-r--r--src/data-flow.cc11
-rw-r--r--src/data-flow.h6
-rw-r--r--src/date.js2
-rw-r--r--src/debug-debugger.js6
-rw-r--r--src/disassembler.cc5
-rw-r--r--src/execution.cc13
-rw-r--r--src/execution.h5
-rw-r--r--src/fast-dtoa.cc18
-rw-r--r--src/flag-definitions.h7
-rw-r--r--src/full-codegen.cc34
-rw-r--r--src/full-codegen.h11
-rw-r--r--src/global-handles.cc8
-rw-r--r--src/handles.cc28
-rw-r--r--src/handles.h8
-rw-r--r--src/heap-inl.h13
-rw-r--r--src/heap.cc236
-rw-r--r--src/heap.h103
-rw-r--r--src/ia32/assembler-ia32.cc2
-rw-r--r--src/ia32/assembler-ia32.h1
-rw-r--r--src/ia32/code-stubs-ia32.cc13
-rw-r--r--src/ia32/codegen-ia32.cc78
-rw-r--r--src/ia32/codegen-ia32.h7
-rw-r--r--src/ia32/full-codegen-ia32.cc7
-rw-r--r--src/ia32/ic-ia32.cc32
-rw-r--r--src/ia32/regexp-macro-assembler-ia32.cc12
-rw-r--r--src/ia32/regexp-macro-assembler-ia32.h1
-rw-r--r--src/ia32/stub-cache-ia32.cc103
-rw-r--r--src/ic.cc27
-rw-r--r--src/ic.h3
-rw-r--r--src/interpreter-irregexp.cc9
-rw-r--r--src/jsregexp.cc18
-rw-r--r--src/liveedit-debugger.js223
-rw-r--r--src/liveedit.cc57
-rw-r--r--src/log-utils.cc16
-rw-r--r--src/log-utils.h5
-rw-r--r--src/log.cc82
-rw-r--r--src/log.h15
-rw-r--r--src/mark-compact.cc49
-rw-r--r--src/messages.js6
-rw-r--r--src/mips/simulator-mips.cc4
-rw-r--r--src/mips/simulator-mips.h6
-rw-r--r--src/mirror-debugger.js2
-rw-r--r--src/objects-debug.cc16
-rw-r--r--src/objects-inl.h40
-rw-r--r--src/objects-visiting.h12
-rw-r--r--src/objects.cc68
-rw-r--r--src/objects.h23
-rw-r--r--src/parser.cc475
-rw-r--r--src/parser.h355
-rw-r--r--src/platform-freebsd.cc4
-rw-r--r--src/platform-linux.cc35
-rw-r--r--src/platform-macos.cc35
-rw-r--r--src/platform-nullos.cc5
-rw-r--r--src/platform-openbsd.cc4
-rw-r--r--src/platform-solaris.cc9
-rw-r--r--src/platform-win32.cc39
-rw-r--r--src/platform.h24
-rw-r--r--src/powers-ten.h2461
-rw-r--r--src/profile-generator.cc164
-rw-r--r--src/profile-generator.h23
-rw-r--r--src/regexp-macro-assembler-irregexp.cc6
-rw-r--r--src/regexp-macro-assembler-irregexp.h1
-rw-r--r--src/regexp-macro-assembler-tracer.cc63
-rw-r--r--src/regexp-macro-assembler-tracer.h1
-rw-r--r--src/regexp-macro-assembler.h1
-rw-r--r--src/regexp.js150
-rw-r--r--src/rewriter.cc40
-rw-r--r--src/rewriter.h31
-rw-r--r--src/runtime.cc160
-rw-r--r--src/runtime.h2
-rw-r--r--src/scopes.cc27
-rw-r--r--src/scopes.h58
-rw-r--r--src/serialize.cc4
-rw-r--r--src/spaces-inl.h9
-rw-r--r--src/spaces.cc52
-rw-r--r--src/spaces.h97
-rw-r--r--src/string-search.cc40
-rw-r--r--src/string-search.h773
-rw-r--r--src/string.js5
-rw-r--r--src/strtod.cc214
-rw-r--r--src/strtod.h (renamed from src/vm-state.cc)13
-rw-r--r--src/stub-cache.cc1
-rw-r--r--src/stub-cache.h3
-rw-r--r--src/top.cc29
-rw-r--r--src/top.h16
-rw-r--r--src/utils.h20
-rw-r--r--src/v8-counters.h13
-rw-r--r--src/v8.cc2
-rw-r--r--src/v8natives.js18
-rw-r--r--src/version.cc6
-rw-r--r--src/vm-state-inl.h6
-rw-r--r--src/vm-state.h10
-rw-r--r--src/x64/builtins-x64.cc2
-rw-r--r--src/x64/code-stubs-x64.cc29
-rw-r--r--src/x64/codegen-x64.cc46
-rw-r--r--src/x64/codegen-x64.h7
-rw-r--r--src/x64/full-codegen-x64.cc14
-rw-r--r--src/x64/ic-x64.cc8
-rw-r--r--src/x64/macro-assembler-x64.cc10
-rw-r--r--src/x64/macro-assembler-x64.h42
-rw-r--r--src/x64/regexp-macro-assembler-x64.cc14
-rw-r--r--src/x64/regexp-macro-assembler-x64.h1
-rw-r--r--src/x64/stub-cache-x64.cc103
133 files changed, 3934 insertions, 4991 deletions
diff --git a/src/SConscript b/src/SConscript
index 7fae8d4b..8995d482 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -42,6 +42,7 @@ SOURCES = {
ast.cc
bootstrapper.cc
builtins.cc
+ cached-powers.cc
checks.cc
circular-queue.cc
code-stubs.cc
@@ -100,7 +101,9 @@ SOURCES = {
serialize.cc
snapshot-common.cc
spaces.cc
+ string-search.cc
string-stream.cc
+ strtod.cc
stub-cache.cc
token.cc
top.cc
@@ -113,7 +116,6 @@ SOURCES = {
variables.cc
version.cc
virtual-frame.cc
- vm-state.cc
zone.cc
"""),
'arch:arm': Split("""
diff --git a/src/api.cc b/src/api.cc
index 5f480c90..962723d4 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// 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:
@@ -28,6 +28,7 @@
#include "v8.h"
#include "api.h"
+
#include "arguments.h"
#include "bootstrapper.h"
#include "compiler.h"
@@ -36,6 +37,7 @@
#include "global-handles.h"
#include "heap-profiler.h"
#include "messages.h"
+#include "parser.h"
#include "platform.h"
#include "profile-generator-inl.h"
#include "serialize.h"
@@ -134,27 +136,27 @@ void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
heap_stats.new_space_size = &new_space_size;
int new_space_capacity;
heap_stats.new_space_capacity = &new_space_capacity;
- int old_pointer_space_size;
+ intptr_t old_pointer_space_size;
heap_stats.old_pointer_space_size = &old_pointer_space_size;
- int old_pointer_space_capacity;
+ intptr_t old_pointer_space_capacity;
heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
- int old_data_space_size;
+ intptr_t old_data_space_size;
heap_stats.old_data_space_size = &old_data_space_size;
- int old_data_space_capacity;
+ intptr_t old_data_space_capacity;
heap_stats.old_data_space_capacity = &old_data_space_capacity;
- int code_space_size;
+ intptr_t code_space_size;
heap_stats.code_space_size = &code_space_size;
- int code_space_capacity;
+ intptr_t code_space_capacity;
heap_stats.code_space_capacity = &code_space_capacity;
- int map_space_size;
+ intptr_t map_space_size;
heap_stats.map_space_size = &map_space_size;
- int map_space_capacity;
+ intptr_t map_space_capacity;
heap_stats.map_space_capacity = &map_space_capacity;
- int cell_space_size;
+ intptr_t cell_space_size;
heap_stats.cell_space_size = &cell_space_size;
- int cell_space_capacity;
+ intptr_t cell_space_capacity;
heap_stats.cell_space_capacity = &cell_space_capacity;
- int lo_space_size;
+ intptr_t lo_space_size;
heap_stats.lo_space_size = &lo_space_size;
int global_handle_count;
heap_stats.global_handle_count = &global_handle_count;
@@ -166,9 +168,9 @@ void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
int destroyed_global_handle_count;
heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count;
- int memory_allocator_size;
+ intptr_t memory_allocator_size;
heap_stats.memory_allocator_size = &memory_allocator_size;
- int memory_allocator_capacity;
+ intptr_t memory_allocator_capacity;
heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
int objects_per_type[LAST_TYPE + 1] = {0};
heap_stats.objects_per_type = objects_per_type;
@@ -1135,13 +1137,13 @@ void ObjectTemplate::SetInternalFieldCount(int value) {
ScriptData* ScriptData::PreCompile(const char* input, int length) {
unibrow::Utf8InputBuffer<> buf(input, length);
- return i::PreParse(i::Handle<i::String>(), &buf, NULL);
+ return i::Parser::PreParse(i::Handle<i::String>(), &buf, NULL);
}
ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
i::Handle<i::String> str = Utils::OpenHandle(*source);
- return i::PreParse(str, NULL, NULL);
+ return i::Parser::PreParse(str, NULL, NULL);
}
@@ -1677,6 +1679,21 @@ Local<String> StackFrame::GetScriptName() const {
}
+Local<String> StackFrame::GetScriptNameOrSourceURL() const {
+ if (IsDeadCheck("v8::StackFrame::GetScriptNameOrSourceURL()")) {
+ return Local<String>();
+ }
+ ENTER_V8;
+ HandleScope scope;
+ i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+ i::Handle<i::Object> name = GetProperty(self, "scriptNameOrSourceURL");
+ if (!name->IsString()) {
+ return Local<String>();
+ }
+ return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
+}
+
+
Local<String> StackFrame::GetFunctionName() const {
if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
ENTER_V8;
@@ -1989,6 +2006,15 @@ void v8::Date::CheckCast(v8::Value* that) {
}
+void v8::RegExp::CheckCast(v8::Value* that) {
+ if (IsDeadCheck("v8::RegExp::Cast()")) return;
+ i::Handle<i::Object> obj = Utils::OpenHandle(that);
+ ApiCheck(obj->IsJSRegExp(),
+ "v8::RegExp::Cast()",
+ "Could not convert to regular expression");
+}
+
+
bool Value::BooleanValue() const {
if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
LOG_API("BooleanValue");
@@ -3710,6 +3736,57 @@ double v8::Date::NumberValue() const {
}
+static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
+ char flags_buf[3];
+ int num_flags = 0;
+ if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
+ if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
+ if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
+ ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
+ return i::Factory::LookupSymbol(
+ i::Vector<const char>(flags_buf, num_flags));
+}
+
+
+Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
+ Flags flags) {
+ EnsureInitialized("v8::RegExp::New()");
+ LOG_API("RegExp::New");
+ ENTER_V8;
+ EXCEPTION_PREAMBLE();
+ i::Handle<i::JSRegExp> obj = i::Execution::NewJSRegExp(
+ Utils::OpenHandle(*pattern),
+ RegExpFlagsToString(flags),
+ &has_pending_exception);
+ EXCEPTION_BAILOUT_CHECK(Local<v8::RegExp>());
+ return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
+}
+
+
+Local<v8::String> v8::RegExp::GetSource() const {
+ if (IsDeadCheck("v8::RegExp::GetSource()")) return Local<v8::String>();
+ i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
+ return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
+}
+
+
+// Assert that the static flags cast in GetFlags is valid.
+#define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \
+ STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \
+ static_cast<int>(i::JSRegExp::internal_flag))
+REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
+REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
+REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
+REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
+#undef REGEXP_FLAG_ASSERT_EQ
+
+v8::RegExp::Flags v8::RegExp::GetFlags() const {
+ if (IsDeadCheck("v8::RegExp::GetFlags()")) return v8::RegExp::kNone;
+ i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
+ return static_cast<RegExp::Flags>(obj->GetFlags().value());
+}
+
+
Local<v8::Array> v8::Array::New(int length) {
EnsureInitialized("v8::Array::New()");
LOG_API("Array::New");
@@ -4265,6 +4342,11 @@ void Debug::DebugBreak() {
}
+void Debug::CancelDebugBreak() {
+ i::StackGuard::Continue(i::DEBUGBREAK);
+}
+
+
void Debug::DebugBreakForCommand(ClientData* data) {
if (!i::V8::IsRunning()) return;
i::Debugger::EnqueueDebugCommand(data);
diff --git a/src/api.h b/src/api.h
index 5c671369..e179e356 100644
--- a/src/api.h
+++ b/src/api.h
@@ -174,6 +174,8 @@ class Utils {
v8::internal::Handle<v8::internal::JSFunction> obj);
static inline Local<String> ToLocal(
v8::internal::Handle<v8::internal::String> obj);
+ static inline Local<RegExp> ToLocal(
+ v8::internal::Handle<v8::internal::JSRegExp> obj);
static inline Local<Object> ToLocal(
v8::internal::Handle<v8::internal::JSObject> obj);
static inline Local<Array> ToLocal(
@@ -209,6 +211,8 @@ class Utils {
OpenHandle(const ObjectTemplate* that);
static inline v8::internal::Handle<v8::internal::Object>
OpenHandle(const Data* data);
+ static inline v8::internal::Handle<v8::internal::JSRegExp>
+ OpenHandle(const RegExp* data);
static inline v8::internal::Handle<v8::internal::JSObject>
OpenHandle(const v8::Object* data);
static inline v8::internal::Handle<v8::internal::JSArray>
@@ -265,6 +269,7 @@ MAKE_TO_LOCAL(ToLocal, Context, Context)
MAKE_TO_LOCAL(ToLocal, Object, Value)
MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
MAKE_TO_LOCAL(ToLocal, String, String)
+MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
MAKE_TO_LOCAL(ToLocal, JSObject, Object)
MAKE_TO_LOCAL(ToLocal, JSArray, Array)
MAKE_TO_LOCAL(ToLocal, Proxy, External)
@@ -297,6 +302,7 @@ MAKE_OPEN_HANDLE(ObjectTemplate, ObjectTemplateInfo)
MAKE_OPEN_HANDLE(Signature, SignatureInfo)
MAKE_OPEN_HANDLE(TypeSwitch, TypeSwitchInfo)
MAKE_OPEN_HANDLE(Data, Object)
+MAKE_OPEN_HANDLE(RegExp, JSRegExp)
MAKE_OPEN_HANDLE(Object, JSObject)
MAKE_OPEN_HANDLE(Array, JSArray)
MAKE_OPEN_HANDLE(String, String)
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 8f801cf9..b3b0766a 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -935,11 +935,8 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ orr(r2, r1, r0);
__ tst(r2, Operand(kSmiTagMask));
__ b(ne, &not_two_smis);
- __ sub(r0, r1, r0);
- __ b(vc, &smi_done);
- // Correct the sign in case of overflow.
- __ rsb(r0, r0, Operand(0, RelocInfo::NONE));
- __ bind(&smi_done);
+ __ mov(r1, Operand(r1, ASR, 1));
+ __ sub(r0, r1, Operand(r0, ASR, 1));
__ Ret();
__ bind(&not_two_smis);
} else if (FLAG_debug_code) {
@@ -2300,13 +2297,7 @@ Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
void StackCheckStub::Generate(MacroAssembler* masm) {
- // Do tail-call to runtime routine. Runtime routines expect at least one
- // argument, so give it a Smi.
- __ mov(r0, Operand(Smi::FromInt(0)));
- __ push(r0);
- __ TailCallRuntime(Runtime::kStackGuard, 1, 1);
-
- __ Ret();
+ __ TailCallRuntime(Runtime::kStackGuard, 0, 1);
}
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index d273e759..684106c3 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -175,7 +175,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Adjust for function-level loop nesting.
ASSERT_EQ(0, loop_nesting_);
- loop_nesting_ = info->loop_nesting();
+ loop_nesting_ = info->is_in_loop() ? 1 : 0;
{
CodeGenState state(this);
@@ -339,7 +339,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
}
// Adjust for function-level loop nesting.
- ASSERT(loop_nesting_ == info->loop_nesting());
+ ASSERT(loop_nesting_ == info->is_in_loop()? 1 : 0);
loop_nesting_ = 0;
// Code generation state must be reset.
@@ -3132,9 +3132,9 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
// Build the function info and instantiate it.
Handle<SharedFunctionInfo> function_info =
- Compiler::BuildFunctionInfo(node, script(), this);
- // Check for stack-overflow exception.
- if (HasStackOverflow()) {
+ Compiler::BuildFunctionInfo(node, script());
+ if (function_info.is_null()) {
+ SetStackOverflow();
ASSERT(frame_->height() == original_height);
return;
}
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 1483c0b5..e6fd6071 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -207,9 +207,7 @@ enum NopMarkerTypes {
class CodeGenerator: public AstVisitor {
public:
- // Takes a function literal, generates code for it. This function should only
- // be called by compiler.cc.
- static Handle<Code> MakeCode(CompilationInfo* info);
+ static bool MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(CompilationInfo* info);
@@ -449,9 +447,6 @@ class CodeGenerator: public AstVisitor {
void Branch(bool if_true, JumpTarget* target);
void CheckStack();
- static InlineFunctionGenerator FindInlineFunctionGenerator(
- Runtime::FunctionId function_id);
-
bool CheckForInlineRuntimeCall(CallRuntime* node);
static Handle<Code> ComputeLazyCompile(int argc);
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 9fc0c096..2855ca4f 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -62,6 +62,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator");
+#ifdef DEBUG
+ if (strlen(FLAG_stop_at) > 0 &&
+ info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+ __ stop("stop-at");
+ }
+#endif
+
int locals_count = scope()->num_stack_slots();
__ Push(lr, fp, cp, r1);
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index d5a700cd..7f83d14a 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -969,7 +969,8 @@ bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
bool LoadIC::PatchInlinedContextualLoad(Address address,
Object* map,
- Object* cell) {
+ Object* cell,
+ bool is_dont_delete) {
// TODO(<bug#>): implement this.
return false;
}
@@ -1584,8 +1585,9 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
// Check that the receiver isn't a smi.
__ BranchOnSmi(r1, &slow);
- // Check that the key is a smi.
- __ BranchOnNotSmi(r0, &slow);
+ // Check that the key is an array index, that is Uint32.
+ __ tst(r0, Operand(kSmiTagMask | kSmiSignMask));
+ __ b(ne, &slow);
// Get the map of the receiver.
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
diff --git a/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
index 8f45886d..37bb1f0a 100644
--- a/src/arm/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -142,7 +142,6 @@ int RegExpMacroAssemblerARM::stack_limit_slack() {
void RegExpMacroAssemblerARM::AdvanceCurrentPosition(int by) {
if (by != 0) {
- Label inside_string;
__ add(current_input_offset(),
current_input_offset(), Operand(by * char_size()));
}
@@ -927,6 +926,19 @@ void RegExpMacroAssemblerARM::ReadStackPointerFromRegister(int reg) {
}
+void RegExpMacroAssemblerARM::SetCurrentPositionFromEnd(int by) {
+ Label after_position;
+ __ cmp(current_input_offset(), Operand(-by * char_size()));
+ __ b(ge, &after_position);
+ __ mov(current_input_offset(), Operand(-by * char_size()));
+ // On RegExp code entry (where this operation is used), the character before
+ // the current position is expected to be already loaded.
+ // We have advanced the position, so it's safe to read backwards.
+ LoadCurrentCharacterUnchecked(-1, 1);
+ __ bind(&after_position);
+}
+
+
void RegExpMacroAssemblerARM::SetRegister(int register_index, int to) {
ASSERT(register_index >= num_saved_registers_); // Reserved for positions!
__ mov(r0, Operand(to));
diff --git a/src/arm/regexp-macro-assembler-arm.h b/src/arm/regexp-macro-assembler-arm.h
index 93a74d7c..4e09f671 100644
--- a/src/arm/regexp-macro-assembler-arm.h
+++ b/src/arm/regexp-macro-assembler-arm.h
@@ -100,6 +100,7 @@ class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
StackCheckFlag check_stack_limit);
virtual void ReadCurrentPositionFromRegister(int reg);
virtual void ReadStackPointerFromRegister(int reg);
+ virtual void SetCurrentPositionFromEnd(int by);
virtual void SetRegister(int register_index, int to);
virtual void Succeed();
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index 64262b2b..84d9d01d 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -37,7 +37,7 @@
#include "arm/constants-arm.h"
#include "arm/simulator-arm.h"
-#if !defined(__arm__)
+#if !defined(__arm__) || defined(USE_SIMULATOR)
// Only build the simulator if not compiling for real ARM hardware.
namespace assembler {
@@ -294,7 +294,7 @@ void Debugger::Debug() {
} else if (GetVFPSingleValue(arg1, &svalue)) {
PrintF("%s: %f \n", arg1, svalue);
} else if (GetVFPDoubleValue(arg1, &dvalue)) {
- PrintF("%s: %lf \n", arg1, dvalue);
+ PrintF("%s: %f \n", arg1, dvalue);
} else {
PrintF("%s unrecognized\n", arg1);
}
@@ -349,7 +349,8 @@ void Debugger::Debug() {
end = cur + words;
while (cur < end) {
- PrintF(" 0x%08x: 0x%08x %10d\n", cur, *cur, *cur);
+ PrintF(" 0x%08x: 0x%08x %10d\n",
+ reinterpret_cast<intptr_t>(cur), *cur, *cur);
cur++;
}
} else if (strcmp(cmd, "disasm") == 0) {
@@ -382,7 +383,8 @@ void Debugger::Debug() {
while (cur < end) {
dasm.InstructionDecode(buffer, cur);
- PrintF(" 0x%08x %s\n", cur, buffer.start());
+ PrintF(" 0x%08x %s\n",
+ reinterpret_cast<intptr_t>(cur), buffer.start());
cur += Instr::kInstrSize;
}
} else if (strcmp(cmd, "gdb") == 0) {
@@ -1061,7 +1063,7 @@ uintptr_t Simulator::StackLimit() const {
// Unsupported instructions use Format to print an error and stop execution.
void Simulator::Format(Instr* instr, const char* format) {
PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
- instr, format);
+ reinterpret_cast<intptr_t>(instr), format);
UNIMPLEMENTED();
}
@@ -2650,7 +2652,7 @@ void Simulator::InstructionDecode(Instr* instr) {
v8::internal::EmbeddedVector<char, 256> buffer;
dasm.InstructionDecode(buffer,
reinterpret_cast<byte*>(instr));
- PrintF(" 0x%08x %s\n", instr, buffer.start());
+ PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.start());
}
if (instr->ConditionField() == special_condition) {
DecodeUnconditional(instr);
@@ -2838,6 +2840,6 @@ uintptr_t Simulator::PopAddress() {
} } // namespace assembler::arm
-#endif // __arm__
+#endif // !__arm__ || USE_SIMULATOR
#endif // V8_TARGET_ARCH_ARM
diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
index fee296e4..d4c8250b 100644
--- a/src/arm/simulator-arm.h
+++ b/src/arm/simulator-arm.h
@@ -38,7 +38,7 @@
#include "allocation.h"
-#if defined(__arm__)
+#if defined(__arm__) && !defined(USE_SIMULATOR)
// When running without a simulator we call the entry directly.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
@@ -70,7 +70,7 @@ class SimulatorStack : public v8::internal::AllStatic {
reinterpret_cast<TryCatch*>(try_catch_address)
-#else // defined(__arm__)
+#else // !defined(__arm__) || defined(USE_SIMULATOR)
// When running with the simulator transition into simulated execution at this
// point.
@@ -356,6 +356,6 @@ class SimulatorStack : public v8::internal::AllStatic {
};
-#endif // defined(__arm__)
+#endif // !defined(__arm__) || defined(USE_SIMULATOR)
#endif // V8_ARM_SIMULATOR_ARM_H_
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 659f29c3..97f94952 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -1643,6 +1643,108 @@ Object* CallStubCompiler::CompileMathFloorCall(Object* object,
}
+Object* CallStubCompiler::CompileMathAbsCall(Object* object,
+ JSObject* holder,
+ JSGlobalPropertyCell* cell,
+ JSFunction* function,
+ String* name) {
+ // ----------- S t a t e -------------
+ // -- r2 : function name
+ // -- lr : return address
+ // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
+ // -- ...
+ // -- sp[argc * 4] : receiver
+ // -----------------------------------
+
+ const int argc = arguments().immediate();
+
+ // If the object is not a JSObject or we got an unexpected number of
+ // arguments, bail out to the regular call.
+ if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
+
+ Label miss;
+ GenerateNameCheck(name, &miss);
+
+ if (cell == NULL) {
+ __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
+
+ STATIC_ASSERT(kSmiTag == 0);
+ __ tst(r1, Operand(kSmiTagMask));
+ __ b(eq, &miss);
+
+ CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
+ &miss);
+ } else {
+ ASSERT(cell->value() == function);
+ GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
+ GenerateLoadFunctionFromCell(cell, function, &miss);
+ }
+
+ // Load the (only) argument into r0.
+ __ ldr(r0, MemOperand(sp, 0 * kPointerSize));
+
+ // Check if the argument is a smi.
+ Label not_smi;
+ STATIC_ASSERT(kSmiTag == 0);
+ __ BranchOnNotSmi(r0, &not_smi);
+
+ // Do bitwise not or do nothing depending on the sign of the
+ // argument.
+ __ eor(r1, r0, Operand(r0, ASR, kBitsPerInt - 1));
+
+ // Add 1 or do nothing depending on the sign of the argument.
+ __ sub(r0, r1, Operand(r0, ASR, kBitsPerInt - 1), SetCC);
+
+ // If the result is still negative, go to the slow case.
+ // This only happens for the most negative smi.
+ Label slow;
+ __ b(mi, &slow);
+
+ // Smi case done.
+ __ Drop(argc + 1);
+ __ Ret();
+
+ // Check if the argument is a heap number and load its exponent and
+ // sign.
+ __ bind(&not_smi);
+ __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, true);
+ __ ldr(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset));
+
+ // Check the sign of the argument. If the argument is positive,
+ // just return it.
+ Label negative_sign;
+ __ tst(r1, Operand(HeapNumber::kSignMask));
+ __ b(ne, &negative_sign);
+ __ Drop(argc + 1);
+ __ Ret();
+
+ // If the argument is negative, clear the sign, and return a new
+ // number.
+ __ bind(&negative_sign);
+ __ eor(r1, r1, Operand(HeapNumber::kSignMask));
+ __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
+ __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
+ __ AllocateHeapNumber(r0, r4, r5, r6, &slow);
+ __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset));
+ __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
+ __ Drop(argc + 1);
+ __ Ret();
+
+ // Tail call the full function. We do not have to patch the receiver
+ // because the function makes no use of it.
+ __ bind(&slow);
+ __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
+
+ __ bind(&miss);
+ // r2: function name.
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
+
+ // Return the generated code.
+ return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
+}
+
+
Object* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder,
JSFunction* function,
diff --git a/src/assembler.cc b/src/assembler.cc
index 6a46f615..b6efdb97 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -465,7 +465,7 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
void RelocInfo::Print() {
PrintF("%p %s", pc_, RelocModeName(rmode_));
if (IsComment(rmode_)) {
- PrintF(" (%s)", data_);
+ PrintF(" (%s)", reinterpret_cast<char*>(data_));
} else if (rmode_ == EMBEDDED_OBJECT) {
PrintF(" (");
target_object()->ShortPrint();
@@ -479,7 +479,7 @@ void RelocInfo::Print() {
Code* code = Code::GetCodeFromTargetAddress(target_address());
PrintF(" (%s) (%p)", Code::Kind2String(code->kind()), target_address());
} else if (IsPosition(rmode_)) {
- PrintF(" (%d)", data());
+ PrintF(" (%" V8_PTR_PREFIX "d)", data());
}
PrintF("\n");
diff --git a/src/ast.cc b/src/ast.cc
index f47dffd8..92f14961 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -398,39 +398,70 @@ Interval RegExpQuantifier::CaptureRegisters() {
}
-bool RegExpAssertion::IsAnchored() {
+bool RegExpAssertion::IsAnchoredAtStart() {
return type() == RegExpAssertion::START_OF_INPUT;
}
-bool RegExpAlternative::IsAnchored() {
+bool RegExpAssertion::IsAnchoredAtEnd() {
+ return type() == RegExpAssertion::END_OF_INPUT;
+}
+
+
+bool RegExpAlternative::IsAnchoredAtStart() {
ZoneList<RegExpTree*>* nodes = this->nodes();
for (int i = 0; i < nodes->length(); i++) {
RegExpTree* node = nodes->at(i);
- if (node->IsAnchored()) { return true; }
+ if (node->IsAnchoredAtStart()) { return true; }
+ if (node->max_match() > 0) { return false; }
+ }
+ return false;
+}
+
+
+bool RegExpAlternative::IsAnchoredAtEnd() {
+ ZoneList<RegExpTree*>* nodes = this->nodes();
+ for (int i = nodes->length() - 1; i >= 0; i--) {
+ RegExpTree* node = nodes->at(i);
+ if (node->IsAnchoredAtEnd()) { return true; }
if (node->max_match() > 0) { return false; }
}
return false;
}
-bool RegExpDisjunction::IsAnchored() {
+bool RegExpDisjunction::IsAnchoredAtStart() {
ZoneList<RegExpTree*>* alternatives = this->alternatives();
for (int i = 0; i < alternatives->length(); i++) {
- if (!alternatives->at(i)->IsAnchored())
+ if (!alternatives->at(i)->IsAnchoredAtStart())
return false;
}
return true;
}
-bool RegExpLookahead::IsAnchored() {
- return is_positive() && body()->IsAnchored();
+bool RegExpDisjunction::IsAnchoredAtEnd() {
+ ZoneList<RegExpTree*>* alternatives = this->alternatives();
+ for (int i = 0; i < alternatives->length(); i++) {
+ if (!alternatives->at(i)->IsAnchoredAtEnd())
+ return false;
+ }
+ return true;
+}
+
+
+bool RegExpLookahead::IsAnchoredAtStart() {
+ return is_positive() && body()->IsAnchoredAtStart();
+}
+
+
+bool RegExpCapture::IsAnchoredAtStart() {
+ return body()->IsAnchoredAtStart();
}
-bool RegExpCapture::IsAnchored() {
- return body()->IsAnchored();
+bool RegExpCapture::IsAnchoredAtEnd() {
+ return body()->IsAnchoredAtEnd();
}
diff --git a/src/ast.h b/src/ast.h
index eadb310d..a01e48da 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -118,35 +118,38 @@ typedef ZoneList<Handle<String> > ZoneStringList;
typedef ZoneList<Handle<Object> > ZoneObjectList;
+#define DECLARE_NODE_TYPE(type) \
+ virtual void Accept(AstVisitor* v); \
+ virtual AstNode::Type node_type() const { return AstNode::k##type; } \
+ virtual type* As##type() { return this; }
+
+
class AstNode: public ZoneObject {
public:
+#define DECLARE_TYPE_ENUM(type) k##type,
+ enum Type {
+ AST_NODE_LIST(DECLARE_TYPE_ENUM)
+ kInvalid = -1
+ };
+#undef DECLARE_TYPE_ENUM
+
virtual ~AstNode() { }
+
virtual void Accept(AstVisitor* v) = 0;
+ virtual Type node_type() const { return kInvalid; }
+
+ // Type testing & conversion functions overridden by concrete subclasses.
+#define DECLARE_NODE_FUNCTIONS(type) \
+ virtual type* As##type() { return NULL; }
+ AST_NODE_LIST(DECLARE_NODE_FUNCTIONS)
+#undef DECLARE_NODE_FUNCTIONS
- // Type testing & conversion.
virtual Statement* AsStatement() { return NULL; }
- virtual Block* AsBlock() { return NULL; }
- virtual ExpressionStatement* AsExpressionStatement() { return NULL; }
- virtual EmptyStatement* AsEmptyStatement() { return NULL; }
virtual Expression* AsExpression() { return NULL; }
- virtual Literal* AsLiteral() { return NULL; }
- virtual Slot* AsSlot() { return NULL; }
- virtual VariableProxy* AsVariableProxy() { return NULL; }
- virtual Property* AsProperty() { return NULL; }
- virtual Call* AsCall() { return NULL; }
virtual TargetCollector* AsTargetCollector() { return NULL; }
virtual BreakableStatement* AsBreakableStatement() { return NULL; }
virtual IterationStatement* AsIterationStatement() { return NULL; }
- virtual ForStatement* AsForStatement() { 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; }
virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; }
- virtual ObjectLiteral* AsObjectLiteral() { return NULL; }
- virtual ArrayLiteral* AsArrayLiteral() { return NULL; }
- virtual CompareOperation* AsCompareOperation() { return NULL; }
};
@@ -155,7 +158,6 @@ class Statement: public AstNode {
Statement() : statement_pos_(RelocInfo::kNoPosition) {}
virtual Statement* AsStatement() { return this; }
- virtual ReturnStatement* AsReturnStatement() { return NULL; }
virtual Assignment* StatementAsSimpleAssignment() { return NULL; }
virtual CountOperation* StatementAsCountOperation() { return NULL; }
@@ -313,9 +315,7 @@ class Block: public BreakableStatement {
public:
inline Block(ZoneStringList* labels, int capacity, bool is_initializer_block);
- virtual void Accept(AstVisitor* v);
-
- virtual Block* AsBlock() { return this; }
+ DECLARE_NODE_TYPE(Block)
virtual Assignment* StatementAsSimpleAssignment() {
if (statements_.length() != 1) return NULL;
@@ -349,7 +349,7 @@ class Declaration: public AstNode {
ASSERT(fun == NULL || mode == Variable::VAR);
}
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(Declaration)
VariableProxy* proxy() const { return proxy_; }
Variable::Mode mode() const { return mode_; }
@@ -390,13 +390,13 @@ class DoWhileStatement: public IterationStatement {
public:
explicit inline DoWhileStatement(ZoneStringList* labels);
+ DECLARE_NODE_TYPE(DoWhileStatement)
+
void Initialize(Expression* cond, Statement* body) {
IterationStatement::Initialize(body);
cond_ = cond;
}
- virtual void Accept(AstVisitor* v);
-
Expression* cond() const { return cond_; }
// Position where condition expression starts. We need it to make
@@ -414,13 +414,13 @@ class WhileStatement: public IterationStatement {
public:
explicit WhileStatement(ZoneStringList* labels);
+ DECLARE_NODE_TYPE(WhileStatement)
+
void Initialize(Expression* cond, Statement* body) {
IterationStatement::Initialize(body);
cond_ = cond;
}
- virtual void Accept(AstVisitor* v);
-
Expression* cond() const { return cond_; }
bool may_have_function_literal() const {
return may_have_function_literal_;
@@ -440,7 +440,7 @@ class ForStatement: public IterationStatement {
public:
explicit inline ForStatement(ZoneStringList* labels);
- virtual ForStatement* AsForStatement() { return this; }
+ DECLARE_NODE_TYPE(ForStatement)
void Initialize(Statement* init,
Expression* cond,
@@ -452,8 +452,6 @@ class ForStatement: public IterationStatement {
next_ = next;
}
- virtual void Accept(AstVisitor* v);
-
Statement* init() const { return init_; }
void set_init(Statement* stmt) { init_ = stmt; }
Expression* cond() const { return cond_; }
@@ -486,14 +484,14 @@ class ForInStatement: public IterationStatement {
public:
explicit inline ForInStatement(ZoneStringList* labels);
+ DECLARE_NODE_TYPE(ForInStatement)
+
void Initialize(Expression* each, Expression* enumerable, Statement* body) {
IterationStatement::Initialize(body);
each_ = each;
enumerable_ = enumerable;
}
- virtual void Accept(AstVisitor* v);
-
Expression* each() const { return each_; }
Expression* enumerable() const { return enumerable_; }
@@ -508,10 +506,7 @@ class ExpressionStatement: public Statement {
explicit ExpressionStatement(Expression* expression)
: expression_(expression) { }
- virtual void Accept(AstVisitor* v);
-
- // Type testing & conversion.
- virtual ExpressionStatement* AsExpressionStatement() { return this; }
+ DECLARE_NODE_TYPE(ExpressionStatement)
virtual Assignment* StatementAsSimpleAssignment();
virtual CountOperation* StatementAsCountOperation();
@@ -529,7 +524,7 @@ class ContinueStatement: public Statement {
explicit ContinueStatement(IterationStatement* target)
: target_(target) { }
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(ContinueStatement)
IterationStatement* target() const { return target_; }
@@ -543,7 +538,7 @@ class BreakStatement: public Statement {
explicit BreakStatement(BreakableStatement* target)
: target_(target) { }
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(BreakStatement)
BreakableStatement* target() const { return target_; }
@@ -557,10 +552,7 @@ class ReturnStatement: public Statement {
explicit ReturnStatement(Expression* expression)
: expression_(expression) { }
- virtual void Accept(AstVisitor* v);
-
- // Type testing & conversion.
- virtual ReturnStatement* AsReturnStatement() { return this; }
+ DECLARE_NODE_TYPE(ReturnStatement)
Expression* expression() { return expression_; }
@@ -574,7 +566,7 @@ class WithEnterStatement: public Statement {
explicit WithEnterStatement(Expression* expression, bool is_catch_block)
: expression_(expression), is_catch_block_(is_catch_block) { }
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(WithEnterStatement)
Expression* expression() const { return expression_; }
@@ -590,7 +582,7 @@ class WithExitStatement: public Statement {
public:
WithExitStatement() { }
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(WithExitStatement)
};
@@ -617,13 +609,13 @@ class SwitchStatement: public BreakableStatement {
public:
explicit inline SwitchStatement(ZoneStringList* labels);
+ DECLARE_NODE_TYPE(SwitchStatement)
+
void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) {
tag_ = tag;
cases_ = cases;
}
- virtual void Accept(AstVisitor* v);
-
Expression* tag() const { return tag_; }
ZoneList<CaseClause*>* cases() const { return cases_; }
@@ -647,7 +639,7 @@ class IfStatement: public Statement {
then_statement_(then_statement),
else_statement_(else_statement) { }
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(IfStatement)
bool HasThenStatement() const { return !then_statement()->IsEmpty(); }
bool HasElseStatement() const { return !else_statement()->IsEmpty(); }
@@ -717,7 +709,7 @@ class TryCatchStatement: public TryStatement {
catch_block_(catch_block) {
}
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(TryCatchStatement)
VariableProxy* catch_var() const { return catch_var_; }
Block* catch_block() const { return catch_block_; }
@@ -734,7 +726,7 @@ class TryFinallyStatement: public TryStatement {
: TryStatement(try_block),
finally_block_(finally_block) { }
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(TryFinallyStatement)
Block* finally_block() const { return finally_block_; }
@@ -745,18 +737,13 @@ class TryFinallyStatement: public TryStatement {
class DebuggerStatement: public Statement {
public:
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(DebuggerStatement)
};
class EmptyStatement: public Statement {
public:
- EmptyStatement() {}
-
- virtual void Accept(AstVisitor* v);
-
- // Type testing & conversion.
- virtual EmptyStatement* AsEmptyStatement() { return this; }
+ DECLARE_NODE_TYPE(EmptyStatement)
};
@@ -764,13 +751,11 @@ class Literal: public Expression {
public:
explicit Literal(Handle<Object> handle) : handle_(handle) { }
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(Literal)
+
virtual bool IsTrivial() { return true; }
virtual bool IsSmiLiteral() { return handle_->IsSmi(); }
- // Type testing & conversion.
- virtual Literal* AsLiteral() { return this; }
-
// Check if this literal is identical to the other literal.
bool IsIdenticalTo(const Literal* other) const {
return handle_.is_identical_to(other->handle_);
@@ -864,8 +849,7 @@ class ObjectLiteral: public MaterializedLiteral {
properties_(properties),
fast_elements_(fast_elements) {}
- virtual ObjectLiteral* AsObjectLiteral() { return this; }
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(ObjectLiteral)
Handle<FixedArray> constant_properties() const {
return constant_properties_;
@@ -891,7 +875,7 @@ class RegExpLiteral: public MaterializedLiteral {
pattern_(pattern),
flags_(flags) {}
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(RegExpLiteral)
Handle<String> pattern() const { return pattern_; }
Handle<String> flags() const { return flags_; }
@@ -914,8 +898,7 @@ class ArrayLiteral: public MaterializedLiteral {
constant_elements_(constant_elements),
values_(values) {}
- virtual void Accept(AstVisitor* v);
- virtual ArrayLiteral* AsArrayLiteral() { return this; }
+ DECLARE_NODE_TYPE(ArrayLiteral)
Handle<FixedArray> constant_elements() const { return constant_elements_; }
ZoneList<Expression*>* values() const { return values_; }
@@ -935,7 +918,7 @@ class CatchExtensionObject: public Expression {
: key_(key), value_(value) {
}
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(CatchExtensionObject)
Literal* key() const { return key_; }
VariableProxy* value() const { return value_; }
@@ -950,17 +933,13 @@ class VariableProxy: public Expression {
public:
explicit VariableProxy(Variable* var);
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(VariableProxy)
// Type testing & conversion
virtual Property* AsProperty() {
return var_ == NULL ? NULL : var_->AsProperty();
}
- virtual VariableProxy* AsVariableProxy() {
- return this;
- }
-
Variable* AsVariable() {
if (this == NULL || var_ == NULL) return NULL;
Expression* rewrite = var_->rewrite();
@@ -1055,10 +1034,7 @@ class Slot: public Expression {
ASSERT(var != NULL);
}
- virtual void Accept(AstVisitor* v);
-
- // Type testing & conversion
- virtual Slot* AsSlot() { return this; }
+ DECLARE_NODE_TYPE(Slot)
bool IsStackAllocated() { return type_ == PARAMETER || type_ == LOCAL; }
@@ -1085,10 +1061,7 @@ class Property: public Expression {
Property(Expression* obj, Expression* key, int pos, Type type = NORMAL)
: obj_(obj), key_(key), pos_(pos), type_(type) { }
- virtual void Accept(AstVisitor* v);
-
- // Type testing & conversion
- virtual Property* AsProperty() { return this; }
+ DECLARE_NODE_TYPE(Property)
virtual bool IsValidLeftHandSide() { return true; }
@@ -1117,10 +1090,7 @@ class Call: public Expression {
Call(Expression* expression, ZoneList<Expression*>* arguments, int pos)
: expression_(expression), arguments_(arguments), pos_(pos) { }
- virtual void Accept(AstVisitor* v);
-
- // Type testing and conversion.
- virtual Call* AsCall() { return this; }
+ DECLARE_NODE_TYPE(Call)
Expression* expression() const { return expression_; }
ZoneList<Expression*>* arguments() const { return arguments_; }
@@ -1142,7 +1112,7 @@ class CallNew: public Expression {
CallNew(Expression* expression, ZoneList<Expression*>* arguments, int pos)
: expression_(expression), arguments_(arguments), pos_(pos) { }
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(CallNew)
Expression* expression() const { return expression_; }
ZoneList<Expression*>* arguments() const { return arguments_; }
@@ -1166,7 +1136,7 @@ class CallRuntime: public Expression {
ZoneList<Expression*>* arguments)
: name_(name), function_(function), arguments_(arguments) { }
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(CallRuntime)
Handle<String> name() const { return name_; }
Runtime::Function* function() const { return function_; }
@@ -1187,11 +1157,9 @@ class UnaryOperation: public Expression {
ASSERT(Token::IsUnaryOp(op));
}
- virtual void Accept(AstVisitor* v);
- virtual bool ResultOverwriteAllowed();
+ DECLARE_NODE_TYPE(UnaryOperation)
- // Type testing & conversion
- virtual UnaryOperation* AsUnaryOperation() { return this; }
+ virtual bool ResultOverwriteAllowed();
Token::Value op() const { return op_; }
Expression* expression() const { return expression_; }
@@ -1215,11 +1183,9 @@ class BinaryOperation: public Expression {
// Create the binary operation corresponding to a compound assignment.
explicit BinaryOperation(Assignment* assignment);
- virtual void Accept(AstVisitor* v);
- virtual bool ResultOverwriteAllowed();
+ DECLARE_NODE_TYPE(BinaryOperation)
- // Type testing & conversion
- virtual BinaryOperation* AsBinaryOperation() { return this; }
+ virtual bool ResultOverwriteAllowed();
Token::Value op() const { return op_; }
Expression* left() const { return left_; }
@@ -1241,12 +1207,12 @@ class IncrementOperation: public Expression {
ASSERT(Token::IsCountOp(op));
}
+ DECLARE_NODE_TYPE(IncrementOperation)
+
Token::Value op() const { return op_; }
bool is_increment() { return op_ == Token::INC; }
Expression* expression() const { return expression_; }
- virtual void Accept(AstVisitor* v);
-
private:
Token::Value op_;
Expression* expression_;
@@ -1259,9 +1225,7 @@ class CountOperation: public Expression {
CountOperation(bool is_prefix, IncrementOperation* increment, int pos)
: is_prefix_(is_prefix), increment_(increment), pos_(pos) { }
- virtual void Accept(AstVisitor* v);
-
- virtual CountOperation* AsCountOperation() { return this; }
+ DECLARE_NODE_TYPE(CountOperation)
bool is_prefix() const { return is_prefix_; }
bool is_postfix() const { return !is_prefix_; }
@@ -1294,16 +1258,13 @@ class CompareOperation: public Expression {
ASSERT(Token::IsCompareOp(op));
}
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(CompareOperation)
Token::Value op() const { return op_; }
Expression* left() const { return left_; }
Expression* right() const { return right_; }
int position() const { return pos_; }
- // Type testing & conversion
- virtual CompareOperation* AsCompareOperation() { return this; }
-
private:
Token::Value op_;
Expression* left_;
@@ -1317,7 +1278,7 @@ class CompareToNull: public Expression {
CompareToNull(bool is_strict, Expression* expression)
: is_strict_(is_strict), expression_(expression) { }
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(CompareToNull)
bool is_strict() const { return is_strict_; }
Token::Value op() const { return is_strict_ ? Token::EQ_STRICT : Token::EQ; }
@@ -1342,7 +1303,7 @@ class Conditional: public Expression {
then_expression_position_(then_expression_position),
else_expression_position_(else_expression_position) { }
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(Conditional)
Expression* condition() const { return condition_; }
Expression* then_expression() const { return then_expression_; }
@@ -1368,8 +1329,7 @@ class Assignment: public Expression {
ASSERT(Token::IsAssignmentOp(op));
}
- virtual void Accept(AstVisitor* v);
- virtual Assignment* AsAssignment() { return this; }
+ DECLARE_NODE_TYPE(Assignment)
Assignment* AsSimpleAssignment() { return !is_compound() ? this : NULL; }
@@ -1406,7 +1366,7 @@ class Throw: public Expression {
Throw(Expression* exception, int pos)
: exception_(exception), pos_(pos) {}
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(Throw)
Expression* exception() const { return exception_; }
int position() const { return pos_; }
@@ -1452,10 +1412,7 @@ class FunctionLiteral: public Expression {
#endif
}
- virtual void Accept(AstVisitor* v);
-
- // Type testing & conversion
- virtual FunctionLiteral* AsFunctionLiteral() { return this; }
+ DECLARE_NODE_TYPE(FunctionLiteral)
Handle<String> name() const { return name_; }
Scope* scope() const { return scope_; }
@@ -1479,6 +1436,11 @@ class FunctionLiteral: public Expression {
bool AllowsLazyCompilation();
+ Handle<String> debug_name() const {
+ if (name_->length() > 0) return name_;
+ return inferred_name();
+ }
+
Handle<String> inferred_name() const { return inferred_name_; }
void set_inferred_name(Handle<String> inferred_name) {
inferred_name_ = inferred_name;
@@ -1522,12 +1484,12 @@ class SharedFunctionInfoLiteral: public Expression {
Handle<SharedFunctionInfo> shared_function_info)
: shared_function_info_(shared_function_info) { }
+ DECLARE_NODE_TYPE(SharedFunctionInfoLiteral)
+
Handle<SharedFunctionInfo> shared_function_info() const {
return shared_function_info_;
}
- virtual void Accept(AstVisitor* v);
-
private:
Handle<SharedFunctionInfo> shared_function_info_;
};
@@ -1535,7 +1497,7 @@ class SharedFunctionInfoLiteral: public Expression {
class ThisFunction: public Expression {
public:
- virtual void Accept(AstVisitor* v);
+ DECLARE_NODE_TYPE(ThisFunction)
};
@@ -1561,7 +1523,8 @@ class RegExpTree: public ZoneObject {
virtual RegExpNode* ToNode(RegExpCompiler* compiler,
RegExpNode* on_success) = 0;
virtual bool IsTextElement() { return false; }
- virtual bool IsAnchored() { return false; }
+ virtual bool IsAnchoredAtStart() { return false; }
+ virtual bool IsAnchoredAtEnd() { return false; }
virtual int min_match() = 0;
virtual int max_match() = 0;
// Returns the interval of registers used for captures within this
@@ -1586,7 +1549,8 @@ class RegExpDisjunction: public RegExpTree {
virtual RegExpDisjunction* AsDisjunction();
virtual Interval CaptureRegisters();
virtual bool IsDisjunction();
- virtual bool IsAnchored();
+ virtual bool IsAnchoredAtStart();
+ virtual bool IsAnchoredAtEnd();
virtual int min_match() { return min_match_; }
virtual int max_match() { return max_match_; }
ZoneList<RegExpTree*>* alternatives() { return alternatives_; }
@@ -1606,7 +1570,8 @@ class RegExpAlternative: public RegExpTree {
virtual RegExpAlternative* AsAlternative();
virtual Interval CaptureRegisters();
virtual bool IsAlternative();
- virtual bool IsAnchored();
+ virtual bool IsAnchoredAtStart();
+ virtual bool IsAnchoredAtEnd();
virtual int min_match() { return min_match_; }
virtual int max_match() { return max_match_; }
ZoneList<RegExpTree*>* nodes() { return nodes_; }
@@ -1633,7 +1598,8 @@ class RegExpAssertion: public RegExpTree {
RegExpNode* on_success);
virtual RegExpAssertion* AsAssertion();
virtual bool IsAssertion();
- virtual bool IsAnchored();
+ virtual bool IsAnchoredAtStart();
+ virtual bool IsAnchoredAtEnd();
virtual int min_match() { return 0; }
virtual int max_match() { return 0; }
Type type() { return type_; }
@@ -1806,7 +1772,8 @@ class RegExpCapture: public RegExpTree {
RegExpCompiler* compiler,
RegExpNode* on_success);
virtual RegExpCapture* AsCapture();
- virtual bool IsAnchored();
+ virtual bool IsAnchoredAtStart();
+ virtual bool IsAnchoredAtEnd();
virtual Interval CaptureRegisters();
virtual bool IsCapture();
virtual int min_match() { return body_->min_match(); }
@@ -1838,7 +1805,7 @@ class RegExpLookahead: public RegExpTree {
virtual RegExpLookahead* AsLookahead();
virtual Interval CaptureRegisters();
virtual bool IsLookahead();
- virtual bool IsAnchored();
+ virtual bool IsAnchoredAtStart();
virtual int min_match() { return 0; }
virtual int max_match() { return 0; }
RegExpTree* body() { return body_; }
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index aa8d8e5a..d7491e1f 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1814,6 +1814,11 @@ Genesis::Genesis(Handle<Object> global_object,
i::Counters::contexts_created_from_scratch.Increment();
}
+ // Add this context to the weak list of global contexts.
+ (*global_context_)->set(Context::NEXT_CONTEXT_LINK,
+ Heap::global_contexts_list());
+ Heap::set_global_contexts_list(*global_context_);
+
result_ = global_context_;
}
diff --git a/src/bytecodes-irregexp.h b/src/bytecodes-irregexp.h
index bcb34c89..93218ea9 100644
--- a/src/bytecodes-irregexp.h
+++ b/src/bytecodes-irregexp.h
@@ -88,7 +88,8 @@ V(CHECK_REGISTER_EQ_POS, 43, 8) /* bc8 reg_idx24 addr32 */ \
V(CHECK_AT_START, 44, 8) /* bc8 pad24 addr32 */ \
V(CHECK_NOT_AT_START, 45, 8) /* bc8 pad24 addr32 */ \
V(CHECK_GREEDY, 46, 8) /* bc8 pad24 addr32 */ \
-V(ADVANCE_CP_AND_GOTO, 47, 8) /* bc8 offset24 addr32 */
+V(ADVANCE_CP_AND_GOTO, 47, 8) /* bc8 offset24 addr32 */ \
+V(SET_CURRENT_POSITION_FROM_END, 48, 4) /* bc8 idx24 */
#define DECLARE_BYTECODES(name, code, length) \
static const int BC_##name = code;
diff --git a/src/cached-powers.cc b/src/cached-powers.cc
new file mode 100644
index 00000000..8f822862
--- /dev/null
+++ b/src/cached-powers.cc
@@ -0,0 +1,152 @@
+// Copyright 2006-2008 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 <stdarg.h>
+#include <limits.h>
+
+#include "v8.h"
+
+#include "cached-powers.h"
+
+namespace v8 {
+namespace internal {
+
+struct CachedPower {
+ uint64_t significand;
+ int16_t binary_exponent;
+ int16_t decimal_exponent;
+};
+
+static const CachedPower kCachedPowers[] = {
+ {V8_2PART_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {V8_2PART_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
+ {V8_2PART_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
+ {V8_2PART_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
+ {V8_2PART_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
+ {V8_2PART_UINT64_C(0xd3515c28, 31559a83), -954, -268},
+ {V8_2PART_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
+ {V8_2PART_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
+ {V8_2PART_UINT64_C(0xaecc4991, 4078536d), -874, -244},
+ {V8_2PART_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
+ {V8_2PART_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
+ {V8_2PART_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
+ {V8_2PART_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
+ {V8_2PART_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
+ {V8_2PART_UINT64_C(0xef340a98, 172aace5), -715, -196},
+ {V8_2PART_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
+ {V8_2PART_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
+ {V8_2PART_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
+ {V8_2PART_UINT64_C(0x936b9fce, bb25c996), -608, -164},
+ {V8_2PART_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
+ {V8_2PART_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+ {V8_2PART_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
+ {V8_2PART_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
+ {V8_2PART_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
+ {V8_2PART_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
+ {V8_2PART_UINT64_C(0x964e858c, 91ba2655), -422, -108},
+ {V8_2PART_UINT64_C(0xdff97724, 70297ebd), -396, -100},
+ {V8_2PART_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+ {V8_2PART_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
+ {V8_2PART_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
+ {V8_2PART_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {V8_2PART_UINT64_C(0xcdb02555, 653131b6), -263, -60},
+ {V8_2PART_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
+ {V8_2PART_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
+ {V8_2PART_UINT64_C(0xaa242499, 697392d3), -183, -36},
+ {V8_2PART_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
+ {V8_2PART_UINT64_C(0xbce50864, 92111aeb), -130, -20},
+ {V8_2PART_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
+ {V8_2PART_UINT64_C(0xd1b71758, e219652c), -77, -4},
+ {V8_2PART_UINT64_C(0x9c400000, 00000000), -50, 4},
+ {V8_2PART_UINT64_C(0xe8d4a510, 00000000), -24, 12},
+ {V8_2PART_UINT64_C(0xad78ebc5, ac620000), 3, 20},
+ {V8_2PART_UINT64_C(0x813f3978, f8940984), 30, 28},
+ {V8_2PART_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
+ {V8_2PART_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
+ {V8_2PART_UINT64_C(0xd5d238a4, abe98068), 109, 52},
+ {V8_2PART_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
+ {V8_2PART_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
+ {V8_2PART_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
+ {V8_2PART_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
+ {V8_2PART_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
+ {V8_2PART_UINT64_C(0x924d692c, a61be758), 269, 100},
+ {V8_2PART_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
+ {V8_2PART_UINT64_C(0xa26da399, 9aef774a), 322, 116},
+ {V8_2PART_UINT64_C(0xf209787b, b47d6b85), 348, 124},
+ {V8_2PART_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
+ {V8_2PART_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
+ {V8_2PART_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
+ {V8_2PART_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
+ {V8_2PART_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
+ {V8_2PART_UINT64_C(0xa59bc234, db398c25), 508, 172},
+ {V8_2PART_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
+ {V8_2PART_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
+ {V8_2PART_UINT64_C(0x88fcf317, f22241e2), 588, 196},
+ {V8_2PART_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
+ {V8_2PART_UINT64_C(0x98165af3, 7b2153df), 641, 212},
+ {V8_2PART_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
+ {V8_2PART_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
+ {V8_2PART_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
+ {V8_2PART_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
+ {V8_2PART_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
+ {V8_2PART_UINT64_C(0xd01fef10, a657842c), 800, 260},
+ {V8_2PART_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
+ {V8_2PART_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
+ {V8_2PART_UINT64_C(0xac2820d9, 623bf429), 880, 284},
+ {V8_2PART_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {V8_2PART_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
+ {V8_2PART_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
+ {V8_2PART_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
+ {V8_2PART_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
+ {V8_2PART_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
+ {V8_2PART_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+};
+
+static const int kCachedPowersLength = ARRAY_SIZE(kCachedPowers);
+static const int kCachedPowersOffset = -kCachedPowers[0].decimal_exponent;
+static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
+static const int kCachedPowersDecimalDistance =
+ kCachedPowers[1].decimal_exponent - kCachedPowers[0].decimal_exponent;
+
+void GetCachedPowerForBinaryExponentRange(int min_exponent,
+ int max_exponent,
+ DiyFp* power,
+ int* decimal_exponent) {
+ int kQ = DiyFp::kSignificandSize;
+ double k = ceiling((min_exponent + kQ - 1) * kD_1_LOG2_10);
+ int foo = kCachedPowersOffset;
+ int index =
+ (foo + static_cast<int>(k) - 1) / kCachedPowersDecimalDistance + 1;
+ ASSERT(0 <= index && index < kCachedPowersLength);
+ CachedPower cached_power = kCachedPowers[index];
+ ASSERT(min_exponent <= cached_power.binary_exponent);
+ ASSERT(cached_power.binary_exponent <= max_exponent);
+ *decimal_exponent = cached_power.decimal_exponent;
+ *power = DiyFp(cached_power.significand, cached_power.binary_exponent);
+}
+
+} } // namespace v8::internal
diff --git a/src/cached-powers.h b/src/cached-powers.h
index 314ccca3..0c783431 100644
--- a/src/cached-powers.h
+++ b/src/cached-powers.h
@@ -33,86 +33,10 @@
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
+void GetCachedPowerForBinaryExponentRange(int min_exponent,
+ int max_exponent,
+ DiyFp* power,
+ int* decimal_exponent);
} } // namespace v8::internal
diff --git a/src/codegen.cc b/src/codegen.cc
index 92241d1c..bda697ab 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -206,10 +206,9 @@ Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
}
-// Generate the code. Takes a function literal, generates code for it, assemble
-// all the pieces into a Code object. This function is only to be called by
-// the compiler.cc code.
-Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
+// Generate the code. Compile the AST and assemble all the pieces into a
+// Code object.
+bool CodeGenerator::MakeCode(CompilationInfo* info) {
Handle<Script> script = info->script();
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
int len = String::cast(script->source())->length();
@@ -224,12 +223,14 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
cgen.Generate(info);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
- return Handle<Code>::null();
+ return false;
}
- InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP;
+ InLoopFlag in_loop = info->is_in_loop() ? IN_LOOP : NOT_IN_LOOP;
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
- return MakeCodeEpilogue(cgen.masm(), flags, info);
+ Handle<Code> code = MakeCodeEpilogue(cgen.masm(), flags, info);
+ info->SetCode(code); // May be an empty handle.
+ return !code.is_null();
}
@@ -325,9 +326,12 @@ void CodeGenerator::ProcessDeclarations(ZoneList<Declaration*>* declarations) {
}
} else {
Handle<SharedFunctionInfo> function =
- Compiler::BuildFunctionInfo(node->fun(), script(), this);
+ Compiler::BuildFunctionInfo(node->fun(), script());
// Check for stack-overflow exception.
- if (HasStackOverflow()) return;
+ if (function.is_null()) {
+ SetStackOverflow();
+ return;
+ }
array->set(j++, *function);
}
}
@@ -357,24 +361,19 @@ const CodeGenerator::InlineFunctionGenerator
#undef INLINE_FUNCTION_GENERATOR_ADDRESS
-CodeGenerator::InlineFunctionGenerator
- CodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
- return kInlineFunctionGenerators[
- static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction)];
-}
-
-
bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
ZoneList<Expression*>* args = node->arguments();
Handle<String> name = node->name();
Runtime::Function* function = node->function();
if (function != NULL && function->intrinsic_type == Runtime::INLINE) {
- InlineFunctionGenerator generator =
- FindInlineFunctionGenerator(function->function_id);
- if (generator != NULL) {
- ((*this).*(generator))(args);
- return true;
- }
+ int lookup_index = static_cast<int>(function->function_id) -
+ static_cast<int>(Runtime::kFirstInlineFunction);
+ ASSERT(lookup_index >= 0);
+ ASSERT(static_cast<size_t>(lookup_index) <
+ ARRAY_SIZE(kInlineFunctionGenerators));
+ InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
+ (this->*generator)(args);
+ return true;
}
return false;
}
diff --git a/src/codegen.h b/src/codegen.h
index 2a4d9d4c..8f923dd3 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -62,7 +62,6 @@
// ComputeCallInitializeInLoop
// ProcessDeclarations
// DeclareGlobals
-// FindInlineRuntimeLUT
// CheckForInlineRuntimeCall
// AnalyzeCondition
// CodeForFunctionPosition
diff --git a/src/compiler.cc b/src/compiler.cc
index 825198ed..6cc09713 100755
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -27,22 +27,58 @@
#include "v8.h"
+#include "compiler.h"
+
#include "bootstrapper.h"
#include "codegen-inl.h"
#include "compilation-cache.h"
-#include "compiler.h"
#include "data-flow.h"
#include "debug.h"
#include "full-codegen.h"
#include "liveedit.h"
#include "oprofile-agent.h"
+#include "parser.h"
#include "rewriter.h"
-#include "scopes.h"
#include "scopeinfo.h"
+#include "scopes.h"
namespace v8 {
namespace internal {
+
+CompilationInfo::CompilationInfo(Handle<Script> script)
+ : flags_(0),
+ function_(NULL),
+ scope_(NULL),
+ script_(script),
+ extension_(NULL),
+ pre_parse_data_(NULL) {
+}
+
+
+CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info)
+ : flags_(IsLazy::encode(true)),
+ function_(NULL),
+ scope_(NULL),
+ shared_info_(shared_info),
+ script_(Handle<Script>(Script::cast(shared_info->script()))),
+ extension_(NULL),
+ pre_parse_data_(NULL) {
+}
+
+
+CompilationInfo::CompilationInfo(Handle<JSFunction> closure)
+ : flags_(IsLazy::encode(true)),
+ function_(NULL),
+ scope_(NULL),
+ closure_(closure),
+ shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
+ script_(Handle<Script>(Script::cast(shared_info_->script()))),
+ extension_(NULL),
+ pre_parse_data_(NULL) {
+}
+
+
// For normal operation the syntax checker is used to determine whether to
// use the full compiler for top level code or not. However if the flag
// --always-full-compiler is specified or debugging is active the full
@@ -56,102 +92,74 @@ static bool AlwaysFullCompiler() {
}
-static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) {
- FunctionLiteral* function = info->function();
- ASSERT(function != NULL);
- // Rewrite the AST by introducing .result assignments where needed.
- if (!Rewriter::Process(function)) {
- // Signal a stack overflow by returning a null handle. The stack
- // overflow exception will be thrown by the caller.
- return Handle<Code>::null();
- }
-
- {
- // Compute top scope and allocate variables. For lazy compilation
- // the top scope only contains the single lazily compiled function,
- // so this doesn't re-allocate variables repeatedly.
- HistogramTimerScope timer(&Counters::variable_allocation);
- Scope* top = info->scope();
- while (top->outer_scope() != NULL) top = top->outer_scope();
- top->AllocateVariables(context);
- }
-
-#ifdef DEBUG
- if (Bootstrapper::IsActive() ?
- FLAG_print_builtin_scopes :
- FLAG_print_scopes) {
- info->scope()->Print();
- }
-#endif
-
- // Optimize the AST.
- if (!Rewriter::Optimize(function)) {
- // Signal a stack overflow by returning a null handle. The stack
- // overflow exception will be thrown by the caller.
- return Handle<Code>::null();
- }
-
- // Generate code and return it. Code generator selection is governed by
- // which backends are enabled and whether the function is considered
- // run-once code or not:
- //
- // --full-compiler enables the dedicated backend for code we expect to be
- // run once
- //
- // The normal choice of backend can be overridden with the flags
- // --always-full-compiler.
- Handle<SharedFunctionInfo> shared = info->shared_info();
- bool is_run_once = (shared.is_null())
- ? info->scope()->is_global_scope()
- : (shared->is_toplevel() || shared->try_full_codegen());
- bool use_full = FLAG_full_compiler && !function->contains_loops();
- if (AlwaysFullCompiler() || (use_full && is_run_once)) {
- return FullCodeGenerator::MakeCode(info);
+static bool MakeCode(CompilationInfo* info) {
+ // Precondition: code has been parsed. Postcondition: the code field in
+ // the compilation info is set if compilation succeeded.
+ ASSERT(info->function() != NULL);
+
+ if (Rewriter::Rewrite(info) &&
+ Scope::Analyze(info) &&
+ Rewriter::Analyze(info)) {
+ // Generate code and return it. Code generator selection is governed by
+ // which backends are enabled and whether the function is considered
+ // run-once code or not.
+ //
+ // --full-compiler enables the dedicated backend for code we expect to
+ // be run once
+ //
+ // The normal choice of backend can be overridden with the flags
+ // --always-full-compiler.
+ Handle<SharedFunctionInfo> shared = info->shared_info();
+ bool is_run_once = (shared.is_null())
+ ? info->scope()->is_global_scope()
+ : (shared->is_toplevel() || shared->try_full_codegen());
+ bool can_use_full =
+ FLAG_full_compiler && !info->function()->contains_loops();
+ if (AlwaysFullCompiler() || (is_run_once && can_use_full)) {
+ return FullCodeGenerator::MakeCode(info);
+ } else {
+ AssignedVariablesAnalyzer ava;
+ return ava.Analyze(info) && CodeGenerator::MakeCode(info);
+ }
}
- AssignedVariablesAnalyzer ava(function);
- if (!ava.Analyze()) return Handle<Code>::null();
- return CodeGenerator::MakeCode(info);
+ return false;
}
#ifdef ENABLE_DEBUGGER_SUPPORT
-Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
- Handle<Context> context = Handle<Context>::null();
- Handle<Code> code = MakeCode(context, info);
+bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) {
+ // Precondition: code has been parsed. Postcondition: the code field in
+ // the compilation info is set if compilation succeeded.
+ bool succeeded = MakeCode(info);
if (!info->shared_info().is_null()) {
Handle<SerializedScopeInfo> scope_info =
SerializedScopeInfo::Create(info->scope());
info->shared_info()->set_scope_info(*scope_info);
}
- return code;
+ return succeeded;
}
#endif
-static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
- bool is_eval,
- Compiler::ValidationState validate,
- Handle<Script> script,
- Handle<Context> context,
- v8::Extension* extension,
- ScriptDataImpl* pre_data) {
+static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
CompilationZoneScope zone_scope(DELETE_ON_EXIT);
PostponeInterruptsScope postpone;
ASSERT(!i::Top::global_context().is_null());
+ Handle<Script> script = info->script();
script->set_context_data((*i::Top::global_context())->data());
- bool is_json = (validate == Compiler::VALIDATE_JSON);
#ifdef ENABLE_DEBUGGER_SUPPORT
- if (is_eval || is_json) {
- script->set_compilation_type(
- is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) :
- Smi::FromInt(Script::COMPILATION_TYPE_EVAL));
+ if (info->is_eval() || info->is_json()) {
+ Script::CompilationType compilation_type = info->is_json()
+ ? Script::COMPILATION_TYPE_JSON
+ : Script::COMPILATION_TYPE_EVAL;
+ script->set_compilation_type(Smi::FromInt(compilation_type));
// For eval scripts add information on the function from which eval was
// called.
- if (is_eval) {
+ if (info->is_eval()) {
StackTraceFrameIterator it;
if (!it.done()) {
script->set_eval_from_shared(
@@ -168,54 +176,47 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
#endif
// Only allow non-global compiles for eval.
- ASSERT(is_eval || is_global);
+ ASSERT(info->is_eval() || info->is_global());
- // Build AST.
- FunctionLiteral* lit =
- MakeAST(is_global, script, extension, pre_data, is_json);
-
- LiveEditFunctionTracker live_edit_tracker(lit);
-
- // Check for parse errors.
- if (lit == NULL) {
- ASSERT(Top::has_pending_exception());
- return Handle<SharedFunctionInfo>::null();
- }
+ if (!Parser::Parse(info)) return Handle<SharedFunctionInfo>::null();
// Measure how long it takes to do the compilation; only take the
// rest of the function into account to avoid overlap with the
// parsing statistics.
- HistogramTimer* rate = is_eval
+ HistogramTimer* rate = info->is_eval()
? &Counters::compile_eval
: &Counters::compile;
HistogramTimerScope timer(rate);
// Compile the code.
- CompilationInfo info(lit, script, is_eval);
- Handle<Code> code = MakeCode(context, &info);
-
- // Check for stack-overflow exceptions.
- if (code.is_null()) {
+ FunctionLiteral* lit = info->function();
+ LiveEditFunctionTracker live_edit_tracker(lit);
+ if (!MakeCode(info)) {
Top::StackOverflow();
return Handle<SharedFunctionInfo>::null();
}
+ ASSERT(!info->code().is_null());
if (script->name()->IsString()) {
PROFILE(CodeCreateEvent(
- is_eval ? Logger::EVAL_TAG :
- Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
- *code, String::cast(script->name())));
+ info->is_eval()
+ ? Logger::EVAL_TAG
+ : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
+ *info->code(),
+ String::cast(script->name())));
OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
- code->instruction_start(),
- code->instruction_size()));
+ info->code()->instruction_start(),
+ info->code()->instruction_size()));
} else {
PROFILE(CodeCreateEvent(
- is_eval ? Logger::EVAL_TAG :
- Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
- *code, ""));
- OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
- code->instruction_start(),
- code->instruction_size()));
+ info->is_eval()
+ ? Logger::EVAL_TAG
+ : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
+ *info->code(),
+ ""));
+ OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script",
+ info->code()->instruction_start(),
+ info->code()->instruction_size()));
}
// Allocate function.
@@ -223,8 +224,8 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
Factory::NewSharedFunctionInfo(
lit->name(),
lit->materialized_literal_count(),
- code,
- SerializedScopeInfo::Create(info.scope()));
+ info->code(),
+ SerializedScopeInfo::Create(info->scope()));
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Compiler::SetFunctionInfo(result, lit, true, script);
@@ -282,7 +283,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
if (pre_data == NULL
&& FLAG_lazy
&& source_length >= FLAG_min_preparse_length) {
- pre_data = PartialPreParse(source, NULL, extension);
+ pre_data = Parser::PartialPreParse(source, NULL, extension);
}
// Create a script object describing the script to be compiled.
@@ -300,13 +301,11 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
: *script_data);
// Compile the function and add it to the cache.
- result = MakeFunctionInfo(true,
- false,
- DONT_VALIDATE_JSON,
- script,
- Handle<Context>::null(),
- extension,
- pre_data);
+ CompilationInfo info(script);
+ info.MarkAsGlobal();
+ info.SetExtension(extension);
+ info.SetPreParseData(pre_data);
+ result = MakeFunctionInfo(&info);
if (extension == NULL && !result.is_null()) {
CompilationCache::PutScript(source, result);
}
@@ -326,9 +325,10 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
Handle<Context> context,
bool is_global,
ValidationState validate) {
- // Note that if validation is required then no path through this
- // function is allowed to return a value without validating that
- // the input is legal json.
+ // Note that if validation is required then no path through this function
+ // is allowed to return a value without validating that the input is legal
+ // json.
+ bool is_json = (validate == VALIDATE_JSON);
int source_length = source->length();
Counters::total_eval_size.Increment(source_length);
@@ -337,27 +337,27 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
// The VM is in the COMPILER state until exiting this function.
VMState state(COMPILER);
- // Do a lookup in the compilation cache; if the entry is not there,
- // invoke the compiler and add the result to the cache. If we're
- // evaluating json we bypass the cache since we can't be sure a
- // potential value in the cache has been validated.
+ // Do a lookup in the compilation cache; if the entry is not there, invoke
+ // the compiler and add the result to the cache. If we're evaluating json
+ // we bypass the cache since we can't be sure a potential value in the
+ // cache has been validated.
Handle<SharedFunctionInfo> result;
- if (validate == DONT_VALIDATE_JSON)
+ if (!is_json) {
result = CompilationCache::LookupEval(source, context, is_global);
+ }
if (result.is_null()) {
// Create a script object describing the script to be compiled.
Handle<Script> script = Factory::NewScript(source);
- result = MakeFunctionInfo(is_global,
- true,
- validate,
- script,
- context,
- NULL,
- NULL);
- if (!result.is_null() && validate != VALIDATE_JSON) {
- // For json it's unlikely that we'll ever see exactly the same
- // string again so we don't use the compilation cache.
+ CompilationInfo info(script);
+ info.MarkAsEval();
+ if (is_global) info.MarkAsGlobal();
+ if (is_json) info.MarkAsJson();
+ info.SetCallingContext(context);
+ result = MakeFunctionInfo(&info);
+ if (!result.is_null() && !is_json) {
+ // For json it's unlikely that we'll ever see exactly the same string
+ // again so we don't use the compilation cache.
CompilationCache::PutEval(source, context, is_global, result);
}
}
@@ -374,140 +374,122 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
PostponeInterruptsScope postpone;
- // Compute name, source code and script data.
Handle<SharedFunctionInfo> shared = info->shared_info();
- Handle<String> name(String::cast(shared->name()));
-
- int start_position = shared->start_position();
- int end_position = shared->end_position();
- bool is_expression = shared->is_expression();
- Counters::total_compile_size.Increment(end_position - start_position);
-
- // Generate the AST for the lazily compiled function. The AST may be
- // NULL in case of parser stack overflow.
- FunctionLiteral* lit = MakeLazyAST(info->script(),
- name,
- start_position,
- end_position,
- is_expression);
-
- // Check for parse errors.
- if (lit == NULL) {
- ASSERT(Top::has_pending_exception());
- return false;
- }
- info->set_function(lit);
-
- // Measure how long it takes to do the lazy compilation; only take
- // the rest of the function into account to avoid overlap with the
- // lazy parsing statistics.
- HistogramTimerScope timer(&Counters::compile_lazy);
-
- // Compile the code.
- Handle<Code> code = MakeCode(Handle<Context>::null(), info);
-
- // Check for stack-overflow exception.
- if (code.is_null()) {
- Top::StackOverflow();
- return false;
- }
+ int compiled_size = shared->end_position() - shared->start_position();
+ Counters::total_compile_size.Increment(compiled_size);
+
+ // Generate the AST for the lazily compiled function.
+ if (Parser::Parse(info)) {
+ // Measure how long it takes to do the lazy compilation; only take the
+ // rest of the function into account to avoid overlap with the lazy
+ // parsing statistics.
+ HistogramTimerScope timer(&Counters::compile_lazy);
+
+ // Compile the code.
+ if (!MakeCode(info)) {
+ Top::StackOverflow();
+ } else {
+ ASSERT(!info->code().is_null());
+ RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
+ Handle<String>(shared->DebugName()),
+ shared->start_position(),
+ info);
+
+ // Update the shared function info with the compiled code and the
+ // scope info. Please note, that the order of the sharedfunction
+ // initialization is important since SerializedScopeInfo::Create might
+ // trigger a GC, causing the ASSERT below to be invalid if the code
+ // was flushed. By setting the code object last we avoid this.
+ Handle<SerializedScopeInfo> scope_info =
+ SerializedScopeInfo::Create(info->scope());
+ shared->set_scope_info(*scope_info);
+ shared->set_code(*info->code());
+ if (!info->closure().is_null()) {
+ info->closure()->set_code(*info->code());
+ }
- RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
- name,
- Handle<String>(shared->inferred_name()),
- start_position,
- info->script(),
- code);
-
- // Update the shared function info with the compiled code and the scope info.
- // Please note, that the order of the sharedfunction initialization is
- // important since SerializedScopeInfo::Create might trigger a GC, causing
- // the ASSERT below to be invalid if the code was flushed. By setting the code
- // object last we avoid this.
- Handle<SerializedScopeInfo> scope_info =
- SerializedScopeInfo::Create(info->scope());
- shared->set_scope_info(*scope_info);
- shared->set_code(*code);
- if (!info->closure().is_null()) {
- info->closure()->set_code(*code);
+ // Set the expected number of properties for instances.
+ FunctionLiteral* lit = info->function();
+ SetExpectedNofPropertiesFromEstimate(shared,
+ lit->expected_property_count());
+
+ // Set the optimization hints after performing lazy compilation, as
+ // these are not set when the function is set up as a lazily compiled
+ // function.
+ shared->SetThisPropertyAssignmentsInfo(
+ lit->has_only_simple_this_property_assignments(),
+ *lit->this_property_assignments());
+
+ // Check the function has compiled code.
+ ASSERT(shared->is_compiled());
+ shared->set_code_age(0);
+ ASSERT(!info->code().is_null());
+ return true;
+ }
}
- // Set the expected number of properties for instances.
- SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
-
- // Set the optimication hints after performing lazy compilation, as these are
- // not set when the function is set up as a lazily compiled function.
- shared->SetThisPropertyAssignmentsInfo(
- lit->has_only_simple_this_property_assignments(),
- *lit->this_property_assignments());
-
- // Check the function has compiled code.
- ASSERT(shared->is_compiled());
- shared->set_code_age(0);
- return true;
+ ASSERT(info->code().is_null());
+ return false;
}
Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
- Handle<Script> script,
- AstVisitor* caller) {
- LiveEditFunctionTracker live_edit_tracker(literal);
+ Handle<Script> script) {
#ifdef DEBUG
// We should not try to compile the same function literal more than
// once.
literal->mark_as_compiled();
#endif
- // Determine if the function can be lazily compiled. This is
- // necessary to allow some of our builtin JS files to be lazily
- // compiled. These builtins cannot be handled lazily by the parser,
- // since we have to know if a function uses the special natives
- // syntax, which is something the parser records.
+ // Precondition: code has been parsed and scopes have been analyzed.
+ CompilationInfo info(script);
+ info.SetFunction(literal);
+ info.SetScope(literal->scope());
+
+ LiveEditFunctionTracker live_edit_tracker(literal);
+ // Determine if the function can be lazily compiled. This is necessary to
+ // allow some of our builtin JS files to be lazily compiled. These
+ // builtins cannot be handled lazily by the parser, since we have to know
+ // if a function uses the special natives syntax, which is something the
+ // parser records.
bool allow_lazy = literal->AllowsLazyCompilation() &&
!LiveEditFunctionTracker::IsActive();
Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
// Generate code
- Handle<Code> code;
if (FLAG_lazy && allow_lazy) {
- code = Handle<Code>(Builtins::builtin(Builtins::LazyCompile));
+ Handle<Code> code(Builtins::builtin(Builtins::LazyCompile));
+ info.SetCode(code);
} else {
- // The bodies of function literals have not yet been visited by
- // the AST optimizer/analyzer.
- if (!Rewriter::Optimize(literal)) {
- return Handle<SharedFunctionInfo>::null();
- }
-
// Generate code and return it. The way that the compilation mode
// is controlled by the command-line flags is described in
// the static helper function MakeCode.
- CompilationInfo info(literal, script, false);
+ //
+ // The bodies of function literals have not yet been visited by
+ // the AST analyzer.
+ if (!Rewriter::Analyze(&info)) return Handle<SharedFunctionInfo>::null();
bool is_run_once = literal->try_full_codegen();
bool use_full = FLAG_full_compiler && !literal->contains_loops();
if (AlwaysFullCompiler() || (use_full && is_run_once)) {
- code = FullCodeGenerator::MakeCode(&info);
+ if (!FullCodeGenerator::MakeCode(&info)) {
+ return Handle<SharedFunctionInfo>::null();
+ }
} else {
// We fall back to the classic V8 code generator.
- AssignedVariablesAnalyzer ava(literal);
- if (!ava.Analyze()) return Handle<SharedFunctionInfo>::null();
- code = CodeGenerator::MakeCode(&info);
- }
-
- // Check for stack-overflow exception.
- if (code.is_null()) {
- caller->SetStackOverflow();
- return Handle<SharedFunctionInfo>::null();
+ AssignedVariablesAnalyzer ava;
+ if (!ava.Analyze(&info)) return Handle<SharedFunctionInfo>::null();
+ if (!CodeGenerator::MakeCode(&info)) {
+ return Handle<SharedFunctionInfo>::null();
+ }
}
// Function compilation complete.
RecordFunctionCompilation(Logger::FUNCTION_TAG,
- literal->name(),
- literal->inferred_name(),
+ literal->debug_name(),
literal->start_position(),
- script,
- code);
+ &info);
scope_info = SerializedScopeInfo::Create(info.scope());
}
@@ -515,7 +497,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
Handle<SharedFunctionInfo> result =
Factory::NewSharedFunctionInfo(literal->name(),
literal->materialized_literal_count(),
- code,
+ info.code(),
scope_info);
SetFunctionInfo(result, literal, false, script);
@@ -555,32 +537,34 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
Handle<String> name,
- Handle<String> inferred_name,
int start_position,
- Handle<Script> script,
- Handle<Code> code) {
- // Log the code generation. If source information is available
- // include script name and line number. Check explicitly whether
- // logging is enabled as finding the line number is not free.
- if (Logger::is_logging()
- || OProfileAgent::is_enabled()
- || CpuProfiler::is_profiling()) {
- Handle<String> func_name(name->length() > 0 ? *name : *inferred_name);
+ CompilationInfo* info) {
+ // Log the code generation. If source information is available include
+ // script name and line number. Check explicitly whether logging is
+ // enabled as finding the line number is not free.
+ if (Logger::is_logging() ||
+ OProfileAgent::is_enabled() ||
+ CpuProfiler::is_profiling()) {
+ Handle<Script> script = info->script();
+ Handle<Code> code = info->code();
if (script->name()->IsString()) {
int line_num = GetScriptLineNumber(script, start_position) + 1;
USE(line_num);
PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
- *code, *func_name,
- String::cast(script->name()), line_num));
- OPROFILE(CreateNativeCodeRegion(*func_name,
+ *code,
+ *name,
+ String::cast(script->name()),
+ line_num));
+ OPROFILE(CreateNativeCodeRegion(*name,
String::cast(script->name()),
line_num,
code->instruction_start(),
code->instruction_size()));
} else {
PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
- *code, *func_name));
- OPROFILE(CreateNativeCodeRegion(*func_name,
+ *code,
+ *name));
+ OPROFILE(CreateNativeCodeRegion(*name,
code->instruction_start(),
code->instruction_size()));
}
diff --git a/src/compiler.h b/src/compiler.h
index ed26603f..d6f4e69d 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// 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:
@@ -30,127 +30,111 @@
#include "ast.h"
#include "frame-element.h"
-#include "parser.h"
#include "register-allocator.h"
#include "zone.h"
namespace v8 {
namespace internal {
+class ScriptDataImpl;
+
// CompilationInfo encapsulates some information known at compile time. It
// is constructed based on the resources available at compile-time.
class CompilationInfo BASE_EMBEDDED {
public:
- // Lazy compilation of a JSFunction.
- CompilationInfo(Handle<JSFunction> closure,
- int loop_nesting,
- Handle<Object> receiver)
- : closure_(closure),
- function_(NULL),
- is_eval_(false),
- loop_nesting_(loop_nesting),
- receiver_(receiver) {
- Initialize();
- ASSERT(!closure_.is_null() &&
- shared_info_.is_null() &&
- script_.is_null());
+ explicit CompilationInfo(Handle<Script> script);
+ explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info);
+ explicit CompilationInfo(Handle<JSFunction> closure);
+
+ bool is_lazy() const { return (flags_ & IsLazy::mask()) != 0; }
+ bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
+ bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
+ bool is_json() const { return (flags_ & IsJson::mask()) != 0; }
+ bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
+ FunctionLiteral* function() const { return function_; }
+ Scope* scope() const { return scope_; }
+ Handle<Code> code() const { return code_; }
+ Handle<JSFunction> closure() const { return closure_; }
+ Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
+ Handle<Script> script() const { return script_; }
+ v8::Extension* extension() const { return extension_; }
+ ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
+ Handle<Context> calling_context() const { return calling_context_; }
+
+ void MarkAsEval() {
+ ASSERT(!is_lazy());
+ flags_ |= IsEval::encode(true);
}
-
- // Lazy compilation based on SharedFunctionInfo.
- explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info)
- : shared_info_(shared_info),
- function_(NULL),
- is_eval_(false),
- loop_nesting_(0) {
- Initialize();
- ASSERT(closure_.is_null() &&
- !shared_info_.is_null() &&
- script_.is_null());
+ void MarkAsGlobal() {
+ ASSERT(!is_lazy());
+ flags_ |= IsGlobal::encode(true);
}
-
- // Eager compilation.
- CompilationInfo(FunctionLiteral* literal, Handle<Script> script, bool is_eval)
- : script_(script),
- function_(literal),
- is_eval_(is_eval),
- loop_nesting_(0) {
- Initialize();
- ASSERT(closure_.is_null() &&
- shared_info_.is_null() &&
- !script_.is_null());
+ void MarkAsJson() {
+ ASSERT(!is_lazy());
+ flags_ |= IsJson::encode(true);
}
-
- // We can only get a JSFunction if we actually have one.
- Handle<JSFunction> closure() { return closure_; }
-
- // We can get a SharedFunctionInfo from a JSFunction or if we actually
- // have one.
- Handle<SharedFunctionInfo> shared_info() {
- if (!closure().is_null()) {
- return Handle<SharedFunctionInfo>(closure()->shared());
- } else {
- return shared_info_;
- }
+ void MarkAsInLoop() {
+ ASSERT(is_lazy());
+ flags_ |= IsInLoop::encode(true);
}
-
- // We can always get a script. Either we have one or we can get a shared
- // function info.
- Handle<Script> script() {
- if (!script_.is_null()) {
- return script_;
- } else {
- ASSERT(shared_info()->script()->IsScript());
- return Handle<Script>(Script::cast(shared_info()->script()));
- }
+ void SetFunction(FunctionLiteral* literal) {
+ ASSERT(function_ == NULL);
+ function_ = literal;
}
-
- // There should always be a function literal, but it may be set after
- // construction (for lazy compilation).
- FunctionLiteral* function() { return function_; }
- void set_function(FunctionLiteral* literal) { function_ = literal; }
-
- // Simple accessors.
- bool is_eval() { return is_eval_; }
- int loop_nesting() { return loop_nesting_; }
- bool has_receiver() { return !receiver_.is_null(); }
- Handle<Object> receiver() { return receiver_; }
-
- bool has_this_properties() { return has_this_properties_; }
- void set_has_this_properties(bool flag) { has_this_properties_ = flag; }
-
- bool has_global_object() {
- return !closure().is_null() && (closure()->context()->global() != NULL);
+ void SetScope(Scope* scope) {
+ ASSERT(scope_ == NULL);
+ scope_ = scope;
}
-
- GlobalObject* global_object() {
- return has_global_object() ? closure()->context()->global() : NULL;
+ void SetCode(Handle<Code> code) { code_ = code; }
+ void SetExtension(v8::Extension* extension) {
+ ASSERT(!is_lazy());
+ extension_ = extension;
+ }
+ void SetPreParseData(ScriptDataImpl* pre_parse_data) {
+ ASSERT(!is_lazy());
+ pre_parse_data_ = pre_parse_data;
+ }
+ void SetCallingContext(Handle<Context> context) {
+ ASSERT(is_eval());
+ calling_context_ = context;
}
-
- bool has_globals() { return has_globals_; }
- void set_has_globals(bool flag) { has_globals_ = flag; }
-
- // Derived accessors.
- Scope* scope() { return function()->scope(); }
private:
- void Initialize() {
- has_this_properties_ = false;
- has_globals_ = false;
- }
+ // Flags using template class BitField<type, start, length>. All are
+ // false by default.
+ //
+ // Compilation is either eager or lazy.
+ class IsLazy: public BitField<bool, 0, 1> {};
+ // Flags that can be set for eager compilation.
+ class IsEval: public BitField<bool, 1, 1> {};
+ class IsGlobal: public BitField<bool, 2, 1> {};
+ class IsJson: public BitField<bool, 3, 1> {};
+ // Flags that can be set for lazy compilation.
+ class IsInLoop: public BitField<bool, 4, 1> {};
+
+ unsigned flags_;
+
+ // Fields filled in by the compilation pipeline.
+ // AST filled in by the parser.
+ FunctionLiteral* function_;
+ // The scope of the function literal as a convenience. Set to indidicate
+ // that scopes have been analyzed.
+ Scope* scope_;
+ // The compiled code.
+ Handle<Code> code_;
+ // Possible initial inputs to the compilation process.
Handle<JSFunction> closure_;
Handle<SharedFunctionInfo> shared_info_;
Handle<Script> script_;
- FunctionLiteral* function_;
-
- bool is_eval_;
- int loop_nesting_;
-
- Handle<Object> receiver_;
+ // Fields possibly needed for eager compilation, NULL by default.
+ v8::Extension* extension_;
+ ScriptDataImpl* pre_parse_data_;
- bool has_this_properties_;
- bool has_globals_;
+ // The context of the caller is needed for eval code, and will be a null
+ // handle otherwise.
+ Handle<Context> calling_context_;
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
};
@@ -163,13 +147,13 @@ class CompilationInfo BASE_EMBEDDED {
// functions, they will be compiled and allocated as part of the compilation
// of the source code.
-// Please note this interface returns shared function infos.
-// This means you need to call Factory::NewFunctionFromSharedFunctionInfo
-// before you have a real function with a context.
+// Please note this interface returns shared function infos. This means you
+// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
+// real function with a context.
class Compiler : public AllStatic {
public:
- enum ValidationState { VALIDATE_JSON, DONT_VALIDATE_JSON };
+ enum ValidationState { DONT_VALIDATE_JSON, VALIDATE_JSON };
// All routines return a JSFunction.
// If an error occurs an exception is raised and
@@ -191,17 +175,14 @@ class Compiler : public AllStatic {
bool is_global,
ValidationState validation);
- // Compile from function info (used for lazy compilation). Returns
- // true on success and false if the compilation resulted in a stack
- // overflow.
+ // Compile from function info (used for lazy compilation). Returns true on
+ // success and false if the compilation resulted in a stack overflow.
static bool CompileLazy(CompilationInfo* info);
- // Compile a shared function info object (the function is possibly
- // lazily compiled). Called recursively from a backend code
- // generator 'caller' to build the shared function info.
+ // Compile a shared function info object (the function is possibly lazily
+ // compiled).
static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
- Handle<Script> script,
- AstVisitor* caller);
+ Handle<Script> script);
// Set the function info for a newly compiled function.
static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
@@ -209,23 +190,18 @@ class Compiler : public AllStatic {
bool is_toplevel,
Handle<Script> script);
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ static bool MakeCodeForLiveEdit(CompilationInfo* info);
+#endif
+
private:
static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
Handle<String> name,
- Handle<String> inferred_name,
int start_position,
- Handle<Script> script,
- Handle<Code> code);
+ CompilationInfo* info);
};
-#ifdef ENABLE_DEBUGGER_SUPPORT
-
-Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info);
-
-#endif
-
-
// During compilation we need a global list of handles to constants
// for frame elements. When the zone gets deleted, we make sure to
// clear this list of handles as well.
diff --git a/src/contexts.cc b/src/contexts.cc
index 723354fc..1ce5007d 100644
--- a/src/contexts.cc
+++ b/src/contexts.cc
@@ -90,7 +90,7 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
do {
if (FLAG_trace_contexts) {
- PrintF(" - looking in context %p", *context);
+ PrintF(" - looking in context %p", reinterpret_cast<void*>(*context));
if (context->IsGlobalContext()) PrintF(" (global context)");
PrintF("\n");
}
@@ -110,7 +110,8 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
if (*attributes != ABSENT) {
// property found
if (FLAG_trace_contexts) {
- PrintF("=> found property in context object %p\n", *extension);
+ PrintF("=> found property in context object %p\n",
+ reinterpret_cast<void*>(*extension));
}
return extension;
}
diff --git a/src/contexts.h b/src/contexts.h
index 78dda6a6..9722a938 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -225,7 +225,15 @@ class Context: public FixedArray {
OUT_OF_MEMORY_INDEX,
MAP_CACHE_INDEX,
CONTEXT_DATA_INDEX,
- GLOBAL_CONTEXT_SLOTS
+
+ // Properties from here are treated as weak references by the full GC.
+ // Scavenge treats them as strong references.
+ NEXT_CONTEXT_LINK,
+
+ // Total number of slots.
+ GLOBAL_CONTEXT_SLOTS,
+
+ FIRST_WEAK_SLOT = NEXT_CONTEXT_LINK
};
// Direct slot access.
@@ -333,6 +341,17 @@ class Context: public FixedArray {
return kHeaderSize + index * kPointerSize - kHeapObjectTag;
}
+ static const int kSize = kHeaderSize + GLOBAL_CONTEXT_SLOTS * kPointerSize;
+
+ // GC support.
+ typedef FixedBodyDescriptor<
+ kHeaderSize, kSize, kSize> ScavengeBodyDescriptor;
+
+ typedef FixedBodyDescriptor<
+ kHeaderSize,
+ kHeaderSize + FIRST_WEAK_SLOT * kPointerSize,
+ kSize> MarkCompactBodyDescriptor;
+
private:
// Unchecked access to the slots.
Object* unchecked_previous() { return get(PREVIOUS_INDEX); }
diff --git a/src/conversions.cc b/src/conversions.cc
index f15a804e..790e807a 100644
--- a/src/conversions.cc
+++ b/src/conversions.cc
@@ -34,6 +34,7 @@
#include "dtoa.h"
#include "factory.h"
#include "scanner.h"
+#include "strtod.h"
namespace v8 {
namespace internal {
@@ -103,8 +104,6 @@ static bool SubStringEquals(Iterator* current,
}
-extern "C" double gay_strtod(const char* s00, const char** se);
-
// Maximum number of significant digits in decimal representation.
// The longest possible double in decimal representation is
// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
@@ -353,8 +352,9 @@ static double InternalStringToInt(Iterator current, EndMark end, int radix) {
}
ASSERT(buffer_pos < kBufferSize);
- buffer[buffer_pos++] = '\0';
- return sign ? -gay_strtod(buffer, NULL) : gay_strtod(buffer, NULL);
+ buffer[buffer_pos] = '\0';
+ Vector<const char> buffer_vector(buffer, buffer_pos);
+ return sign ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
}
// The following code causes accumulating rounding error for numbers greater
@@ -462,7 +462,6 @@ static double InternalStringToDouble(Iterator current,
++current;
if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
} else if (*current == '-') {
- buffer[buffer_pos++] = '-';
++current;
if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
sign = true;
@@ -478,8 +477,8 @@ static double InternalStringToDouble(Iterator current,
return JUNK_STRING_VALUE;
}
- ASSERT(buffer_pos == 0 || buffer[0] == '-');
- return buffer_pos > 0 ? -V8_INFINITY : V8_INFINITY;
+ ASSERT(buffer_pos == 0);
+ return sign ? -V8_INFINITY : V8_INFINITY;
}
bool leading_zero = false;
@@ -496,7 +495,6 @@ static double InternalStringToDouble(Iterator current,
return JUNK_STRING_VALUE; // "0x".
}
- bool sign = (buffer_pos > 0 && buffer[0] == '-');
return InternalStringToIntDouble<4>(current,
end,
sign,
@@ -533,6 +531,9 @@ static double InternalStringToDouble(Iterator current,
}
if (*current == '.') {
+ if (octal && !allow_trailing_junk) return JUNK_STRING_VALUE;
+ if (octal) goto parsing_done;
+
++current;
if (current == end) {
if (significant_digits == 0 && !leading_zero) {
@@ -553,16 +554,16 @@ static double InternalStringToDouble(Iterator current,
}
}
- ASSERT(buffer_pos < kBufferSize);
- buffer[buffer_pos++] = '.';
+ // We don't emit a '.', but adjust the exponent instead.
fractional_part = true;
- // There is the fractional part.
+ // There is a fractional part.
while (*current >= '0' && *current <= '9') {
if (significant_digits < kMaxSignificantDigits) {
ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos++] = static_cast<char>(*current);
significant_digits++;
+ exponent--;
} else {
// Ignore insignificant digits in the fractional part.
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
@@ -638,60 +639,25 @@ static double InternalStringToDouble(Iterator current,
exponent += insignificant_digits;
if (octal) {
- bool sign = buffer[0] == '-';
- int start_pos = (sign ? 1 : 0);
-
- return InternalStringToIntDouble<3>(buffer + start_pos,
+ return InternalStringToIntDouble<3>(buffer,
buffer + buffer_pos,
sign,
allow_trailing_junk);
}
if (nonzero_digit_dropped) {
- if (insignificant_digits) buffer[buffer_pos++] = '.';
buffer[buffer_pos++] = '1';
- }
-
- // If the number has no more than kMaxDigitsInInt digits and doesn't have
- // fractional part it could be parsed faster (without checks for
- // spaces, overflow, etc.).
- const int kMaxDigitsInInt = 9 * sizeof(int) / 4; // NOLINT
-
- if (exponent != 0) {
- ASSERT(buffer_pos < kBufferSize);
- buffer[buffer_pos++] = 'e';
- if (exponent < 0) {
- ASSERT(buffer_pos < kBufferSize);
- buffer[buffer_pos++] = '-';
- exponent = -exponent;
- }
- if (exponent > 999) exponent = 999; // Result will be Infinity or 0 or -0.
-
- const int exp_digits = 3;
- for (int i = 0; i < exp_digits; i++) {
- buffer[buffer_pos + exp_digits - 1 - i] = '0' + exponent % 10;
- exponent /= 10;
- }
- ASSERT(exponent == 0);
- buffer_pos += exp_digits;
- } else if (!fractional_part && significant_digits <= kMaxDigitsInInt) {
- if (significant_digits == 0) return SignedZero(sign);
- ASSERT(buffer_pos > 0);
- int num = 0;
- int start_pos = (buffer[0] == '-' ? 1 : 0);
- for (int i = start_pos; i < buffer_pos; i++) {
- ASSERT(buffer[i] >= '0' && buffer[i] <= '9');
- num = 10 * num + (buffer[i] - '0');
- }
- return static_cast<double>(start_pos == 0 ? num : -num);
+ exponent--;
}
ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos] = '\0';
- return gay_strtod(buffer, NULL);
+ double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
+ return sign? -converted: converted;
}
+
double StringToDouble(String* str, int flags, double empty_string_val) {
StringShape shape(str);
if (shape.IsSequentialAscii()) {
diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
index acf3349b..da19a450 100644
--- a/src/cpu-profiler.cc
+++ b/src/cpu-profiler.cc
@@ -188,6 +188,20 @@ bool ProfilerEventsProcessor::IsKnownFunction(Address start) {
}
+void ProfilerEventsProcessor::ProcessMovedFunctions() {
+ for (int i = 0; i < moved_functions_.length(); ++i) {
+ JSFunction* function = moved_functions_[i];
+ CpuProfiler::FunctionCreateEvent(function);
+ }
+ moved_functions_.Clear();
+}
+
+
+void ProfilerEventsProcessor::RememberMovedFunction(JSFunction* function) {
+ moved_functions_.Add(function);
+}
+
+
void ProfilerEventsProcessor::RegExpCodeCreateEvent(
Logger::LogEventsAndTags tag,
const char* prefix,
@@ -426,8 +440,12 @@ void CpuProfiler::FunctionCreateEvent(JSFunction* function) {
}
-void CpuProfiler::FunctionCreateEventFromMove(JSFunction* function,
- HeapObject* source) {
+void CpuProfiler::ProcessMovedFunctions() {
+ singleton_->processor_->ProcessMovedFunctions();
+}
+
+
+void CpuProfiler::FunctionCreateEventFromMove(JSFunction* function) {
// This function is called from GC iterators (during Scavenge,
// MC, and MS), so marking bits can be set on objects. That's
// why unchecked accessors are used here.
@@ -436,27 +454,7 @@ void CpuProfiler::FunctionCreateEventFromMove(JSFunction* function,
if (function->unchecked_code() == Builtins::builtin(Builtins::LazyCompile)
|| singleton_->processor_->IsKnownFunction(function->address())) return;
- int security_token_id = TokenEnumerator::kNoSecurityToken;
- // In debug mode, assertions may fail for contexts,
- // and we can live without security tokens in debug mode.
-#ifndef DEBUG
- if (function->unchecked_context()->IsContext()) {
- security_token_id = singleton_->token_enumerator_->GetTokenId(
- function->context()->global_context()->security_token());
- }
- // Security token may not be moved yet.
- if (security_token_id == TokenEnumerator::kNoSecurityToken) {
- JSFunction* old_function = reinterpret_cast<JSFunction*>(source);
- if (old_function->unchecked_context()->IsContext()) {
- security_token_id = singleton_->token_enumerator_->GetTokenId(
- old_function->context()->global_context()->security_token());
- }
- }
-#endif
- singleton_->processor_->FunctionCreateEvent(
- function->address(),
- function->unchecked_code()->address(),
- security_token_id);
+ singleton_->processor_->RememberMovedFunction(function);
}
diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h
index 86f9f671..d3158d7a 100644
--- a/src/cpu-profiler.h
+++ b/src/cpu-profiler.h
@@ -165,6 +165,8 @@ class ProfilerEventsProcessor : public Thread {
// Puts current stack into tick sample events buffer.
void AddCurrentStack();
bool IsKnownFunction(Address start);
+ void ProcessMovedFunctions();
+ void RememberMovedFunction(JSFunction* function);
// Tick sample events are filled directly in the buffer of the circular
// queue (because the structure is of fixed width, but usually not all
@@ -202,6 +204,7 @@ class ProfilerEventsProcessor : public Thread {
// Used from the VM thread.
HashMap* known_functions_;
+ List<JSFunction*> moved_functions_;
};
} } // namespace v8::internal
@@ -251,17 +254,18 @@ class CpuProfiler {
String* source, int line);
static void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, int args_count);
+ static void CodeMovingGCEvent() {}
static void CodeMoveEvent(Address from, Address to);
static void CodeDeleteEvent(Address from);
static void FunctionCreateEvent(JSFunction* function);
// Reports function creation in case we had missed it (e.g.
// if it was created from compiled code).
- static void FunctionCreateEventFromMove(JSFunction* function,
- HeapObject* source);
+ static void FunctionCreateEventFromMove(JSFunction* function);
static void FunctionMoveEvent(Address from, Address to);
static void FunctionDeleteEvent(Address from);
static void GetterCallbackEvent(String* name, Address entry_point);
static void RegExpCodeCreateEvent(Code* code, String* source);
+ static void ProcessMovedFunctions();
static void SetterCallbackEvent(String* name, Address entry_point);
static INLINE(bool is_profiling()) {
diff --git a/src/d8.js b/src/d8.js
index 5c3da13a..a758e09c 100644
--- a/src/d8.js
+++ b/src/d8.js
@@ -949,7 +949,7 @@ function DebugResponseDetails(response) {
case 'suspend':
details.text = 'stopped';
break;
-
+
case 'setbreakpoint':
result = 'set breakpoint #';
result += body.breakpoint;
@@ -961,7 +961,7 @@ function DebugResponseDetails(response) {
result += body.breakpoint;
details.text = result;
break;
-
+
case 'listbreakpoints':
result = 'breakpoints: (' + body.breakpoints.length + ')';
for (var i = 0; i < body.breakpoints.length; i++) {
diff --git a/src/data-flow.cc b/src/data-flow.cc
index 44a10506..be824460 100644
--- a/src/data-flow.cc
+++ b/src/data-flow.cc
@@ -42,7 +42,7 @@ void BitVector::Print() {
if (Contains(i)) {
if (!first) PrintF(",");
first = false;
- PrintF("%d");
+ PrintF("%d", i);
}
}
PrintF("}");
@@ -50,12 +50,13 @@ void BitVector::Print() {
#endif
-bool AssignedVariablesAnalyzer::Analyze() {
- Scope* scope = fun_->scope();
+bool AssignedVariablesAnalyzer::Analyze(CompilationInfo* info) {
+ info_ = info;
+ Scope* scope = info->scope();
int variables = scope->num_parameters() + scope->num_stack_slots();
if (variables == 0) return true;
av_.ExpandTo(variables);
- VisitStatements(fun_->body());
+ VisitStatements(info->function()->body());
return !HasStackOverflow();
}
@@ -129,7 +130,7 @@ int AssignedVariablesAnalyzer::BitIndex(Variable* var) {
if (slot->type() == Slot::PARAMETER) {
return slot->index();
} else {
- return fun_->scope()->num_parameters() + slot->index();
+ return info_->scope()->num_parameters() + slot->index();
}
}
diff --git a/src/data-flow.h b/src/data-flow.h
index 540db162..efce1ea7 100644
--- a/src/data-flow.h
+++ b/src/data-flow.h
@@ -198,8 +198,8 @@ class WorkList BASE_EMBEDDED {
// is guaranteed to be a smi.
class AssignedVariablesAnalyzer : public AstVisitor {
public:
- explicit AssignedVariablesAnalyzer(FunctionLiteral* fun) : fun_(fun) { }
- bool Analyze();
+ explicit AssignedVariablesAnalyzer() : info_(NULL) { }
+ bool Analyze(CompilationInfo* info);
private:
Variable* FindSmiLoopVariable(ForStatement* stmt);
@@ -219,7 +219,7 @@ class AssignedVariablesAnalyzer : public AstVisitor {
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
- FunctionLiteral* fun_;
+ CompilationInfo* info_;
// Accumulator for assigned variables set.
BitVector av_;
diff --git a/src/date.js b/src/date.js
index b101ea66..96014707 100644
--- a/src/date.js
+++ b/src/date.js
@@ -246,7 +246,7 @@ function LocalTime(time) {
var ltcache = {
- key: null,
+ key: null,
val: null
};
diff --git a/src/debug-debugger.js b/src/debug-debugger.js
index 34eb0f0e..a0c68081 100644
--- a/src/debug-debugger.js
+++ b/src/debug-debugger.js
@@ -2118,7 +2118,7 @@ DebugCommandProcessor.prototype.changeLiveRequest_ = function(request, response)
}
var script_id = request.arguments.script_id;
var preview_only = !!request.arguments.preview_only;
-
+
var scripts = %DebugGetLoadedScripts();
var the_script = null;
@@ -2139,11 +2139,11 @@ DebugCommandProcessor.prototype.changeLiveRequest_ = function(request, response)
}
var new_source = request.arguments.new_source;
-
+
var result_description = Debug.LiveEdit.SetScriptSource(the_script,
new_source, preview_only, change_log);
response.body = {change_log: change_log, result: result_description};
-
+
if (!preview_only && !this.running_ && result_description.stack_modified) {
response.body.stepin_recommended = true;
}
diff --git a/src/disassembler.cc b/src/disassembler.cc
index e79421fe..2a4ea74e 100644
--- a/src/disassembler.cc
+++ b/src/disassembler.cc
@@ -44,7 +44,10 @@ namespace internal {
void Disassembler::Dump(FILE* f, byte* begin, byte* end) {
for (byte* pc = begin; pc < end; pc++) {
if (f == NULL) {
- PrintF("%" V8PRIxPTR " %4" V8PRIdPTR " %02x\n", pc, pc - begin, *pc);
+ PrintF("%" V8PRIxPTR " %4" V8PRIdPTR " %02x\n",
+ reinterpret_cast<intptr_t>(pc),
+ pc - begin,
+ *pc);
} else {
fprintf(f, "%" V8PRIxPTR " %4" V8PRIdPTR " %02x\n",
reinterpret_cast<uintptr_t>(pc), pc - begin, *pc);
diff --git a/src/execution.cc b/src/execution.cc
index 54216784..68623247 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -473,6 +473,19 @@ Handle<Object> Execution::NewDate(double time, bool* exc) {
#undef RETURN_NATIVE_CALL
+Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
+ Handle<String> flags,
+ bool* exc) {
+ Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
+ Handle<JSFunction>(Top::global_context()->regexp_function()),
+ pattern,
+ flags,
+ exc);
+ if (*exc) return Handle<JSRegExp>();
+ return Handle<JSRegExp>::cast(re_obj);
+}
+
+
Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
int int_index = static_cast<int>(index);
if (int_index < 0 || int_index >= string->length()) {
diff --git a/src/execution.h b/src/execution.h
index 28235033..15d85ef4 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -105,6 +105,11 @@ class Execution : public AllStatic {
// Create a new date object from 'time'.
static Handle<Object> NewDate(double time, bool* exc);
+ // Create a new regular expression object from 'pattern' and 'flags'.
+ static Handle<JSRegExp> NewJSRegExp(Handle<String> pattern,
+ Handle<String> flags,
+ bool* exc);
+
// Used to implement [] notation on strings (calls JS code)
static Handle<Object> CharAt(Handle<String> str, uint32_t index);
diff --git a/src/fast-dtoa.cc b/src/fast-dtoa.cc
index d2a00cc6..ce825f9d 100644
--- a/src/fast-dtoa.cc
+++ b/src/fast-dtoa.cc
@@ -609,8 +609,13 @@ static bool Grisu3(double v,
ASSERT(boundary_plus.e() == w.e());
DiyFp ten_mk; // Cached power of ten: 10^-k
int mk; // -k
- GetCachedPower(w.e() + DiyFp::kSignificandSize, kMinimalTargetExponent,
- kMaximalTargetExponent, &mk, &ten_mk);
+ int ten_mk_minimal_binary_exponent =
+ kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
+ int ten_mk_maximal_binary_exponent =
+ kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
+ GetCachedPowerForBinaryExponentRange(ten_mk_minimal_binary_exponent,
+ ten_mk_maximal_binary_exponent,
+ &ten_mk, &mk);
ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
DiyFp::kSignificandSize) &&
(kMaximalTargetExponent >= w.e() + ten_mk.e() +
@@ -662,8 +667,13 @@ static bool Grisu3Counted(double v,
DiyFp w = Double(v).AsNormalizedDiyFp();
DiyFp ten_mk; // Cached power of ten: 10^-k
int mk; // -k
- GetCachedPower(w.e() + DiyFp::kSignificandSize, kMinimalTargetExponent,
- kMaximalTargetExponent, &mk, &ten_mk);
+ int ten_mk_minimal_binary_exponent =
+ kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
+ int ten_mk_maximal_binary_exponent =
+ kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
+ GetCachedPowerForBinaryExponentRange(ten_mk_minimal_binary_exponent,
+ ten_mk_maximal_binary_exponent,
+ &ten_mk, &mk);
ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
DiyFp::kSignificandSize) &&
(kMaximalTargetExponent >= w.e() + ten_mk.e() +
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 263a2a40..2474c62b 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -108,6 +108,8 @@ DEFINE_bool(enable_sse2, true,
"enable use of SSE2 instructions if available")
DEFINE_bool(enable_sse3, true,
"enable use of SSE3 instructions if available")
+DEFINE_bool(enable_sse4_1, true,
+ "enable use of SSE4.1 instructions if available")
DEFINE_bool(enable_cmov, true,
"enable use of CMOV instruction if available")
DEFINE_bool(enable_rdtsc, true,
@@ -179,8 +181,8 @@ DEFINE_bool(always_inline_smi_code, false,
"always inline smi code in non-opt code")
// heap.cc
-DEFINE_int(max_new_space_size, 0, "max size of the new generation")
-DEFINE_int(max_old_space_size, 0, "max size of the old generation")
+DEFINE_int(max_new_space_size, 0, "max size of the new generation (in kBytes)")
+DEFINE_int(max_old_space_size, 0, "max size of the old generation (in Mbytes)")
DEFINE_bool(gc_global, false, "always perform global GCs")
DEFINE_int(gc_interval, -1, "garbage collect after <n> allocations")
DEFINE_bool(trace_gc, false,
@@ -410,6 +412,7 @@ DEFINE_bool(sliding_state_window, false,
"Update sliding state window counters.")
DEFINE_string(logfile, "v8.log", "Specify the name of the log file.")
DEFINE_bool(oprofile, false, "Enable JIT agent for OProfile.")
+DEFINE_bool(ll_prof, false, "Enable low-level linux profiler.")
//
// Heap protection flags
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index fa835cb0..97987c27 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -277,7 +277,7 @@ void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
#define __ ACCESS_MASM(masm())
-Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
+bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
Handle<Script> script = info->script();
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
int len = String::cast(script->source())->length();
@@ -291,10 +291,13 @@ Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
cgen.Generate(info);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
- return Handle<Code>::null();
+ return false;
}
+
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP);
- return CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
+ Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
+ info->SetCode(code); // may be an empty handle.
+ return !code.is_null();
}
@@ -462,9 +465,12 @@ void FullCodeGenerator::VisitDeclarations(
}
} else {
Handle<SharedFunctionInfo> function =
- Compiler::BuildFunctionInfo(decl->fun(), script(), this);
+ Compiler::BuildFunctionInfo(decl->fun(), script());
// Check for stack-overflow exception.
- if (HasStackOverflow()) return;
+ if (function.is_null()) {
+ SetStackOverflow();
+ return;
+ }
array->set(j++, *function);
}
}
@@ -1122,9 +1128,14 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) {
__ bind(&true_case);
SetExpressionPosition(expr->then_expression(),
expr->then_expression_position());
- Visit(expr->then_expression());
- // If control flow falls through Visit, jump to done.
- if (!context()->IsTest()) {
+ if (context()->IsTest()) {
+ const TestContext* for_test = TestContext::cast(context());
+ VisitForControl(expr->then_expression(),
+ for_test->true_label(),
+ for_test->false_label(),
+ NULL);
+ } else {
+ Visit(expr->then_expression());
__ jmp(&done);
}
@@ -1156,8 +1167,11 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
// Build the function boilerplate and instantiate it.
Handle<SharedFunctionInfo> function_info =
- Compiler::BuildFunctionInfo(expr, script(), this);
- if (HasStackOverflow()) return;
+ Compiler::BuildFunctionInfo(expr, script());
+ if (function_info.is_null()) {
+ SetStackOverflow();
+ return;
+ }
EmitNewClosure(function_info);
}
diff --git a/src/full-codegen.h b/src/full-codegen.h
index 03024e19..201507b2 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -74,7 +74,7 @@ class FullCodeGenerator: public AstVisitor {
context_(NULL) {
}
- static Handle<Code> MakeCode(CompilationInfo* info);
+ static bool MakeCode(CompilationInfo* info);
void Generate(CompilationInfo* info);
@@ -604,6 +604,15 @@ class FullCodeGenerator: public AstVisitor {
false_label_(false_label),
fall_through_(fall_through) { }
+ static const TestContext* cast(const ExpressionContext* context) {
+ ASSERT(context->IsTest());
+ return reinterpret_cast<const TestContext*>(context);
+ }
+
+ Label* true_label() const { return true_label_; }
+ Label* false_label() const { return false_label_; }
+ Label* fall_through() const { return fall_through_; }
+
virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const;
diff --git a/src/global-handles.cc b/src/global-handles.cc
index a909caf3..02073227 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -486,7 +486,7 @@ void GlobalHandles::PrintStats() {
}
PrintF("Global Handle Statistics:\n");
- PrintF(" allocated memory = %dB\n", sizeof(Node) * total);
+ PrintF(" allocated memory = %" V8_PTR_PREFIX "dB\n", sizeof(Node) * total);
PrintF(" # weak = %d\n", weak);
PrintF(" # pending = %d\n", pending);
PrintF(" # near_death = %d\n", near_death);
@@ -497,8 +497,10 @@ void GlobalHandles::PrintStats() {
void GlobalHandles::Print() {
PrintF("Global handles:\n");
for (Node* current = head_; current != NULL; current = current->next()) {
- PrintF(" handle %p to %p (weak=%d)\n", current->handle().location(),
- *current->handle(), current->state_ == Node::WEAK);
+ PrintF(" handle %p to %p (weak=%d)\n",
+ reinterpret_cast<void*>(current->handle().location()),
+ reinterpret_cast<void*>(*current->handle()),
+ current->state_ == Node::WEAK);
}
}
diff --git a/src/handles.cc b/src/handles.cc
index 78a7fcf9..8fe29bb7 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -175,7 +175,7 @@ static int ExpectedNofPropertiesFromEstimate(int estimate) {
// Inobject slack tracking will reclaim redundant inobject space later,
// so we can afford to adjust the estimate generously.
- return estimate + 6;
+ return estimate + 8;
}
@@ -635,8 +635,19 @@ v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver,
}
+static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
+ int len = array->length();
+ for (int i = 0; i < len; i++) {
+ Object* e = array->get(i);
+ if (!(e->IsString() || e->IsNumber())) return false;
+ }
+ return true;
+}
+
+
Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
KeyCollectionType type) {
+ USE(ContainsOnlyValidKeys);
Handle<FixedArray> content = Factory::empty_fixed_array();
Handle<JSObject> arguments_boilerplate =
Handle<JSObject>(
@@ -664,6 +675,7 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
Factory::NewFixedArray(current->NumberOfEnumElements());
current->GetEnumElementKeys(*element_keys);
content = UnionOfKeys(content, element_keys);
+ ASSERT(ContainsOnlyValidKeys(content));
// Add the element keys from the interceptor.
if (current->HasIndexedInterceptor()) {
@@ -671,6 +683,7 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
GetKeysForIndexedInterceptor(object, current);
if (!result.IsEmpty())
content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
+ ASSERT(ContainsOnlyValidKeys(content));
}
// We can cache the computed property keys if access checks are
@@ -692,6 +705,7 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
// Compute the property keys and cache them if possible.
content =
UnionOfKeys(content, GetEnumPropertyKeys(current, cache_enum_keys));
+ ASSERT(ContainsOnlyValidKeys(content));
// Add the property keys from the interceptor.
if (current->HasNamedInterceptor()) {
@@ -699,6 +713,7 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
GetKeysForNamedInterceptor(object, current);
if (!result.IsEmpty())
content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
+ ASSERT(ContainsOnlyValidKeys(content));
}
// If we only want local properties we bail out after the first
@@ -785,15 +800,16 @@ bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
bool CompileLazy(Handle<JSFunction> function,
- Handle<Object> receiver,
ClearExceptionFlag flag) {
if (function->shared()->is_compiled()) {
function->set_code(function->shared()->code());
+ PROFILE(FunctionCreateEvent(*function));
function->shared()->set_code_age(0);
return true;
} else {
- CompilationInfo info(function, 0, receiver);
+ CompilationInfo info(function);
bool result = CompileLazyHelper(&info, flag);
+ ASSERT(!result || function->is_compiled());
PROFILE(FunctionCreateEvent(*function));
return result;
}
@@ -801,15 +817,17 @@ bool CompileLazy(Handle<JSFunction> function,
bool CompileLazyInLoop(Handle<JSFunction> function,
- Handle<Object> receiver,
ClearExceptionFlag flag) {
if (function->shared()->is_compiled()) {
function->set_code(function->shared()->code());
+ PROFILE(FunctionCreateEvent(*function));
function->shared()->set_code_age(0);
return true;
} else {
- CompilationInfo info(function, 1, receiver);
+ CompilationInfo info(function);
+ info.MarkAsInLoop();
bool result = CompileLazyHelper(&info, flag);
+ ASSERT(!result || function->is_compiled());
PROFILE(FunctionCreateEvent(*function));
return result;
}
diff --git a/src/handles.h b/src/handles.h
index 135dbfb5..69170ff2 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -345,13 +345,9 @@ bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag);
-bool CompileLazy(Handle<JSFunction> function,
- Handle<Object> receiver,
- ClearExceptionFlag flag);
+bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag);
-bool CompileLazyInLoop(Handle<JSFunction> function,
- Handle<Object> receiver,
- ClearExceptionFlag flag);
+bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag flag);
class NoHandleAllocation BASE_EMBEDDED {
public:
diff --git a/src/heap-inl.h b/src/heap-inl.h
index b68f5c1c..104292df 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -36,7 +36,7 @@ namespace v8 {
namespace internal {
void Heap::UpdateOldSpaceLimits() {
- int old_gen_size = PromotedSpaceSize();
+ intptr_t old_gen_size = PromotedSpaceSize();
old_gen_promotion_limit_ =
old_gen_size + Max(kMinimumPromotionLimit, old_gen_size / 3);
old_gen_allocation_limit_ =
@@ -76,7 +76,7 @@ Object* Heap::AllocateRaw(int size_in_bytes,
if (FLAG_gc_interval >= 0 &&
!disallow_allocation_failure_ &&
Heap::allocation_timeout_-- <= 0) {
- return Failure::RetryAfterGC(size_in_bytes, space);
+ return Failure::RetryAfterGC(space);
}
Counters::objs_since_last_full.Increment();
Counters::objs_since_last_young.Increment();
@@ -389,8 +389,12 @@ void Heap::SetLastScriptId(Object* last_script_id) {
}
+#ifdef DEBUG
#define GC_GREEDY_CHECK() \
- ASSERT(!FLAG_gc_greedy || v8::internal::Heap::GarbageCollectionGreedyCheck())
+ if (FLAG_gc_greedy) v8::internal::Heap::GarbageCollectionGreedyCheck()
+#else
+#define GC_GREEDY_CHECK() { }
+#endif
// Calls the FUNCTION_CALL function and retries it up to three times
@@ -409,8 +413,7 @@ void Heap::SetLastScriptId(Object* last_script_id) {
v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_0", true);\
} \
if (!__object__->IsRetryAfterGC()) RETURN_EMPTY; \
- Heap::CollectGarbage(Failure::cast(__object__)->requested(), \
- Failure::cast(__object__)->allocation_space()); \
+ Heap::CollectGarbage(Failure::cast(__object__)->allocation_space()); \
__object__ = FUNCTION_CALL; \
if (!__object__->IsFailure()) RETURN_VALUE; \
if (__object__->IsOutOfMemoryFailure()) { \
diff --git a/src/heap.cc b/src/heap.cc
index 047e3316..675639a3 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -54,6 +54,7 @@ namespace internal {
String* Heap::hidden_symbol_;
Object* Heap::roots_[Heap::kRootListLength];
+Object* Heap::global_contexts_list_;
NewSpace Heap::new_space_;
OldSpace* Heap::old_pointer_space_ = NULL;
@@ -63,8 +64,8 @@ MapSpace* Heap::map_space_ = NULL;
CellSpace* Heap::cell_space_ = NULL;
LargeObjectSpace* Heap::lo_space_ = NULL;
-int Heap::old_gen_promotion_limit_ = kMinimumPromotionLimit;
-int Heap::old_gen_allocation_limit_ = kMinimumAllocationLimit;
+intptr_t Heap::old_gen_promotion_limit_ = kMinimumPromotionLimit;
+intptr_t Heap::old_gen_allocation_limit_ = kMinimumAllocationLimit;
int Heap::old_gen_exhausted_ = false;
@@ -75,19 +76,19 @@ int Heap::amount_of_external_allocated_memory_at_last_global_gc_ = 0;
// a multiple of Page::kPageSize.
#if defined(ANDROID)
int Heap::max_semispace_size_ = 2*MB;
-int Heap::max_old_generation_size_ = 192*MB;
+intptr_t Heap::max_old_generation_size_ = 192*MB;
int Heap::initial_semispace_size_ = 128*KB;
-size_t Heap::code_range_size_ = 0;
+intptr_t Heap::code_range_size_ = 0;
#elif defined(V8_TARGET_ARCH_X64)
int Heap::max_semispace_size_ = 16*MB;
-int Heap::max_old_generation_size_ = 1*GB;
+intptr_t Heap::max_old_generation_size_ = 1*GB;
int Heap::initial_semispace_size_ = 1*MB;
-size_t Heap::code_range_size_ = 512*MB;
+intptr_t Heap::code_range_size_ = 512*MB;
#else
int Heap::max_semispace_size_ = 8*MB;
-int Heap::max_old_generation_size_ = 512*MB;
+intptr_t Heap::max_old_generation_size_ = 512*MB;
int Heap::initial_semispace_size_ = 512*KB;
-size_t Heap::code_range_size_ = 0;
+intptr_t Heap::code_range_size_ = 0;
#endif
// The snapshot semispace size will be the default semispace size if
@@ -108,7 +109,7 @@ HeapObjectCallback Heap::gc_safe_size_of_old_object_ = NULL;
// Will be 4 * reserved_semispace_size_ to ensure that young
// generation can be aligned to its size.
int Heap::survived_since_last_expansion_ = 0;
-int Heap::external_allocation_limit_ = 0;
+intptr_t Heap::external_allocation_limit_ = 0;
Heap::HeapState Heap::gc_state_ = NOT_IN_GC;
@@ -137,13 +138,13 @@ int Heap::allocation_timeout_ = 0;
bool Heap::disallow_allocation_failure_ = false;
#endif // DEBUG
-int GCTracer::alive_after_last_gc_ = 0;
+intptr_t GCTracer::alive_after_last_gc_ = 0;
double GCTracer::last_gc_end_timestamp_ = 0.0;
int GCTracer::max_gc_pause_ = 0;
-int GCTracer::max_alive_after_gc_ = 0;
+intptr_t GCTracer::max_alive_after_gc_ = 0;
int GCTracer::min_in_mutator_ = kMaxInt;
-int Heap::Capacity() {
+intptr_t Heap::Capacity() {
if (!HasBeenSetup()) return 0;
return new_space_.Capacity() +
@@ -155,7 +156,7 @@ int Heap::Capacity() {
}
-int Heap::CommittedMemory() {
+intptr_t Heap::CommittedMemory() {
if (!HasBeenSetup()) return 0;
return new_space_.CommittedMemory() +
@@ -168,7 +169,7 @@ int Heap::CommittedMemory() {
}
-int Heap::Available() {
+intptr_t Heap::Available() {
if (!HasBeenSetup()) return 0;
return new_space_.Available() +
@@ -289,33 +290,46 @@ void Heap::ReportStatisticsBeforeGC() {
#if defined(ENABLE_LOGGING_AND_PROFILING)
void Heap::PrintShortHeapStatistics() {
if (!FLAG_trace_gc_verbose) return;
- PrintF("Memory allocator, used: %8d, available: %8d\n",
+ PrintF("Memory allocator, used: %8" V8_PTR_PREFIX "d"
+ ", available: %8" V8_PTR_PREFIX "d\n",
MemoryAllocator::Size(),
MemoryAllocator::Available());
- PrintF("New space, used: %8d, available: %8d\n",
+ PrintF("New space, used: %8" V8_PTR_PREFIX "d"
+ ", available: %8" V8_PTR_PREFIX "d\n",
Heap::new_space_.Size(),
new_space_.Available());
- PrintF("Old pointers, used: %8d, available: %8d, waste: %8d\n",
+ PrintF("Old pointers, used: %8" V8_PTR_PREFIX "d"
+ ", available: %8" V8_PTR_PREFIX "d"
+ ", waste: %8" V8_PTR_PREFIX "d\n",
old_pointer_space_->Size(),
old_pointer_space_->Available(),
old_pointer_space_->Waste());
- PrintF("Old data space, used: %8d, available: %8d, waste: %8d\n",
+ PrintF("Old data space, used: %8" V8_PTR_PREFIX "d"
+ ", available: %8" V8_PTR_PREFIX "d"
+ ", waste: %8" V8_PTR_PREFIX "d\n",
old_data_space_->Size(),
old_data_space_->Available(),
old_data_space_->Waste());
- PrintF("Code space, used: %8d, available: %8d, waste: %8d\n",
+ PrintF("Code space, used: %8" V8_PTR_PREFIX "d"
+ ", available: %8" V8_PTR_PREFIX "d"
+ ", waste: %8" V8_PTR_PREFIX "d\n",
code_space_->Size(),
code_space_->Available(),
code_space_->Waste());
- PrintF("Map space, used: %8d, available: %8d, waste: %8d\n",
+ PrintF("Map space, used: %8" V8_PTR_PREFIX "d"
+ ", available: %8" V8_PTR_PREFIX "d"
+ ", waste: %8" V8_PTR_PREFIX "d\n",
map_space_->Size(),
map_space_->Available(),
map_space_->Waste());
- PrintF("Cell space, used: %8d, available: %8d, waste: %8d\n",
+ PrintF("Cell space, used: %8" V8_PTR_PREFIX "d"
+ ", available: %8" V8_PTR_PREFIX "d"
+ ", waste: %8" V8_PTR_PREFIX "d\n",
cell_space_->Size(),
cell_space_->Available(),
cell_space_->Waste());
- PrintF("Large object space, used: %8d, avaialble: %8d\n",
+ PrintF("Large object space, used: %8" V8_PTR_PREFIX "d"
+ ", available: %8" V8_PTR_PREFIX "d\n",
lo_space_->Size(),
lo_space_->Available());
}
@@ -364,8 +378,8 @@ void Heap::GarbageCollectionPrologue() {
#endif
}
-int Heap::SizeOfObjects() {
- int total = 0;
+intptr_t Heap::SizeOfObjects() {
+ intptr_t total = 0;
AllSpaces spaces;
for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
total += space->Size();
@@ -388,7 +402,7 @@ void Heap::GarbageCollectionEpilogue() {
if (FLAG_code_stats) ReportCodeStatistics("After GC");
#endif
- Counters::alive_after_last_gc.Set(SizeOfObjects());
+ Counters::alive_after_last_gc.Set(static_cast<int>(SizeOfObjects()));
Counters::symbol_table_capacity.Set(symbol_table()->Capacity());
Counters::number_of_symbols.Set(symbol_table()->NumberOfElements());
@@ -407,7 +421,7 @@ void Heap::CollectAllGarbage(bool force_compaction,
// not matter, so long as we do not specify NEW_SPACE, which would not
// cause a full GC.
MarkCompactCollector::SetForceCompaction(force_compaction);
- CollectGarbage(0, OLD_POINTER_SPACE, collectionPolicy);
+ CollectGarbage(OLD_POINTER_SPACE, collectionPolicy);
MarkCompactCollector::SetForceCompaction(false);
}
@@ -418,8 +432,7 @@ void Heap::CollectAllAvailableGarbage() {
}
-bool Heap::CollectGarbage(int requested_size,
- AllocationSpace space,
+void Heap::CollectGarbage(AllocationSpace space,
CollectionPolicy collectionPolicy) {
// The VM is in the GC state until exiting this function.
VMState state(GC);
@@ -456,25 +469,8 @@ bool Heap::CollectGarbage(int requested_size,
#ifdef ENABLE_LOGGING_AND_PROFILING
if (FLAG_log_gc) HeapProfiler::WriteSample();
+ if (CpuProfiler::is_profiling()) CpuProfiler::ProcessMovedFunctions();
#endif
-
- switch (space) {
- case NEW_SPACE:
- return new_space_.Available() >= requested_size;
- case OLD_POINTER_SPACE:
- return old_pointer_space_->Available() >= requested_size;
- case OLD_DATA_SPACE:
- return old_data_space_->Available() >= requested_size;
- case CODE_SPACE:
- return code_space_->Available() >= requested_size;
- case MAP_SPACE:
- return map_space_->Available() >= requested_size;
- case CELL_SPACE:
- return cell_space_->Available() >= requested_size;
- case LO_SPACE:
- return lo_space_->Available() >= requested_size;
- }
- return false;
}
@@ -529,27 +525,27 @@ void Heap::ReserveSpace(
while (gc_performed) {
gc_performed = false;
if (!new_space->ReserveSpace(new_space_size)) {
- Heap::CollectGarbage(new_space_size, NEW_SPACE);
+ Heap::CollectGarbage(NEW_SPACE);
gc_performed = true;
}
if (!old_pointer_space->ReserveSpace(pointer_space_size)) {
- Heap::CollectGarbage(pointer_space_size, OLD_POINTER_SPACE);
+ Heap::CollectGarbage(OLD_POINTER_SPACE);
gc_performed = true;
}
if (!(old_data_space->ReserveSpace(data_space_size))) {
- Heap::CollectGarbage(data_space_size, OLD_DATA_SPACE);
+ Heap::CollectGarbage(OLD_DATA_SPACE);
gc_performed = true;
}
if (!(code_space->ReserveSpace(code_space_size))) {
- Heap::CollectGarbage(code_space_size, CODE_SPACE);
+ Heap::CollectGarbage(CODE_SPACE);
gc_performed = true;
}
if (!(map_space->ReserveSpace(map_space_size))) {
- Heap::CollectGarbage(map_space_size, MAP_SPACE);
+ Heap::CollectGarbage(MAP_SPACE);
gc_performed = true;
}
if (!(cell_space->ReserveSpace(cell_space_size))) {
- Heap::CollectGarbage(cell_space_size, CELL_SPACE);
+ Heap::CollectGarbage(CELL_SPACE);
gc_performed = true;
}
// We add a slack-factor of 2 in order to have space for a series of
@@ -561,7 +557,7 @@ void Heap::ReserveSpace(
large_object_size += cell_space_size + map_space_size + code_space_size +
data_space_size + pointer_space_size;
if (!(lo_space->ReserveSpace(large_object_size))) {
- Heap::CollectGarbage(large_object_size, LO_SPACE);
+ Heap::CollectGarbage(LO_SPACE);
gc_performed = true;
}
}
@@ -611,19 +607,14 @@ void Heap::ClearJSFunctionResultCaches() {
}
-class ClearThreadNormalizedMapCachesVisitor: public ThreadVisitor {
- virtual void VisitThread(ThreadLocalTop* top) {
- Context* context = top->context_;
- if (context == NULL) return;
- context->global()->global_context()->normalized_map_cache()->Clear();
- }
-};
-
-
void Heap::ClearNormalizedMapCaches() {
if (Bootstrapper::IsActive()) return;
- ClearThreadNormalizedMapCachesVisitor visitor;
- ThreadManager::IterateArchivedThreads(&visitor);
+
+ Object* context = global_contexts_list_;
+ while (!context->IsUndefined()) {
+ Context::cast(context)->normalized_map_cache()->Clear();
+ context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
+ }
}
@@ -672,6 +663,10 @@ void Heap::UpdateSurvivalRateTrend(int start_new_space_size) {
void Heap::PerformGarbageCollection(GarbageCollector collector,
GCTracer* tracer,
CollectionPolicy collectionPolicy) {
+ if (collector != SCAVENGER) {
+ PROFILE(CodeMovingGCEvent());
+ }
+
VerifySymbolTable();
if (collector == MARK_COMPACTOR && global_gc_prologue_callback_) {
ASSERT(!allocation_allowed_);
@@ -690,7 +685,7 @@ void Heap::PerformGarbageCollection(GarbageCollector collector,
EnsureFromSpaceIsCommitted();
- int start_new_space_size = Heap::new_space()->Size();
+ int start_new_space_size = Heap::new_space()->SizeAsInt();
if (collector == MARK_COMPACTOR) {
// Perform mark-sweep with optional compaction.
@@ -962,7 +957,7 @@ void Heap::Scavenge() {
DescriptorLookupCache::Clear();
// Used for updating survived_since_last_expansion_ at function end.
- int survived_watermark = PromotedSpaceSize();
+ intptr_t survived_watermark = PromotedSpaceSize();
CheckNewSpaceExpansionCriteria();
@@ -1021,6 +1016,9 @@ void Heap::Scavenge() {
}
}
+ // Scavenge object reachable from the global contexts list directly.
+ scavenge_visitor.VisitPointer(BitCast<Object**>(&global_contexts_list_));
+
new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
UpdateNewSpaceReferencesInExternalStringTable(
@@ -1032,8 +1030,8 @@ void Heap::Scavenge() {
new_space_.set_age_mark(new_space_.top());
// Update how much has survived scavenge.
- IncrementYoungSurvivorsCounter(
- (PromotedSpaceSize() - survived_watermark) + new_space_.Size());
+ IncrementYoungSurvivorsCounter(static_cast<int>(
+ (PromotedSpaceSize() - survived_watermark) + new_space_.Size()));
LOG(ResourceEvent("scavenge", "end"));
@@ -1088,6 +1086,44 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable(
}
+void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) {
+ Object* head = undefined_value();
+ Context* tail = NULL;
+ Object* candidate = global_contexts_list_;
+ while (!candidate->IsUndefined()) {
+ // Check whether to keep the candidate in the list.
+ Context* candidate_context = reinterpret_cast<Context*>(candidate);
+ Object* retain = retainer->RetainAs(candidate);
+ if (retain != NULL) {
+ if (head->IsUndefined()) {
+ // First element in the list.
+ head = candidate_context;
+ } else {
+ // Subsequent elements in the list.
+ ASSERT(tail != NULL);
+ tail->set_unchecked(Context::NEXT_CONTEXT_LINK,
+ candidate_context,
+ UPDATE_WRITE_BARRIER);
+ }
+ // Retained context is new tail.
+ tail = candidate_context;
+ }
+ // Move to next element in the list.
+ candidate = candidate_context->get(Context::NEXT_CONTEXT_LINK);
+ }
+
+ // Terminate the list if there is one or more elements.
+ if (tail != NULL) {
+ tail->set_unchecked(Context::NEXT_CONTEXT_LINK,
+ Heap::undefined_value(),
+ UPDATE_WRITE_BARRIER);
+ }
+
+ // Update the head of the list of contexts.
+ Heap::global_contexts_list_ = head;
+}
+
+
class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> {
public:
static inline void VisitPointer(Object** p) {
@@ -1144,6 +1180,9 @@ class ScavengingVisitor : public StaticVisitorBase {
table_.Register(kVisitShortcutCandidate, &EvacuateShortcutCandidate);
table_.Register(kVisitByteArray, &EvacuateByteArray);
table_.Register(kVisitFixedArray, &EvacuateFixedArray);
+ table_.Register(kVisitGlobalContext,
+ &ObjectEvacuationStrategy<POINTER_OBJECT>::
+ VisitSpecialized<Context::kSize>);
typedef ObjectEvacuationStrategy<POINTER_OBJECT> PointerObject;
@@ -1222,7 +1261,7 @@ class ScavengingVisitor : public StaticVisitorBase {
if (Logger::is_logging() || CpuProfiler::is_profiling()) {
if (target->IsJSFunction()) {
PROFILE(FunctionMoveEvent(source->address(), target->address()));
- PROFILE(FunctionCreateEventFromMove(JSFunction::cast(target), source));
+ PROFILE(FunctionCreateEventFromMove(JSFunction::cast(target)));
}
}
#endif
@@ -1634,7 +1673,9 @@ bool Heap::CreateInitialMaps() {
obj = AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (obj->IsFailure()) return false;
- set_global_context_map(Map::cast(obj));
+ Map* global_context_map = Map::cast(obj);
+ global_context_map->set_visitor_id(StaticVisitorBase::kVisitGlobalContext);
+ set_global_context_map(global_context_map);
obj = AllocateMap(SHARED_FUNCTION_INFO_TYPE,
SharedFunctionInfo::kAlignedSize);
@@ -3418,7 +3459,7 @@ bool Heap::IdleNotification() {
HistogramTimerScope scope(&Counters::gc_context);
CollectAllGarbage(false);
} else {
- CollectGarbage(0, NEW_SPACE);
+ CollectGarbage(NEW_SPACE);
}
new_space_.Shrink();
last_gc_count = gc_count_;
@@ -3496,8 +3537,10 @@ void Heap::ReportHeapStatistics(const char* title) {
PrintF(">>>>>> =============== %s (%d) =============== >>>>>>\n",
title, gc_count_);
PrintF("mark-compact GC : %d\n", mc_count_);
- PrintF("old_gen_promotion_limit_ %d\n", old_gen_promotion_limit_);
- PrintF("old_gen_allocation_limit_ %d\n", old_gen_allocation_limit_);
+ PrintF("old_gen_promotion_limit_ %" V8_PTR_PREFIX "d\n",
+ old_gen_promotion_limit_);
+ PrintF("old_gen_allocation_limit_ %" V8_PTR_PREFIX "d\n",
+ old_gen_allocation_limit_);
PrintF("\n");
PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles());
@@ -4069,15 +4112,16 @@ bool Heap::ConfigureHeap(int max_semispace_size, int max_old_gen_size) {
bool Heap::ConfigureHeapDefault() {
- return ConfigureHeap(FLAG_max_new_space_size / 2, FLAG_max_old_space_size);
+ return ConfigureHeap(
+ FLAG_max_new_space_size * (KB / 2), FLAG_max_old_space_size * MB);
}
void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
*stats->start_marker = HeapStats::kStartMarker;
*stats->end_marker = HeapStats::kEndMarker;
- *stats->new_space_size = new_space_.Size();
- *stats->new_space_capacity = new_space_.Capacity();
+ *stats->new_space_size = new_space_.SizeAsInt();
+ *stats->new_space_capacity = static_cast<int>(new_space_.Capacity());
*stats->old_pointer_space_size = old_pointer_space_->Size();
*stats->old_pointer_space_capacity = old_pointer_space_->Capacity();
*stats->old_data_space_size = old_data_space_->Size();
@@ -4111,7 +4155,7 @@ void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
}
-int Heap::PromotedSpaceSize() {
+intptr_t Heap::PromotedSpaceSize() {
return old_pointer_space_->Size()
+ old_data_space_->Size()
+ code_space_->Size()
@@ -4220,10 +4264,12 @@ bool Heap::Setup(bool create_heap_objects) {
// Create initial objects
if (!CreateInitialObjects()) return false;
+
+ global_contexts_list_ = undefined_value();
}
- LOG(IntEvent("heap-capacity", Capacity()));
- LOG(IntEvent("heap-available", Available()));
+ LOG(IntPtrTEvent("heap-capacity", Capacity()));
+ LOG(IntPtrTEvent("heap-available", Available()));
#ifdef ENABLE_LOGGING_AND_PROFILING
// This should be called only after initial objects have been created.
@@ -4257,7 +4303,8 @@ void Heap::TearDown() {
PrintF("mark_compact_count=%d ", mc_count_);
PrintF("max_gc_pause=%d ", GCTracer::get_max_gc_pause());
PrintF("min_in_mutator=%d ", GCTracer::get_min_in_mutator());
- PrintF("max_alive_after_gc=%d ", GCTracer::get_max_alive_after_gc());
+ PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ",
+ GCTracer::get_max_alive_after_gc());
PrintF("\n\n");
}
@@ -4383,7 +4430,9 @@ class PrintHandleVisitor: public ObjectVisitor {
public:
void VisitPointers(Object** start, Object** end) {
for (Object** p = start; p < end; p++)
- PrintF(" handle %p to %p\n", p, *p);
+ PrintF(" handle %p to %p\n",
+ reinterpret_cast<void*>(p),
+ reinterpret_cast<void*>(*p));
}
};
@@ -4736,8 +4785,8 @@ void Heap::TracePathToGlobal() {
#endif
-static int CountTotalHolesSize() {
- int holes_size = 0;
+static intptr_t CountTotalHolesSize() {
+ intptr_t holes_size = 0;
OldSpaces spaces;
for (OldSpace* space = spaces.next();
space != NULL;
@@ -4835,13 +4884,14 @@ GCTracer::~GCTracer() {
PrintF("sweepns=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP_NEWSPACE]));
PrintF("compact=%d ", static_cast<int>(scopes_[Scope::MC_COMPACT]));
- PrintF("total_size_before=%d ", start_size_);
- PrintF("total_size_after=%d ", Heap::SizeOfObjects());
- PrintF("holes_size_before=%d ", in_free_list_or_wasted_before_gc_);
- PrintF("holes_size_after=%d ", CountTotalHolesSize());
+ PrintF("total_size_before=%" V8_PTR_PREFIX "d ", start_size_);
+ PrintF("total_size_after=%" V8_PTR_PREFIX "d ", Heap::SizeOfObjects());
+ PrintF("holes_size_before=%" V8_PTR_PREFIX "d ",
+ in_free_list_or_wasted_before_gc_);
+ PrintF("holes_size_after=%" V8_PTR_PREFIX "d ", CountTotalHolesSize());
- PrintF("allocated=%d ", allocated_since_last_gc_);
- PrintF("promoted=%d ", promoted_objects_size_);
+ PrintF("allocated=%" V8_PTR_PREFIX "d ", allocated_since_last_gc_);
+ PrintF("promoted=%" V8_PTR_PREFIX "d ", promoted_objects_size_);
PrintF("\n");
}
@@ -4917,11 +4967,11 @@ int DescriptorLookupCache::results_[DescriptorLookupCache::kLength];
#ifdef DEBUG
-bool Heap::GarbageCollectionGreedyCheck() {
+void Heap::GarbageCollectionGreedyCheck() {
ASSERT(FLAG_gc_greedy);
- if (Bootstrapper::IsActive()) return true;
- if (disallow_allocation_failure()) return true;
- return CollectGarbage(0, NEW_SPACE);
+ if (Bootstrapper::IsActive()) return;
+ if (disallow_allocation_failure()) return;
+ CollectGarbage(NEW_SPACE);
}
#endif
diff --git a/src/heap.h b/src/heap.h
index 8a11530d..6d32a4b6 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -202,9 +202,10 @@ namespace internal {
V(closure_symbol, "(closure)")
-// Forward declaration of the GCTracer class.
+// Forward declarations.
class GCTracer;
class HeapStats;
+class WeakObjectRetainer;
typedef String* (*ExternalStringTableUpdaterCallback)(Object** pointer);
@@ -245,31 +246,31 @@ class Heap : public AllStatic {
// semi space. The young generation consists of two semi spaces and
// we reserve twice the amount needed for those in order to ensure
// that new space can be aligned to its size.
- static int MaxReserved() {
+ static intptr_t MaxReserved() {
return 4 * reserved_semispace_size_ + max_old_generation_size_;
}
static int MaxSemiSpaceSize() { return max_semispace_size_; }
static int ReservedSemiSpaceSize() { return reserved_semispace_size_; }
static int InitialSemiSpaceSize() { return initial_semispace_size_; }
- static int MaxOldGenerationSize() { return max_old_generation_size_; }
+ static intptr_t MaxOldGenerationSize() { return max_old_generation_size_; }
// Returns the capacity of the heap in bytes w/o growing. Heap grows when
// more spaces are needed until it reaches the limit.
- static int Capacity();
+ static intptr_t Capacity();
// Returns the amount of memory currently committed for the heap.
- static int CommittedMemory();
+ static intptr_t CommittedMemory();
// Returns the available bytes in space w/o growing.
// Heap doesn't guarantee that it can allocate an object that requires
// all available bytes. Check MaxHeapObjectSize() instead.
- static int Available();
+ static intptr_t Available();
// Returns the maximum object size in paged space.
static inline int MaxObjectSizeInPagedSpace();
// Returns of size of all objects residing in the heap.
- static int SizeOfObjects();
+ static intptr_t SizeOfObjects();
// Return the starting address and a mask for the new space. And-masking an
// address with the mask will result in the start address of the new space
@@ -696,8 +697,7 @@ class Heap : public AllStatic {
// Performs garbage collection operation.
// Returns whether required_space bytes are available after the collection.
- static bool CollectGarbage(int required_space,
- AllocationSpace space,
+ static void CollectGarbage(AllocationSpace space,
CollectionPolicy collectionPolicy = NORMAL);
// Performs a full garbage collection. Force compaction if the
@@ -717,7 +717,7 @@ class Heap : public AllStatic {
#ifdef DEBUG
// Utility used with flag gc-greedy.
- static bool GarbageCollectionGreedyCheck();
+ static void GarbageCollectionGreedyCheck();
#endif
static void AddGCPrologueCallback(
@@ -767,6 +767,11 @@ class Heap : public AllStatic {
// not match the empty string.
static String* hidden_symbol() { return hidden_symbol_; }
+ static void set_global_contexts_list(Object* object) {
+ global_contexts_list_ = object;
+ }
+ static Object* global_contexts_list() { return global_contexts_list_; }
+
// Iterates over all roots in the heap.
static void IterateRoots(ObjectVisitor* v, VisitMode mode);
// Iterates over all strong roots in the heap.
@@ -870,6 +875,11 @@ class Heap : public AllStatic {
// Generated code can embed this address to get access to the roots.
static Object** roots_address() { return roots_; }
+ // Get address of global contexts list for serialization support.
+ static Object** global_contexts_list_address() {
+ return &global_contexts_list_;
+ }
+
#ifdef DEBUG
static void Print();
static void PrintHandles();
@@ -1051,6 +1061,8 @@ class Heap : public AllStatic {
static void UpdateNewSpaceReferencesInExternalStringTable(
ExternalStringTableUpdaterCallback updater_func);
+ static void ProcessWeakReferences(WeakObjectRetainer* retainer);
+
// Helper function that governs the promotion policy from new space to
// old. If the object's old address lies below the new space's age
// mark or if we've already filled the bottom 1/16th of the to space,
@@ -1069,8 +1081,8 @@ class Heap : public AllStatic {
static int reserved_semispace_size_;
static int max_semispace_size_;
static int initial_semispace_size_;
- static int max_old_generation_size_;
- static size_t code_range_size_;
+ static intptr_t max_old_generation_size_;
+ static intptr_t code_range_size_;
// For keeping track of how much data has survived
// scavenge since last new space expansion.
@@ -1098,7 +1110,7 @@ class Heap : public AllStatic {
static HeapState gc_state_;
// Returns the size of object residing in non new spaces.
- static int PromotedSpaceSize();
+ static intptr_t PromotedSpaceSize();
// Returns the amount of external memory registered since last global gc.
static int PromotedExternalMemorySize();
@@ -1133,16 +1145,16 @@ class Heap : public AllStatic {
// Limit that triggers a global GC on the next (normally caused) GC. This
// is checked when we have already decided to do a GC to help determine
// which collector to invoke.
- static int old_gen_promotion_limit_;
+ static intptr_t old_gen_promotion_limit_;
// Limit that triggers a global GC as soon as is reasonable. This is
// checked before expanding a paged space in the old generation and on
// every allocation in large object space.
- static int old_gen_allocation_limit_;
+ static intptr_t old_gen_allocation_limit_;
// Limit on the amount of externally allocated memory allowed
// between global GCs. If reached a global GC is forced.
- static int external_allocation_limit_;
+ static intptr_t external_allocation_limit_;
// The amount of external memory registered through the API kept alive
// by global handles
@@ -1157,6 +1169,8 @@ class Heap : public AllStatic {
static Object* roots_[kRootListLength];
+ static Object* global_contexts_list_;
+
struct StringTypeTable {
InstanceType type;
int size;
@@ -1231,8 +1245,8 @@ class Heap : public AllStatic {
GCTracer* tracer,
CollectionPolicy collectionPolicy);
- static const int kMinimumPromotionLimit = 2 * MB;
- static const int kMinimumAllocationLimit = 8 * MB;
+ static const intptr_t kMinimumPromotionLimit = 2 * MB;
+ static const intptr_t kMinimumAllocationLimit = 8 * MB;
inline static void UpdateOldSpaceLimits();
@@ -1385,24 +1399,24 @@ class HeapStats {
int* start_marker; // 0
int* new_space_size; // 1
int* new_space_capacity; // 2
- int* old_pointer_space_size; // 3
- int* old_pointer_space_capacity; // 4
- int* old_data_space_size; // 5
- int* old_data_space_capacity; // 6
- int* code_space_size; // 7
- int* code_space_capacity; // 8
- int* map_space_size; // 9
- int* map_space_capacity; // 10
- int* cell_space_size; // 11
- int* cell_space_capacity; // 12
- int* lo_space_size; // 13
+ intptr_t* old_pointer_space_size; // 3
+ intptr_t* old_pointer_space_capacity; // 4
+ intptr_t* old_data_space_size; // 5
+ intptr_t* old_data_space_capacity; // 6
+ intptr_t* code_space_size; // 7
+ intptr_t* code_space_capacity; // 8
+ intptr_t* map_space_size; // 9
+ intptr_t* map_space_capacity; // 10
+ intptr_t* cell_space_size; // 11
+ intptr_t* cell_space_capacity; // 12
+ intptr_t* lo_space_size; // 13
int* global_handle_count; // 14
int* weak_global_handle_count; // 15
int* pending_global_handle_count; // 16
int* near_death_global_handle_count; // 17
int* destroyed_global_handle_count; // 18
- int* memory_allocator_size; // 19
- int* memory_allocator_capacity; // 20
+ intptr_t* memory_allocator_size; // 19
+ intptr_t* memory_allocator_capacity; // 20
int* objects_per_type; // 21
int* size_per_type; // 22
int* os_error; // 23
@@ -1837,7 +1851,7 @@ class GCTracer BASE_EMBEDDED {
static int get_max_gc_pause() { return max_gc_pause_; }
// Returns maximum size of objects alive after GC.
- static int get_max_alive_after_gc() { return max_alive_after_gc_; }
+ static intptr_t get_max_alive_after_gc() { return max_alive_after_gc_; }
// Returns minimal interval between two subsequent collections.
static int get_min_in_mutator() { return min_in_mutator_; }
@@ -1852,7 +1866,7 @@ class GCTracer BASE_EMBEDDED {
}
double start_time_; // Timestamp set in the constructor.
- int start_size_; // Size of objects in heap set in constructor.
+ intptr_t start_size_; // Size of objects in heap set in constructor.
GarbageCollector collector_; // Type of collector.
// A count (including this one, eg, the first collection is 1) of the
@@ -1884,30 +1898,30 @@ class GCTracer BASE_EMBEDDED {
// Total amount of space either wasted or contained in one of free lists
// before the current GC.
- int in_free_list_or_wasted_before_gc_;
+ intptr_t in_free_list_or_wasted_before_gc_;
// Difference between space used in the heap at the beginning of the current
// collection and the end of the previous collection.
- int allocated_since_last_gc_;
+ intptr_t allocated_since_last_gc_;
// Amount of time spent in mutator that is time elapsed between end of the
// previous collection and the beginning of the current one.
double spent_in_mutator_;
// Size of objects promoted during the current collection.
- int promoted_objects_size_;
+ intptr_t promoted_objects_size_;
// Maximum GC pause.
static int max_gc_pause_;
// Maximum size of objects alive after GC.
- static int max_alive_after_gc_;
+ static intptr_t max_alive_after_gc_;
// Minimal interval between two subsequent collections.
static int min_in_mutator_;
// Size of objects alive after last GC.
- static int alive_after_last_gc_;
+ static intptr_t alive_after_last_gc_;
static double last_gc_end_timestamp_;
};
@@ -2043,6 +2057,19 @@ class ExternalStringTable : public AllStatic {
static List<Object*> old_space_strings_;
};
+
+// Abstract base class for checking whether a weak object should be retained.
+class WeakObjectRetainer {
+ public:
+ virtual ~WeakObjectRetainer() {}
+
+ // Return whether this object should be retained. If NULL is returned the
+ // object has no references. Otherwise the address of the retained object
+ // should be returned as in some GC situations the object has been moved.
+ virtual Object* RetainAs(Object* object) = 0;
+};
+
+
} } // namespace v8::internal
#endif // V8_HEAP_H_
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index e2f45470..e201179c 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -2414,7 +2414,7 @@ void Assembler::pxor(XMMRegister dst, XMMRegister src) {
void Assembler::ptest(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(CpuFeatures::IsEnabled(SSE4_1));
EnsureSpace ensure_space(this);
last_pc_ = pc_;
EMIT(0x66);
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index 1dab0a60..d8051c87 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -376,6 +376,7 @@ class CpuFeatures : public AllStatic {
static bool IsSupported(CpuFeature f) {
if (f == SSE2 && !FLAG_enable_sse2) return false;
if (f == SSE3 && !FLAG_enable_sse3) return false;
+ if (f == SSE4_1 && !FLAG_enable_sse4_1) return false;
if (f == CMOV && !FLAG_enable_cmov) return false;
if (f == RDTSC && !FLAG_enable_rdtsc) return false;
return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 3e2b7ae1..348bb148 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -2638,7 +2638,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ j(not_zero, &non_smi, not_taken);
__ sub(edx, Operand(eax)); // Return on the result of the subtraction.
__ j(no_overflow, &smi_done);
- __ neg(edx); // Correct sign in case of overflow.
+ __ not_(edx); // Correct sign in case of overflow. edx is never 0 here.
__ bind(&smi_done);
__ mov(eax, edx);
__ ret(0);
@@ -2964,16 +2964,7 @@ void CompareStub::BranchIfNonSymbol(MacroAssembler* masm,
void StackCheckStub::Generate(MacroAssembler* masm) {
- // Because builtins always remove the receiver from the stack, we
- // have to fake one to avoid underflowing the stack. The receiver
- // must be inserted below the return address on the stack so we
- // temporarily store that in a register.
- __ pop(eax);
- __ push(Immediate(Smi::FromInt(0)));
- __ push(eax);
-
- // Do tail-call to runtime routine.
- __ TailCallRuntime(Runtime::kStackGuard, 1, 1);
+ __ TailCallRuntime(Runtime::kStackGuard, 0, 1);
}
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index 9c8573ce..f2ac7f70 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -179,20 +179,11 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Adjust for function-level loop nesting.
ASSERT_EQ(0, loop_nesting_);
- loop_nesting_ = info->loop_nesting();
+ loop_nesting_ = info->is_in_loop() ? 1 : 0;
JumpTarget::set_compiling_deferred_code(false);
-#ifdef DEBUG
- if (strlen(FLAG_stop_at) > 0 &&
- info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
- frame_->SpillAll();
- __ int3();
- }
-#endif
-
- // New scope to get automatic timing calculation.
- { HistogramTimerScope codegen_timer(&Counters::code_generation);
+ {
CodeGenState state(this);
// Entry:
@@ -203,6 +194,14 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// esi: callee's context
allocator_->Initialize();
+#ifdef DEBUG
+ if (strlen(FLAG_stop_at) > 0 &&
+ info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+ frame_->SpillAll();
+ __ int3();
+ }
+#endif
+
frame_->Enter();
// Allocate space for locals and initialize them.
@@ -358,7 +357,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
}
// Adjust for function-level loop nesting.
- ASSERT_EQ(loop_nesting_, info->loop_nesting());
+ ASSERT_EQ(loop_nesting_, info->is_in_loop() ? 1 : 0);
loop_nesting_ = 0;
// Code generation state must be reset.
@@ -369,7 +368,6 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Process any deferred code using the register allocator.
if (!HasStackOverflow()) {
- HistogramTimerScope deferred_timer(&Counters::deferred_code_generation);
JumpTarget::set_compiling_deferred_code(true);
ProcessDeferred();
JumpTarget::set_compiling_deferred_code(false);
@@ -4925,9 +4923,12 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
ASSERT(!in_safe_int32_mode());
// Build the function info and instantiate it.
Handle<SharedFunctionInfo> function_info =
- Compiler::BuildFunctionInfo(node, script(), this);
+ Compiler::BuildFunctionInfo(node, script());
// Check for stack-overflow exception.
- if (HasStackOverflow()) return;
+ if (function_info.is_null()) {
+ SetStackOverflow();
+ return;
+ }
Result result = InstantiateFunction(function_info);
frame()->Push(&result);
}
@@ -9149,7 +9150,8 @@ class DeferredReferenceGetNamedValue: public DeferredCode {
: dst_(dst),
receiver_(receiver),
name_(name),
- is_contextual_(is_contextual) {
+ is_contextual_(is_contextual),
+ is_dont_delete_(false) {
set_comment(is_contextual
? "[ DeferredReferenceGetNamedValue (contextual)"
: "[ DeferredReferenceGetNamedValue");
@@ -9159,12 +9161,18 @@ class DeferredReferenceGetNamedValue: public DeferredCode {
Label* patch_site() { return &patch_site_; }
+ void set_is_dont_delete(bool value) {
+ ASSERT(is_contextual_);
+ is_dont_delete_ = value;
+ }
+
private:
Label patch_site_;
Register dst_;
Register receiver_;
Handle<String> name_;
bool is_contextual_;
+ bool is_dont_delete_;
};
@@ -9181,8 +9189,8 @@ void DeferredReferenceGetNamedValue::Generate() {
// The call must be followed by:
// - a test eax instruction to indicate that the inobject property
// case was inlined.
- // - a mov ecx instruction to indicate that the contextual property
- // load was inlined.
+ // - a mov ecx or mov edx instruction to indicate that the
+ // contextual property load was inlined.
//
// Store the delta to the map check instruction here in the test
// instruction. Use masm_-> instead of the __ macro since the
@@ -9191,8 +9199,11 @@ void DeferredReferenceGetNamedValue::Generate() {
// Here we use masm_-> instead of the __ macro because this is the
// instruction that gets patched and coverage code gets in the way.
if (is_contextual_) {
- masm_->mov(ecx, -delta_to_patch_site);
+ masm_->mov(is_dont_delete_ ? edx : ecx, -delta_to_patch_site);
__ IncrementCounter(&Counters::named_load_global_inline_miss, 1);
+ if (is_dont_delete_) {
+ __ IncrementCounter(&Counters::dont_delete_hint_miss, 1);
+ }
} else {
masm_->test(eax, Immediate(-delta_to_patch_site));
__ IncrementCounter(&Counters::named_load_inline_miss, 1);
@@ -9436,9 +9447,34 @@ Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
}
__ mov(result.reg(),
FieldOperand(result.reg(), JSGlobalPropertyCell::kValueOffset));
- __ cmp(result.reg(), Factory::the_hole_value());
- deferred->Branch(equal);
+ bool is_dont_delete = false;
+ if (!info_->closure().is_null()) {
+ // When doing lazy compilation we can check if the global cell
+ // already exists and use its "don't delete" status as a hint.
+ AssertNoAllocation no_gc;
+ v8::internal::GlobalObject* global_object =
+ info_->closure()->context()->global();
+ LookupResult lookup;
+ global_object->LocalLookupRealNamedProperty(*name, &lookup);
+ if (lookup.IsProperty() && lookup.type() == NORMAL) {
+ ASSERT(lookup.holder() == global_object);
+ ASSERT(global_object->property_dictionary()->ValueAt(
+ lookup.GetDictionaryEntry())->IsJSGlobalPropertyCell());
+ is_dont_delete = lookup.IsDontDelete();
+ }
+ }
+ deferred->set_is_dont_delete(is_dont_delete);
+ if (!is_dont_delete) {
+ __ cmp(result.reg(), Factory::the_hole_value());
+ deferred->Branch(equal);
+ } else if (FLAG_debug_code) {
+ __ cmp(result.reg(), Factory::the_hole_value());
+ __ Check(not_equal, "DontDelete cells can't contain the hole");
+ }
__ IncrementCounter(&Counters::named_load_global_inline, 1);
+ if (is_dont_delete) {
+ __ IncrementCounter(&Counters::dont_delete_hint_hit, 1);
+ }
} else {
// The initial (invalid) offset has to be large enough to force a 32-bit
// instruction encoding to allow patching with an arbitrary offset. Use
diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h
index c4a03d11..b0724092 100644
--- a/src/ia32/codegen-ia32.h
+++ b/src/ia32/codegen-ia32.h
@@ -300,9 +300,7 @@ enum ArgumentsAllocationMode {
class CodeGenerator: public AstVisitor {
public:
- // Takes a function literal, generates code for it. This function should only
- // be called by compiler.cc.
- static Handle<Code> MakeCode(CompilationInfo* info);
+ static bool MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(CompilationInfo* info);
@@ -626,9 +624,6 @@ class CodeGenerator: public AstVisitor {
void CheckStack();
- static InlineFunctionGenerator FindInlineFunctionGenerator(
- Runtime::FunctionId function_id);
-
bool CheckForInlineRuntimeCall(CallRuntime* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index cf53f4b8..150df995 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -61,6 +61,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator");
+#ifdef DEBUG
+ if (strlen(FLAG_stop_at) > 0 &&
+ info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+ __ int3();
+ }
+#endif
+
__ push(ebp); // Caller's frame pointer.
__ mov(ebp, esp);
__ push(esi); // Callee's context.
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index 413c36e9..b5f4deef 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -885,8 +885,8 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
__ test(edx, Immediate(kSmiTagMask));
__ j(zero, &slow, not_taken);
- // Check that the key is a smi.
- __ test(eax, Immediate(kSmiTagMask));
+ // Check that the key is an array index, that is Uint32.
+ __ test(eax, Immediate(kSmiTagMask | kSmiSignMask));
__ j(not_zero, &slow, not_taken);
// Get the map of the receiver.
@@ -1662,17 +1662,37 @@ bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
// One byte opcode for mov ecx,0xXXXXXXXX.
+// Marks inlined contextual loads using all kinds of cells. Generated
+// code has the hole check:
+// mov reg, <cell>
+// mov reg, (<cell>, value offset)
+// cmp reg, <the hole>
+// je slow
+// ;; use reg
static const byte kMovEcxByte = 0xB9;
+// One byte opcode for mov edx,0xXXXXXXXX.
+// Marks inlined contextual loads using only "don't delete"
+// cells. Generated code doesn't have the hole check:
+// mov reg, <cell>
+// mov reg, (<cell>, value offset)
+// ;; use reg
+static const byte kMovEdxByte = 0xBA;
+
bool LoadIC::PatchInlinedContextualLoad(Address address,
Object* map,
- Object* cell) {
+ Object* cell,
+ bool is_dont_delete) {
// The address of the instruction following the call.
Address mov_instruction_address =
address + Assembler::kCallTargetAddressOffset;
- // If the instruction following the call is not a cmp eax, nothing
- // was inlined.
- if (*mov_instruction_address != kMovEcxByte) return false;
+ // If the instruction following the call is not a mov ecx/edx,
+ // nothing was inlined.
+ byte b = *mov_instruction_address;
+ if (b != kMovEcxByte && b != kMovEdxByte) return false;
+ // If we don't have the hole check generated, we can only support
+ // "don't delete" cells.
+ if (b == kMovEdxByte && !is_dont_delete) return false;
Address delta_address = mov_instruction_address + 1;
// The delta to the start of the map check instruction.
diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index 2aab7a8d..e2853e88 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -133,7 +133,6 @@ int RegExpMacroAssemblerIA32::stack_limit_slack() {
void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) {
if (by != 0) {
- Label inside_string;
__ add(Operand(edi), Immediate(by * char_size()));
}
}
@@ -964,6 +963,17 @@ void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) {
__ add(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
}
+void RegExpMacroAssemblerIA32::SetCurrentPositionFromEnd(int by) {
+ NearLabel after_position;
+ __ cmp(edi, -by * char_size());
+ __ j(greater_equal, &after_position);
+ __ mov(edi, -by * char_size());
+ // On RegExp code entry (where this operation is used), the character before
+ // the current position is expected to be already loaded.
+ // We have advanced the position, so it's safe to read backwards.
+ LoadCurrentCharacterUnchecked(-1, 1);
+ __ bind(&after_position);
+}
void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) {
ASSERT(register_index >= num_saved_registers_); // Reserved for positions!
diff --git a/src/ia32/regexp-macro-assembler-ia32.h b/src/ia32/regexp-macro-assembler-ia32.h
index 8b8eeed6..51e2cb01 100644
--- a/src/ia32/regexp-macro-assembler-ia32.h
+++ b/src/ia32/regexp-macro-assembler-ia32.h
@@ -98,6 +98,7 @@ class RegExpMacroAssemblerIA32: public NativeRegExpMacroAssembler {
StackCheckFlag check_stack_limit);
virtual void ReadCurrentPositionFromRegister(int reg);
virtual void ReadStackPointerFromRegister(int reg);
+ virtual void SetCurrentPositionFromEnd(int by);
virtual void SetRegister(int register_index, int to);
virtual void Succeed();
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index dd0d6364..bb0a46cd 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -1944,6 +1944,109 @@ Object* CallStubCompiler::CompileMathFloorCall(Object* object,
}
+Object* CallStubCompiler::CompileMathAbsCall(Object* object,
+ JSObject* holder,
+ JSGlobalPropertyCell* cell,
+ JSFunction* function,
+ String* name) {
+ // ----------- S t a t e -------------
+ // -- ecx : name
+ // -- esp[0] : return address
+ // -- esp[(argc - n) * 4] : arg[n] (zero-based)
+ // -- ...
+ // -- esp[(argc + 1) * 4] : receiver
+ // -----------------------------------
+
+ const int argc = arguments().immediate();
+
+ // If the object is not a JSObject or we got an unexpected number of
+ // arguments, bail out to the regular call.
+ if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
+
+ Label miss;
+ GenerateNameCheck(name, &miss);
+
+ if (cell == NULL) {
+ __ mov(edx, Operand(esp, 2 * kPointerSize));
+
+ STATIC_ASSERT(kSmiTag == 0);
+ __ test(edx, Immediate(kSmiTagMask));
+ __ j(zero, &miss);
+
+ CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name,
+ &miss);
+ } else {
+ ASSERT(cell->value() == function);
+ GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
+ GenerateLoadFunctionFromCell(cell, function, &miss);
+ }
+
+ // Load the (only) argument into eax.
+ __ mov(eax, Operand(esp, 1 * kPointerSize));
+
+ // Check if the argument is a smi.
+ Label not_smi;
+ STATIC_ASSERT(kSmiTag == 0);
+ __ test(eax, Immediate(kSmiTagMask));
+ __ j(not_zero, &not_smi);
+
+ // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
+ // otherwise.
+ __ mov(ebx, eax);
+ __ sar(ebx, kBitsPerInt - 1);
+
+ // Do bitwise not or do nothing depending on ebx.
+ __ xor_(eax, Operand(ebx));
+
+ // Add 1 or do nothing depending on ebx.
+ __ sub(eax, Operand(ebx));
+
+ // If the result is still negative, go to the slow case.
+ // This only happens for the most negative smi.
+ Label slow;
+ __ j(negative, &slow);
+
+ // Smi case done.
+ __ ret(2 * kPointerSize);
+
+ // Check if the argument is a heap number and load its exponent and
+ // sign into ebx.
+ __ bind(&not_smi);
+ __ CheckMap(eax, Factory::heap_number_map(), &slow, true);
+ __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset));
+
+ // Check the sign of the argument. If the argument is positive,
+ // just return it.
+ Label negative_sign;
+ __ test(ebx, Immediate(HeapNumber::kSignMask));
+ __ j(not_zero, &negative_sign);
+ __ ret(2 * kPointerSize);
+
+ // If the argument is negative, clear the sign, and return a new
+ // number.
+ __ bind(&negative_sign);
+ __ and_(ebx, ~HeapNumber::kSignMask);
+ __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset));
+ __ AllocateHeapNumber(eax, edi, edx, &slow);
+ __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx);
+ __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
+ __ ret(2 * kPointerSize);
+
+ // Tail call the full function. We do not have to patch the receiver
+ // because the function makes no use of it.
+ __ bind(&slow);
+ __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
+
+ __ bind(&miss);
+ // ecx: function name.
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
+
+ // Return the generated code.
+ return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
+}
+
+
Object* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder,
JSFunction* function,
diff --git a/src/ic.cc b/src/ic.cc
index 5b62a8a0..adf365af 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -299,7 +299,10 @@ void LoadIC::ClearInlinedVersion(Address address) {
// present) to guarantee failure by holding an invalid map (the null
// value). The offset can be patched to anything.
PatchInlinedLoad(address, Heap::null_value(), 0);
- PatchInlinedContextualLoad(address, Heap::null_value(), Heap::null_value());
+ PatchInlinedContextualLoad(address,
+ Heap::null_value(),
+ Heap::null_value(),
+ true);
}
@@ -848,7 +851,10 @@ Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) {
JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(
lookup.holder()->property_dictionary()->ValueAt(
lookup.GetDictionaryEntry()));
- if (PatchInlinedContextualLoad(address(), map, cell)) {
+ if (PatchInlinedContextualLoad(address(),
+ map,
+ cell,
+ lookup.IsDontDelete())) {
set_target(megamorphic_stub());
TRACE_IC_NAMED("[LoadIC : inline contextual patch %s]\n", name);
ASSERT(cell->value() != Heap::the_hole_value());
@@ -1541,18 +1547,17 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
// Static IC stub generators.
//
-static Object* CompileFunction(Object* result,
- Handle<Object> object,
- InLoopFlag in_loop) {
+static JSFunction* CompileFunction(JSFunction* function,
+ InLoopFlag in_loop) {
// Compile now with optimization.
HandleScope scope;
- Handle<JSFunction> function = Handle<JSFunction>(JSFunction::cast(result));
+ Handle<JSFunction> function_handle(function);
if (in_loop == IN_LOOP) {
- CompileLazyInLoop(function, object, CLEAR_EXCEPTION);
+ CompileLazyInLoop(function_handle, CLEAR_EXCEPTION);
} else {
- CompileLazy(function, object, CLEAR_EXCEPTION);
+ CompileLazy(function_handle, CLEAR_EXCEPTION);
}
- return *function;
+ return *function_handle;
}
@@ -1575,7 +1580,7 @@ Object* CallIC_Miss(Arguments args) {
if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
return result;
}
- return CompileFunction(result, args.at<Object>(0), ic.target()->ic_in_loop());
+ return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop());
}
@@ -1591,7 +1596,7 @@ Object* KeyedCallIC_Miss(Arguments args) {
if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
return result;
}
- return CompileFunction(result, args.at<Object>(0), ic.target()->ic_in_loop());
+ return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop());
}
diff --git a/src/ic.h b/src/ic.h
index a5fada09..437e45a9 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -300,7 +300,8 @@ class LoadIC: public IC {
static bool PatchInlinedContextualLoad(Address address,
Object* map,
- Object* cell);
+ Object* cell,
+ bool is_dont_delete);
friend class IC;
};
diff --git a/src/interpreter-irregexp.cc b/src/interpreter-irregexp.cc
index a904447f..c9c3cc4c 100644
--- a/src/interpreter-irregexp.cc
+++ b/src/interpreter-irregexp.cc
@@ -607,6 +607,15 @@ static bool RawMatch(const byte* code_base,
pc = code_base + Load32Aligned(pc + 4);
}
break;
+ BYTECODE(SET_CURRENT_POSITION_FROM_END) {
+ int by = static_cast<uint32_t>(insn) >> BYTECODE_SHIFT;
+ if (subject.length() - current > by) {
+ current = subject.length() - by;
+ current_char = subject[current - 1];
+ }
+ pc += BC_SET_CURRENT_POSITION_FROM_END_LENGTH;
+ break;
+ }
default:
UNREACHABLE();
break;
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index 30d4dcbf..3c5ddfbe 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -125,7 +125,7 @@ Handle<Object> RegExpImpl::Compile(Handle<JSRegExp> re,
PostponeInterruptsScope postpone;
RegExpCompileData parse_result;
FlatStringReader reader(pattern);
- if (!ParseRegExp(&reader, flags.is_multiline(), &parse_result)) {
+ if (!Parser::ParseRegExp(&reader, flags.is_multiline(), &parse_result)) {
// Throw an exception if we fail to parse the pattern.
ThrowRegExpException(re,
pattern,
@@ -267,7 +267,7 @@ bool RegExpImpl::CompileIrregexp(Handle<JSRegExp> re, bool is_ascii) {
RegExpCompileData compile_data;
FlatStringReader reader(pattern);
- if (!ParseRegExp(&reader, flags.is_multiline(), &compile_data)) {
+ if (!Parser::ParseRegExp(&reader, flags.is_multiline(), &compile_data)) {
// Throw an exception if we fail to parse the pattern.
// THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once.
ThrowRegExpException(re,
@@ -5180,7 +5180,10 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(RegExpCompileData* data,
&compiler,
compiler.accept());
RegExpNode* node = captured_body;
- if (!data->tree->IsAnchored()) {
+ bool is_end_anchored = data->tree->IsAnchoredAtEnd();
+ bool is_start_anchored = data->tree->IsAnchoredAtStart();
+ int max_length = data->tree->max_match();
+ if (!is_start_anchored) {
// Add a .*? at the beginning, outside the body capture, unless
// this expression is anchored at the beginning.
RegExpNode* loop_node =
@@ -5236,6 +5239,15 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(RegExpCompileData* data,
RegExpMacroAssemblerIrregexp macro_assembler(codes);
#endif // V8_INTERPRETED_REGEXP
+ // Inserted here, instead of in Assembler, because it depends on information
+ // in the AST that isn't replicated in the Node structure.
+ static const int kMaxBacksearchLimit = 1024;
+ if (is_end_anchored &&
+ !is_start_anchored &&
+ max_length < kMaxBacksearchLimit) {
+ macro_assembler.SetCurrentPositionFromEnd(max_length);
+ }
+
return compiler.Assemble(&macro_assembler,
node,
data->capture_count,
diff --git a/src/liveedit-debugger.js b/src/liveedit-debugger.js
index be97989b..83b703f8 100644
--- a/src/liveedit-debugger.js
+++ b/src/liveedit-debugger.js
@@ -46,8 +46,7 @@ Debug.LiveEdit = new function() {
// Forward declaration for minifier.
var FunctionStatus;
-
-
+
// Applies the change to the script.
// The change is in form of list of chunks encoded in a single array as
// a series of triplets (pos1_start, pos1_end, pos2_end)
@@ -58,7 +57,7 @@ Debug.LiveEdit = new function() {
// Gather compile information about old version of script.
var old_compile_info = GatherCompileInfo(old_source, script);
-
+
// Build tree structures for old and new versions of the script.
var root_old_node = BuildCodeInfoTree(old_compile_info);
@@ -69,7 +68,7 @@ Debug.LiveEdit = new function() {
// Find all SharedFunctionInfo's that were compiled from this script.
FindLiveSharedInfos(root_old_node, script);
-
+
// Gather compile information about new version of script.
var new_compile_info;
try {
@@ -81,7 +80,7 @@ Debug.LiveEdit = new function() {
// Link recompiled script data with other data.
FindCorrespondingFunctions(root_old_node, root_new_node);
-
+
// Prepare to-do lists.
var replace_code_list = new Array();
var link_to_old_script_list = new Array();
@@ -104,7 +103,7 @@ Debug.LiveEdit = new function() {
CollectNew(node_list[i].children);
}
}
-
+
if (old_node.status == FunctionStatus.DAMAGED) {
CollectDamaged(old_node);
return;
@@ -131,17 +130,17 @@ Debug.LiveEdit = new function() {
},
updated: false
};
-
+
if (preview_only) {
return preview_description;
}
-
+
HarvestTodo(root_old_node);
-
+
// Collect shared infos for functions whose code need to be patched.
var replaced_function_infos = new Array();
for (var i = 0; i < replace_code_list.length; i++) {
- var info_wrapper = replace_code_list[i].live_shared_info_wrapper;
+ var info_wrapper = replace_code_list[i].live_shared_info_wrapper;
if (info_wrapper) {
replaced_function_infos.push(info_wrapper);
}
@@ -149,14 +148,14 @@ Debug.LiveEdit = new function() {
// We haven't changed anything before this line yet.
// Committing all changes.
-
+
// Check that function being patched is not currently on stack or drop them.
var dropped_functions_number =
CheckStackActivations(replaced_function_infos, change_log);
-
- preview_description.stack_modified = dropped_functions_number != 0;
-
- // Start with breakpoints. Convert their line/column positions and
+
+ preview_description.stack_modified = dropped_functions_number != 0;
+
+ // Start with breakpoints. Convert their line/column positions and
// temporary remove.
var break_points_restorer = TemporaryRemoveBreakPoints(script, change_log);
@@ -169,24 +168,24 @@ Debug.LiveEdit = new function() {
old_script = void 0;
} else {
var old_script_name = CreateNameForOldScript(script);
-
+
// Update the script text and create a new script representing an old
// version of the script.
old_script = %LiveEditReplaceScript(script, new_source,
old_script_name);
-
+
var link_to_old_script_report = new Array();
change_log.push( { linked_to_old_script: link_to_old_script_report } );
-
+
// We need to link to old script all former nested functions.
for (var i = 0; i < link_to_old_script_list.length; i++) {
LinkToOldScript(link_to_old_script_list[i], old_script,
link_to_old_script_report);
}
-
+
preview_description.created_script_name = old_script_name;
}
-
+
// Link to an actual script all the functions that we are going to use.
for (var i = 0; i < link_to_original_script_list.length; i++) {
%LiveEditFunctionSetScript(
@@ -196,26 +195,26 @@ Debug.LiveEdit = new function() {
for (var i = 0; i < replace_code_list.length; i++) {
PatchFunctionCode(replace_code_list[i], change_log);
}
-
+
var position_patch_report = new Array();
change_log.push( {position_patched: position_patch_report} );
-
+
for (var i = 0; i < update_positions_list.length; i++) {
// TODO(LiveEdit): take into account wether it's source_changed or
// unchanged and whether positions changed at all.
PatchPositions(update_positions_list[i], diff_array,
position_patch_report);
}
-
+
break_points_restorer(pos_translator, old_script);
-
+
preview_description.updated = true;
return preview_description;
}
// Function is public.
this.ApplyPatchMultiChunk = ApplyPatchMultiChunk;
-
+
// Fully compiles source string as a script. Returns Array of
// FunctionCompileInfo -- a descriptions of all functions of the script.
// Elements of array are ordered by start positions of functions (from top
@@ -224,7 +223,7 @@ Debug.LiveEdit = new function() {
//
// All functions get compiled linked to script provided as parameter script.
// TODO(LiveEdit): consider not using actual scripts as script, because
- // we have to manually erase all links right after compile.
+ // we have to manually erase all links right after compile.
function GatherCompileInfo(source, script) {
// Get function info, elements are partially sorted (it is a tree of
// nested functions serialized as parent followed by serialized children.
@@ -291,7 +290,7 @@ Debug.LiveEdit = new function() {
return compile_info;
}
-
+
// Replaces function's Code.
function PatchFunctionCode(old_node, change_log) {
var new_info = old_node.corresponding_node.info;
@@ -318,7 +317,7 @@ Debug.LiveEdit = new function() {
}
}
}
-
+
change_log.push( {function_patched: new_info.function_name} );
} else {
change_log.push( {function_patched: new_info.function_name,
@@ -326,7 +325,7 @@ Debug.LiveEdit = new function() {
}
}
-
+
// Makes a function associated with another instance of a script (the
// one representing its old version). This way the function still
// may access its own text.
@@ -340,12 +339,12 @@ Debug.LiveEdit = new function() {
{ name: old_info_node.info.function_name, not_found: true } );
}
}
-
+
// Returns function that restores breakpoints.
function TemporaryRemoveBreakPoints(original_script, change_log) {
var script_break_points = GetScriptBreakPoints(original_script);
-
+
var break_points_update_report = [];
change_log.push( { break_points_update: break_points_update_report } );
@@ -354,11 +353,11 @@ Debug.LiveEdit = new function() {
var break_point = script_break_points[i];
break_point.clear();
-
- // TODO(LiveEdit): be careful with resource offset here.
+
+ // TODO(LiveEdit): be careful with resource offset here.
var break_point_position = Debug.findScriptSourcePosition(original_script,
break_point.line(), break_point.column());
-
+
var old_position_description = {
position: break_point_position,
line: break_point.line(),
@@ -366,8 +365,8 @@ Debug.LiveEdit = new function() {
}
break_point_old_positions.push(old_position_description);
}
-
-
+
+
// Restores breakpoints and creates their copies in the "old" copy of
// the script.
return function (pos_translator, old_script_copy_opt) {
@@ -378,19 +377,19 @@ Debug.LiveEdit = new function() {
if (old_script_copy_opt) {
var clone = break_point.cloneForOtherScript(old_script_copy_opt);
clone.set(old_script_copy_opt);
-
+
break_points_update_report.push( {
type: "copied_to_old",
id: break_point.number(),
- new_id: clone.number(),
+ new_id: clone.number(),
positions: break_point_old_positions[i]
} );
}
-
+
var updated_position = pos_translator.Translate(
break_point_old_positions[i].position,
PosTranslator.ShiftWithTopInsideChunkHandler);
-
+
var new_location =
original_script.locationFromPosition(updated_position, false);
@@ -401,9 +400,9 @@ Debug.LiveEdit = new function() {
line: new_location.line,
column: new_location.column
}
-
+
break_point.set(original_script);
-
+
break_points_update_report.push( { type: "position_changed",
id: break_point.number(),
old_positions: break_point_old_positions[i],
@@ -413,7 +412,7 @@ Debug.LiveEdit = new function() {
}
}
-
+
function Assert(condition, message) {
if (!condition) {
if (message) {
@@ -430,7 +429,7 @@ Debug.LiveEdit = new function() {
this.len1 = len1;
this.len2 = len2;
}
-
+
function PosTranslator(diff_array) {
var chunks = new Array();
var current_diff = 0;
@@ -441,16 +440,16 @@ Debug.LiveEdit = new function() {
var pos2_end = diff_array[i + 2];
chunks.push(new DiffChunk(pos1_begin, pos2_begin, pos1_end - pos1_begin,
pos2_end - pos2_begin));
- current_diff = pos2_end - pos1_end;
+ current_diff = pos2_end - pos1_end;
}
this.chunks = chunks;
}
PosTranslator.prototype.GetChunks = function() {
return this.chunks;
}
-
+
PosTranslator.prototype.Translate = function(pos, inside_chunk_handler) {
- var array = this.chunks;
+ var array = this.chunks;
if (array.length == 0 || pos < array[0].pos1) {
return pos;
}
@@ -467,9 +466,9 @@ Debug.LiveEdit = new function() {
}
var chunk = array[chunk_index1];
if (pos >= chunk.pos1 + chunk.len1) {
- return pos + chunk.pos2 + chunk.len2 - chunk.pos1 - chunk.len1;
+ return pos + chunk.pos2 + chunk.len2 - chunk.pos1 - chunk.len1;
}
-
+
if (!inside_chunk_handler) {
inside_chunk_handler = PosTranslator.DefaultInsideChunkHandler;
}
@@ -479,17 +478,17 @@ Debug.LiveEdit = new function() {
PosTranslator.DefaultInsideChunkHandler = function(pos, diff_chunk) {
Assert(false, "Cannot translate position in changed area");
}
-
+
PosTranslator.ShiftWithTopInsideChunkHandler =
function(pos, diff_chunk) {
// We carelessly do not check whether we stay inside the chunk after
// translation.
- return pos - diff_chunk.pos1 + diff_chunk.pos2;
+ return pos - diff_chunk.pos1 + diff_chunk.pos2;
}
-
+
var FunctionStatus = {
// No change to function or its inner functions; however its positions
- // in script may have been shifted.
+ // in script may have been shifted.
UNCHANGED: "unchanged",
// The code of a function remains unchanged, but something happened inside
// some inner functions.
@@ -500,14 +499,14 @@ Debug.LiveEdit = new function() {
// Function is changed but cannot be patched.
DAMAGED: "damaged"
}
-
+
function CodeInfoTreeNode(code_info, children, array_index) {
this.info = code_info;
this.children = children;
// an index in array of compile_info
- this.array_index = array_index;
+ this.array_index = array_index;
this.parent = void 0;
-
+
this.status = FunctionStatus.UNCHANGED;
// Status explanation is used for debugging purposes and will be shown
// in user UI if some explanations are needed.
@@ -516,26 +515,26 @@ Debug.LiveEdit = new function() {
this.new_end_pos = void 0;
this.corresponding_node = void 0;
this.unmatched_new_nodes = void 0;
-
+
// 'Textual' correspondence/matching is weaker than 'pure'
// correspondence/matching. We need 'textual' level for visual presentation
// in UI, we use 'pure' level for actual code manipulation.
// Sometimes only function body is changed (functions in old and new script
// textually correspond), but we cannot patch the code, so we see them
- // as an old function deleted and new function created.
+ // as an old function deleted and new function created.
this.textual_corresponding_node = void 0;
this.textually_unmatched_new_nodes = void 0;
-
+
this.live_shared_info_wrapper = void 0;
}
-
+
// From array of function infos that is implicitly a tree creates
// an actual tree of functions in script.
function BuildCodeInfoTree(code_info_array) {
// Throughtout all function we iterate over input array.
var index = 0;
- // Recursive function that builds a branch of tree.
+ // Recursive function that builds a branch of tree.
function BuildNode() {
var my_index = index;
index++;
@@ -551,7 +550,7 @@ Debug.LiveEdit = new function() {
}
return node;
}
-
+
var root = BuildNode();
Assert(index == code_info_array.length);
return root;
@@ -570,7 +569,7 @@ Debug.LiveEdit = new function() {
this.current = function() { return chunks[chunk_index]; }
this.next = function() {
var chunk = chunks[chunk_index];
- pos_diff = chunk.pos2 + chunk.len2 - (chunk.pos1 + chunk.len1);
+ pos_diff = chunk.pos2 + chunk.len2 - (chunk.pos1 + chunk.len1);
chunk_index++;
}
this.done = function() { return chunk_index >= chunks.length; }
@@ -582,7 +581,7 @@ Debug.LiveEdit = new function() {
// below function start.
function ProcessInternals(info_node) {
info_node.new_start_pos = chunk_it.TranslatePos(
- info_node.info.start_position);
+ info_node.info.start_position);
var child_index = 0;
var code_changed = false;
var source_changed = false;
@@ -591,7 +590,7 @@ Debug.LiveEdit = new function() {
chunk_it.current().pos1 < info_node.info.end_position) {
if (child_index < info_node.children.length) {
var child = info_node.children[child_index];
-
+
if (child.info.end_position <= chunk_it.current().pos1) {
ProcessUnchangedChild(child);
child_index++;
@@ -620,7 +619,7 @@ Debug.LiveEdit = new function() {
continue;
}
} else {
- if (chunk_it.current().pos1 + chunk_it.current().len1 <=
+ if (chunk_it.current().pos1 + chunk_it.current().len1 <=
info_node.info.end_position) {
info_node.status = FunctionStatus.CHANGED;
chunk_it.next();
@@ -645,14 +644,14 @@ Debug.LiveEdit = new function() {
info_node.status = FunctionStatus.SOURCE_CHANGED;
}
info_node.new_end_pos =
- chunk_it.TranslatePos(info_node.info.end_position);
+ chunk_it.TranslatePos(info_node.info.end_position);
}
-
+
function ProcessUnchangedChild(node) {
node.new_start_pos = chunk_it.TranslatePos(node.info.start_position);
node.new_end_pos = chunk_it.TranslatePos(node.info.end_position);
}
-
+
ProcessInternals(code_info_tree);
}
@@ -670,7 +669,7 @@ Debug.LiveEdit = new function() {
function ProcessChildren(old_node, new_node) {
var old_children = old_node.children;
var new_children = new_node.children;
-
+
var unmatched_new_nodes_list = [];
var textually_unmatched_new_nodes_list = [];
@@ -728,13 +727,13 @@ Debug.LiveEdit = new function() {
old_index++;
}
}
-
+
while (new_index < new_children.length) {
unmatched_new_nodes_list.push(new_children[new_index]);
textually_unmatched_new_nodes_list.push(new_children[new_index]);
new_index++;
}
-
+
if (old_node.status == FunctionStatus.CHANGED) {
var why_wrong_expectations =
WhyFunctionExpectationsDiffer(old_node.info, new_node.info);
@@ -749,23 +748,23 @@ Debug.LiveEdit = new function() {
}
ProcessChildren(old_code_tree, new_code_tree);
-
+
old_code_tree.corresponding_node = new_code_tree;
old_code_tree.textual_corresponding_node = new_code_tree;
Assert(old_code_tree.status != FunctionStatus.DAMAGED,
"Script became damaged");
}
-
+
function FindLiveSharedInfos(old_code_tree, script) {
var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script);
-
+
var shared_infos = new Array();
-
+
for (var i = 0; i < shared_raw_list.length; i++) {
shared_infos.push(new SharedInfoWrapper(shared_raw_list[i]));
}
-
+
// Finds SharedFunctionInfo that corresponds compile info with index
// in old version of the script.
function FindFunctionInfo(compile_info) {
@@ -777,7 +776,7 @@ Debug.LiveEdit = new function() {
}
}
}
-
+
function TraverseTree(node) {
var info_wrapper = FindFunctionInfo(node.info);
if (info_wrapper) {
@@ -791,7 +790,7 @@ Debug.LiveEdit = new function() {
TraverseTree(old_code_tree);
}
-
+
// An object describing function compilation details. Its index fields
// apply to indexes inside array that stores these objects.
function FunctionCompileInfo(raw_array) {
@@ -807,7 +806,7 @@ Debug.LiveEdit = new function() {
this.next_sibling_index = null;
this.raw_array = raw_array;
}
-
+
function SharedInfoWrapper(raw_array) {
this.function_name = raw_array[0];
this.start_position = raw_array[1];
@@ -821,7 +820,7 @@ Debug.LiveEdit = new function() {
var shared_info_wrapper = old_info_node.live_shared_info_wrapper;
if (!shared_info_wrapper) {
// TODO(LiveEdit): function is not compiled yet or is already collected.
- report_array.push(
+ report_array.push(
{ name: old_info_node.info.function_name, info_not_found: true } );
return;
}
@@ -835,44 +834,44 @@ Debug.LiveEdit = new function() {
// TODO(635): try better than this; support several changes.
return script.name + " (old)";
}
-
+
// Compares a function interface old and new version, whether it
// changed or not. Returns explanation if they differ.
function WhyFunctionExpectationsDiffer(function_info1, function_info2) {
// Check that function has the same number of parameters (there may exist
// an adapter, that won't survive function parameter number change).
if (function_info1.param_num != function_info2.param_num) {
- return "Changed parameter number: " + function_info1.param_num +
+ return "Changed parameter number: " + function_info1.param_num +
" and " + function_info2.param_num;
}
var scope_info1 = function_info1.scope_info;
var scope_info2 = function_info2.scope_info;
- var scope_info1_text;
- var scope_info2_text;
-
+ var scope_info1_text;
+ var scope_info2_text;
+
if (scope_info1) {
- scope_info1_text = scope_info1.toString();
+ scope_info1_text = scope_info1.toString();
} else {
scope_info1_text = "";
}
if (scope_info2) {
- scope_info2_text = scope_info2.toString();
+ scope_info2_text = scope_info2.toString();
} else {
scope_info2_text = "";
}
-
+
if (scope_info1_text != scope_info2_text) {
return "Incompatible variable maps: [" + scope_info1_text +
- "] and [" + scope_info2_text + "]";
+ "] and [" + scope_info2_text + "]";
}
// No differences. Return undefined.
return;
}
-
+
// Minifier forward declaration.
var FunctionPatchabilityStatus;
-
+
// For array of wrapped shared function infos checks that none of them
// have activations on stack (of any thread). Throws a Failure exception
// if this proves to be false.
@@ -886,7 +885,7 @@ Debug.LiveEdit = new function() {
// Extra array element may contain error message.
throw new Failure(result[shared_list.length]);
}
-
+
var problems = new Array();
var dropped = new Array();
for (var i = 0; i < shared_list.length; i++) {
@@ -896,7 +895,7 @@ Debug.LiveEdit = new function() {
} else if (result[i] != FunctionPatchabilityStatus.AVAILABLE_FOR_PATCH) {
var description = {
name: shared.function_name,
- start_pos: shared.start_position,
+ start_pos: shared.start_position,
end_pos: shared.end_position,
replace_problem:
FunctionPatchabilityStatus.SymbolName(result[i])
@@ -911,10 +910,10 @@ Debug.LiveEdit = new function() {
change_log.push( { functions_on_stack: problems } );
throw new Failure("Blocked by functions on stack");
}
-
+
return dropped.length;
}
-
+
// A copy of the FunctionPatchabilityStatus enum from liveedit.h
var FunctionPatchabilityStatus = {
AVAILABLE_FOR_PATCH: 1,
@@ -923,17 +922,17 @@ Debug.LiveEdit = new function() {
BLOCKED_UNDER_NATIVE_CODE: 4,
REPLACED_ON_ACTIVE_STACK: 5
}
-
+
FunctionPatchabilityStatus.SymbolName = function(code) {
var enum = FunctionPatchabilityStatus;
for (name in enum) {
if (enum[name] == code) {
return name;
}
- }
+ }
}
-
-
+
+
// A logical failure in liveedit process. This means that change_log
// is valid and consistent description of what happened.
function Failure(message) {
@@ -941,11 +940,11 @@ Debug.LiveEdit = new function() {
}
// Function (constructor) is public.
this.Failure = Failure;
-
+
Failure.prototype.toString = function() {
return "LiveEdit Failure: " + this.message;
}
-
+
// A testing entry.
function GetPcFromSourcePos(func, source_pos) {
return %GetFunctionCodePositionFromSource(func, source_pos);
@@ -962,7 +961,7 @@ Debug.LiveEdit = new function() {
}
// Function is public.
this.SetScriptSource = SetScriptSource;
-
+
function CompareStringsLinewise(s1, s2) {
return %LiveEditCompareStringsLinewise(s1, s2);
}
@@ -978,19 +977,19 @@ Debug.LiveEdit = new function() {
function ApplySingleChunkPatch(script, change_pos, change_len, new_str,
change_log) {
var old_source = script.source;
-
+
// Prepare new source string.
var new_source = old_source.substring(0, change_pos) +
new_str + old_source.substring(change_pos + change_len);
-
+
return ApplyPatchMultiChunk(script,
[ change_pos, change_pos + change_len, change_pos + new_str.length],
new_source, false, change_log);
}
-
+
// Creates JSON description for a change tree.
function DescribeChangeTree(old_code_tree) {
-
+
function ProcessOldNode(node) {
var child_infos = [];
for (var i = 0; i < node.children.length; i++) {
@@ -1011,7 +1010,7 @@ Debug.LiveEdit = new function() {
positions: DescribePositions(node),
status: node.status,
children: child_infos,
- new_children: new_child_infos
+ new_children: new_child_infos
};
if (node.status_explanation) {
res.status_explanation = node.status_explanation;
@@ -1021,7 +1020,7 @@ Debug.LiveEdit = new function() {
}
return res;
}
-
+
function ProcessNewNode(node) {
var child_infos = [];
// Do not list ancestors.
@@ -1037,18 +1036,18 @@ Debug.LiveEdit = new function() {
};
return res;
}
-
+
function DescribePositions(node) {
return {
start_position: node.info.start_position,
end_position: node.info.end_position
};
}
-
+
return ProcessOldNode(old_code_tree);
}
-
+
// Functions are public for tests.
this.TestApi = {
PosTranslator: PosTranslator,
diff --git a/src/liveedit.cc b/src/liveedit.cc
index c07e83f6..3cbd2446 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -29,13 +29,15 @@
#include "v8.h"
#include "liveedit.h"
+
#include "compiler.h"
-#include "oprofile-agent.h"
-#include "scopes.h"
-#include "scopeinfo.h"
-#include "global-handles.h"
#include "debug.h"
+#include "global-handles.h"
#include "memory.h"
+#include "oprofile-agent.h"
+#include "parser.h"
+#include "scopeinfo.h"
+#include "scopes.h"
namespace v8 {
namespace internal {
@@ -396,45 +398,31 @@ Handle<JSArray> LiveEdit::CompareStringsLinewise(Handle<String> s1,
static void CompileScriptForTracker(Handle<Script> script) {
- const bool is_eval = false;
- const bool is_global = true;
// TODO(635): support extensions.
- Extension* extension = NULL;
-
PostponeInterruptsScope postpone;
- // Only allow non-global compiles for eval.
- ASSERT(is_eval || is_global);
-
// Build AST.
- ScriptDataImpl* pre_data = NULL;
- FunctionLiteral* lit = MakeAST(is_global, script, extension, pre_data);
-
- // Check for parse errors.
- if (lit == NULL) {
- ASSERT(Top::has_pending_exception());
- return;
- }
-
- // Compile the code.
- CompilationInfo info(lit, script, is_eval);
-
- LiveEditFunctionTracker tracker(lit);
- Handle<Code> code = MakeCodeForLiveEdit(&info);
-
- // Check for stack-overflow exceptions.
- if (code.is_null()) {
- Top::StackOverflow();
- return;
+ CompilationInfo info(script);
+ info.MarkAsGlobal();
+ if (Parser::Parse(&info)) {
+ // Compile the code.
+ LiveEditFunctionTracker tracker(info.function());
+ if (Compiler::MakeCodeForLiveEdit(&info)) {
+ ASSERT(!info.code().is_null());
+ tracker.RecordRootFunctionInfo(info.code());
+ } else {
+ Top::StackOverflow();
+ }
}
- tracker.RecordRootFunctionInfo(code);
}
+
// Unwraps JSValue object, returning its field "value"
static Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) {
return Handle<Object>(jsValue->value());
}
+
// Wraps any object into a OpaqueReference, that will hide the object
// from JavaScript.
static Handle<JSValue> WrapInJSValue(Object* object) {
@@ -445,6 +433,7 @@ static Handle<JSValue> WrapInJSValue(Object* object) {
return result;
}
+
// Simple helper class that creates more or less typed structures over
// JSArray object. This is an adhoc method of passing structures from C++
// to JavaScript.
@@ -465,6 +454,7 @@ class JSArrayBasedStruct {
Handle<JSArray> GetJSArray() {
return array_;
}
+
protected:
void SetField(int field_position, Handle<Object> value) {
SetElement(array_, field_position, value);
@@ -479,6 +469,7 @@ class JSArrayBasedStruct {
Object* res = GetField(field_position);
return Smi::cast(res)->value();
}
+
private:
Handle<JSArray> array_;
};
@@ -551,6 +542,7 @@ class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
friend class JSArrayBasedStruct<FunctionInfoWrapper>;
};
+
// Wraps SharedFunctionInfo along with some of its fields for passing it
// back to JavaScript. SharedFunctionInfo object itself is additionally
// wrapped into BlindReference for sanitizing reasons.
@@ -591,6 +583,7 @@ class SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> {
friend class JSArrayBasedStruct<SharedInfoWrapper>;
};
+
class FunctionInfoListener {
public:
FunctionInfoListener() {
@@ -617,7 +610,6 @@ class FunctionInfoListener {
current_parent_index_ = info.GetParentIndex();
}
- public:
// Saves only function code, because for a script function we
// may never create a SharedFunctionInfo object.
void FunctionCode(Handle<Code> function_code) {
@@ -705,6 +697,7 @@ class FunctionInfoListener {
int current_parent_index_;
};
+
static FunctionInfoListener* active_function_info_listener = NULL;
JSArray* LiveEdit::GatherCompileInfo(Handle<Script> script,
diff --git a/src/log-utils.cc b/src/log-utils.cc
index 62f0ca62..d6d8754b 100644
--- a/src/log-utils.cc
+++ b/src/log-utils.cc
@@ -122,6 +122,7 @@ int LogDynamicBuffer::WriteInternal(const char* data, int data_size) {
bool Log::is_stopped_ = false;
Log::WritePtr Log::Write = NULL;
FILE* Log::output_handle_ = NULL;
+FILE* Log::output_code_handle_ = NULL;
LogDynamicBuffer* Log::output_buffer_ = NULL;
// Must be the same message as in Logger::PauseProfiler.
const char* Log::kDynamicBufferSeal = "profiler,\"pause\"\n";
@@ -143,9 +144,22 @@ void Log::OpenStdout() {
}
+static const char kCodeLogExt[] = ".code";
+
+
void Log::OpenFile(const char* name) {
ASSERT(!IsEnabled());
output_handle_ = OS::FOpen(name, OS::LogFileOpenMode);
+ if (FLAG_ll_prof) {
+ // Open a file for logging the contents of code objects so that
+ // they can be disassembled later.
+ size_t name_len = strlen(name);
+ ScopedVector<char> code_name(
+ static_cast<int>(name_len + sizeof(kCodeLogExt)));
+ memcpy(code_name.start(), name, name_len);
+ memcpy(code_name.start() + name_len, kCodeLogExt, sizeof(kCodeLogExt));
+ output_code_handle_ = OS::FOpen(code_name.start(), OS::LogFileOpenMode);
+ }
Write = WriteToFile;
Init();
}
@@ -165,6 +179,8 @@ void Log::Close() {
if (Write == WriteToFile) {
if (output_handle_ != NULL) fclose(output_handle_);
output_handle_ = NULL;
+ if (output_code_handle_ != NULL) fclose(output_code_handle_);
+ output_code_handle_ = NULL;
} else if (Write == WriteToMemory) {
delete output_buffer_;
output_buffer_ = NULL;
diff --git a/src/log-utils.h b/src/log-utils.h
index 8889f1b7..ffea9282 100644
--- a/src/log-utils.h
+++ b/src/log-utils.h
@@ -132,6 +132,7 @@ class Log : public AllStatic {
size_t rv = fwrite(msg, 1, length, output_handle_);
ASSERT(static_cast<size_t>(length) == rv);
USE(rv);
+ fflush(output_handle_);
return length;
}
@@ -151,6 +152,9 @@ class Log : public AllStatic {
// mutex_ should be acquired before using output_handle_ or output_buffer_.
static FILE* output_handle_;
+ // Used when low-level profiling is active to save code object contents.
+ static FILE* output_code_handle_;
+
static LogDynamicBuffer* output_buffer_;
// Size of dynamic buffer block (and dynamic buffer initial size).
@@ -170,6 +174,7 @@ class Log : public AllStatic {
// mutex_ should be acquired before using it.
static char* message_buffer_;
+ friend class Logger;
friend class LogMessageBuilder;
friend class LogRecordCompressor;
};
diff --git a/src/log.cc b/src/log.cc
index 5c700576..1b0fdeb5 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -191,11 +191,12 @@ class Ticker: public Sampler {
~Ticker() { if (IsActive()) Stop(); }
- void SampleStack(TickSample* sample) {
+ virtual void SampleStack(TickSample* sample) {
+ ASSERT(IsSynchronous());
StackTracer::Trace(sample);
}
- void Tick(TickSample* sample) {
+ virtual void Tick(TickSample* sample) {
if (profiler_) profiler_->Insert(sample);
if (window_) window_->AddState(sample->state);
}
@@ -393,6 +394,13 @@ void Logger::IntEvent(const char* name, int value) {
}
+void Logger::IntPtrTEvent(const char* name, intptr_t value) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+ if (FLAG_log) UncheckedIntPtrTEvent(name, value);
+#endif
+}
+
+
#ifdef ENABLE_LOGGING_AND_PROFILING
void Logger::UncheckedIntEvent(const char* name, int value) {
if (!Log::IsEnabled()) return;
@@ -403,6 +411,16 @@ void Logger::UncheckedIntEvent(const char* name, int value) {
#endif
+#ifdef ENABLE_LOGGING_AND_PROFILING
+void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
+ if (!Log::IsEnabled()) return;
+ LogMessageBuilder msg;
+ msg.Append("%s,%" V8_PTR_PREFIX "d\n", name, value);
+ msg.WriteToLogFile();
+}
+#endif
+
+
void Logger::HandleEvent(const char* name, Object** location) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (!Log::IsEnabled() || !FLAG_log_handles) return;
@@ -748,6 +766,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
msg.Append(*p);
}
msg.Append('"');
+ LowLevelCodeCreateEvent(code, &msg);
if (FLAG_compress_log) {
ASSERT(compression_helper_ != NULL);
if (!compression_helper_->HandleMessage(&msg)) return;
@@ -767,6 +786,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, String* name) {
msg.Append("%s,%s,", log_events_[CODE_CREATION_EVENT], log_events_[tag]);
msg.AppendAddress(code->address());
msg.Append(",%d,\"%s\"", code->ExecutableSize(), *str);
+ LowLevelCodeCreateEvent(code, &msg);
if (FLAG_compress_log) {
ASSERT(compression_helper_ != NULL);
if (!compression_helper_->HandleMessage(&msg)) return;
@@ -791,6 +811,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
msg.AppendAddress(code->address());
msg.Append(",%d,\"%s %s:%d\"",
code->ExecutableSize(), *str, *sourcestr, line);
+ LowLevelCodeCreateEvent(code, &msg);
if (FLAG_compress_log) {
ASSERT(compression_helper_ != NULL);
if (!compression_helper_->HandleMessage(&msg)) return;
@@ -808,6 +829,7 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count) {
msg.Append("%s,%s,", log_events_[CODE_CREATION_EVENT], log_events_[tag]);
msg.AppendAddress(code->address());
msg.Append(",%d,\"args_count: %d\"", code->ExecutableSize(), args_count);
+ LowLevelCodeCreateEvent(code, &msg);
if (FLAG_compress_log) {
ASSERT(compression_helper_ != NULL);
if (!compression_helper_->HandleMessage(&msg)) return;
@@ -818,6 +840,17 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count) {
}
+void Logger::CodeMovingGCEvent() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+ if (!Log::IsEnabled() || !FLAG_log_code || !FLAG_ll_prof) return;
+ LogMessageBuilder msg;
+ msg.Append("%s\n", log_events_[CODE_MOVING_GC]);
+ msg.WriteToLogFile();
+ OS::SignalCodeMovingGC();
+#endif
+}
+
+
void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (!Log::IsEnabled() || !FLAG_log_code) return;
@@ -828,6 +861,7 @@ void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
msg.Append(",%d,\"", code->ExecutableSize());
msg.AppendDetailed(source, false);
msg.Append('\"');
+ LowLevelCodeCreateEvent(code, &msg);
if (FLAG_compress_log) {
ASSERT(compression_helper_ != NULL);
if (!compression_helper_->HandleMessage(&msg)) return;
@@ -892,8 +926,7 @@ void Logger::FunctionCreateEvent(JSFunction* function) {
}
-void Logger::FunctionCreateEventFromMove(JSFunction* function,
- HeapObject*) {
+void Logger::FunctionCreateEventFromMove(JSFunction* function) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (function->unchecked_code() != Builtins::builtin(Builtins::LazyCompile)) {
FunctionCreateEvent(function);
@@ -1005,11 +1038,12 @@ void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
void Logger::HeapSampleStats(const char* space, const char* kind,
- int capacity, int used) {
+ intptr_t capacity, intptr_t used) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (!Log::IsEnabled() || !FLAG_log_gc) return;
LogMessageBuilder msg;
- msg.Append("heap-sample-stats,\"%s\",\"%s\",%d,%d\n",
+ msg.Append("heap-sample-stats,\"%s\",\"%s\","
+ "%" V8_PTR_PREFIX "d,%" V8_PTR_PREFIX "d\n",
space, kind, capacity, used);
msg.WriteToLogFile();
#endif
@@ -1322,6 +1356,34 @@ void Logger::LogCodeObject(Object* object) {
}
+void Logger::LogCodeInfo() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+ if (!Log::IsEnabled() || !FLAG_log_code || !FLAG_ll_prof) return;
+#if V8_TARGET_ARCH_IA32
+ const char arch[] = "ia32";
+#elif V8_TARGET_ARCH_X64
+ const char arch[] = "x64";
+#elif V8_TARGET_ARCH_ARM
+ const char arch[] = "arm";
+#else
+ const char arch[] = "unknown";
+#endif
+ LogMessageBuilder msg;
+ msg.Append("code-info,%s,%d\n", arch, Code::kHeaderSize);
+ msg.WriteToLogFile();
+#endif // ENABLE_LOGGING_AND_PROFILING
+}
+
+
+void Logger::LowLevelCodeCreateEvent(Code* code, LogMessageBuilder* msg) {
+ if (!FLAG_ll_prof || Log::output_code_handle_ == NULL) return;
+ int pos = static_cast<int>(ftell(Log::output_code_handle_));
+ fwrite(code->instruction_start(), 1, code->instruction_size(),
+ Log::output_code_handle_);
+ msg->Append(",%d", pos);
+}
+
+
void Logger::LogCodeObjects() {
AssertNoAllocation no_alloc;
HeapIterator iterator;
@@ -1433,6 +1495,12 @@ bool Logger::Setup() {
// --prof implies --log-code.
if (FLAG_prof) FLAG_log_code = true;
+ // --ll-prof implies --log-code and --log-snapshot-positions.
+ if (FLAG_ll_prof) {
+ FLAG_log_code = true;
+ FLAG_log_snapshot_positions = true;
+ }
+
// --prof_lazy controls --log-code, implies --noprof_auto.
if (FLAG_prof_lazy) {
FLAG_log_code = false;
@@ -1494,6 +1562,8 @@ bool Logger::Setup() {
ASSERT(VMState::is_outermost_external());
+ if (FLAG_ll_prof) LogCodeInfo();
+
ticker_ = new Ticker(kSamplingIntervalMs);
if (FLAG_sliding_state_window && sliding_state_window_ == NULL) {
diff --git a/src/log.h b/src/log.h
index 2534e1e8..3a4d79b8 100644
--- a/src/log.h
+++ b/src/log.h
@@ -91,6 +91,7 @@ class CompressionHelper;
V(CODE_CREATION_EVENT, "code-creation", "cc") \
V(CODE_MOVE_EVENT, "code-move", "cm") \
V(CODE_DELETE_EVENT, "code-delete", "cd") \
+ V(CODE_MOVING_GC, "code-moving-gc", "cg") \
V(FUNCTION_CREATION_EVENT, "function-creation", "fc") \
V(FUNCTION_MOVE_EVENT, "function-move", "fm") \
V(FUNCTION_DELETE_EVENT, "function-delete", "fd") \
@@ -159,6 +160,7 @@ class Logger {
// Emits an event with an int value -> (name, value).
static void IntEvent(const char* name, int value);
+ static void IntPtrTEvent(const char* name, intptr_t value);
// Emits an event with an handle value -> (name, location).
static void HandleEvent(const char* name, Object** location);
@@ -208,6 +210,7 @@ class Logger {
static void CodeCreateEvent(LogEventsAndTags tag, Code* code, String* name,
String* source, int line);
static void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count);
+ static void CodeMovingGCEvent();
// Emits a code create event for a RegExp.
static void RegExpCodeCreateEvent(Code* code, String* source);
// Emits a code move event.
@@ -216,8 +219,7 @@ class Logger {
static void CodeDeleteEvent(Address from);
// Emits a function object create event.
static void FunctionCreateEvent(JSFunction* function);
- static void FunctionCreateEventFromMove(JSFunction* function,
- HeapObject*);
+ static void FunctionCreateEventFromMove(JSFunction* function);
// Emits a function move event.
static void FunctionMoveEvent(Address from, Address to);
// Emits a function delete event.
@@ -237,7 +239,7 @@ class Logger {
static void HeapSampleJSProducerEvent(const char* constructor,
Address* stack);
static void HeapSampleStats(const char* space, const char* kind,
- int capacity, int used);
+ intptr_t capacity, intptr_t used);
static void SharedLibraryEvent(const char* library_path,
uintptr_t start,
@@ -316,6 +318,12 @@ class Logger {
// Used for logging stubs found in the snapshot.
static void LogCodeObject(Object* code_object);
+ // Emits general information about generated code.
+ static void LogCodeInfo();
+
+ // Handles code creation when low-level profiling is active.
+ static void LowLevelCodeCreateEvent(Code* code, LogMessageBuilder* msg);
+
// Emits a profiler tick event. Used by the profiler thread.
static void TickEvent(TickSample* sample, bool overflow);
@@ -326,6 +334,7 @@ class Logger {
// Logs an IntEvent regardless of whether FLAG_log is true.
static void UncheckedIntEvent(const char* name, int value);
+ static void UncheckedIntPtrTEvent(const char* name, intptr_t value);
// Stops logging and profiling in case of insufficient resources.
static void StopLoggingAndProfiling();
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index c847b842..ad928ea3 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -167,8 +167,8 @@ void MarkCompactCollector::Finish() {
// reclaiming the waste and free list blocks).
static const int kFragmentationLimit = 15; // Percent.
static const int kFragmentationAllowed = 1 * MB; // Absolute.
- int old_gen_recoverable = 0;
- int old_gen_used = 0;
+ intptr_t old_gen_recoverable = 0;
+ intptr_t old_gen_used = 0;
OldSpaces spaces;
for (OldSpace* space = spaces.next(); space != NULL; space = spaces.next()) {
@@ -282,6 +282,11 @@ class StaticMarkingVisitor : public StaticVisitorBase {
FixedArray::BodyDescriptor,
void>::Visit);
+ table_.Register(kVisitGlobalContext,
+ &FixedBodyVisitor<StaticMarkingVisitor,
+ Context::MarkCompactBodyDescriptor,
+ void>::Visit);
+
table_.Register(kVisitSharedFunctionInfo, &VisitSharedFunctionInfo);
table_.Register(kVisitByteArray, &DataObjectVisitor::Visit);
@@ -578,6 +583,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
VisitPointers(SLOT_ADDR(object,
JSFunction::kCodeEntryOffset + kPointerSize),
SLOT_ADDR(object, JSFunction::kSize));
+
#undef SLOT_ADDR
}
@@ -738,6 +744,21 @@ class SymbolTableCleaner : public ObjectVisitor {
};
+// Implementation of WeakObjectRetainer for mark compact GCs. All marked objects
+// are retained.
+class MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
+ public:
+ virtual Object* RetainAs(Object* object) {
+ MapWord first_word = HeapObject::cast(object)->map_word();
+ if (first_word.IsMarked()) {
+ return object;
+ } else {
+ return NULL;
+ }
+ }
+};
+
+
void MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) {
ASSERT(!object->IsMarked());
ASSERT(Heap::Contains(object));
@@ -1069,6 +1090,10 @@ void MarkCompactCollector::MarkLiveObjects() {
ExternalStringTable::Iterate(&v);
ExternalStringTable::CleanUp();
+ // Process the weak references.
+ MarkCompactWeakObjectRetainer mark_compact_object_retainer;
+ Heap::ProcessWeakReferences(&mark_compact_object_retainer);
+
// Remove object groups after marking phase.
GlobalHandles::RemoveObjectGroups();
}
@@ -1639,6 +1664,9 @@ static void SweepNewSpace(NewSpace* space) {
}
}
+ // Update pointer from the global contexts list.
+ updating_visitor.VisitPointer(Heap::global_contexts_list_address());
+
// Update pointers from external string table.
Heap::UpdateNewSpaceReferencesInExternalStringTable(
&UpdateNewSpaceReferenceInExternalStringTableEntry);
@@ -2008,8 +2036,10 @@ class MapCompact {
#ifdef DEBUG
if (FLAG_gc_verbose) {
- PrintF("update %p : %p -> %p\n", obj->address(),
- map, new_map);
+ PrintF("update %p : %p -> %p\n",
+ obj->address(),
+ reinterpret_cast<void*>(map),
+ reinterpret_cast<void*>(new_map));
}
#endif
}
@@ -2068,8 +2098,8 @@ void MarkCompactCollector::SweepSpaces() {
&UpdatePointerToNewGen,
Heap::WATERMARK_SHOULD_BE_VALID);
- int live_maps_size = Heap::map_space()->Size();
- int live_maps = live_maps_size / Map::kSize;
+ intptr_t live_maps_size = Heap::map_space()->Size();
+ int live_maps = static_cast<int>(live_maps_size / Map::kSize);
ASSERT(live_map_objects_size_ == live_maps_size);
if (Heap::map_space()->NeedsCompaction(live_maps)) {
@@ -2243,6 +2273,9 @@ void MarkCompactCollector::UpdatePointers() {
Heap::IterateRoots(&updating_visitor, VISIT_ONLY_STRONG);
GlobalHandles::IterateWeakRoots(&updating_visitor);
+ // Update the pointer to the head of the weak list of global contexts.
+ updating_visitor.VisitPointer(&Heap::global_contexts_list_);
+
int live_maps_size = IterateLiveObjects(Heap::map_space(),
&UpdatePointersInOldObject);
int live_pointer_olds_size = IterateLiveObjects(Heap::old_pointer_space(),
@@ -2520,7 +2553,7 @@ int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj,
HeapObject* copied_to = HeapObject::FromAddress(new_addr);
if (copied_to->IsJSFunction()) {
PROFILE(FunctionMoveEvent(old_addr, new_addr));
- PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to), obj));
+ PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to)));
}
HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr));
@@ -2613,7 +2646,7 @@ int MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
HeapObject* copied_to = HeapObject::FromAddress(new_addr);
if (copied_to->IsJSFunction()) {
PROFILE(FunctionMoveEvent(old_addr, new_addr));
- PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to), obj));
+ PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to)));
}
HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr));
diff --git a/src/messages.js b/src/messages.js
index 4f492bc5..7f9c0f8d 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -438,18 +438,18 @@ Script.prototype.lineCount = function() {
/**
* Returns the name of script if available, contents of sourceURL comment
- * otherwise. See
+ * otherwise. See
* http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
* for details on using //@ sourceURL comment to identify scritps that don't
* have name.
- *
+ *
* @return {?string} script name if present, value for //@ sourceURL comment
* otherwise.
*/
Script.prototype.nameOrSourceURL = function() {
if (this.name)
return this.name;
- // TODO(608): the spaces in a regexp below had to be escaped as \040
+ // TODO(608): the spaces in a regexp below had to be escaped as \040
// because this file is being processed by js2c whose handling of spaces
// in regexps is broken. Also, ['"] are excluded from allowed URLs to
// avoid matches against sources that invoke evals with sourceURL.
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
index 57bed6a0..59a53732 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -39,7 +39,7 @@
namespace v8i = v8::internal;
-#if !defined(__mips)
+#if !defined(__mips) || defined(USE_SIMULATOR)
// Only build the simulator if not compiling for real MIPS hardware.
namespace assembler {
@@ -1645,6 +1645,6 @@ uintptr_t Simulator::PopAddress() {
} } // namespace assembler::mips
-#endif // __mips
+#endif // !__mips || USE_SIMULATOR
#endif // V8_TARGET_ARCH_MIPS
diff --git a/src/mips/simulator-mips.h b/src/mips/simulator-mips.h
index d5dfc301..6e42683a 100644
--- a/src/mips/simulator-mips.h
+++ b/src/mips/simulator-mips.h
@@ -38,7 +38,7 @@
#include "allocation.h"
-#if defined(__mips)
+#if defined(__mips) && !defined(USE_SIMULATOR)
// When running without a simulator we call the entry directly.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
@@ -79,7 +79,7 @@ class SimulatorStack : public v8::internal::AllStatic {
reinterpret_cast<TryCatch*>(try_catch_address)
-#else // #if defined(__mips)
+#else // #if !defined(__mips) || defined(USE_SIMULATOR)
// When running with the simulator transition into simulated execution at this
// point.
@@ -305,7 +305,7 @@ class SimulatorStack : public v8::internal::AllStatic {
}
};
-#endif // defined(__mips)
+#endif // !defined(__mips) || defined(USE_SIMULATOR)
#endif // V8_MIPS_SIMULATOR_MIPS_H_
diff --git a/src/mirror-debugger.js b/src/mirror-debugger.js
index 761b9b31..6b9e9655 100644
--- a/src/mirror-debugger.js
+++ b/src/mirror-debugger.js
@@ -1611,7 +1611,7 @@ FrameMirror.prototype.invocationText = function() {
result += ' returning ';
result += this.returnValue().toText();
}
-
+
return result;
}
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index ed08468e..5883f8b3 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -89,7 +89,7 @@ void Failure::FailureVerify() {
void HeapObject::PrintHeader(const char* id) {
- PrintF("%p: [%s]\n", this, id);
+ PrintF("%p: [%s]\n", reinterpret_cast<void*>(this), id);
}
@@ -522,9 +522,9 @@ void JSObject::PrintElements() {
void JSObject::JSObjectPrint() {
- PrintF("%p: [JSObject]\n", this);
- PrintF(" - map = %p\n", map());
- PrintF(" - prototype = %p\n", GetPrototype());
+ PrintF("%p: [JSObject]\n", reinterpret_cast<void*>(this));
+ PrintF(" - map = %p\n", reinterpret_cast<void*>(map()));
+ PrintF(" - prototype = %p\n", reinterpret_cast<void*>(GetPrototype()));
PrintF(" {\n");
PrintProperties();
PrintElements();
@@ -744,7 +744,7 @@ void String::StringVerify() {
void JSFunction::JSFunctionPrint() {
HeapObject::PrintHeader("Function");
- PrintF(" - map = 0x%p\n", map());
+ PrintF(" - map = 0x%p\n", reinterpret_cast<void*>(map()));
PrintF(" - initial_map = ");
if (has_initial_map()) {
initial_map()->ShortPrint();
@@ -1224,9 +1224,9 @@ void BreakPointInfo::BreakPointInfoVerify() {
void BreakPointInfo::BreakPointInfoPrint() {
HeapObject::PrintHeader("BreakPointInfo");
- PrintF("\n - code_position: %d", code_position());
- PrintF("\n - source_position: %d", source_position());
- PrintF("\n - statement_position: %d", statement_position());
+ PrintF("\n - code_position: %d", code_position()->value());
+ PrintF("\n - source_position: %d", source_position()->value());
+ PrintF("\n - statement_position: %d", statement_position()->value());
PrintF("\n - break_point_objects: ");
break_point_objects()->ShortPrint();
}
diff --git a/src/objects-inl.h b/src/objects-inl.h
index f63d6725..11f9d348 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -844,15 +844,6 @@ bool Failure::IsOutOfMemoryException() const {
}
-int Failure::requested() const {
- const int kShiftBits =
- kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
- STATIC_ASSERT(kShiftBits >= 0);
- ASSERT(type() == RETRY_AFTER_GC);
- return static_cast<int>(value() >> kShiftBits);
-}
-
-
AllocationSpace Failure::allocation_space() const {
ASSERT_EQ(RETRY_AFTER_GC, type());
return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
@@ -881,20 +872,14 @@ intptr_t Failure::value() const {
}
-Failure* Failure::RetryAfterGC(int requested_bytes) {
- // Assert that the space encoding fits in the three bytes allotted for it.
- ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
- uintptr_t requested =
- static_cast<uintptr_t>(requested_bytes >> kObjectAlignmentBits);
- int tag_bits = kSpaceTagSize + kFailureTypeTagSize + kFailureTagSize;
- if (((requested << tag_bits) >> tag_bits) != requested) {
- // No room for entire requested size in the bits. Round down to
- // maximally representable size.
- requested = static_cast<intptr_t>(
- (~static_cast<uintptr_t>(0)) >> (tag_bits + 1));
- }
- int value = static_cast<int>(requested << kSpaceTagSize) | NEW_SPACE;
- return Construct(RETRY_AFTER_GC, value);
+Failure* Failure::RetryAfterGC() {
+ return RetryAfterGC(NEW_SPACE);
+}
+
+
+Failure* Failure::RetryAfterGC(AllocationSpace space) {
+ ASSERT((space & ~kSpaceTagMask) == 0);
+ return Construct(RETRY_AFTER_GC, space);
}
@@ -1485,6 +1470,15 @@ void FixedArray::set_unchecked(int index, Smi* value) {
}
+void FixedArray::set_unchecked(int index,
+ Object* value,
+ WriteBarrierMode mode) {
+ int offset = kHeaderSize + index * kPointerSize;
+ WRITE_FIELD(this, offset, value);
+ CONDITIONAL_WRITE_BARRIER(this, offset, mode);
+}
+
+
void FixedArray::set_null_unchecked(int index) {
ASSERT(index >= 0 && index < this->length());
ASSERT(!Heap::InNewSpace(Heap::null_value()));
diff --git a/src/objects-visiting.h b/src/objects-visiting.h
index a6d6b12c..ed76cb97 100644
--- a/src/objects-visiting.h
+++ b/src/objects-visiting.h
@@ -25,8 +25,8 @@
// (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_OBJECTS_ITERATION_H_
-#define V8_OBJECTS_ITERATION_H_
+#ifndef V8_OBJECTS_VISITING_H_
+#define V8_OBJECTS_VISITING_H_
// This file provides base classes and auxiliary methods for defining
// static object visitors used during GC.
@@ -50,6 +50,7 @@ class StaticVisitorBase : public AllStatic {
kVisitShortcutCandidate,
kVisitByteArray,
kVisitFixedArray,
+ kVisitGlobalContext,
// For data objects, JS objects and structs along with generic visitor which
// can visit object of any size we provide visitors specialized by
@@ -263,6 +264,11 @@ class StaticNewSpaceVisitor : public StaticVisitorBase {
FixedArray::BodyDescriptor,
int>::Visit);
+ table_.Register(kVisitGlobalContext,
+ &FixedBodyVisitor<StaticVisitor,
+ Context::ScavengeBodyDescriptor,
+ int>::Visit);
+
table_.Register(kVisitByteArray, &VisitByteArray);
table_.Register(kVisitSharedFunctionInfo,
@@ -389,4 +395,4 @@ void Code::CodeIterateBody() {
} } // namespace v8::internal
-#endif // V8_OBJECTS_ITERATION_H_
+#endif // V8_OBJECTS_VISITING_H_
diff --git a/src/objects.cc b/src/objects.cc
index 737bf572..ac20b2e6 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1,4 +1,4 @@
-// Copyright 2006-2009 the V8 project authors. All rights reserved.
+// 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:
@@ -574,28 +574,6 @@ void Failure::FailurePrint() {
}
-Failure* Failure::RetryAfterGC(int requested_bytes, AllocationSpace space) {
- ASSERT((space & ~kSpaceTagMask) == 0);
- // TODO(X64): Stop using Smi validation for non-smi checks, even if they
- // happen to be identical at the moment.
-
- int requested = requested_bytes >> kObjectAlignmentBits;
- int value = (requested << kSpaceTagSize) | space;
- // We can't very well allocate a heap number in this situation, and if the
- // requested memory is so large it seems reasonable to say that this is an
- // out of memory situation. This fixes a crash in
- // js1_5/Regress/regress-303213.js.
- if (value >> kSpaceTagSize != requested ||
- !Smi::IsValid(value) ||
- value != ((value << kFailureTypeTagSize) >> kFailureTypeTagSize) ||
- !Smi::IsValid(value << kFailureTypeTagSize)) {
- Top::context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
- }
- return Construct(RETRY_AFTER_GC, value);
-}
-
-
// Should a word be prefixed by 'a' or 'an' in order to read naturally in
// English? Returns false for non-ASCII or words that don't start with
// a capital letter. The a/an rule follows pronunciation in English.
@@ -1180,7 +1158,11 @@ String* JSObject::constructor_name() {
if (map()->constructor()->IsJSFunction()) {
JSFunction* constructor = JSFunction::cast(map()->constructor());
String* name = String::cast(constructor->shared()->name());
- return name->length() > 0 ? name : constructor->shared()->inferred_name();
+ if (name->length() > 0) return name;
+ String* inferred_name = constructor->shared()->inferred_name();
+ if (inferred_name->length() > 0) return inferred_name;
+ Object* proto = GetPrototype();
+ if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
}
// If the constructor is not present, return "Object".
return Heap::Object_symbol();
@@ -3601,9 +3583,17 @@ Object* FixedArray::AddKeysFromJSArray(JSArray* array) {
Object* FixedArray::UnionOfKeys(FixedArray* other) {
int len0 = length();
+#ifdef DEBUG
+ if (FLAG_enable_slow_asserts) {
+ for (int i = 0; i < len0; i++) {
+ ASSERT(get(i)->IsString() || get(i)->IsNumber());
+ }
+ }
+#endif
int len1 = other->length();
- // Optimize if either is empty.
- if (len0 == 0) return other;
+ // Optimize if 'other' is empty.
+ // We cannot optimize if 'this' is empty, as other may have holes
+ // or non keys.
if (len1 == 0) return this;
// Compute how many elements are not in this.
@@ -3623,14 +3613,18 @@ Object* FixedArray::UnionOfKeys(FixedArray* other) {
FixedArray* result = FixedArray::cast(obj);
WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
for (int i = 0; i < len0; i++) {
- result->set(i, get(i), mode);
+ Object* e = get(i);
+ ASSERT(e->IsString() || e->IsNumber());
+ result->set(i, e, mode);
}
// Fill in the extra keys.
int index = 0;
for (int y = 0; y < len1; y++) {
Object* value = other->get(y);
if (!value->IsTheHole() && !HasKey(this, value)) {
- result->set(len0 + index, other->get(y), mode);
+ Object* e = other->get(y);
+ ASSERT(e->IsString() || e->IsNumber());
+ result->set(len0 + index, e, mode);
index++;
}
}
@@ -5227,6 +5221,13 @@ Object* Oddball::Initialize(const char* to_string, Object* to_number) {
}
+String* SharedFunctionInfo::DebugName() {
+ Object* n = name();
+ if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
+ return String::cast(n);
+}
+
+
bool SharedFunctionInfo::HasSourceCode() {
return !script()->IsUndefined() &&
!reinterpret_cast<Script*>(script())->source()->IsUndefined();
@@ -6454,7 +6455,7 @@ Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) {
// When we set the is_extensible flag to false we always force
// the element into dictionary mode (and force them to stay there).
if (!map()->is_extensible()) {
- Handle<Object> number(Heap::NumberFromUint32(index));
+ Handle<Object> number(Factory::NewNumberFromUint(index));
Handle<String> index_string(Factory::NumberToString(number));
Handle<Object> args[1] = { index_string };
return Top::Throw(*Factory::NewTypeError("object_not_extensible",
@@ -8568,7 +8569,9 @@ Object* NumberDictionary::Set(uint32_t key,
details = PropertyDetails(details.attributes(),
details.type(),
DetailsAt(entry).index());
- SetEntry(entry, NumberDictionaryShape::AsObject(key), value, details);
+ Object* object_key = NumberDictionaryShape::AsObject(key);
+ if (object_key->IsFailure()) return object_key;
+ SetEntry(entry, object_key, value, details);
return this;
}
@@ -8719,6 +8722,11 @@ Object* StringDictionary::TransformPropertiesToFastFor(
int inobject_props = obj->map()->inobject_properties();
int number_of_allocated_fields =
number_of_fields + unused_property_fields - inobject_props;
+ if (number_of_allocated_fields < 0) {
+ // There is enough inobject space for all fields (including unused).
+ number_of_allocated_fields = 0;
+ unused_property_fields = inobject_props - number_of_fields;
+ }
// Allocate the fixed array for the fields.
Object* fields = Heap::AllocateFixedArray(number_of_allocated_fields);
diff --git a/src/objects.h b/src/objects.h
index 7f301b5c..d917a575 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1,4 +1,4 @@
-// Copyright 2006-2009 the V8 project authors. All rights reserved.
+// 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:
@@ -794,7 +794,7 @@ class Smi: public Object {
//
// Failures are a single word, encoded as follows:
// +-------------------------+---+--+--+
-// |...rrrrrrrrrrrrrrrrrrrrrr|sss|tt|11|
+// |.........unused..........|sss|tt|11|
// +-------------------------+---+--+--+
// 7 6 4 32 10
//
@@ -810,11 +810,6 @@ class Smi: public Object {
// allocation space tag is 000 for all failure types except
// RETRY_AFTER_GC. For RETRY_AFTER_GC, the possible values are the
// allocation spaces (the encoding is found in globals.h).
-//
-// The remaining bits is the size of the allocation request in units
-// of the pointer size, and is zeroed except for RETRY_AFTER_GC
-// failures. The 25 bits (on a 32 bit platform) gives a representable
-// range of 2^27 bytes (128MB).
// Failure type tag info.
const int kFailureTypeTagSize = 2;
@@ -836,15 +831,11 @@ class Failure: public Object {
// Returns the space that needs to be collected for RetryAfterGC failures.
inline AllocationSpace allocation_space() const;
- // Returns the number of bytes requested (up to the representable maximum)
- // for RetryAfterGC failures.
- inline int requested() const;
-
inline bool IsInternalError() const;
inline bool IsOutOfMemoryException() const;
- static Failure* RetryAfterGC(int requested_bytes, AllocationSpace space);
- static inline Failure* RetryAfterGC(int requested_bytes); // NEW_SPACE
+ static inline Failure* RetryAfterGC(AllocationSpace space);
+ static inline Failure* RetryAfterGC(); // NEW_SPACE
static inline Failure* Exception();
static inline Failure* InternalError();
static inline Failure* OutOfMemoryException();
@@ -1760,6 +1751,7 @@ class FixedArray: public HeapObject {
// Setters with less debug checks for the GC to use.
inline void set_unchecked(int index, Smi* value);
inline void set_null_unchecked(int index);
+ inline void set_unchecked(int index, Object* value, WriteBarrierMode mode);
// Gives access to raw memory which stores the array's data.
inline Object** data_start();
@@ -3537,7 +3529,7 @@ class SharedFunctionInfo: public HeapObject {
// Important: inobject slack tracking is not attempted during the snapshot
// creation.
- static const int kGenerousAllocationCount = 16;
+ static const int kGenerousAllocationCount = 8;
// [construction_count]: Counter for constructor calls made during
// the tracking phase.
@@ -3621,6 +3613,9 @@ class SharedFunctionInfo: public HeapObject {
// properties.
DECL_ACCESSORS(inferred_name, String)
+ // The function's name if it is non-empty, otherwise the inferred name.
+ String* DebugName();
+
// Position of the 'function' token in the script source.
inline int function_token_position();
inline void set_function_token_position(int function_token_position);
diff --git a/src/parser.cc b/src/parser.cc
index a3f469af..7690e92d 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -47,14 +47,6 @@
namespace v8 {
namespace internal {
-class ParserFactory;
-class ParserLog;
-class TemporaryScope;
-class Target;
-
-template <typename T> class ZoneListWrapper;
-
-
// PositionStack is used for on-stack allocation of token positions for
// new expressions. Please look at ParseNewExpression.
@@ -95,254 +87,6 @@ class PositionStack {
};
-class Parser {
- public:
- Parser(Handle<Script> script, bool allow_natives_syntax,
- v8::Extension* extension, ParserMode is_pre_parsing,
- ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data);
- virtual ~Parser() { }
-
- // Pre-parse the program from the character stream; returns true on
- // success, false if a stack-overflow happened during parsing.
- bool PreParseProgram(Handle<String> source, unibrow::CharacterStream* stream);
-
- void ReportMessage(const char* message, Vector<const char*> args);
- virtual void ReportMessageAt(Scanner::Location loc,
- const char* message,
- Vector<const char*> args) = 0;
-
-
- // Returns NULL if parsing failed.
- FunctionLiteral* ParseProgram(Handle<String> source,
- bool in_global_context);
- FunctionLiteral* ParseLazy(Handle<String> source,
- Handle<String> name,
- int start_position,
- int end_position,
- bool is_expression);
- FunctionLiteral* ParseJson(Handle<String> source);
-
- // The minimum number of contiguous assignment that will
- // be treated as an initialization block. Benchmarks show that
- // the overhead exceeds the savings below this limit.
- static const int kMinInitializationBlock = 3;
-
- protected:
-
- enum Mode {
- PARSE_LAZILY,
- PARSE_EAGERLY
- };
-
- // Report syntax error
- void ReportUnexpectedToken(Token::Value token);
- void ReportInvalidPreparseData(Handle<String> name, bool* ok);
-
- Handle<Script> script_;
- Scanner scanner_;
-
- Scope* top_scope_;
- int with_nesting_level_;
-
- TemporaryScope* temp_scope_;
- Mode mode_;
-
- Target* target_stack_; // for break, continue statements
- bool allow_natives_syntax_;
- v8::Extension* extension_;
- ParserFactory* factory_;
- ParserLog* log_;
- bool is_pre_parsing_;
- ScriptDataImpl* pre_data_;
- FuncNameInferrer* fni_;
-
- bool inside_with() const { return with_nesting_level_ > 0; }
- ParserFactory* factory() const { return factory_; }
- ParserLog* log() const { return log_; }
- Scanner& scanner() { return scanner_; }
- Mode mode() const { return mode_; }
- ScriptDataImpl* pre_data() const { return pre_data_; }
-
- // All ParseXXX functions take as the last argument an *ok parameter
- // which is set to false if parsing failed; it is unchanged otherwise.
- // By making the 'exception handling' explicit, we are forced to check
- // for failure at the call sites.
- void* ParseSourceElements(ZoneListWrapper<Statement>* processor,
- int end_token, bool* ok);
- Statement* ParseStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseFunctionDeclaration(bool* ok);
- Statement* ParseNativeDeclaration(bool* ok);
- Block* ParseBlock(ZoneStringList* labels, bool* ok);
- Block* ParseVariableStatement(bool* ok);
- Block* ParseVariableDeclarations(bool accept_IN, Expression** var, bool* ok);
- Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels,
- bool* ok);
- IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseContinueStatement(bool* ok);
- Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseReturnStatement(bool* ok);
- Block* WithHelper(Expression* obj,
- ZoneStringList* labels,
- bool is_catch_block,
- bool* ok);
- Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
- CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
- SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
- DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok);
- WhileStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseForStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseThrowStatement(bool* ok);
- Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
- TryStatement* ParseTryStatement(bool* ok);
- DebuggerStatement* ParseDebuggerStatement(bool* ok);
-
- Expression* ParseExpression(bool accept_IN, bool* ok);
- Expression* ParseAssignmentExpression(bool accept_IN, bool* ok);
- Expression* ParseConditionalExpression(bool accept_IN, bool* ok);
- Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
- Expression* ParseUnaryExpression(bool* ok);
- Expression* ParsePostfixExpression(bool* ok);
- Expression* ParseLeftHandSideExpression(bool* ok);
- Expression* ParseNewExpression(bool* ok);
- Expression* ParseMemberExpression(bool* ok);
- Expression* ParseNewPrefix(PositionStack* stack, bool* ok);
- Expression* ParseMemberWithNewPrefixesExpression(PositionStack* stack,
- bool* ok);
- Expression* ParsePrimaryExpression(bool* ok);
- Expression* ParseArrayLiteral(bool* ok);
- Expression* ParseObjectLiteral(bool* ok);
- ObjectLiteral::Property* ParseObjectLiteralGetSet(bool is_getter, bool* ok);
- Expression* ParseRegExpLiteral(bool seen_equal, bool* ok);
-
- Expression* NewCompareNode(Token::Value op,
- Expression* x,
- Expression* y,
- int position);
-
- // Populate the constant properties fixed array for a materialized object
- // literal.
- void BuildObjectLiteralConstantProperties(
- 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.
- void BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* properties,
- Handle<FixedArray> constants,
- bool* is_simple,
- int* depth);
-
- // Decide if a property should be in the object boilerplate.
- bool IsBoilerplateProperty(ObjectLiteral::Property* property);
- // If the expression is a literal, return the literal value;
- // if the expression is a materialized literal and is simple return a
- // compile time value as encoded by CompileTimeValue::GetValue().
- // Otherwise, return undefined literal as the placeholder
- // in the object literal boilerplate.
- Handle<Object> GetBoilerplateValue(Expression* expression);
-
- enum FunctionLiteralType {
- EXPRESSION,
- DECLARATION,
- NESTED
- };
-
- ZoneList<Expression*>* ParseArguments(bool* ok);
- FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name,
- int function_token_position,
- FunctionLiteralType type,
- bool* ok);
-
-
- // Magical syntax support.
- Expression* ParseV8Intrinsic(bool* ok);
-
- INLINE(Token::Value peek()) { return scanner_.peek(); }
- INLINE(Token::Value Next()) { return scanner_.Next(); }
- INLINE(void Consume(Token::Value token));
- void Expect(Token::Value token, bool* ok);
- bool Check(Token::Value token);
- void ExpectSemicolon(bool* ok);
-
- Handle<String> GetSymbol(bool* ok);
-
- // Get odd-ball literals.
- Literal* GetLiteralUndefined();
- Literal* GetLiteralTheHole();
- Literal* GetLiteralNumber(double value);
-
- Handle<String> ParseIdentifier(bool* ok);
- Handle<String> ParseIdentifierName(bool* ok);
- Handle<String> ParseIdentifierOrGetOrSet(bool* is_get,
- bool* is_set,
- bool* ok);
-
- // Parser support
- virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
- FunctionLiteral* fun,
- bool resolve,
- bool* ok) = 0;
-
- bool TargetStackContainsLabel(Handle<String> label);
- BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
- IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok);
-
- void RegisterTargetUse(BreakTarget* target, Target* stop);
-
- // Create a number literal.
- Literal* NewNumberLiteral(double value);
-
- // Generate AST node that throw a ReferenceError with the given type.
- Expression* NewThrowReferenceError(Handle<String> type);
-
- // Generate AST node that throw a SyntaxError with the given
- // type. The first argument may be null (in the handle sense) in
- // which case no arguments are passed to the constructor.
- Expression* NewThrowSyntaxError(Handle<String> type, Handle<Object> first);
-
- // Generate AST node that throw a TypeError with the given
- // type. Both arguments must be non-null (in the handle sense).
- Expression* NewThrowTypeError(Handle<String> type,
- Handle<Object> first,
- Handle<Object> second);
-
- // Generic AST generator for throwing errors from compiled code.
- Expression* NewThrowError(Handle<String> constructor,
- Handle<String> type,
- Vector< Handle<Object> > arguments);
-
- // JSON is a subset of JavaScript, as specified in, e.g., the ECMAScript 5
- // specification section 15.12.1 (and appendix A.8).
- // The grammar is given section 15.12.1.2 (and appendix A.8.2).
-
- // Parse JSON input as a single JSON value.
- Expression* ParseJson(bool* ok);
-
- // Parse a single JSON value from input (grammar production JSONValue).
- // A JSON value is either a (double-quoted) string literal, a number literal,
- // one of "true", "false", or "null", or an object or array literal.
- Expression* ParseJsonValue(bool* ok);
- // Parse a JSON object literal (grammar production JSONObject).
- // An object literal is a squiggly-braced and comma separated sequence
- // (possibly empty) of key/value pairs, where the key is a JSON string
- // literal, the value is a JSON value, and the two are spearated by a colon.
- // A JavaScript object also allows numbers and identifiers as keys.
- Expression* ParseJsonObject(bool* ok);
- // Parses a JSON array literal (grammar production JSONArray). An array
- // literal is a square-bracketed and comma separated sequence (possibly empty)
- // of JSON values.
- // A JavaScript array allows leaving out values from the sequence.
- Expression* ParseJsonArray(bool* ok);
-
- friend class Target;
- friend class TargetScope;
- friend class LexicalScope;
- friend class TemporaryScope;
-};
-
-
template <typename T, int initial_size>
class BufferedZoneList {
public:
@@ -877,12 +621,30 @@ class ParserLog BASE_EMBEDDED {
virtual int function_position() { return 0; }
virtual int symbol_position() { return 0; }
virtual int symbol_ids() { return 0; }
+ virtual void PauseRecording() {}
+ virtual void ResumeRecording() {}
virtual Vector<unsigned> ExtractData() {
return Vector<unsigned>();
};
};
+
+class ConditionalLogPauseScope {
+ public:
+ ConditionalLogPauseScope(bool pause, ParserLog* log)
+ : log_(log), pause_(pause) {
+ if (pause) log->PauseRecording();
+ }
+ ~ConditionalLogPauseScope() {
+ if (pause_) log_->ResumeRecording();
+ }
+ private:
+ ParserLog* log_;
+ bool pause_;
+};
+
+
class AstBuildingParserFactory : public ParserFactory {
public:
explicit AstBuildingParserFactory(int expected_symbols)
@@ -970,15 +732,31 @@ class PartialParserRecorder: public ParserLog {
return data;
}
+ virtual void PauseRecording() {
+ pause_count_++;
+ is_recording_ = false;
+ }
+
+ virtual void ResumeRecording() {
+ ASSERT(pause_count_ > 0);
+ if (--pause_count_ == 0) is_recording_ = !has_error();
+ }
+
protected:
bool has_error() {
return static_cast<bool>(preamble_[ScriptDataImpl::kHasErrorOffset]);
}
+ bool is_recording() {
+ return is_recording_;
+ }
void WriteString(Vector<const char> str);
Collector<unsigned> function_store_;
unsigned preamble_[ScriptDataImpl::kHeaderSize];
+ bool is_recording_;
+ int pause_count_;
+
#ifdef DEBUG
int prev_start;
#endif
@@ -991,6 +769,7 @@ class CompleteParserRecorder: public PartialParserRecorder {
CompleteParserRecorder();
virtual void LogSymbol(int start, Vector<const char> literal) {
+ if (!is_recording_) return;
int hash = vector_hash(literal);
HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true);
int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
@@ -1061,13 +840,6 @@ class CompleteParserRecorder: public PartialParserRecorder {
};
-void ScriptDataImpl::SkipFunctionEntry(int start) {
- ASSERT(function_index_ + FunctionEntry::kSize <= store_.length());
- ASSERT(static_cast<int>(store_[function_index_]) == start);
- function_index_ += FunctionEntry::kSize;
-}
-
-
FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
// The current pre-data entry must be a FunctionEntry with the given
// start position.
@@ -1126,7 +898,10 @@ bool ScriptDataImpl::SanityCheck() {
-PartialParserRecorder::PartialParserRecorder() : function_store_(0) {
+PartialParserRecorder::PartialParserRecorder()
+ : function_store_(0),
+ is_recording_(true),
+ pause_count_(0) {
preamble_[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber;
preamble_[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion;
preamble_[ScriptDataImpl::kHasErrorOffset] = false;
@@ -1202,6 +977,7 @@ void PartialParserRecorder::LogMessage(Scanner::Location loc,
for (int i = 0; i < args.length(); i++) {
WriteString(CStrVector(args[i]));
}
+ is_recording_ = false;
}
@@ -1248,7 +1024,7 @@ FunctionEntry PartialParserRecorder::LogFunction(int start) {
ASSERT(start > prev_start);
prev_start = start;
#endif
- if (has_error()) return FunctionEntry();
+ if (!is_recording_) return FunctionEntry();
FunctionEntry result(function_store_.AddBlock(FunctionEntry::kSize, 0));
result.set_start_pos(start);
return result;
@@ -1343,6 +1119,8 @@ Scope* ParserFactory::NewScope(Scope* parent, Scope::Type type,
bool inside_with) {
ASSERT(parent != NULL);
parent->type_ = type;
+ // Initialize function is hijacked by DummyScope to increment scope depth.
+ parent->Initialize(inside_with);
return parent;
}
@@ -1415,6 +1193,7 @@ class LexicalScope BASE_EMBEDDED {
}
~LexicalScope() {
+ parser_->top_scope_->Leave();
parser_->top_scope_ = prev_scope_;
parser_->with_nesting_level_ = prev_level_;
}
@@ -1480,7 +1259,8 @@ bool Parser::PreParseProgram(Handle<String> source,
NoHandleAllocation no_handle_allocation;
scanner_.Initialize(source, stream, JAVASCRIPT);
ASSERT(target_stack_ == NULL);
- mode_ = PARSE_EAGERLY;
+ mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
+ if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
DummyScope top_scope;
LexicalScope scope(this, &top_scope);
TemporaryScope temp_scope(this);
@@ -1551,21 +1331,20 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
}
-FunctionLiteral* Parser::ParseLazy(Handle<String> source,
- Handle<String> name,
- int start_position,
- int end_position,
- bool is_expression) {
+FunctionLiteral* Parser::ParseLazy(Handle<SharedFunctionInfo> info) {
CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
HistogramTimerScope timer(&Counters::parse_lazy);
+ Handle<String> source(String::cast(script_->source()));
Counters::total_parse_size.Increment(source->length());
+ Handle<String> name(String::cast(info->name()));
fni_ = new FuncNameInferrer();
fni_->PushEnclosingName(name);
// Initialize parser state.
source->TryFlatten();
- scanner_.Initialize(source, start_position, end_position, JAVASCRIPT);
+ scanner_.Initialize(source, info->start_position(), info->end_position(),
+ JAVASCRIPT);
ASSERT(target_stack_ == NULL);
mode_ = PARSE_EAGERLY;
@@ -1580,7 +1359,8 @@ FunctionLiteral* Parser::ParseLazy(Handle<String> source,
LexicalScope lexical_scope(this, scope);
TemporaryScope temp_scope(this);
- FunctionLiteralType type = is_expression ? EXPRESSION : DECLARATION;
+ FunctionLiteralType type =
+ info->is_expression() ? EXPRESSION : DECLARATION;
bool ok = true;
result = ParseFunctionLiteral(name, RelocInfo::kNoPosition, type, &ok);
// Make sure the results agree.
@@ -1601,6 +1381,7 @@ FunctionLiteral* Parser::ParseLazy(Handle<String> source,
return result;
}
+
FunctionLiteral* Parser::ParseJson(Handle<String> source) {
CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
@@ -1658,7 +1439,10 @@ void Parser::ReportMessage(const char* type, Vector<const char*> args) {
Handle<String> Parser::GetSymbol(bool* ok) {
- log()->LogSymbol(scanner_.location().beg_pos, scanner_.literal());
+ if (is_pre_parsing_) {
+ log()->LogSymbol(scanner_.location().beg_pos, scanner_.literal());
+ return Handle<String>::null();
+ }
int symbol_id = -1;
if (pre_data() != NULL) {
symbol_id = pre_data()->GetSymbolIdentifier();
@@ -1971,7 +1755,7 @@ void* Parser::ParseSourceElements(ZoneListWrapper<Statement>* processor,
}
// Propagate the collected information on this property assignments.
- if (top_scope_->is_function_scope()) {
+ if (!is_pre_parsing_ && top_scope_->is_function_scope()) {
bool only_simple_this_property_assignments =
this_property_assignment_finder.only_simple_this_property_assignments()
&& top_scope_->declarations()->length() == 0;
@@ -4123,8 +3907,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
int num_parameters = 0;
// Parse function body.
- { Scope::Type type = Scope::FUNCTION_SCOPE;
- Scope* scope = factory()->NewScope(top_scope_, type, inside_with());
+ { Scope* scope =
+ factory()->NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
LexicalScope lexical_scope(this, scope);
TemporaryScope temp_scope(this);
top_scope_->SetScopeName(name);
@@ -4155,7 +3939,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
// NOTE: We create a proxy and resolve it here so that in the
// future we can change the AST to only refer to VariableProxies
// instead of Variables and Proxis as is the case now.
- if (!function_name.is_null() && function_name->length() > 0) {
+ if (!is_pre_parsing_
+ && !function_name.is_null()
+ && function_name->length() > 0) {
Variable* fvar = top_scope_->DeclareFunctionVar(function_name);
VariableProxy* fproxy =
top_scope_->NewUnresolved(function_name, inside_with());
@@ -4189,22 +3975,18 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
}
Counters::total_preparse_skipped.Increment(end_pos - function_block_pos);
scanner_.SeekForward(end_pos);
- pre_data()->Skip(entry.predata_function_skip(),
- entry.predata_symbol_skip());
materialized_literal_count = entry.literal_count();
expected_property_count = entry.property_count();
only_simple_this_property_assignments = false;
this_property_assignments = Factory::empty_fixed_array();
Expect(Token::RBRACE, CHECK_OK);
} else {
- if (pre_data() != NULL) {
- // Skip pre-data entry for non-lazily compiled function.
- pre_data()->SkipFunctionEntry(function_block_pos);
+ FunctionEntry entry;
+ if (is_lazily_compiled) entry = log()->LogFunction(function_block_pos);
+ {
+ ConditionalLogPauseScope pause_if(is_lazily_compiled, log());
+ ParseSourceElements(&body, Token::RBRACE, CHECK_OK);
}
- FunctionEntry entry = log()->LogFunction(function_block_pos);
- int predata_function_position_before = log()->function_position();
- int predata_symbol_position_before = log()->symbol_position();
- ParseSourceElements(&body, Token::RBRACE, CHECK_OK);
materialized_literal_count = temp_scope.materialized_literal_count();
expected_property_count = temp_scope.expected_property_count();
only_simple_this_property_assignments =
@@ -4214,13 +3996,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
Expect(Token::RBRACE, CHECK_OK);
end_pos = scanner_.location().end_pos;
if (entry.is_valid()) {
+ ASSERT(is_lazily_compiled);
+ ASSERT(is_pre_parsing_);
entry.set_end_pos(end_pos);
entry.set_literal_count(materialized_literal_count);
entry.set_property_count(expected_property_count);
- entry.set_predata_function_skip(
- log()->function_position() - predata_function_position_before);
- entry.set_predata_symbol_skip(
- log()->symbol_position() - predata_symbol_position_before);
}
}
@@ -5440,12 +5220,6 @@ RegExpTree* RegExpParser::ParseCharacterClass() {
// ----------------------------------------------------------------------------
// The Parser interface.
-// MakeAST() is just a wrapper for the corresponding Parser calls
-// so we don't have to expose the entire Parser class in the .h file.
-
-static bool always_allow_natives_syntax = false;
-
-
ParserMessage::~ParserMessage() {
for (int i = 0; i < args().length(); i++)
DeleteArray(args()[i]);
@@ -5475,14 +5249,12 @@ bool ScriptDataImpl::HasError() {
// Preparse, but only collect data that is immediately useful,
// even if the preparser data is only used once.
-ScriptDataImpl* PartialPreParse(Handle<String> source,
- unibrow::CharacterStream* stream,
- v8::Extension* extension) {
+ScriptDataImpl* Parser::PartialPreParse(Handle<String> source,
+ unibrow::CharacterStream* stream,
+ v8::Extension* extension) {
Handle<Script> no_script;
bool allow_natives_syntax =
- always_allow_natives_syntax ||
- FLAG_allow_natives_syntax ||
- Bootstrapper::IsActive();
+ FLAG_allow_natives_syntax || Bootstrapper::IsActive();
PartialPreParser parser(no_script, allow_natives_syntax, extension);
if (!parser.PreParseProgram(source, stream)) return NULL;
// Extract the accumulated data from the recorder as a single
@@ -5535,14 +5307,12 @@ int ScriptDataImpl::ReadNumber(byte** source) {
}
-ScriptDataImpl* PreParse(Handle<String> source,
- unibrow::CharacterStream* stream,
- v8::Extension* extension) {
+ScriptDataImpl* Parser::PreParse(Handle<String> source,
+ unibrow::CharacterStream* stream,
+ v8::Extension* extension) {
Handle<Script> no_script;
bool allow_natives_syntax =
- always_allow_natives_syntax ||
- FLAG_allow_natives_syntax ||
- Bootstrapper::IsActive();
+ FLAG_allow_natives_syntax || Bootstrapper::IsActive();
CompletePreParser parser(no_script, allow_natives_syntax, extension);
if (!parser.PreParseProgram(source, stream)) return NULL;
// Extract the accumulated data from the recorder as a single
@@ -5552,9 +5322,9 @@ ScriptDataImpl* PreParse(Handle<String> source,
}
-bool ParseRegExp(FlatStringReader* input,
- bool multiline,
- RegExpCompileData* result) {
+bool Parser::ParseRegExp(FlatStringReader* input,
+ bool multiline,
+ RegExpCompileData* result) {
ASSERT(result != NULL);
RegExpParser parser(input, &result->error, multiline);
RegExpTree* tree = parser.ParsePattern();
@@ -5574,59 +5344,44 @@ bool ParseRegExp(FlatStringReader* input,
}
-FunctionLiteral* MakeAST(bool compile_in_global_context,
- Handle<Script> script,
- v8::Extension* extension,
- ScriptDataImpl* pre_data,
- bool is_json) {
- bool allow_natives_syntax =
- always_allow_natives_syntax ||
- FLAG_allow_natives_syntax ||
- Bootstrapper::IsActive();
- AstBuildingParser parser(script, allow_natives_syntax, extension, pre_data);
- if (pre_data != NULL && pre_data->has_error()) {
- Scanner::Location loc = pre_data->MessageLocation();
- const char* message = pre_data->BuildMessage();
- Vector<const char*> args = pre_data->BuildArgs();
- parser.ReportMessageAt(loc, message, args);
- DeleteArray(message);
- for (int i = 0; i < args.length(); i++) {
- DeleteArray(args[i]);
- }
- DeleteArray(args.start());
- return NULL;
- }
- Handle<String> source = Handle<String>(String::cast(script->source()));
- FunctionLiteral* result;
- if (is_json) {
- ASSERT(compile_in_global_context);
- result = parser.ParseJson(source);
+bool Parser::Parse(CompilationInfo* info) {
+ ASSERT(info->function() == NULL);
+ FunctionLiteral* result = NULL;
+ Handle<Script> script = info->script();
+ if (info->is_lazy()) {
+ AstBuildingParser parser(script, true, NULL, NULL);
+ result = parser.ParseLazy(info->shared_info());
} else {
- result = parser.ParseProgram(source, compile_in_global_context);
+ bool allow_natives_syntax =
+ FLAG_allow_natives_syntax || Bootstrapper::IsActive();
+ ScriptDataImpl* pre_data = info->pre_parse_data();
+ AstBuildingParser parser(script, allow_natives_syntax, info->extension(),
+ pre_data);
+ if (pre_data != NULL && pre_data->has_error()) {
+ Scanner::Location loc = pre_data->MessageLocation();
+ const char* message = pre_data->BuildMessage();
+ Vector<const char*> args = pre_data->BuildArgs();
+ parser.ReportMessageAt(loc, message, args);
+ DeleteArray(message);
+ for (int i = 0; i < args.length(); i++) {
+ DeleteArray(args[i]);
+ }
+ DeleteArray(args.start());
+ ASSERT(Top::has_pending_exception());
+ } else {
+ Handle<String> source = Handle<String>(String::cast(script->source()));
+ // JSON is always global.
+ ASSERT(!info->is_json() || info->is_global());
+ result = info->is_json()
+ ? parser.ParseJson(source)
+ : parser.ParseProgram(source, info->is_global());
+ }
}
- return result;
-}
-
-FunctionLiteral* MakeLazyAST(Handle<Script> script,
- Handle<String> name,
- int start_position,
- int end_position,
- bool is_expression) {
- bool allow_natives_syntax_before = always_allow_natives_syntax;
- always_allow_natives_syntax = true;
- AstBuildingParser parser(script, true, NULL, NULL); // always allow
- always_allow_natives_syntax = allow_natives_syntax_before;
- // Parse the function by pointing to the function source in the script source.
- Handle<String> script_source(String::cast(script->source()));
- FunctionLiteral* result =
- parser.ParseLazy(script_source, name,
- start_position, end_position, is_expression);
- return result;
+ info->SetFunction(result);
+ return (result != NULL);
}
-
#undef NEW
-
} } // namespace v8::internal
diff --git a/src/parser.h b/src/parser.h
index 8c008572..7142551c 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// 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:
@@ -28,12 +28,23 @@
#ifndef V8_PARSER_H_
#define V8_PARSER_H_
-#include "scanner.h"
#include "allocation.h"
+#include "ast.h"
+#include "scanner.h"
namespace v8 {
namespace internal {
+class CompilationInfo;
+class FuncNameInferrer;
+class ParserFactory;
+class ParserLog;
+class PositionStack;
+class Target;
+class TemporaryScope;
+
+template <typename T> class ZoneListWrapper;
+
class ParserMessage : public Malloced {
public:
@@ -72,19 +83,9 @@ class FunctionEntry BASE_EMBEDDED {
backing_[kPropertyCountOffset] = value;
}
- int predata_function_skip() { return backing_[kPredataFunctionSkipOffset]; }
- void set_predata_function_skip(int value) {
- backing_[kPredataFunctionSkipOffset] = value;
- }
-
- int predata_symbol_skip() { return backing_[kPredataSymbolSkipOffset]; }
- void set_predata_symbol_skip(int value) {
- backing_[kPredataSymbolSkipOffset] = value;
- }
-
bool is_valid() { return backing_.length() > 0; }
- static const int kSize = 6;
+ static const int kSize = 4;
private:
Vector<unsigned> backing_;
@@ -92,8 +93,6 @@ class FunctionEntry BASE_EMBEDDED {
static const int kEndPosOffset = 1;
static const int kLiteralCountOffset = 2;
static const int kPropertyCountOffset = 3;
- static const int kPredataFunctionSkipOffset = 4;
- static const int kPredataSymbolSkipOffset = 5;
};
@@ -117,7 +116,6 @@ class ScriptDataImpl : public ScriptData {
FunctionEntry GetFunctionEntry(int start);
int GetSymbolIdentifier();
- void SkipFunctionEntry(int start);
bool SanityCheck();
Scanner::Location MessageLocation();
@@ -133,28 +131,8 @@ class ScriptDataImpl : public ScriptData {
unsigned magic() { return store_[kMagicOffset]; }
unsigned version() { return store_[kVersionOffset]; }
- // Skip forward in the preparser data by the given number
- // of unsigned ints of function entries and the given number of bytes of
- // symbol id encoding.
- void Skip(int function_entries, int symbol_entries) {
- ASSERT(function_entries >= 0);
- ASSERT(function_entries
- <= (static_cast<int>(store_[kFunctionsSizeOffset])
- - (function_index_ - kHeaderSize)));
- ASSERT(symbol_entries >= 0);
- ASSERT(symbol_entries <= symbol_data_end_ - symbol_data_);
-
- unsigned max_function_skip = store_[kFunctionsSizeOffset] -
- static_cast<unsigned>(function_index_ - kHeaderSize);
- function_index_ +=
- Min(static_cast<unsigned>(function_entries), max_function_skip);
- symbol_data_ +=
- Min(static_cast<unsigned>(symbol_entries),
- static_cast<unsigned>(symbol_data_end_ - symbol_data_));
- }
-
static const unsigned kMagicNumber = 0xBadDead;
- static const unsigned kCurrentVersion = 3;
+ static const unsigned kCurrentVersion = 4;
static const int kMagicOffset = 0;
static const int kVersionOffset = 1;
@@ -186,9 +164,10 @@ class ScriptDataImpl : public ScriptData {
ScriptDataImpl(const char* backing_store, int length)
: store_(reinterpret_cast<unsigned*>(const_cast<char*>(backing_store)),
- length / sizeof(unsigned)),
+ length / static_cast<int>(sizeof(unsigned))),
owns_store_(false) {
- ASSERT_EQ(0, reinterpret_cast<intptr_t>(backing_store) % sizeof(unsigned));
+ ASSERT_EQ(0, static_cast<int>(
+ reinterpret_cast<intptr_t>(backing_store) % sizeof(unsigned)));
}
// Read strings written by ParserRecorder::WriteString.
@@ -198,46 +177,268 @@ class ScriptDataImpl : public ScriptData {
};
-// The parser: Takes a script and and context information, and builds a
-// FunctionLiteral AST node. Returns NULL and deallocates any allocated
-// AST nodes if parsing failed.
-FunctionLiteral* MakeAST(bool compile_in_global_context,
- Handle<Script> script,
- v8::Extension* extension,
- ScriptDataImpl* pre_data,
- bool is_json = false);
-
-// Generic preparser generating full preparse data.
-ScriptDataImpl* PreParse(Handle<String> source,
- unibrow::CharacterStream* stream,
- v8::Extension* extension);
-
-// Preparser that only does preprocessing that makes sense if only used
-// immediately after.
-ScriptDataImpl* PartialPreParse(Handle<String> source,
- unibrow::CharacterStream* stream,
- v8::Extension* extension);
-
-
-bool ParseRegExp(FlatStringReader* input,
- bool multiline,
- RegExpCompileData* result);
+class Parser {
+ public:
+ Parser(Handle<Script> script, bool allow_natives_syntax,
+ v8::Extension* extension, ParserMode is_pre_parsing,
+ ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data);
+ virtual ~Parser() { }
+
+ // Parses the source code represented by the compilation info and sets its
+ // function literal. Returns false (and deallocates any allocated AST
+ // nodes) if parsing failed.
+ static bool Parse(CompilationInfo* info);
+
+ // Generic preparser generating full preparse data.
+ static ScriptDataImpl* PreParse(Handle<String> source,
+ unibrow::CharacterStream* stream,
+ v8::Extension* extension);
+
+ // Preparser that only does preprocessing that makes sense if only used
+ // immediately after.
+ static ScriptDataImpl* PartialPreParse(Handle<String> source,
+ unibrow::CharacterStream* stream,
+ v8::Extension* extension);
+
+ static bool ParseRegExp(FlatStringReader* input,
+ bool multiline,
+ RegExpCompileData* result);
+
+ // Pre-parse the program from the character stream; returns true on
+ // success, false if a stack-overflow happened during parsing.
+ bool PreParseProgram(Handle<String> source, unibrow::CharacterStream* stream);
+
+ void ReportMessage(const char* message, Vector<const char*> args);
+ virtual void ReportMessageAt(Scanner::Location loc,
+ const char* message,
+ Vector<const char*> args) = 0;
+
+
+ // Returns NULL if parsing failed.
+ FunctionLiteral* ParseProgram(Handle<String> source,
+ bool in_global_context);
+ FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info);
+ FunctionLiteral* ParseJson(Handle<String> source);
+
+ // The minimum number of contiguous assignment that will
+ // be treated as an initialization block. Benchmarks show that
+ // the overhead exceeds the savings below this limit.
+ static const int kMinInitializationBlock = 3;
+
+ protected:
+
+ enum Mode {
+ PARSE_LAZILY,
+ PARSE_EAGERLY
+ };
+ // Report syntax error
+ void ReportUnexpectedToken(Token::Value token);
+ void ReportInvalidPreparseData(Handle<String> name, bool* ok);
+
+ Handle<Script> script_;
+ Scanner scanner_;
+
+ Scope* top_scope_;
+ int with_nesting_level_;
+
+ TemporaryScope* temp_scope_;
+ Mode mode_;
+
+ Target* target_stack_; // for break, continue statements
+ bool allow_natives_syntax_;
+ v8::Extension* extension_;
+ ParserFactory* factory_;
+ ParserLog* log_;
+ bool is_pre_parsing_;
+ ScriptDataImpl* pre_data_;
+ FuncNameInferrer* fni_;
+
+ bool inside_with() const { return with_nesting_level_ > 0; }
+ ParserFactory* factory() const { return factory_; }
+ ParserLog* log() const { return log_; }
+ Scanner& scanner() { return scanner_; }
+ Mode mode() const { return mode_; }
+ ScriptDataImpl* pre_data() const { return pre_data_; }
+
+ // All ParseXXX functions take as the last argument an *ok parameter
+ // which is set to false if parsing failed; it is unchanged otherwise.
+ // By making the 'exception handling' explicit, we are forced to check
+ // for failure at the call sites.
+ void* ParseSourceElements(ZoneListWrapper<Statement>* processor,
+ int end_token, bool* ok);
+ Statement* ParseStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseFunctionDeclaration(bool* ok);
+ Statement* ParseNativeDeclaration(bool* ok);
+ Block* ParseBlock(ZoneStringList* labels, bool* ok);
+ Block* ParseVariableStatement(bool* ok);
+ Block* ParseVariableDeclarations(bool accept_IN, Expression** var, bool* ok);
+ Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels,
+ bool* ok);
+ IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseContinueStatement(bool* ok);
+ Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseReturnStatement(bool* ok);
+ Block* WithHelper(Expression* obj,
+ ZoneStringList* labels,
+ bool is_catch_block,
+ bool* ok);
+ Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
+ CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
+ SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
+ DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok);
+ WhileStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseForStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseThrowStatement(bool* ok);
+ Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
+ TryStatement* ParseTryStatement(bool* ok);
+ DebuggerStatement* ParseDebuggerStatement(bool* ok);
+
+ Expression* ParseExpression(bool accept_IN, bool* ok);
+ Expression* ParseAssignmentExpression(bool accept_IN, bool* ok);
+ Expression* ParseConditionalExpression(bool accept_IN, bool* ok);
+ Expression* ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
+ Expression* ParseUnaryExpression(bool* ok);
+ Expression* ParsePostfixExpression(bool* ok);
+ Expression* ParseLeftHandSideExpression(bool* ok);
+ Expression* ParseNewExpression(bool* ok);
+ Expression* ParseMemberExpression(bool* ok);
+ Expression* ParseNewPrefix(PositionStack* stack, bool* ok);
+ Expression* ParseMemberWithNewPrefixesExpression(PositionStack* stack,
+ bool* ok);
+ Expression* ParsePrimaryExpression(bool* ok);
+ Expression* ParseArrayLiteral(bool* ok);
+ Expression* ParseObjectLiteral(bool* ok);
+ ObjectLiteral::Property* ParseObjectLiteralGetSet(bool is_getter, bool* ok);
+ Expression* ParseRegExpLiteral(bool seen_equal, bool* ok);
+
+ Expression* NewCompareNode(Token::Value op,
+ Expression* x,
+ Expression* y,
+ int position);
+
+ // Populate the constant properties fixed array for a materialized object
+ // literal.
+ void BuildObjectLiteralConstantProperties(
+ 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.
+ void BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* properties,
+ Handle<FixedArray> constants,
+ bool* is_simple,
+ int* depth);
+
+ // Decide if a property should be in the object boilerplate.
+ bool IsBoilerplateProperty(ObjectLiteral::Property* property);
+ // If the expression is a literal, return the literal value;
+ // if the expression is a materialized literal and is simple return a
+ // compile time value as encoded by CompileTimeValue::GetValue().
+ // Otherwise, return undefined literal as the placeholder
+ // in the object literal boilerplate.
+ Handle<Object> GetBoilerplateValue(Expression* expression);
+
+ enum FunctionLiteralType {
+ EXPRESSION,
+ DECLARATION,
+ NESTED
+ };
-// Support for doing lazy compilation. The script is the script containing full
-// source of the script where the function is declared. The start_position and
-// end_position specifies the part of the script source which has the source
-// for the function declaration in the form:
-//
-// (<formal parameters>) { <function body> }
-//
-// without any function keyword or name.
-//
-FunctionLiteral* MakeLazyAST(Handle<Script> script,
- Handle<String> name,
- int start_position,
- int end_position,
- bool is_expression);
+ ZoneList<Expression*>* ParseArguments(bool* ok);
+ FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name,
+ int function_token_position,
+ FunctionLiteralType type,
+ bool* ok);
+
+
+ // Magical syntax support.
+ Expression* ParseV8Intrinsic(bool* ok);
+
+ INLINE(Token::Value peek()) { return scanner_.peek(); }
+ INLINE(Token::Value Next()) { return scanner_.Next(); }
+ INLINE(void Consume(Token::Value token));
+ void Expect(Token::Value token, bool* ok);
+ bool Check(Token::Value token);
+ void ExpectSemicolon(bool* ok);
+
+ Handle<String> GetSymbol(bool* ok);
+
+ // Get odd-ball literals.
+ Literal* GetLiteralUndefined();
+ Literal* GetLiteralTheHole();
+ Literal* GetLiteralNumber(double value);
+
+ Handle<String> ParseIdentifier(bool* ok);
+ Handle<String> ParseIdentifierName(bool* ok);
+ Handle<String> ParseIdentifierOrGetOrSet(bool* is_get,
+ bool* is_set,
+ bool* ok);
+
+ // Parser support
+ virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
+ FunctionLiteral* fun,
+ bool resolve,
+ bool* ok) = 0;
+
+ bool TargetStackContainsLabel(Handle<String> label);
+ BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
+ IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok);
+
+ void RegisterTargetUse(BreakTarget* target, Target* stop);
+
+ // Create a number literal.
+ Literal* NewNumberLiteral(double value);
+
+ // Generate AST node that throw a ReferenceError with the given type.
+ Expression* NewThrowReferenceError(Handle<String> type);
+
+ // Generate AST node that throw a SyntaxError with the given
+ // type. The first argument may be null (in the handle sense) in
+ // which case no arguments are passed to the constructor.
+ Expression* NewThrowSyntaxError(Handle<String> type, Handle<Object> first);
+
+ // Generate AST node that throw a TypeError with the given
+ // type. Both arguments must be non-null (in the handle sense).
+ Expression* NewThrowTypeError(Handle<String> type,
+ Handle<Object> first,
+ Handle<Object> second);
+
+ // Generic AST generator for throwing errors from compiled code.
+ Expression* NewThrowError(Handle<String> constructor,
+ Handle<String> type,
+ Vector< Handle<Object> > arguments);
+
+ // JSON is a subset of JavaScript, as specified in, e.g., the ECMAScript 5
+ // specification section 15.12.1 (and appendix A.8).
+ // The grammar is given section 15.12.1.2 (and appendix A.8.2).
+
+ // Parse JSON input as a single JSON value.
+ Expression* ParseJson(bool* ok);
+
+ // Parse a single JSON value from input (grammar production JSONValue).
+ // A JSON value is either a (double-quoted) string literal, a number literal,
+ // one of "true", "false", or "null", or an object or array literal.
+ Expression* ParseJsonValue(bool* ok);
+ // Parse a JSON object literal (grammar production JSONObject).
+ // An object literal is a squiggly-braced and comma separated sequence
+ // (possibly empty) of key/value pairs, where the key is a JSON string
+ // literal, the value is a JSON value, and the two are spearated by a colon.
+ // A JavaScript object also allows numbers and identifiers as keys.
+ Expression* ParseJsonObject(bool* ok);
+ // Parses a JSON array literal (grammar production JSONArray). An array
+ // literal is a square-bracketed and comma separated sequence (possibly empty)
+ // of JSON values.
+ // A JavaScript array allows leaving out values from the sequence.
+ Expression* ParseJsonArray(bool* ok);
+
+ friend class Target;
+ friend class TargetScope;
+ friend class LexicalScope;
+ friend class TemporaryScope;
+};
// Support for handling complex values (array and object literals) that
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index ae44944f..1003de15 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -291,6 +291,10 @@ void OS::LogSharedLibraryAddresses() {
}
+void OS::SignalCodeMovingGC() {
+}
+
+
int OS::StackWalk(Vector<OS::StackFrame> frames) {
int frames_size = frames.length();
ScopedVector<void*> addresses(frames_size);
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index f7d8609b..c01c0d24 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -397,6 +397,30 @@ void OS::LogSharedLibraryAddresses() {
}
+static const char kGCFakeMmap[] = "/tmp/__v8_gc__";
+
+
+void OS::SignalCodeMovingGC() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+ // Support for ll_prof.py.
+ //
+ // The Linux profiler built into the kernel logs all mmap's with
+ // PROT_EXEC so that analysis tools can properly attribute ticks. We
+ // do a mmap with a name known by ll_prof.py and immediately munmap
+ // it. This injects a GC marker into the stream of events generated
+ // by the kernel and allows us to synchronize V8 code log and the
+ // kernel log.
+ int size = sysconf(_SC_PAGESIZE);
+ FILE* f = fopen(kGCFakeMmap, "w+");
+ void* addr = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_PRIVATE,
+ fileno(f), 0);
+ ASSERT(addr != MAP_FAILED);
+ munmap(addr, size);
+ fclose(f);
+#endif
+}
+
+
int OS::StackWalk(Vector<OS::StackFrame> frames) {
// backtrace is a glibc extension.
#ifdef __GLIBC__
@@ -748,6 +772,7 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
USE(info);
if (signal != SIGPROF) return;
if (active_sampler_ == NULL) return;
+ if (!IsVmThread()) return;
TickSample sample_obj;
TickSample* sample = CpuProfiler::TickSampleEvent();
@@ -755,6 +780,7 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
// We always sample the VM state.
sample->state = VMState::current_state();
+
// If profiling, we extract the current pc and sp.
if (active_sampler_->IsProfiling()) {
// Extracting the sample from the context is extremely machine dependent.
@@ -783,9 +809,7 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
// Implement this on MIPS.
UNIMPLEMENTED();
#endif
- if (IsVmThread()) {
- active_sampler_->SampleStack(sample);
- }
+ active_sampler_->SampleStack(sample);
}
active_sampler_->Tick(sample);
@@ -806,7 +830,10 @@ class Sampler::PlatformData : public Malloced {
Sampler::Sampler(int interval, bool profiling)
- : interval_(interval), profiling_(profiling), active_(false) {
+ : interval_(interval),
+ profiling_(profiling),
+ synchronous_(profiling),
+ active_(false) {
data_ = new PlatformData();
}
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index 47193de7..3e4daf3b 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -245,6 +245,10 @@ void OS::LogSharedLibraryAddresses() {
}
+void OS::SignalCodeMovingGC() {
+}
+
+
uint64_t OS::CpuFeaturesImpliedByPlatform() {
// MacOSX requires all these to install so we can assume they are present.
// These constants are defined by the CPUid instructions.
@@ -549,17 +553,24 @@ class Sampler::PlatformData : public Malloced {
// Sampler thread handler.
void Runner() {
- // Loop until the sampler is disengaged, keeping the specified samling freq.
+ // Loop until the sampler is disengaged, keeping the specified
+ // sampling frequency.
for ( ; sampler_->IsActive(); OS::Sleep(sampler_->interval_)) {
TickSample sample_obj;
TickSample* sample = CpuProfiler::TickSampleEvent();
if (sample == NULL) sample = &sample_obj;
+ // If the sampler runs in sync with the JS thread, we try to
+ // suspend it. If we fail, we skip the current sample.
+ if (sampler_->IsSynchronous()) {
+ if (KERN_SUCCESS != thread_suspend(profiled_thread_)) continue;
+ }
+
// We always sample the VM state.
sample->state = VMState::current_state();
+
// If profiling, we record the pc and sp of the profiled thread.
- if (sampler_->IsProfiling()
- && KERN_SUCCESS == thread_suspend(profiled_thread_)) {
+ if (sampler_->IsProfiling()) {
#if V8_HOST_ARCH_X64
thread_state_flavor_t flavor = x86_THREAD_STATE64;
x86_thread_state64_t state;
@@ -591,11 +602,14 @@ class Sampler::PlatformData : public Malloced {
sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
sampler_->SampleStack(sample);
}
- thread_resume(profiled_thread_);
}
// Invoke tick handler with program counter and stack pointer.
sampler_->Tick(sample);
+
+ // If the sampler runs in sync with the JS thread, we have to
+ // remember to resume it.
+ if (sampler_->IsSynchronous()) thread_resume(profiled_thread_);
}
}
};
@@ -613,7 +627,10 @@ static void* SamplerEntry(void* arg) {
Sampler::Sampler(int interval, bool profiling)
- : interval_(interval), profiling_(profiling), active_(false) {
+ : interval_(interval),
+ profiling_(profiling),
+ synchronous_(profiling),
+ active_(false) {
data_ = new PlatformData(this);
}
@@ -624,9 +641,9 @@ Sampler::~Sampler() {
void Sampler::Start() {
- // If we are profiling, we need to be able to access the calling
- // thread.
- if (IsProfiling()) {
+ // If we are starting a synchronous sampler, we need to be able to
+ // access the calling thread.
+ if (IsSynchronous()) {
data_->profiled_thread_ = mach_thread_self();
}
@@ -655,7 +672,7 @@ void Sampler::Stop() {
pthread_join(data_->sampler_thread_, NULL);
// Deallocate Mach port for thread.
- if (IsProfiling()) {
+ if (IsSynchronous()) {
mach_port_deallocate(data_->task_self_, data_->profiled_thread_);
}
}
diff --git a/src/platform-nullos.cc b/src/platform-nullos.cc
index b8392e88..b5caa5e1 100644
--- a/src/platform-nullos.cc
+++ b/src/platform-nullos.cc
@@ -240,6 +240,11 @@ void OS::LogSharedLibraryAddresses() {
}
+void OS::SignalCodeMovingGC() {
+ UNIMPLEMENTED();
+}
+
+
int OS::StackWalk(Vector<OS::StackFrame> frames) {
UNIMPLEMENTED();
return 0;
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index 05ed9eee..e03059ad 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -289,6 +289,10 @@ void OS::LogSharedLibraryAddresses() {
}
+void OS::SignalCodeMovingGC() {
+}
+
+
int OS::StackWalk(Vector<OS::StackFrame> frames) {
UNIMPLEMENTED();
return 1;
diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc
index 6d97ed7e..fcd69deb 100644
--- a/src/platform-solaris.cc
+++ b/src/platform-solaris.cc
@@ -256,6 +256,10 @@ void OS::LogSharedLibraryAddresses() {
}
+void OS::SignalCodeMovingGC() {
+}
+
+
struct StackWalker {
Vector<OS::StackFrame>& frames;
int index;
@@ -598,7 +602,10 @@ class Sampler::PlatformData : public Malloced {
Sampler::Sampler(int interval, bool profiling)
- : interval_(interval), profiling_(profiling), active_(false) {
+ : interval_(interval),
+ profiling_(profiling),
+ synchronous_(profiling),
+ active_(false) {
data_ = new PlatformData();
}
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 86314a80..caea16cb 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -845,14 +845,15 @@ void* OS::Allocate(const size_t requested,
bool is_executable) {
// The address range used to randomize RWX allocations in OS::Allocate
// Try not to map pages into the default range that windows loads DLLs
+ // Use a multiple of 64k to prevent committing unused memory.
// Note: This does not guarantee RWX regions will be within the
// range kAllocationRandomAddressMin to kAllocationRandomAddressMax
#ifdef V8_HOST_ARCH_64_BIT
static const intptr_t kAllocationRandomAddressMin = 0x0000000080000000;
- static const intptr_t kAllocationRandomAddressMax = 0x000004FFFFFFFFFF;
+ static const intptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000;
#else
static const intptr_t kAllocationRandomAddressMin = 0x04000000;
- static const intptr_t kAllocationRandomAddressMax = 0x4FFFFFFF;
+ static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000;
#endif
// VirtualAlloc rounds allocated size to page size automatically.
@@ -1217,6 +1218,10 @@ void OS::LogSharedLibraryAddresses() {
}
+void OS::SignalCodeMovingGC() {
+}
+
+
// Walk the stack using the facilities in dbghelp.dll and tlhelp32.dll
// Switch off warning 4748 (/GS can not protect parameters and local variables
@@ -1838,17 +1843,25 @@ class Sampler::PlatformData : public Malloced {
// Context used for sampling the register state of the profiled thread.
CONTEXT context;
memset(&context, 0, sizeof(context));
- // Loop until the sampler is disengaged, keeping the specified samling freq.
+ // Loop until the sampler is disengaged, keeping the specified
+ // sampling frequency.
for ( ; sampler_->IsActive(); Sleep(sampler_->interval_)) {
TickSample sample_obj;
TickSample* sample = CpuProfiler::TickSampleEvent();
if (sample == NULL) sample = &sample_obj;
+ // If the sampler runs in sync with the JS thread, we try to
+ // suspend it. If we fail, we skip the current sample.
+ if (sampler_->IsSynchronous()) {
+ static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
+ if (SuspendThread(profiled_thread_) == kSuspendFailed) continue;
+ }
+
// We always sample the VM state.
sample->state = VMState::current_state();
+
// If profiling, we record the pc and sp of the profiled thread.
- if (sampler_->IsProfiling()
- && SuspendThread(profiled_thread_) != (DWORD)-1) {
+ if (sampler_->IsProfiling()) {
context.ContextFlags = CONTEXT_FULL;
if (GetThreadContext(profiled_thread_, &context) != 0) {
#if V8_HOST_ARCH_X64
@@ -1862,11 +1875,14 @@ class Sampler::PlatformData : public Malloced {
#endif
sampler_->SampleStack(sample);
}
- ResumeThread(profiled_thread_);
}
// Invoke tick handler with program counter and stack pointer.
sampler_->Tick(sample);
+
+ // If the sampler runs in sync with the JS thread, we have to
+ // remember to resume it.
+ if (sampler_->IsSynchronous()) ResumeThread(profiled_thread_);
}
}
};
@@ -1883,7 +1899,10 @@ static unsigned int __stdcall SamplerEntry(void* arg) {
// Initialize a profile sampler.
Sampler::Sampler(int interval, bool profiling)
- : interval_(interval), profiling_(profiling), active_(false) {
+ : interval_(interval),
+ profiling_(profiling),
+ synchronous_(profiling),
+ active_(false) {
data_ = new PlatformData(this);
}
@@ -1895,9 +1914,9 @@ Sampler::~Sampler() {
// Start profiling.
void Sampler::Start() {
- // If we are profiling, we need to be able to access the calling
- // thread.
- if (IsProfiling()) {
+ // If we are starting a synchronous sampler, we need to be able to
+ // access the calling thread.
+ if (IsSynchronous()) {
// Get a handle to the calling thread. This is the thread that we are
// going to profile. We need to make a copy of the handle because we are
// going to use it in the sampler thread. Using GetThreadHandle() will
diff --git a/src/platform.h b/src/platform.h
index e9e7c223..42e6eae9 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -257,11 +257,16 @@ class OS {
static char* StrChr(char* str, int c);
static void StrNCpy(Vector<char> dest, const char* src, size_t n);
- // Support for profiler. Can do nothing, in which case ticks
- // occuring in shared libraries will not be properly accounted
- // for.
+ // Support for the profiler. Can do nothing, in which case ticks
+ // occuring in shared libraries will not be properly accounted for.
static void LogSharedLibraryAddresses();
+ // Support for the profiler. Notifies the external profiling
+ // process that a code moving garbage collection starts. Can do
+ // nothing, in which case the code objects must not move (e.g., by
+ // using --never-compact) if accurate profiling is desired.
+ static void SignalCodeMovingGC();
+
// The return value indicates the CPU features we are sure of because of the
// OS. For example MacOSX doesn't run on any x86 CPUs that don't have SSE2
// instructions.
@@ -563,17 +568,24 @@ class Sampler {
void Start();
void Stop();
- // Is the sampler used for profiling.
- inline bool IsProfiling() { return profiling_; }
+ // Is the sampler used for profiling?
+ bool IsProfiling() const { return profiling_; }
+
+ // Is the sampler running in sync with the JS thread? On platforms
+ // where the sampler is implemented with a thread that wakes up
+ // every now and then, having a synchronous sampler implies
+ // suspending/resuming the JS thread.
+ bool IsSynchronous() const { return synchronous_; }
// Whether the sampler is running (that is, consumes resources).
- inline bool IsActive() { return active_; }
+ bool IsActive() const { return active_; }
class PlatformData;
private:
const int interval_;
const bool profiling_;
+ const bool synchronous_;
bool active_;
PlatformData* data_; // Platform specific data.
DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
diff --git a/src/powers-ten.h b/src/powers-ten.h
deleted file mode 100644
index 93d92d91..00000000
--- a/src/powers-ten.h
+++ /dev/null
@@ -1,2461 +0,0 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// ------------ GENERATED FILE ----------------
-// command used:
-// tools/generate-ten-powers --from -308 --to 342 --mantissa-size 64 --round round -o src/powers-ten.h // NOLINT
-
-// This file is intended to be included inside another .h or .cc files
-// with the following defines set:
-// GRISU_CACHE_STRUCT: should expand to the name of a struct that will
-// hold the cached powers of ten. Each entry will hold a 64-bit
-// significand, a 16-bit signed binary exponent, and a 16-bit
-// signed decimal exponent. Each entry will be constructed as follows:
-// { significand, binary_exponent, decimal_exponent }.
-// GRISU_CACHE_NAME(i): generates the name for the different caches.
-// The parameter i will be a number in the range 1-20. A cache will
-// hold every i'th element of a full cache. GRISU_CACHE_NAME(1) will
-// thus hold all elements. The higher i the fewer elements it has.
-// Ideally the user should only reference one cache and let the
-// compiler remove the unused ones.
-// GRISU_CACHE_MAX_DISTANCE(i): generates the name for the maximum
-// binary exponent distance between all elements of a given cache.
-// GRISU_CACHE_OFFSET: is used as variable name for the decimal
-// exponent offset. It is equal to -cache[0].decimal_exponent.
-// GRISU_UINT64_C: used to construct 64-bit values in a platform
-// independent way. In order to encode 0x123456789ABCDEF0 the macro
-// will be invoked as follows: GRISU_UINT64_C(0x12345678,9ABCDEF0).
-
-
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(1)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0x8fd0c162, 06306bac), -1083, -307},
- {GRISU_UINT64_C(0xb3c4f1ba, 87bc8697), -1080, -306},
- {GRISU_UINT64_C(0xe0b62e29, 29aba83c), -1077, -305},
- {GRISU_UINT64_C(0x8c71dcd9, ba0b4926), -1073, -304},
- {GRISU_UINT64_C(0xaf8e5410, 288e1b6f), -1070, -303},
- {GRISU_UINT64_C(0xdb71e914, 32b1a24b), -1067, -302},
- {GRISU_UINT64_C(0x892731ac, 9faf056f), -1063, -301},
- {GRISU_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
- {GRISU_UINT64_C(0xd64d3d9d, b981787d), -1057, -299},
- {GRISU_UINT64_C(0x85f04682, 93f0eb4e), -1053, -298},
- {GRISU_UINT64_C(0xa76c5823, 38ed2622), -1050, -297},
- {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
- {GRISU_UINT64_C(0x82cca4db, 847945ca), -1043, -295},
- {GRISU_UINT64_C(0xa37fce12, 6597973d), -1040, -294},
- {GRISU_UINT64_C(0xcc5fc196, fefd7d0c), -1037, -293},
- {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
- {GRISU_UINT64_C(0x9faacf3d, f73609b1), -1030, -291},
- {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
- {GRISU_UINT64_C(0xf97ae3d0, d2446f25), -1024, -289},
- {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
- {GRISU_UINT64_C(0xc2e801fb, 244576d5), -1017, -287},
- {GRISU_UINT64_C(0xf3a20279, ed56d48a), -1014, -286},
- {GRISU_UINT64_C(0x9845418c, 345644d7), -1010, -285},
- {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
- {GRISU_UINT64_C(0xedec366b, 11c6cb8f), -1004, -283},
- {GRISU_UINT64_C(0x94b3a202, eb1c3f39), -1000, -282},
- {GRISU_UINT64_C(0xb9e08a83, a5e34f08), -997, -281},
- {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
- {GRISU_UINT64_C(0x91376c36, d99995be), -990, -279},
- {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
- {GRISU_UINT64_C(0xe2e69915, b3fff9f9), -984, -277},
- {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
- {GRISU_UINT64_C(0xb1442798, f49ffb4b), -977, -275},
- {GRISU_UINT64_C(0xdd95317f, 31c7fa1d), -974, -274},
- {GRISU_UINT64_C(0x8a7d3eef, 7f1cfc52), -970, -273},
- {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
- {GRISU_UINT64_C(0xd863b256, 369d4a41), -964, -271},
- {GRISU_UINT64_C(0x873e4f75, e2224e68), -960, -270},
- {GRISU_UINT64_C(0xa90de353, 5aaae202), -957, -269},
- {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
- {GRISU_UINT64_C(0x8412d999, 1ed58092), -950, -267},
- {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
- {GRISU_UINT64_C(0xce5d73ff, 402d98e4), -944, -265},
- {GRISU_UINT64_C(0x80fa687f, 881c7f8e), -940, -264},
- {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
- {GRISU_UINT64_C(0xc9874347, 44ac874f), -934, -262},
- {GRISU_UINT64_C(0xfbe91419, 15d7a922), -931, -261},
- {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
- {GRISU_UINT64_C(0xc4ce17b3, 99107c23), -924, -259},
- {GRISU_UINT64_C(0xf6019da0, 7f549b2b), -921, -258},
- {GRISU_UINT64_C(0x99c10284, 4f94e0fb), -917, -257},
- {GRISU_UINT64_C(0xc0314325, 637a193a), -914, -256},
- {GRISU_UINT64_C(0xf03d93ee, bc589f88), -911, -255},
- {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
- {GRISU_UINT64_C(0xbbb01b92, 83253ca3), -904, -253},
- {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
- {GRISU_UINT64_C(0x92a1958a, 7675175f), -897, -251},
- {GRISU_UINT64_C(0xb749faed, 14125d37), -894, -250},
- {GRISU_UINT64_C(0xe51c79a8, 5916f485), -891, -249},
- {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
- {GRISU_UINT64_C(0xb2fe3f0b, 8599ef08), -884, -247},
- {GRISU_UINT64_C(0xdfbdcece, 67006ac9), -881, -246},
- {GRISU_UINT64_C(0x8bd6a141, 006042be), -877, -245},
- {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
- {GRISU_UINT64_C(0xda7f5bf5, 90966849), -871, -243},
- {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
- {GRISU_UINT64_C(0xaab37fd7, d8f58179), -864, -241},
- {GRISU_UINT64_C(0xd5605fcd, cf32e1d7), -861, -240},
- {GRISU_UINT64_C(0x855c3be0, a17fcd26), -857, -239},
- {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
- {GRISU_UINT64_C(0xd0601d8e, fc57b08c), -851, -237},
- {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
- {GRISU_UINT64_C(0xa2cb1717, b52481ed), -844, -235},
- {GRISU_UINT64_C(0xcb7ddcdd, a26da269), -841, -234},
- {GRISU_UINT64_C(0xfe5d5415, 0b090b03), -838, -233},
- {GRISU_UINT64_C(0x9efa548d, 26e5a6e2), -834, -232},
- {GRISU_UINT64_C(0xc6b8e9b0, 709f109a), -831, -231},
- {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
- {GRISU_UINT64_C(0x9b407691, d7fc44f8), -824, -229},
- {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
- {GRISU_UINT64_C(0xf294b943, e17a2bc4), -818, -227},
- {GRISU_UINT64_C(0x979cf3ca, 6cec5b5b), -814, -226},
- {GRISU_UINT64_C(0xbd8430bd, 08277231), -811, -225},
- {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
- {GRISU_UINT64_C(0x940f4613, ae5ed137), -804, -223},
- {GRISU_UINT64_C(0xb9131798, 99f68584), -801, -222},
- {GRISU_UINT64_C(0xe757dd7e, c07426e5), -798, -221},
- {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
- {GRISU_UINT64_C(0xb4bca50b, 065abe63), -791, -219},
- {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
- {GRISU_UINT64_C(0x8d3360f0, 9cf6e4bd), -784, -217},
- {GRISU_UINT64_C(0xb080392c, c4349ded), -781, -216},
- {GRISU_UINT64_C(0xdca04777, f541c568), -778, -215},
- {GRISU_UINT64_C(0x89e42caa, f9491b61), -774, -214},
- {GRISU_UINT64_C(0xac5d37d5, b79b6239), -771, -213},
- {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
- {GRISU_UINT64_C(0x86a8d39e, f77164bd), -764, -211},
- {GRISU_UINT64_C(0xa8530886, b54dbdec), -761, -210},
- {GRISU_UINT64_C(0xd267caa8, 62a12d67), -758, -209},
- {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
- {GRISU_UINT64_C(0xa4611653, 8d0deb78), -751, -207},
- {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
- {GRISU_UINT64_C(0x806bd971, 4632dff6), -744, -205},
- {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
- {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
- {GRISU_UINT64_C(0xfad2a4b1, 3d1b5d6c), -735, -202},
- {GRISU_UINT64_C(0x9cc3a6ee, c6311a64), -731, -201},
- {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
- {GRISU_UINT64_C(0xf4f1b4d5, 15acb93c), -725, -199},
- {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
- {GRISU_UINT64_C(0xbf5cd546, 78eef0b7), -718, -197},
- {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
- {GRISU_UINT64_C(0x9580869f, 0e7aac0f), -711, -195},
- {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
- {GRISU_UINT64_C(0xe998d258, 869facd7), -705, -193},
- {GRISU_UINT64_C(0x91ff8377, 5423cc06), -701, -192},
- {GRISU_UINT64_C(0xb67f6455, 292cbf08), -698, -191},
- {GRISU_UINT64_C(0xe41f3d6a, 7377eeca), -695, -190},
- {GRISU_UINT64_C(0x8e938662, 882af53e), -691, -189},
- {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
- {GRISU_UINT64_C(0xdec681f9, f4c31f31), -685, -187},
- {GRISU_UINT64_C(0x8b3c113c, 38f9f37f), -681, -186},
- {GRISU_UINT64_C(0xae0b158b, 4738705f), -678, -185},
- {GRISU_UINT64_C(0xd98ddaee, 19068c76), -675, -184},
- {GRISU_UINT64_C(0x87f8a8d4, cfa417ca), -671, -183},
- {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
- {GRISU_UINT64_C(0xd47487cc, 8470652b), -665, -181},
- {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
- {GRISU_UINT64_C(0xa5fb0a17, c777cf0a), -658, -179},
- {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
- {GRISU_UINT64_C(0x81ac1fe2, 93d599c0), -651, -177},
- {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
- {GRISU_UINT64_C(0xca9cf1d2, 06fdc03c), -645, -175},
- {GRISU_UINT64_C(0xfd442e46, 88bd304b), -642, -174},
- {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
- {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
- {GRISU_UINT64_C(0xf7549530, e188c129), -632, -171},
- {GRISU_UINT64_C(0x9a94dd3e, 8cf578ba), -628, -170},
- {GRISU_UINT64_C(0xc13a148e, 3032d6e8), -625, -169},
- {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
- {GRISU_UINT64_C(0x96f5600f, 15a7b7e5), -618, -167},
- {GRISU_UINT64_C(0xbcb2b812, db11a5de), -615, -166},
- {GRISU_UINT64_C(0xebdf6617, 91d60f56), -612, -165},
- {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
- {GRISU_UINT64_C(0xb84687c2, 69ef3bfb), -605, -163},
- {GRISU_UINT64_C(0xe65829b3, 046b0afa), -602, -162},
- {GRISU_UINT64_C(0x8ff71a0f, e2c2e6dc), -598, -161},
- {GRISU_UINT64_C(0xb3f4e093, db73a093), -595, -160},
- {GRISU_UINT64_C(0xe0f218b8, d25088b8), -592, -159},
- {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
- {GRISU_UINT64_C(0xafbd2350, 644eead0), -585, -157},
- {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
- {GRISU_UINT64_C(0x894bc396, ce5da772), -578, -155},
- {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
- {GRISU_UINT64_C(0xd686619b, a27255a3), -572, -153},
- {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
- {GRISU_UINT64_C(0xa798fc41, 96e952e7), -565, -151},
- {GRISU_UINT64_C(0xd17f3b51, fca3a7a1), -562, -150},
- {GRISU_UINT64_C(0x82ef8513, 3de648c5), -558, -149},
- {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
- {GRISU_UINT64_C(0xcc963fee, 10b7d1b3), -552, -147},
- {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
- {GRISU_UINT64_C(0x9fd561f1, fd0f9bd4), -545, -145},
- {GRISU_UINT64_C(0xc7caba6e, 7c5382c9), -542, -144},
- {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
- {GRISU_UINT64_C(0x9c1661a6, 51213e2d), -535, -142},
- {GRISU_UINT64_C(0xc31bfa0f, e5698db8), -532, -141},
- {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
- {GRISU_UINT64_C(0x986ddb5c, 6b3a76b8), -525, -139},
- {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
- {GRISU_UINT64_C(0xee2ba6c0, 678b597f), -519, -137},
- {GRISU_UINT64_C(0x94db4838, 40b717f0), -515, -136},
- {GRISU_UINT64_C(0xba121a46, 50e4ddec), -512, -135},
- {GRISU_UINT64_C(0xe896a0d7, e51e1566), -509, -134},
- {GRISU_UINT64_C(0x915e2486, ef32cd60), -505, -133},
- {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
- {GRISU_UINT64_C(0xe3231912, d5bf60e6), -499, -131},
- {GRISU_UINT64_C(0x8df5efab, c5979c90), -495, -130},
- {GRISU_UINT64_C(0xb1736b96, b6fd83b4), -492, -129},
- {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
- {GRISU_UINT64_C(0x8aa22c0d, bef60ee4), -485, -127},
- {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
- {GRISU_UINT64_C(0xd89d64d5, 7a607745), -479, -125},
- {GRISU_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
- {GRISU_UINT64_C(0xa93af6c6, c79b5d2e), -472, -123},
- {GRISU_UINT64_C(0xd389b478, 79823479), -469, -122},
- {GRISU_UINT64_C(0x843610cb, 4bf160cc), -465, -121},
- {GRISU_UINT64_C(0xa54394fe, 1eedb8ff), -462, -120},
- {GRISU_UINT64_C(0xce947a3d, a6a9273e), -459, -119},
- {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
- {GRISU_UINT64_C(0xa163ff80, 2a3426a9), -452, -117},
- {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
- {GRISU_UINT64_C(0xfc2c3f38, 41f17c68), -446, -115},
- {GRISU_UINT64_C(0x9d9ba783, 2936edc1), -442, -114},
- {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
- {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
- {GRISU_UINT64_C(0x99ea0196, 163fa42e), -432, -111},
- {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
- {GRISU_UINT64_C(0xf07da27a, 82c37088), -426, -109},
- {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
- {GRISU_UINT64_C(0xbbe226ef, b628afeb), -419, -107},
- {GRISU_UINT64_C(0xeadab0ab, a3b2dbe5), -416, -106},
- {GRISU_UINT64_C(0x92c8ae6b, 464fc96f), -412, -105},
- {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
- {GRISU_UINT64_C(0xe5599087, 9ddcaabe), -406, -103},
- {GRISU_UINT64_C(0x8f57fa54, c2a9eab7), -402, -102},
- {GRISU_UINT64_C(0xb32df8e9, f3546564), -399, -101},
- {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
- {GRISU_UINT64_C(0x8bfbea76, c619ef36), -392, -99},
- {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
- {GRISU_UINT64_C(0xdab99e59, 958885c5), -386, -97},
- {GRISU_UINT64_C(0x88b402f7, fd75539b), -382, -96},
- {GRISU_UINT64_C(0xaae103b5, fcd2a882), -379, -95},
- {GRISU_UINT64_C(0xd59944a3, 7c0752a2), -376, -94},
- {GRISU_UINT64_C(0x857fcae6, 2d8493a5), -372, -93},
- {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
- {GRISU_UINT64_C(0xd097ad07, a71f26b2), -366, -91},
- {GRISU_UINT64_C(0x825ecc24, c8737830), -362, -90},
- {GRISU_UINT64_C(0xa2f67f2d, fa90563b), -359, -89},
- {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
- {GRISU_UINT64_C(0xfea126b7, d78186bd), -353, -87},
- {GRISU_UINT64_C(0x9f24b832, e6b0f436), -349, -86},
- {GRISU_UINT64_C(0xc6ede63f, a05d3144), -346, -85},
- {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
- {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
- {GRISU_UINT64_C(0xc24452da, 229b021c), -336, -82},
- {GRISU_UINT64_C(0xf2d56790, ab41c2a3), -333, -81},
- {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
- {GRISU_UINT64_C(0xbdb6b8e9, 05cb600f), -326, -79},
- {GRISU_UINT64_C(0xed246723, 473e3813), -323, -78},
- {GRISU_UINT64_C(0x9436c076, 0c86e30c), -319, -77},
- {GRISU_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
- {GRISU_UINT64_C(0xe7958cb8, 7392c2c3), -313, -75},
- {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
- {GRISU_UINT64_C(0xb4ecd5f0, 1a4aa828), -306, -73},
- {GRISU_UINT64_C(0xe2280b6c, 20dd5232), -303, -72},
- {GRISU_UINT64_C(0x8d590723, 948a535f), -299, -71},
- {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
- {GRISU_UINT64_C(0xdcdb1b27, 98182245), -293, -69},
- {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
- {GRISU_UINT64_C(0xac8b2d36, eed2dac6), -286, -67},
- {GRISU_UINT64_C(0xd7adf884, aa879177), -283, -66},
- {GRISU_UINT64_C(0x86ccbb52, ea94baeb), -279, -65},
- {GRISU_UINT64_C(0xa87fea27, a539e9a5), -276, -64},
- {GRISU_UINT64_C(0xd29fe4b1, 8e88640f), -273, -63},
- {GRISU_UINT64_C(0x83a3eeee, f9153e89), -269, -62},
- {GRISU_UINT64_C(0xa48ceaaa, b75a8e2b), -266, -61},
- {GRISU_UINT64_C(0xcdb02555, 653131b6), -263, -60},
- {GRISU_UINT64_C(0x808e1755, 5f3ebf12), -259, -59},
- {GRISU_UINT64_C(0xa0b19d2a, b70e6ed6), -256, -58},
- {GRISU_UINT64_C(0xc8de0475, 64d20a8c), -253, -57},
- {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
- {GRISU_UINT64_C(0x9ced737b, b6c4183d), -246, -55},
- {GRISU_UINT64_C(0xc428d05a, a4751e4d), -243, -54},
- {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
- {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
- {GRISU_UINT64_C(0xbf8fdb78, 849a5f97), -233, -51},
- {GRISU_UINT64_C(0xef73d256, a5c0f77d), -230, -50},
- {GRISU_UINT64_C(0x95a86376, 27989aae), -226, -49},
- {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
- {GRISU_UINT64_C(0xe9d71b68, 9dde71b0), -220, -47},
- {GRISU_UINT64_C(0x92267121, 62ab070e), -216, -46},
- {GRISU_UINT64_C(0xb6b00d69, bb55c8d1), -213, -45},
- {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
- {GRISU_UINT64_C(0x8eb98a7a, 9a5b04e3), -206, -43},
- {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
- {GRISU_UINT64_C(0xdf01e85f, 912e37a3), -200, -41},
- {GRISU_UINT64_C(0x8b61313b, babce2c6), -196, -40},
- {GRISU_UINT64_C(0xae397d8a, a96c1b78), -193, -39},
- {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
- {GRISU_UINT64_C(0x881cea14, 545c7575), -186, -37},
- {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
- {GRISU_UINT64_C(0xd4ad2dbf, c3d07788), -180, -35},
- {GRISU_UINT64_C(0x84ec3c97, da624ab5), -176, -34},
- {GRISU_UINT64_C(0xa6274bbd, d0fadd62), -173, -33},
- {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
- {GRISU_UINT64_C(0x81ceb32c, 4b43fcf5), -166, -31},
- {GRISU_UINT64_C(0xa2425ff7, 5e14fc32), -163, -30},
- {GRISU_UINT64_C(0xcad2f7f5, 359a3b3e), -160, -29},
- {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
- {GRISU_UINT64_C(0x9e74d1b7, 91e07e48), -153, -27},
- {GRISU_UINT64_C(0xc6120625, 76589ddb), -150, -26},
- {GRISU_UINT64_C(0xf79687ae, d3eec551), -147, -25},
- {GRISU_UINT64_C(0x9abe14cd, 44753b53), -143, -24},
- {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
- {GRISU_UINT64_C(0xf1c90080, baf72cb1), -137, -22},
- {GRISU_UINT64_C(0x971da050, 74da7bef), -133, -21},
- {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
- {GRISU_UINT64_C(0xec1e4a7d, b69561a5), -127, -19},
- {GRISU_UINT64_C(0x9392ee8e, 921d5d07), -123, -18},
- {GRISU_UINT64_C(0xb877aa32, 36a4b449), -120, -17},
- {GRISU_UINT64_C(0xe69594be, c44de15b), -117, -16},
- {GRISU_UINT64_C(0x901d7cf7, 3ab0acd9), -113, -15},
- {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
- {GRISU_UINT64_C(0xe12e1342, 4bb40e13), -107, -13},
- {GRISU_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
- {GRISU_UINT64_C(0xafebff0b, cb24aaff), -100, -11},
- {GRISU_UINT64_C(0xdbe6fece, bdedd5bf), -97, -10},
- {GRISU_UINT64_C(0x89705f41, 36b4a597), -93, -9},
- {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
- {GRISU_UINT64_C(0xd6bf94d5, e57a42bc), -87, -7},
- {GRISU_UINT64_C(0x8637bd05, af6c69b6), -83, -6},
- {GRISU_UINT64_C(0xa7c5ac47, 1b478423), -80, -5},
- {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
- {GRISU_UINT64_C(0x83126e97, 8d4fdf3b), -73, -3},
- {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
- {GRISU_UINT64_C(0xcccccccc, cccccccd), -67, -1},
- {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
- {GRISU_UINT64_C(0xa0000000, 00000000), -60, 1},
- {GRISU_UINT64_C(0xc8000000, 00000000), -57, 2},
- {GRISU_UINT64_C(0xfa000000, 00000000), -54, 3},
- {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
- {GRISU_UINT64_C(0xc3500000, 00000000), -47, 5},
- {GRISU_UINT64_C(0xf4240000, 00000000), -44, 6},
- {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
- {GRISU_UINT64_C(0xbebc2000, 00000000), -37, 8},
- {GRISU_UINT64_C(0xee6b2800, 00000000), -34, 9},
- {GRISU_UINT64_C(0x9502f900, 00000000), -30, 10},
- {GRISU_UINT64_C(0xba43b740, 00000000), -27, 11},
- {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
- {GRISU_UINT64_C(0x9184e72a, 00000000), -20, 13},
- {GRISU_UINT64_C(0xb5e620f4, 80000000), -17, 14},
- {GRISU_UINT64_C(0xe35fa931, a0000000), -14, 15},
- {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
- {GRISU_UINT64_C(0xb1a2bc2e, c5000000), -7, 17},
- {GRISU_UINT64_C(0xde0b6b3a, 76400000), -4, 18},
- {GRISU_UINT64_C(0x8ac72304, 89e80000), 0, 19},
- {GRISU_UINT64_C(0xad78ebc5, ac620000), 3, 20},
- {GRISU_UINT64_C(0xd8d726b7, 177a8000), 6, 21},
- {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
- {GRISU_UINT64_C(0xa968163f, 0a57b400), 13, 23},
- {GRISU_UINT64_C(0xd3c21bce, cceda100), 16, 24},
- {GRISU_UINT64_C(0x84595161, 401484a0), 20, 25},
- {GRISU_UINT64_C(0xa56fa5b9, 9019a5c8), 23, 26},
- {GRISU_UINT64_C(0xcecb8f27, f4200f3a), 26, 27},
- {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
- {GRISU_UINT64_C(0xa18f07d7, 36b90be5), 33, 29},
- {GRISU_UINT64_C(0xc9f2c9cd, 04674edf), 36, 30},
- {GRISU_UINT64_C(0xfc6f7c40, 45812296), 39, 31},
- {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
- {GRISU_UINT64_C(0xc5371912, 364ce305), 46, 33},
- {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
- {GRISU_UINT64_C(0x9a130b96, 3a6c115c), 53, 35},
- {GRISU_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
- {GRISU_UINT64_C(0xf0bdc21a, bb48db20), 59, 37},
- {GRISU_UINT64_C(0x96769950, b50d88f4), 63, 38},
- {GRISU_UINT64_C(0xbc143fa4, e250eb31), 66, 39},
- {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
- {GRISU_UINT64_C(0x92efd1b8, d0cf37be), 73, 41},
- {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
- {GRISU_UINT64_C(0xe596b7b0, c643c719), 79, 43},
- {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
- {GRISU_UINT64_C(0xb35dbf82, 1ae4f38c), 86, 45},
- {GRISU_UINT64_C(0xe0352f62, a19e306f), 89, 46},
- {GRISU_UINT64_C(0x8c213d9d, a502de45), 93, 47},
- {GRISU_UINT64_C(0xaf298d05, 0e4395d7), 96, 48},
- {GRISU_UINT64_C(0xdaf3f046, 51d47b4c), 99, 49},
- {GRISU_UINT64_C(0x88d8762b, f324cd10), 103, 50},
- {GRISU_UINT64_C(0xab0e93b6, efee0054), 106, 51},
- {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
- {GRISU_UINT64_C(0x85a36366, eb71f041), 113, 53},
- {GRISU_UINT64_C(0xa70c3c40, a64e6c52), 116, 54},
- {GRISU_UINT64_C(0xd0cf4b50, cfe20766), 119, 55},
- {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
- {GRISU_UINT64_C(0xa321f2d7, 226895c8), 126, 57},
- {GRISU_UINT64_C(0xcbea6f8c, eb02bb3a), 129, 58},
- {GRISU_UINT64_C(0xfee50b70, 25c36a08), 132, 59},
- {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
- {GRISU_UINT64_C(0xc722f0ef, 9d80aad6), 139, 61},
- {GRISU_UINT64_C(0xf8ebad2b, 84e0d58c), 142, 62},
- {GRISU_UINT64_C(0x9b934c3b, 330c8577), 146, 63},
- {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
- {GRISU_UINT64_C(0xf316271c, 7fc3908b), 152, 65},
- {GRISU_UINT64_C(0x97edd871, cfda3a57), 156, 66},
- {GRISU_UINT64_C(0xbde94e8e, 43d0c8ec), 159, 67},
- {GRISU_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
- {GRISU_UINT64_C(0x945e455f, 24fb1cf9), 166, 69},
- {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
- {GRISU_UINT64_C(0xe7d34c64, a9c85d44), 172, 71},
- {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
- {GRISU_UINT64_C(0xb51d13ae, a4a488dd), 179, 73},
- {GRISU_UINT64_C(0xe264589a, 4dcdab15), 182, 74},
- {GRISU_UINT64_C(0x8d7eb760, 70a08aed), 186, 75},
- {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
- {GRISU_UINT64_C(0xdd15fe86, affad912), 192, 77},
- {GRISU_UINT64_C(0x8a2dbf14, 2dfcc7ab), 196, 78},
- {GRISU_UINT64_C(0xacb92ed9, 397bf996), 199, 79},
- {GRISU_UINT64_C(0xd7e77a8f, 87daf7fc), 202, 80},
- {GRISU_UINT64_C(0x86f0ac99, b4e8dafd), 206, 81},
- {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
- {GRISU_UINT64_C(0xd2d80db0, 2aabd62c), 212, 83},
- {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
- {GRISU_UINT64_C(0xa4b8cab1, a1563f52), 219, 85},
- {GRISU_UINT64_C(0xcde6fd5e, 09abcf27), 222, 86},
- {GRISU_UINT64_C(0x80b05e5a, c60b6178), 226, 87},
- {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
- {GRISU_UINT64_C(0xc913936d, d571c84c), 232, 89},
- {GRISU_UINT64_C(0xfb587849, 4ace3a5f), 235, 90},
- {GRISU_UINT64_C(0x9d174b2d, cec0e47b), 239, 91},
- {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
- {GRISU_UINT64_C(0xf5746577, 930d6501), 245, 93},
- {GRISU_UINT64_C(0x9968bf6a, bbe85f20), 249, 94},
- {GRISU_UINT64_C(0xbfc2ef45, 6ae276e9), 252, 95},
- {GRISU_UINT64_C(0xefb3ab16, c59b14a3), 255, 96},
- {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
- {GRISU_UINT64_C(0xbb445da9, ca61281f), 262, 98},
- {GRISU_UINT64_C(0xea157514, 3cf97227), 265, 99},
- {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
- {GRISU_UINT64_C(0xb6e0c377, cfa2e12e), 272, 101},
- {GRISU_UINT64_C(0xe498f455, c38b997a), 275, 102},
- {GRISU_UINT64_C(0x8edf98b5, 9a373fec), 279, 103},
- {GRISU_UINT64_C(0xb2977ee3, 00c50fe7), 282, 104},
- {GRISU_UINT64_C(0xdf3d5e9b, c0f653e1), 285, 105},
- {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
- {GRISU_UINT64_C(0xae67f1e9, aec07188), 292, 107},
- {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
- {GRISU_UINT64_C(0x884134fe, 908658b2), 299, 109},
- {GRISU_UINT64_C(0xaa51823e, 34a7eedf), 302, 110},
- {GRISU_UINT64_C(0xd4e5e2cd, c1d1ea96), 305, 111},
- {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
- {GRISU_UINT64_C(0xa6539930, bf6bff46), 312, 113},
- {GRISU_UINT64_C(0xcfe87f7c, ef46ff17), 315, 114},
- {GRISU_UINT64_C(0x81f14fae, 158c5f6e), 319, 115},
- {GRISU_UINT64_C(0xa26da399, 9aef774a), 322, 116},
- {GRISU_UINT64_C(0xcb090c80, 01ab551c), 325, 117},
- {GRISU_UINT64_C(0xfdcb4fa0, 02162a63), 328, 118},
- {GRISU_UINT64_C(0x9e9f11c4, 014dda7e), 332, 119},
- {GRISU_UINT64_C(0xc646d635, 01a1511e), 335, 120},
- {GRISU_UINT64_C(0xf7d88bc2, 4209a565), 338, 121},
- {GRISU_UINT64_C(0x9ae75759, 6946075f), 342, 122},
- {GRISU_UINT64_C(0xc1a12d2f, c3978937), 345, 123},
- {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
- {GRISU_UINT64_C(0x9745eb4d, 50ce6333), 352, 125},
- {GRISU_UINT64_C(0xbd176620, a501fc00), 355, 126},
- {GRISU_UINT64_C(0xec5d3fa8, ce427b00), 358, 127},
- {GRISU_UINT64_C(0x93ba47c9, 80e98ce0), 362, 128},
- {GRISU_UINT64_C(0xb8a8d9bb, e123f018), 365, 129},
- {GRISU_UINT64_C(0xe6d3102a, d96cec1e), 368, 130},
- {GRISU_UINT64_C(0x9043ea1a, c7e41393), 372, 131},
- {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
- {GRISU_UINT64_C(0xe16a1dc9, d8545e95), 378, 133},
- {GRISU_UINT64_C(0x8ce2529e, 2734bb1d), 382, 134},
- {GRISU_UINT64_C(0xb01ae745, b101e9e4), 385, 135},
- {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
- {GRISU_UINT64_C(0x899504ae, 72497eba), 392, 137},
- {GRISU_UINT64_C(0xabfa45da, 0edbde69), 395, 138},
- {GRISU_UINT64_C(0xd6f8d750, 9292d603), 398, 139},
- {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
- {GRISU_UINT64_C(0xa7f26836, f282b733), 405, 141},
- {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
- {GRISU_UINT64_C(0x8335616a, ed761f1f), 412, 143},
- {GRISU_UINT64_C(0xa402b9c5, a8d3a6e7), 415, 144},
- {GRISU_UINT64_C(0xcd036837, 130890a1), 418, 145},
- {GRISU_UINT64_C(0x80222122, 6be55a65), 422, 146},
- {GRISU_UINT64_C(0xa02aa96b, 06deb0fe), 425, 147},
- {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
- {GRISU_UINT64_C(0xfa42a8b7, 3abbf48d), 431, 149},
- {GRISU_UINT64_C(0x9c69a972, 84b578d8), 435, 150},
- {GRISU_UINT64_C(0xc38413cf, 25e2d70e), 438, 151},
- {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
- {GRISU_UINT64_C(0x98bf2f79, d5993803), 445, 153},
- {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
- {GRISU_UINT64_C(0xeeaaba2e, 5dbf6785), 451, 155},
- {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
- {GRISU_UINT64_C(0xba756174, 393d88e0), 458, 157},
- {GRISU_UINT64_C(0xe912b9d1, 478ceb17), 461, 158},
- {GRISU_UINT64_C(0x91abb422, ccb812ef), 465, 159},
- {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
- {GRISU_UINT64_C(0xe39c4976, 5fdf9d95), 471, 161},
- {GRISU_UINT64_C(0x8e41ade9, fbebc27d), 475, 162},
- {GRISU_UINT64_C(0xb1d21964, 7ae6b31c), 478, 163},
- {GRISU_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
- {GRISU_UINT64_C(0x8aec23d6, 80043bee), 485, 165},
- {GRISU_UINT64_C(0xada72ccc, 20054aea), 488, 166},
- {GRISU_UINT64_C(0xd910f7ff, 28069da4), 491, 167},
- {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
- {GRISU_UINT64_C(0xa99541bf, 57452b28), 498, 169},
- {GRISU_UINT64_C(0xd3fa922f, 2d1675f2), 501, 170},
- {GRISU_UINT64_C(0x847c9b5d, 7c2e09b7), 505, 171},
- {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
- {GRISU_UINT64_C(0xcf02b2c2, 1207ef2f), 511, 173},
- {GRISU_UINT64_C(0x8161afb9, 4b44f57d), 515, 174},
- {GRISU_UINT64_C(0xa1ba1ba7, 9e1632dc), 518, 175},
- {GRISU_UINT64_C(0xca28a291, 859bbf93), 521, 176},
- {GRISU_UINT64_C(0xfcb2cb35, e702af78), 524, 177},
- {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
- {GRISU_UINT64_C(0xc56baec2, 1c7a1916), 531, 179},
- {GRISU_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
- {GRISU_UINT64_C(0x9a3c2087, a63f6399), 538, 181},
- {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
- {GRISU_UINT64_C(0xf0fdf2d3, f3c30b9f), 544, 183},
- {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
- {GRISU_UINT64_C(0xbc4665b5, 96706115), 551, 185},
- {GRISU_UINT64_C(0xeb57ff22, fc0c795a), 554, 186},
- {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
- {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
- {GRISU_UINT64_C(0xe5d3ef28, 2a242e82), 564, 189},
- {GRISU_UINT64_C(0x8fa47579, 1a569d11), 568, 190},
- {GRISU_UINT64_C(0xb38d92d7, 60ec4455), 571, 191},
- {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
- {GRISU_UINT64_C(0x8c469ab8, 43b89563), 578, 193},
- {GRISU_UINT64_C(0xaf584166, 54a6babb), 581, 194},
- {GRISU_UINT64_C(0xdb2e51bf, e9d0696a), 584, 195},
- {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
- {GRISU_UINT64_C(0xab3c2fdd, eeaad25b), 591, 197},
- {GRISU_UINT64_C(0xd60b3bd5, 6a5586f2), 594, 198},
- {GRISU_UINT64_C(0x85c70565, 62757457), 598, 199},
- {GRISU_UINT64_C(0xa738c6be, bb12d16d), 601, 200},
- {GRISU_UINT64_C(0xd106f86e, 69d785c8), 604, 201},
- {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
- {GRISU_UINT64_C(0xa34d7216, 42b06084), 611, 203},
- {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
- {GRISU_UINT64_C(0xff290242, c83396ce), 617, 205},
- {GRISU_UINT64_C(0x9f79a169, bd203e41), 621, 206},
- {GRISU_UINT64_C(0xc75809c4, 2c684dd1), 624, 207},
- {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
- {GRISU_UINT64_C(0x9bbcc7a1, 42b17ccc), 631, 209},
- {GRISU_UINT64_C(0xc2abf989, 935ddbfe), 634, 210},
- {GRISU_UINT64_C(0xf356f7eb, f83552fe), 637, 211},
- {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
- {GRISU_UINT64_C(0xbe1bf1b0, 59e9a8d6), 644, 213},
- {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
- {GRISU_UINT64_C(0x9485d4d1, c63e8be8), 651, 215},
- {GRISU_UINT64_C(0xb9a74a06, 37ce2ee1), 654, 216},
- {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
- {GRISU_UINT64_C(0x910ab1d4, db9914a0), 661, 218},
- {GRISU_UINT64_C(0xb54d5e4a, 127f59c8), 664, 219},
- {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
- {GRISU_UINT64_C(0x8da471a9, de737e24), 671, 221},
- {GRISU_UINT64_C(0xb10d8e14, 56105dad), 674, 222},
- {GRISU_UINT64_C(0xdd50f199, 6b947519), 677, 223},
- {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
- {GRISU_UINT64_C(0xace73cbf, dc0bfb7b), 684, 225},
- {GRISU_UINT64_C(0xd8210bef, d30efa5a), 687, 226},
- {GRISU_UINT64_C(0x8714a775, e3e95c78), 691, 227},
- {GRISU_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
- {GRISU_UINT64_C(0xd31045a8, 341ca07c), 697, 229},
- {GRISU_UINT64_C(0x83ea2b89, 2091e44e), 701, 230},
- {GRISU_UINT64_C(0xa4e4b66b, 68b65d61), 704, 231},
- {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
- {GRISU_UINT64_C(0x80d2ae83, e9ce78f4), 711, 233},
- {GRISU_UINT64_C(0xa1075a24, e4421731), 714, 234},
- {GRISU_UINT64_C(0xc94930ae, 1d529cfd), 717, 235},
- {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
- {GRISU_UINT64_C(0x9d412e08, 06e88aa6), 724, 237},
- {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
- {GRISU_UINT64_C(0xf5b5d7ec, 8acb58a3), 730, 239},
- {GRISU_UINT64_C(0x9991a6f3, d6bf1766), 734, 240},
- {GRISU_UINT64_C(0xbff610b0, cc6edd3f), 737, 241},
- {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
- {GRISU_UINT64_C(0x95f83d0a, 1fb69cd9), 744, 243},
- {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
- {GRISU_UINT64_C(0xea53df5f, d18d5514), 750, 245},
- {GRISU_UINT64_C(0x92746b9b, e2f8552c), 754, 246},
- {GRISU_UINT64_C(0xb7118682, dbb66a77), 757, 247},
- {GRISU_UINT64_C(0xe4d5e823, 92a40515), 760, 248},
- {GRISU_UINT64_C(0x8f05b116, 3ba6832d), 764, 249},
- {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
- {GRISU_UINT64_C(0xdf78e4b2, bd342cf7), 770, 251},
- {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
- {GRISU_UINT64_C(0xae9672ab, a3d0c321), 777, 253},
- {GRISU_UINT64_C(0xda3c0f56, 8cc4f3e9), 780, 254},
- {GRISU_UINT64_C(0x88658996, 17fb1871), 784, 255},
- {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
- {GRISU_UINT64_C(0xd51ea6fa, 85785631), 790, 257},
- {GRISU_UINT64_C(0x8533285c, 936b35df), 794, 258},
- {GRISU_UINT64_C(0xa67ff273, b8460357), 797, 259},
- {GRISU_UINT64_C(0xd01fef10, a657842c), 800, 260},
- {GRISU_UINT64_C(0x8213f56a, 67f6b29c), 804, 261},
- {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
- {GRISU_UINT64_C(0xcb3f2f76, 42717713), 810, 263},
- {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
- {GRISU_UINT64_C(0x9ec95d14, 63e8a507), 817, 265},
- {GRISU_UINT64_C(0xc67bb459, 7ce2ce49), 820, 266},
- {GRISU_UINT64_C(0xf81aa16f, dc1b81db), 823, 267},
- {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
- {GRISU_UINT64_C(0xc1d4ce1f, 63f57d73), 830, 269},
- {GRISU_UINT64_C(0xf24a01a7, 3cf2dcd0), 833, 270},
- {GRISU_UINT64_C(0x976e4108, 8617ca02), 837, 271},
- {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
- {GRISU_UINT64_C(0xec9c459d, 51852ba3), 843, 273},
- {GRISU_UINT64_C(0x93e1ab82, 52f33b46), 847, 274},
- {GRISU_UINT64_C(0xb8da1662, e7b00a17), 850, 275},
- {GRISU_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
- {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
- {GRISU_UINT64_C(0xb484f9dc, 9641e9db), 860, 278},
- {GRISU_UINT64_C(0xe1a63853, bbd26451), 863, 279},
- {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
- {GRISU_UINT64_C(0xb049dc01, 6abc5e60), 870, 281},
- {GRISU_UINT64_C(0xdc5c5301, c56b75f7), 873, 282},
- {GRISU_UINT64_C(0x89b9b3e1, 1b6329bb), 877, 283},
- {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
- {GRISU_UINT64_C(0xd732290f, bacaf134), 883, 285},
- {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
- {GRISU_UINT64_C(0xa81f3014, 49ee8c70), 890, 287},
- {GRISU_UINT64_C(0xd226fc19, 5c6a2f8c), 893, 288},
- {GRISU_UINT64_C(0x83585d8f, d9c25db8), 897, 289},
- {GRISU_UINT64_C(0xa42e74f3, d032f526), 900, 290},
- {GRISU_UINT64_C(0xcd3a1230, c43fb26f), 903, 291},
- {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
- {GRISU_UINT64_C(0xa0555e36, 1951c367), 910, 293},
- {GRISU_UINT64_C(0xc86ab5c3, 9fa63441), 913, 294},
- {GRISU_UINT64_C(0xfa856334, 878fc151), 916, 295},
- {GRISU_UINT64_C(0x9c935e00, d4b9d8d2), 920, 296},
- {GRISU_UINT64_C(0xc3b83581, 09e84f07), 923, 297},
- {GRISU_UINT64_C(0xf4a642e1, 4c6262c9), 926, 298},
- {GRISU_UINT64_C(0x98e7e9cc, cfbd7dbe), 930, 299},
- {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
- {GRISU_UINT64_C(0xeeea5d50, 04981478), 936, 301},
- {GRISU_UINT64_C(0x95527a52, 02df0ccb), 940, 302},
- {GRISU_UINT64_C(0xbaa718e6, 8396cffe), 943, 303},
- {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
- {GRISU_UINT64_C(0x91d28b74, 16cdd27e), 950, 305},
- {GRISU_UINT64_C(0xb6472e51, 1c81471e), 953, 306},
- {GRISU_UINT64_C(0xe3d8f9e5, 63a198e5), 956, 307},
- {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
- {GRISU_UINT64_C(0xb201833b, 35d63f73), 963, 309},
- {GRISU_UINT64_C(0xde81e40a, 034bcf50), 966, 310},
- {GRISU_UINT64_C(0x8b112e86, 420f6192), 970, 311},
- {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
- {GRISU_UINT64_C(0xd94ad8b1, c7380874), 976, 313},
- {GRISU_UINT64_C(0x87cec76f, 1c830549), 980, 314},
- {GRISU_UINT64_C(0xa9c2794a, e3a3c69b), 983, 315},
- {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
- {GRISU_UINT64_C(0x849feec2, 81d7f329), 990, 317},
- {GRISU_UINT64_C(0xa5c7ea73, 224deff3), 993, 318},
- {GRISU_UINT64_C(0xcf39e50f, eae16bf0), 996, 319},
- {GRISU_UINT64_C(0x81842f29, f2cce376), 1000, 320},
- {GRISU_UINT64_C(0xa1e53af4, 6f801c53), 1003, 321},
- {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
- {GRISU_UINT64_C(0xfcf62c1d, ee382c42), 1009, 323},
- {GRISU_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
- {GRISU_UINT64_C(0xc5a05277, 621be294), 1016, 325},
- {GRISU_UINT64_C(0xf7086715, 3aa2db39), 1019, 326},
- {GRISU_UINT64_C(0x9a65406d, 44a5c903), 1023, 327},
- {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
- {GRISU_UINT64_C(0xf13e34aa, bb430a15), 1029, 329},
- {GRISU_UINT64_C(0x96c6e0ea, b509e64d), 1033, 330},
- {GRISU_UINT64_C(0xbc789925, 624c5fe1), 1036, 331},
- {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
- {GRISU_UINT64_C(0x933e37a5, 34cbaae8), 1043, 333},
- {GRISU_UINT64_C(0xb80dc58e, 81fe95a1), 1046, 334},
- {GRISU_UINT64_C(0xe61136f2, 227e3b0a), 1049, 335},
- {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
- {GRISU_UINT64_C(0xb3bd72ed, 2af29e20), 1056, 337},
- {GRISU_UINT64_C(0xe0accfa8, 75af45a8), 1059, 338},
- {GRISU_UINT64_C(0x8c6c01c9, 498d8b89), 1063, 339},
- {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
- {GRISU_UINT64_C(0xdb68c2ca, 82ed2a06), 1069, 341},
- {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(1) = 4;
-// nb elements (1): 651
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(2)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0xb3c4f1ba, 87bc8697), -1080, -306},
- {GRISU_UINT64_C(0x8c71dcd9, ba0b4926), -1073, -304},
- {GRISU_UINT64_C(0xdb71e914, 32b1a24b), -1067, -302},
- {GRISU_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
- {GRISU_UINT64_C(0x85f04682, 93f0eb4e), -1053, -298},
- {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
- {GRISU_UINT64_C(0xa37fce12, 6597973d), -1040, -294},
- {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
- {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
- {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
- {GRISU_UINT64_C(0xf3a20279, ed56d48a), -1014, -286},
- {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
- {GRISU_UINT64_C(0x94b3a202, eb1c3f39), -1000, -282},
- {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
- {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
- {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
- {GRISU_UINT64_C(0xdd95317f, 31c7fa1d), -974, -274},
- {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
- {GRISU_UINT64_C(0x873e4f75, e2224e68), -960, -270},
- {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
- {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
- {GRISU_UINT64_C(0x80fa687f, 881c7f8e), -940, -264},
- {GRISU_UINT64_C(0xc9874347, 44ac874f), -934, -262},
- {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
- {GRISU_UINT64_C(0xf6019da0, 7f549b2b), -921, -258},
- {GRISU_UINT64_C(0xc0314325, 637a193a), -914, -256},
- {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
- {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
- {GRISU_UINT64_C(0xb749faed, 14125d37), -894, -250},
- {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
- {GRISU_UINT64_C(0xdfbdcece, 67006ac9), -881, -246},
- {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
- {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
- {GRISU_UINT64_C(0xd5605fcd, cf32e1d7), -861, -240},
- {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
- {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
- {GRISU_UINT64_C(0xcb7ddcdd, a26da269), -841, -234},
- {GRISU_UINT64_C(0x9efa548d, 26e5a6e2), -834, -232},
- {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
- {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
- {GRISU_UINT64_C(0x979cf3ca, 6cec5b5b), -814, -226},
- {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
- {GRISU_UINT64_C(0xb9131798, 99f68584), -801, -222},
- {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
- {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
- {GRISU_UINT64_C(0xb080392c, c4349ded), -781, -216},
- {GRISU_UINT64_C(0x89e42caa, f9491b61), -774, -214},
- {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
- {GRISU_UINT64_C(0xa8530886, b54dbdec), -761, -210},
- {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
- {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
- {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
- {GRISU_UINT64_C(0xfad2a4b1, 3d1b5d6c), -735, -202},
- {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
- {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
- {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
- {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
- {GRISU_UINT64_C(0x91ff8377, 5423cc06), -701, -192},
- {GRISU_UINT64_C(0xe41f3d6a, 7377eeca), -695, -190},
- {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
- {GRISU_UINT64_C(0x8b3c113c, 38f9f37f), -681, -186},
- {GRISU_UINT64_C(0xd98ddaee, 19068c76), -675, -184},
- {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
- {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
- {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
- {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
- {GRISU_UINT64_C(0xfd442e46, 88bd304b), -642, -174},
- {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
- {GRISU_UINT64_C(0x9a94dd3e, 8cf578ba), -628, -170},
- {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
- {GRISU_UINT64_C(0xbcb2b812, db11a5de), -615, -166},
- {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
- {GRISU_UINT64_C(0xe65829b3, 046b0afa), -602, -162},
- {GRISU_UINT64_C(0xb3f4e093, db73a093), -595, -160},
- {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
- {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
- {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
- {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
- {GRISU_UINT64_C(0xd17f3b51, fca3a7a1), -562, -150},
- {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
- {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
- {GRISU_UINT64_C(0xc7caba6e, 7c5382c9), -542, -144},
- {GRISU_UINT64_C(0x9c1661a6, 51213e2d), -535, -142},
- {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
- {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
- {GRISU_UINT64_C(0x94db4838, 40b717f0), -515, -136},
- {GRISU_UINT64_C(0xe896a0d7, e51e1566), -509, -134},
- {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
- {GRISU_UINT64_C(0x8df5efab, c5979c90), -495, -130},
- {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
- {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
- {GRISU_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
- {GRISU_UINT64_C(0xd389b478, 79823479), -469, -122},
- {GRISU_UINT64_C(0xa54394fe, 1eedb8ff), -462, -120},
- {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
- {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
- {GRISU_UINT64_C(0x9d9ba783, 2936edc1), -442, -114},
- {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
- {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
- {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
- {GRISU_UINT64_C(0xeadab0ab, a3b2dbe5), -416, -106},
- {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
- {GRISU_UINT64_C(0x8f57fa54, c2a9eab7), -402, -102},
- {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
- {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
- {GRISU_UINT64_C(0x88b402f7, fd75539b), -382, -96},
- {GRISU_UINT64_C(0xd59944a3, 7c0752a2), -376, -94},
- {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
- {GRISU_UINT64_C(0x825ecc24, c8737830), -362, -90},
- {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
- {GRISU_UINT64_C(0x9f24b832, e6b0f436), -349, -86},
- {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
- {GRISU_UINT64_C(0xc24452da, 229b021c), -336, -82},
- {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
- {GRISU_UINT64_C(0xed246723, 473e3813), -323, -78},
- {GRISU_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
- {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
- {GRISU_UINT64_C(0xe2280b6c, 20dd5232), -303, -72},
- {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
- {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
- {GRISU_UINT64_C(0xd7adf884, aa879177), -283, -66},
- {GRISU_UINT64_C(0xa87fea27, a539e9a5), -276, -64},
- {GRISU_UINT64_C(0x83a3eeee, f9153e89), -269, -62},
- {GRISU_UINT64_C(0xcdb02555, 653131b6), -263, -60},
- {GRISU_UINT64_C(0xa0b19d2a, b70e6ed6), -256, -58},
- {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
- {GRISU_UINT64_C(0xc428d05a, a4751e4d), -243, -54},
- {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
- {GRISU_UINT64_C(0xef73d256, a5c0f77d), -230, -50},
- {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
- {GRISU_UINT64_C(0x92267121, 62ab070e), -216, -46},
- {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
- {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
- {GRISU_UINT64_C(0x8b61313b, babce2c6), -196, -40},
- {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
- {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
- {GRISU_UINT64_C(0x84ec3c97, da624ab5), -176, -34},
- {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
- {GRISU_UINT64_C(0xa2425ff7, 5e14fc32), -163, -30},
- {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
- {GRISU_UINT64_C(0xc6120625, 76589ddb), -150, -26},
- {GRISU_UINT64_C(0x9abe14cd, 44753b53), -143, -24},
- {GRISU_UINT64_C(0xf1c90080, baf72cb1), -137, -22},
- {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
- {GRISU_UINT64_C(0x9392ee8e, 921d5d07), -123, -18},
- {GRISU_UINT64_C(0xe69594be, c44de15b), -117, -16},
- {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
- {GRISU_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
- {GRISU_UINT64_C(0xdbe6fece, bdedd5bf), -97, -10},
- {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
- {GRISU_UINT64_C(0x8637bd05, af6c69b6), -83, -6},
- {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
- {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
- {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
- {GRISU_UINT64_C(0xc8000000, 00000000), -57, 2},
- {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
- {GRISU_UINT64_C(0xf4240000, 00000000), -44, 6},
- {GRISU_UINT64_C(0xbebc2000, 00000000), -37, 8},
- {GRISU_UINT64_C(0x9502f900, 00000000), -30, 10},
- {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
- {GRISU_UINT64_C(0xb5e620f4, 80000000), -17, 14},
- {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
- {GRISU_UINT64_C(0xde0b6b3a, 76400000), -4, 18},
- {GRISU_UINT64_C(0xad78ebc5, ac620000), 3, 20},
- {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
- {GRISU_UINT64_C(0xd3c21bce, cceda100), 16, 24},
- {GRISU_UINT64_C(0xa56fa5b9, 9019a5c8), 23, 26},
- {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
- {GRISU_UINT64_C(0xc9f2c9cd, 04674edf), 36, 30},
- {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
- {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
- {GRISU_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
- {GRISU_UINT64_C(0x96769950, b50d88f4), 63, 38},
- {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
- {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
- {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
- {GRISU_UINT64_C(0xe0352f62, a19e306f), 89, 46},
- {GRISU_UINT64_C(0xaf298d05, 0e4395d7), 96, 48},
- {GRISU_UINT64_C(0x88d8762b, f324cd10), 103, 50},
- {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
- {GRISU_UINT64_C(0xa70c3c40, a64e6c52), 116, 54},
- {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
- {GRISU_UINT64_C(0xcbea6f8c, eb02bb3a), 129, 58},
- {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
- {GRISU_UINT64_C(0xf8ebad2b, 84e0d58c), 142, 62},
- {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
- {GRISU_UINT64_C(0x97edd871, cfda3a57), 156, 66},
- {GRISU_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
- {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
- {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
- {GRISU_UINT64_C(0xe264589a, 4dcdab15), 182, 74},
- {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
- {GRISU_UINT64_C(0x8a2dbf14, 2dfcc7ab), 196, 78},
- {GRISU_UINT64_C(0xd7e77a8f, 87daf7fc), 202, 80},
- {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
- {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
- {GRISU_UINT64_C(0xcde6fd5e, 09abcf27), 222, 86},
- {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
- {GRISU_UINT64_C(0xfb587849, 4ace3a5f), 235, 90},
- {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
- {GRISU_UINT64_C(0x9968bf6a, bbe85f20), 249, 94},
- {GRISU_UINT64_C(0xefb3ab16, c59b14a3), 255, 96},
- {GRISU_UINT64_C(0xbb445da9, ca61281f), 262, 98},
- {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
- {GRISU_UINT64_C(0xe498f455, c38b997a), 275, 102},
- {GRISU_UINT64_C(0xb2977ee3, 00c50fe7), 282, 104},
- {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
- {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
- {GRISU_UINT64_C(0xaa51823e, 34a7eedf), 302, 110},
- {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
- {GRISU_UINT64_C(0xcfe87f7c, ef46ff17), 315, 114},
- {GRISU_UINT64_C(0xa26da399, 9aef774a), 322, 116},
- {GRISU_UINT64_C(0xfdcb4fa0, 02162a63), 328, 118},
- {GRISU_UINT64_C(0xc646d635, 01a1511e), 335, 120},
- {GRISU_UINT64_C(0x9ae75759, 6946075f), 342, 122},
- {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
- {GRISU_UINT64_C(0xbd176620, a501fc00), 355, 126},
- {GRISU_UINT64_C(0x93ba47c9, 80e98ce0), 362, 128},
- {GRISU_UINT64_C(0xe6d3102a, d96cec1e), 368, 130},
- {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
- {GRISU_UINT64_C(0x8ce2529e, 2734bb1d), 382, 134},
- {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
- {GRISU_UINT64_C(0xabfa45da, 0edbde69), 395, 138},
- {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
- {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
- {GRISU_UINT64_C(0xa402b9c5, a8d3a6e7), 415, 144},
- {GRISU_UINT64_C(0x80222122, 6be55a65), 422, 146},
- {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
- {GRISU_UINT64_C(0x9c69a972, 84b578d8), 435, 150},
- {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
- {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
- {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
- {GRISU_UINT64_C(0xe912b9d1, 478ceb17), 461, 158},
- {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
- {GRISU_UINT64_C(0x8e41ade9, fbebc27d), 475, 162},
- {GRISU_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
- {GRISU_UINT64_C(0xada72ccc, 20054aea), 488, 166},
- {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
- {GRISU_UINT64_C(0xd3fa922f, 2d1675f2), 501, 170},
- {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
- {GRISU_UINT64_C(0x8161afb9, 4b44f57d), 515, 174},
- {GRISU_UINT64_C(0xca28a291, 859bbf93), 521, 176},
- {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
- {GRISU_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
- {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
- {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
- {GRISU_UINT64_C(0xeb57ff22, fc0c795a), 554, 186},
- {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
- {GRISU_UINT64_C(0x8fa47579, 1a569d11), 568, 190},
- {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
- {GRISU_UINT64_C(0xaf584166, 54a6babb), 581, 194},
- {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
- {GRISU_UINT64_C(0xd60b3bd5, 6a5586f2), 594, 198},
- {GRISU_UINT64_C(0xa738c6be, bb12d16d), 601, 200},
- {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
- {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
- {GRISU_UINT64_C(0x9f79a169, bd203e41), 621, 206},
- {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
- {GRISU_UINT64_C(0xc2abf989, 935ddbfe), 634, 210},
- {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
- {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
- {GRISU_UINT64_C(0xb9a74a06, 37ce2ee1), 654, 216},
- {GRISU_UINT64_C(0x910ab1d4, db9914a0), 661, 218},
- {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
- {GRISU_UINT64_C(0xb10d8e14, 56105dad), 674, 222},
- {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
- {GRISU_UINT64_C(0xd8210bef, d30efa5a), 687, 226},
- {GRISU_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
- {GRISU_UINT64_C(0x83ea2b89, 2091e44e), 701, 230},
- {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
- {GRISU_UINT64_C(0xa1075a24, e4421731), 714, 234},
- {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
- {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
- {GRISU_UINT64_C(0x9991a6f3, d6bf1766), 734, 240},
- {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
- {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
- {GRISU_UINT64_C(0x92746b9b, e2f8552c), 754, 246},
- {GRISU_UINT64_C(0xe4d5e823, 92a40515), 760, 248},
- {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
- {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
- {GRISU_UINT64_C(0xda3c0f56, 8cc4f3e9), 780, 254},
- {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
- {GRISU_UINT64_C(0x8533285c, 936b35df), 794, 258},
- {GRISU_UINT64_C(0xd01fef10, a657842c), 800, 260},
- {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
- {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
- {GRISU_UINT64_C(0xc67bb459, 7ce2ce49), 820, 266},
- {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
- {GRISU_UINT64_C(0xf24a01a7, 3cf2dcd0), 833, 270},
- {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
- {GRISU_UINT64_C(0x93e1ab82, 52f33b46), 847, 274},
- {GRISU_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
- {GRISU_UINT64_C(0xb484f9dc, 9641e9db), 860, 278},
- {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
- {GRISU_UINT64_C(0xdc5c5301, c56b75f7), 873, 282},
- {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
- {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
- {GRISU_UINT64_C(0xd226fc19, 5c6a2f8c), 893, 288},
- {GRISU_UINT64_C(0xa42e74f3, d032f526), 900, 290},
- {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
- {GRISU_UINT64_C(0xc86ab5c3, 9fa63441), 913, 294},
- {GRISU_UINT64_C(0x9c935e00, d4b9d8d2), 920, 296},
- {GRISU_UINT64_C(0xf4a642e1, 4c6262c9), 926, 298},
- {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
- {GRISU_UINT64_C(0x95527a52, 02df0ccb), 940, 302},
- {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
- {GRISU_UINT64_C(0xb6472e51, 1c81471e), 953, 306},
- {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
- {GRISU_UINT64_C(0xde81e40a, 034bcf50), 966, 310},
- {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
- {GRISU_UINT64_C(0x87cec76f, 1c830549), 980, 314},
- {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
- {GRISU_UINT64_C(0xa5c7ea73, 224deff3), 993, 318},
- {GRISU_UINT64_C(0x81842f29, f2cce376), 1000, 320},
- {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
- {GRISU_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
- {GRISU_UINT64_C(0xf7086715, 3aa2db39), 1019, 326},
- {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
- {GRISU_UINT64_C(0x96c6e0ea, b509e64d), 1033, 330},
- {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
- {GRISU_UINT64_C(0xb80dc58e, 81fe95a1), 1046, 334},
- {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
- {GRISU_UINT64_C(0xe0accfa8, 75af45a8), 1059, 338},
- {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
- {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(2) = 7;
-// nb elements (2): 326
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(3)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0xe0b62e29, 29aba83c), -1077, -305},
- {GRISU_UINT64_C(0xdb71e914, 32b1a24b), -1067, -302},
- {GRISU_UINT64_C(0xd64d3d9d, b981787d), -1057, -299},
- {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
- {GRISU_UINT64_C(0xcc5fc196, fefd7d0c), -1037, -293},
- {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
- {GRISU_UINT64_C(0xc2e801fb, 244576d5), -1017, -287},
- {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
- {GRISU_UINT64_C(0xb9e08a83, a5e34f08), -997, -281},
- {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
- {GRISU_UINT64_C(0xb1442798, f49ffb4b), -977, -275},
- {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
- {GRISU_UINT64_C(0xa90de353, 5aaae202), -957, -269},
- {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
- {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
- {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
- {GRISU_UINT64_C(0x99c10284, 4f94e0fb), -917, -257},
- {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
- {GRISU_UINT64_C(0x92a1958a, 7675175f), -897, -251},
- {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
- {GRISU_UINT64_C(0x8bd6a141, 006042be), -877, -245},
- {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
- {GRISU_UINT64_C(0x855c3be0, a17fcd26), -857, -239},
- {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
- {GRISU_UINT64_C(0xfe5d5415, 0b090b03), -838, -233},
- {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
- {GRISU_UINT64_C(0xf294b943, e17a2bc4), -818, -227},
- {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
- {GRISU_UINT64_C(0xe757dd7e, c07426e5), -798, -221},
- {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
- {GRISU_UINT64_C(0xdca04777, f541c568), -778, -215},
- {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
- {GRISU_UINT64_C(0xd267caa8, 62a12d67), -758, -209},
- {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
- {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
- {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
- {GRISU_UINT64_C(0xbf5cd546, 78eef0b7), -718, -197},
- {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
- {GRISU_UINT64_C(0xb67f6455, 292cbf08), -698, -191},
- {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
- {GRISU_UINT64_C(0xae0b158b, 4738705f), -678, -185},
- {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
- {GRISU_UINT64_C(0xa5fb0a17, c777cf0a), -658, -179},
- {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
- {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
- {GRISU_UINT64_C(0x9a94dd3e, 8cf578ba), -628, -170},
- {GRISU_UINT64_C(0x96f5600f, 15a7b7e5), -618, -167},
- {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
- {GRISU_UINT64_C(0x8ff71a0f, e2c2e6dc), -598, -161},
- {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
- {GRISU_UINT64_C(0x894bc396, ce5da772), -578, -155},
- {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
- {GRISU_UINT64_C(0x82ef8513, 3de648c5), -558, -149},
- {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
- {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
- {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
- {GRISU_UINT64_C(0xee2ba6c0, 678b597f), -519, -137},
- {GRISU_UINT64_C(0xe896a0d7, e51e1566), -509, -134},
- {GRISU_UINT64_C(0xe3231912, d5bf60e6), -499, -131},
- {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
- {GRISU_UINT64_C(0xd89d64d5, 7a607745), -479, -125},
- {GRISU_UINT64_C(0xd389b478, 79823479), -469, -122},
- {GRISU_UINT64_C(0xce947a3d, a6a9273e), -459, -119},
- {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
- {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
- {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
- {GRISU_UINT64_C(0xbbe226ef, b628afeb), -419, -107},
- {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
- {GRISU_UINT64_C(0xb32df8e9, f3546564), -399, -101},
- {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
- {GRISU_UINT64_C(0xaae103b5, fcd2a882), -379, -95},
- {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
- {GRISU_UINT64_C(0xa2f67f2d, fa90563b), -359, -89},
- {GRISU_UINT64_C(0x9f24b832, e6b0f436), -349, -86},
- {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
- {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
- {GRISU_UINT64_C(0x9436c076, 0c86e30c), -319, -77},
- {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
- {GRISU_UINT64_C(0x8d590723, 948a535f), -299, -71},
- {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
- {GRISU_UINT64_C(0x86ccbb52, ea94baeb), -279, -65},
- {GRISU_UINT64_C(0x83a3eeee, f9153e89), -269, -62},
- {GRISU_UINT64_C(0x808e1755, 5f3ebf12), -259, -59},
- {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
- {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
- {GRISU_UINT64_C(0xef73d256, a5c0f77d), -230, -50},
- {GRISU_UINT64_C(0xe9d71b68, 9dde71b0), -220, -47},
- {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
- {GRISU_UINT64_C(0xdf01e85f, 912e37a3), -200, -41},
- {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
- {GRISU_UINT64_C(0xd4ad2dbf, c3d07788), -180, -35},
- {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
- {GRISU_UINT64_C(0xcad2f7f5, 359a3b3e), -160, -29},
- {GRISU_UINT64_C(0xc6120625, 76589ddb), -150, -26},
- {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
- {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
- {GRISU_UINT64_C(0xb877aa32, 36a4b449), -120, -17},
- {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
- {GRISU_UINT64_C(0xafebff0b, cb24aaff), -100, -11},
- {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
- {GRISU_UINT64_C(0xa7c5ac47, 1b478423), -80, -5},
- {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
- {GRISU_UINT64_C(0xa0000000, 00000000), -60, 1},
- {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
- {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
- {GRISU_UINT64_C(0x9502f900, 00000000), -30, 10},
- {GRISU_UINT64_C(0x9184e72a, 00000000), -20, 13},
- {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
- {GRISU_UINT64_C(0x8ac72304, 89e80000), 0, 19},
- {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
- {GRISU_UINT64_C(0x84595161, 401484a0), 20, 25},
- {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
- {GRISU_UINT64_C(0xfc6f7c40, 45812296), 39, 31},
- {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
- {GRISU_UINT64_C(0xf0bdc21a, bb48db20), 59, 37},
- {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
- {GRISU_UINT64_C(0xe596b7b0, c643c719), 79, 43},
- {GRISU_UINT64_C(0xe0352f62, a19e306f), 89, 46},
- {GRISU_UINT64_C(0xdaf3f046, 51d47b4c), 99, 49},
- {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
- {GRISU_UINT64_C(0xd0cf4b50, cfe20766), 119, 55},
- {GRISU_UINT64_C(0xcbea6f8c, eb02bb3a), 129, 58},
- {GRISU_UINT64_C(0xc722f0ef, 9d80aad6), 139, 61},
- {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
- {GRISU_UINT64_C(0xbde94e8e, 43d0c8ec), 159, 67},
- {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
- {GRISU_UINT64_C(0xb51d13ae, a4a488dd), 179, 73},
- {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
- {GRISU_UINT64_C(0xacb92ed9, 397bf996), 199, 79},
- {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
- {GRISU_UINT64_C(0xa4b8cab1, a1563f52), 219, 85},
- {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
- {GRISU_UINT64_C(0x9d174b2d, cec0e47b), 239, 91},
- {GRISU_UINT64_C(0x9968bf6a, bbe85f20), 249, 94},
- {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
- {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
- {GRISU_UINT64_C(0x8edf98b5, 9a373fec), 279, 103},
- {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
- {GRISU_UINT64_C(0x884134fe, 908658b2), 299, 109},
- {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
- {GRISU_UINT64_C(0x81f14fae, 158c5f6e), 319, 115},
- {GRISU_UINT64_C(0xfdcb4fa0, 02162a63), 328, 118},
- {GRISU_UINT64_C(0xf7d88bc2, 4209a565), 338, 121},
- {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
- {GRISU_UINT64_C(0xec5d3fa8, ce427b00), 358, 127},
- {GRISU_UINT64_C(0xe6d3102a, d96cec1e), 368, 130},
- {GRISU_UINT64_C(0xe16a1dc9, d8545e95), 378, 133},
- {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
- {GRISU_UINT64_C(0xd6f8d750, 9292d603), 398, 139},
- {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
- {GRISU_UINT64_C(0xcd036837, 130890a1), 418, 145},
- {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
- {GRISU_UINT64_C(0xc38413cf, 25e2d70e), 438, 151},
- {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
- {GRISU_UINT64_C(0xba756174, 393d88e0), 458, 157},
- {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
- {GRISU_UINT64_C(0xb1d21964, 7ae6b31c), 478, 163},
- {GRISU_UINT64_C(0xada72ccc, 20054aea), 488, 166},
- {GRISU_UINT64_C(0xa99541bf, 57452b28), 498, 169},
- {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
- {GRISU_UINT64_C(0xa1ba1ba7, 9e1632dc), 518, 175},
- {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
- {GRISU_UINT64_C(0x9a3c2087, a63f6399), 538, 181},
- {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
- {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
- {GRISU_UINT64_C(0x8fa47579, 1a569d11), 568, 190},
- {GRISU_UINT64_C(0x8c469ab8, 43b89563), 578, 193},
- {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
- {GRISU_UINT64_C(0x85c70565, 62757457), 598, 199},
- {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
- {GRISU_UINT64_C(0xff290242, c83396ce), 617, 205},
- {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
- {GRISU_UINT64_C(0xf356f7eb, f83552fe), 637, 211},
- {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
- {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
- {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
- {GRISU_UINT64_C(0xdd50f199, 6b947519), 677, 223},
- {GRISU_UINT64_C(0xd8210bef, d30efa5a), 687, 226},
- {GRISU_UINT64_C(0xd31045a8, 341ca07c), 697, 229},
- {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
- {GRISU_UINT64_C(0xc94930ae, 1d529cfd), 717, 235},
- {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
- {GRISU_UINT64_C(0xbff610b0, cc6edd3f), 737, 241},
- {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
- {GRISU_UINT64_C(0xb7118682, dbb66a77), 757, 247},
- {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
- {GRISU_UINT64_C(0xae9672ab, a3d0c321), 777, 253},
- {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
- {GRISU_UINT64_C(0xa67ff273, b8460357), 797, 259},
- {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
- {GRISU_UINT64_C(0x9ec95d14, 63e8a507), 817, 265},
- {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
- {GRISU_UINT64_C(0x976e4108, 8617ca02), 837, 271},
- {GRISU_UINT64_C(0x93e1ab82, 52f33b46), 847, 274},
- {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
- {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
- {GRISU_UINT64_C(0x89b9b3e1, 1b6329bb), 877, 283},
- {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
- {GRISU_UINT64_C(0x83585d8f, d9c25db8), 897, 289},
- {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
- {GRISU_UINT64_C(0xfa856334, 878fc151), 916, 295},
- {GRISU_UINT64_C(0xf4a642e1, 4c6262c9), 926, 298},
- {GRISU_UINT64_C(0xeeea5d50, 04981478), 936, 301},
- {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
- {GRISU_UINT64_C(0xe3d8f9e5, 63a198e5), 956, 307},
- {GRISU_UINT64_C(0xde81e40a, 034bcf50), 966, 310},
- {GRISU_UINT64_C(0xd94ad8b1, c7380874), 976, 313},
- {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
- {GRISU_UINT64_C(0xcf39e50f, eae16bf0), 996, 319},
- {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
- {GRISU_UINT64_C(0xc5a05277, 621be294), 1016, 325},
- {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
- {GRISU_UINT64_C(0xbc789925, 624c5fe1), 1036, 331},
- {GRISU_UINT64_C(0xb80dc58e, 81fe95a1), 1046, 334},
- {GRISU_UINT64_C(0xb3bd72ed, 2af29e20), 1056, 337},
- {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(3) = 10;
-// nb elements (3): 217
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(4)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0x8c71dcd9, ba0b4926), -1073, -304},
- {GRISU_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
- {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
- {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
- {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
- {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
- {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
- {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
- {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
- {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
- {GRISU_UINT64_C(0x80fa687f, 881c7f8e), -940, -264},
- {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
- {GRISU_UINT64_C(0xc0314325, 637a193a), -914, -256},
- {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
- {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
- {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
- {GRISU_UINT64_C(0xd5605fcd, cf32e1d7), -861, -240},
- {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
- {GRISU_UINT64_C(0x9efa548d, 26e5a6e2), -834, -232},
- {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
- {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
- {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
- {GRISU_UINT64_C(0xb080392c, c4349ded), -781, -216},
- {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
- {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
- {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
- {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
- {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
- {GRISU_UINT64_C(0x91ff8377, 5423cc06), -701, -192},
- {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
- {GRISU_UINT64_C(0xd98ddaee, 19068c76), -675, -184},
- {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
- {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
- {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
- {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
- {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
- {GRISU_UINT64_C(0xb3f4e093, db73a093), -595, -160},
- {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
- {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
- {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
- {GRISU_UINT64_C(0xc7caba6e, 7c5382c9), -542, -144},
- {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
- {GRISU_UINT64_C(0x94db4838, 40b717f0), -515, -136},
- {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
- {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
- {GRISU_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
- {GRISU_UINT64_C(0xa54394fe, 1eedb8ff), -462, -120},
- {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
- {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
- {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
- {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
- {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
- {GRISU_UINT64_C(0x88b402f7, fd75539b), -382, -96},
- {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
- {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
- {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
- {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
- {GRISU_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
- {GRISU_UINT64_C(0xe2280b6c, 20dd5232), -303, -72},
- {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
- {GRISU_UINT64_C(0xa87fea27, a539e9a5), -276, -64},
- {GRISU_UINT64_C(0xcdb02555, 653131b6), -263, -60},
- {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
- {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
- {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
- {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
- {GRISU_UINT64_C(0x8b61313b, babce2c6), -196, -40},
- {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
- {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
- {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
- {GRISU_UINT64_C(0x9abe14cd, 44753b53), -143, -24},
- {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
- {GRISU_UINT64_C(0xe69594be, c44de15b), -117, -16},
- {GRISU_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
- {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
- {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
- {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
- {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
- {GRISU_UINT64_C(0xbebc2000, 00000000), -37, 8},
- {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
- {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
- {GRISU_UINT64_C(0xad78ebc5, ac620000), 3, 20},
- {GRISU_UINT64_C(0xd3c21bce, cceda100), 16, 24},
- {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
- {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
- {GRISU_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
- {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
- {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
- {GRISU_UINT64_C(0xaf298d05, 0e4395d7), 96, 48},
- {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
- {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
- {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
- {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
- {GRISU_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
- {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
- {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
- {GRISU_UINT64_C(0xd7e77a8f, 87daf7fc), 202, 80},
- {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
- {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
- {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
- {GRISU_UINT64_C(0xefb3ab16, c59b14a3), 255, 96},
- {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
- {GRISU_UINT64_C(0xb2977ee3, 00c50fe7), 282, 104},
- {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
- {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
- {GRISU_UINT64_C(0xa26da399, 9aef774a), 322, 116},
- {GRISU_UINT64_C(0xc646d635, 01a1511e), 335, 120},
- {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
- {GRISU_UINT64_C(0x93ba47c9, 80e98ce0), 362, 128},
- {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
- {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
- {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
- {GRISU_UINT64_C(0xa402b9c5, a8d3a6e7), 415, 144},
- {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
- {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
- {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
- {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
- {GRISU_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
- {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
- {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
- {GRISU_UINT64_C(0xca28a291, 859bbf93), 521, 176},
- {GRISU_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
- {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
- {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
- {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
- {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
- {GRISU_UINT64_C(0xa738c6be, bb12d16d), 601, 200},
- {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
- {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
- {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
- {GRISU_UINT64_C(0xb9a74a06, 37ce2ee1), 654, 216},
- {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
- {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
- {GRISU_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
- {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
- {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
- {GRISU_UINT64_C(0x9991a6f3, d6bf1766), 734, 240},
- {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
- {GRISU_UINT64_C(0xe4d5e823, 92a40515), 760, 248},
- {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
- {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
- {GRISU_UINT64_C(0xd01fef10, a657842c), 800, 260},
- {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
- {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
- {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
- {GRISU_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
- {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
- {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
- {GRISU_UINT64_C(0xd226fc19, 5c6a2f8c), 893, 288},
- {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
- {GRISU_UINT64_C(0x9c935e00, d4b9d8d2), 920, 296},
- {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
- {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
- {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
- {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
- {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
- {GRISU_UINT64_C(0x81842f29, f2cce376), 1000, 320},
- {GRISU_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
- {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
- {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
- {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
- {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(4) = 14;
-// nb elements (4): 163
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(5)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0xaf8e5410, 288e1b6f), -1070, -303},
- {GRISU_UINT64_C(0x85f04682, 93f0eb4e), -1053, -298},
- {GRISU_UINT64_C(0xcc5fc196, fefd7d0c), -1037, -293},
- {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
- {GRISU_UINT64_C(0xedec366b, 11c6cb8f), -1004, -283},
- {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
- {GRISU_UINT64_C(0x8a7d3eef, 7f1cfc52), -970, -273},
- {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
- {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
- {GRISU_UINT64_C(0xf6019da0, 7f549b2b), -921, -258},
- {GRISU_UINT64_C(0xbbb01b92, 83253ca3), -904, -253},
- {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
- {GRISU_UINT64_C(0xda7f5bf5, 90966849), -871, -243},
- {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
- {GRISU_UINT64_C(0xfe5d5415, 0b090b03), -838, -233},
- {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
- {GRISU_UINT64_C(0x940f4613, ae5ed137), -804, -223},
- {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
- {GRISU_UINT64_C(0xac5d37d5, b79b6239), -771, -213},
- {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
- {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
- {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
- {GRISU_UINT64_C(0xe998d258, 869facd7), -705, -193},
- {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
- {GRISU_UINT64_C(0x87f8a8d4, cfa417ca), -671, -183},
- {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
- {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
- {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
- {GRISU_UINT64_C(0xb84687c2, 69ef3bfb), -605, -163},
- {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
- {GRISU_UINT64_C(0xd686619b, a27255a3), -572, -153},
- {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
- {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
- {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
- {GRISU_UINT64_C(0x915e2486, ef32cd60), -505, -133},
- {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
- {GRISU_UINT64_C(0xa93af6c6, c79b5d2e), -472, -123},
- {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
- {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
- {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
- {GRISU_UINT64_C(0xe5599087, 9ddcaabe), -406, -103},
- {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
- {GRISU_UINT64_C(0x857fcae6, 2d8493a5), -372, -93},
- {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
- {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
- {GRISU_UINT64_C(0xed246723, 473e3813), -323, -78},
- {GRISU_UINT64_C(0xb4ecd5f0, 1a4aa828), -306, -73},
- {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
- {GRISU_UINT64_C(0xd29fe4b1, 8e88640f), -273, -63},
- {GRISU_UINT64_C(0xa0b19d2a, b70e6ed6), -256, -58},
- {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
- {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
- {GRISU_UINT64_C(0x8eb98a7a, 9a5b04e3), -206, -43},
- {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
- {GRISU_UINT64_C(0xa6274bbd, d0fadd62), -173, -33},
- {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
- {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
- {GRISU_UINT64_C(0x9392ee8e, 921d5d07), -123, -18},
- {GRISU_UINT64_C(0xe12e1342, 4bb40e13), -107, -13},
- {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
- {GRISU_UINT64_C(0x83126e97, 8d4fdf3b), -73, -3},
- {GRISU_UINT64_C(0xc8000000, 00000000), -57, 2},
- {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
- {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
- {GRISU_UINT64_C(0xb1a2bc2e, c5000000), -7, 17},
- {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
- {GRISU_UINT64_C(0xcecb8f27, f4200f3a), 26, 27},
- {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
- {GRISU_UINT64_C(0xf0bdc21a, bb48db20), 59, 37},
- {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
- {GRISU_UINT64_C(0x8c213d9d, a502de45), 93, 47},
- {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
- {GRISU_UINT64_C(0xa321f2d7, 226895c8), 126, 57},
- {GRISU_UINT64_C(0xf8ebad2b, 84e0d58c), 142, 62},
- {GRISU_UINT64_C(0xbde94e8e, 43d0c8ec), 159, 67},
- {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
- {GRISU_UINT64_C(0xdd15fe86, affad912), 192, 77},
- {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
- {GRISU_UINT64_C(0x80b05e5a, c60b6178), 226, 87},
- {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
- {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
- {GRISU_UINT64_C(0xe498f455, c38b997a), 275, 102},
- {GRISU_UINT64_C(0xae67f1e9, aec07188), 292, 107},
- {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
- {GRISU_UINT64_C(0xcb090c80, 01ab551c), 325, 117},
- {GRISU_UINT64_C(0x9ae75759, 6946075f), 342, 122},
- {GRISU_UINT64_C(0xec5d3fa8, ce427b00), 358, 127},
- {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
- {GRISU_UINT64_C(0x899504ae, 72497eba), 392, 137},
- {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
- {GRISU_UINT64_C(0xa02aa96b, 06deb0fe), 425, 147},
- {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
- {GRISU_UINT64_C(0xba756174, 393d88e0), 458, 157},
- {GRISU_UINT64_C(0x8e41ade9, fbebc27d), 475, 162},
- {GRISU_UINT64_C(0xd910f7ff, 28069da4), 491, 167},
- {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
- {GRISU_UINT64_C(0xfcb2cb35, e702af78), 524, 177},
- {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
- {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
- {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
- {GRISU_UINT64_C(0xab3c2fdd, eeaad25b), 591, 197},
- {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
- {GRISU_UINT64_C(0xc75809c4, 2c684dd1), 624, 207},
- {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
- {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
- {GRISU_UINT64_C(0xb10d8e14, 56105dad), 674, 222},
- {GRISU_UINT64_C(0x8714a775, e3e95c78), 691, 227},
- {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
- {GRISU_UINT64_C(0x9d412e08, 06e88aa6), 724, 237},
- {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
- {GRISU_UINT64_C(0xb7118682, dbb66a77), 757, 247},
- {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
- {GRISU_UINT64_C(0xd51ea6fa, 85785631), 790, 257},
- {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
- {GRISU_UINT64_C(0xf81aa16f, dc1b81db), 823, 267},
- {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
- {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
- {GRISU_UINT64_C(0xdc5c5301, c56b75f7), 873, 282},
- {GRISU_UINT64_C(0xa81f3014, 49ee8c70), 890, 287},
- {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
- {GRISU_UINT64_C(0xc3b83581, 09e84f07), 923, 297},
- {GRISU_UINT64_C(0x95527a52, 02df0ccb), 940, 302},
- {GRISU_UINT64_C(0xe3d8f9e5, 63a198e5), 956, 307},
- {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
- {GRISU_UINT64_C(0x849feec2, 81d7f329), 990, 317},
- {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
- {GRISU_UINT64_C(0x9a65406d, 44a5c903), 1023, 327},
- {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
- {GRISU_UINT64_C(0xb3bd72ed, 2af29e20), 1056, 337},
- {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(5) = 17;
-// nb elements (5): 131
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(6)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0xdb71e914, 32b1a24b), -1067, -302},
- {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
- {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
- {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
- {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
- {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
- {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
- {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
- {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
- {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
- {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
- {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
- {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
- {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
- {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
- {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
- {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
- {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
- {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
- {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
- {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
- {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
- {GRISU_UINT64_C(0x9a94dd3e, 8cf578ba), -628, -170},
- {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
- {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
- {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
- {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
- {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
- {GRISU_UINT64_C(0xe896a0d7, e51e1566), -509, -134},
- {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
- {GRISU_UINT64_C(0xd389b478, 79823479), -469, -122},
- {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
- {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
- {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
- {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
- {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
- {GRISU_UINT64_C(0x9f24b832, e6b0f436), -349, -86},
- {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
- {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
- {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
- {GRISU_UINT64_C(0x83a3eeee, f9153e89), -269, -62},
- {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
- {GRISU_UINT64_C(0xef73d256, a5c0f77d), -230, -50},
- {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
- {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
- {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
- {GRISU_UINT64_C(0xc6120625, 76589ddb), -150, -26},
- {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
- {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
- {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
- {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
- {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
- {GRISU_UINT64_C(0x9502f900, 00000000), -30, 10},
- {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
- {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
- {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
- {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
- {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
- {GRISU_UINT64_C(0xe0352f62, a19e306f), 89, 46},
- {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
- {GRISU_UINT64_C(0xcbea6f8c, eb02bb3a), 129, 58},
- {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
- {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
- {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
- {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
- {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
- {GRISU_UINT64_C(0x9968bf6a, bbe85f20), 249, 94},
- {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
- {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
- {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
- {GRISU_UINT64_C(0xfdcb4fa0, 02162a63), 328, 118},
- {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
- {GRISU_UINT64_C(0xe6d3102a, d96cec1e), 368, 130},
- {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
- {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
- {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
- {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
- {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
- {GRISU_UINT64_C(0xada72ccc, 20054aea), 488, 166},
- {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
- {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
- {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
- {GRISU_UINT64_C(0x8fa47579, 1a569d11), 568, 190},
- {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
- {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
- {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
- {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
- {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
- {GRISU_UINT64_C(0xd8210bef, d30efa5a), 687, 226},
- {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
- {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
- {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
- {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
- {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
- {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
- {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
- {GRISU_UINT64_C(0x93e1ab82, 52f33b46), 847, 274},
- {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
- {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
- {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
- {GRISU_UINT64_C(0xf4a642e1, 4c6262c9), 926, 298},
- {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
- {GRISU_UINT64_C(0xde81e40a, 034bcf50), 966, 310},
- {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
- {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
- {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
- {GRISU_UINT64_C(0xb80dc58e, 81fe95a1), 1046, 334},
- {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(6) = 20;
-// nb elements (6): 109
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(7)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0x892731ac, 9faf056f), -1063, -301},
- {GRISU_UINT64_C(0xa37fce12, 6597973d), -1040, -294},
- {GRISU_UINT64_C(0xc2e801fb, 244576d5), -1017, -287},
- {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
- {GRISU_UINT64_C(0x8a7d3eef, 7f1cfc52), -970, -273},
- {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
- {GRISU_UINT64_C(0xc4ce17b3, 99107c23), -924, -259},
- {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
- {GRISU_UINT64_C(0x8bd6a141, 006042be), -877, -245},
- {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
- {GRISU_UINT64_C(0xc6b8e9b0, 709f109a), -831, -231},
- {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
- {GRISU_UINT64_C(0x8d3360f0, 9cf6e4bd), -784, -217},
- {GRISU_UINT64_C(0xa8530886, b54dbdec), -761, -210},
- {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
- {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
- {GRISU_UINT64_C(0x8e938662, 882af53e), -691, -189},
- {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
- {GRISU_UINT64_C(0xca9cf1d2, 06fdc03c), -645, -175},
- {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
- {GRISU_UINT64_C(0x8ff71a0f, e2c2e6dc), -598, -161},
- {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
- {GRISU_UINT64_C(0xcc963fee, 10b7d1b3), -552, -147},
- {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
- {GRISU_UINT64_C(0x915e2486, ef32cd60), -505, -133},
- {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
- {GRISU_UINT64_C(0xce947a3d, a6a9273e), -459, -119},
- {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
- {GRISU_UINT64_C(0x92c8ae6b, 464fc96f), -412, -105},
- {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
- {GRISU_UINT64_C(0xd097ad07, a71f26b2), -366, -91},
- {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
- {GRISU_UINT64_C(0x9436c076, 0c86e30c), -319, -77},
- {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
- {GRISU_UINT64_C(0xd29fe4b1, 8e88640f), -273, -63},
- {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
- {GRISU_UINT64_C(0x95a86376, 27989aae), -226, -49},
- {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
- {GRISU_UINT64_C(0xd4ad2dbf, c3d07788), -180, -35},
- {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
- {GRISU_UINT64_C(0x971da050, 74da7bef), -133, -21},
- {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
- {GRISU_UINT64_C(0xd6bf94d5, e57a42bc), -87, -7},
- {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
- {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
- {GRISU_UINT64_C(0xb5e620f4, 80000000), -17, 14},
- {GRISU_UINT64_C(0xd8d726b7, 177a8000), 6, 21},
- {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
- {GRISU_UINT64_C(0x9a130b96, 3a6c115c), 53, 35},
- {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
- {GRISU_UINT64_C(0xdaf3f046, 51d47b4c), 99, 49},
- {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
- {GRISU_UINT64_C(0x9b934c3b, 330c8577), 146, 63},
- {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
- {GRISU_UINT64_C(0xdd15fe86, affad912), 192, 77},
- {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
- {GRISU_UINT64_C(0x9d174b2d, cec0e47b), 239, 91},
- {GRISU_UINT64_C(0xbb445da9, ca61281f), 262, 98},
- {GRISU_UINT64_C(0xdf3d5e9b, c0f653e1), 285, 105},
- {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
- {GRISU_UINT64_C(0x9e9f11c4, 014dda7e), 332, 119},
- {GRISU_UINT64_C(0xbd176620, a501fc00), 355, 126},
- {GRISU_UINT64_C(0xe16a1dc9, d8545e95), 378, 133},
- {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
- {GRISU_UINT64_C(0xa02aa96b, 06deb0fe), 425, 147},
- {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
- {GRISU_UINT64_C(0xe39c4976, 5fdf9d95), 471, 161},
- {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
- {GRISU_UINT64_C(0xa1ba1ba7, 9e1632dc), 518, 175},
- {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
- {GRISU_UINT64_C(0xe5d3ef28, 2a242e82), 564, 189},
- {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
- {GRISU_UINT64_C(0xa34d7216, 42b06084), 611, 203},
- {GRISU_UINT64_C(0xc2abf989, 935ddbfe), 634, 210},
- {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
- {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
- {GRISU_UINT64_C(0xa4e4b66b, 68b65d61), 704, 231},
- {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
- {GRISU_UINT64_C(0xea53df5f, d18d5514), 750, 245},
- {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
- {GRISU_UINT64_C(0xa67ff273, b8460357), 797, 259},
- {GRISU_UINT64_C(0xc67bb459, 7ce2ce49), 820, 266},
- {GRISU_UINT64_C(0xec9c459d, 51852ba3), 843, 273},
- {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
- {GRISU_UINT64_C(0xa81f3014, 49ee8c70), 890, 287},
- {GRISU_UINT64_C(0xc86ab5c3, 9fa63441), 913, 294},
- {GRISU_UINT64_C(0xeeea5d50, 04981478), 936, 301},
- {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
- {GRISU_UINT64_C(0xa9c2794a, e3a3c69b), 983, 315},
- {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
- {GRISU_UINT64_C(0xf13e34aa, bb430a15), 1029, 329},
- {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(7) = 24;
-// nb elements (7): 93
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(8)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
- {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
- {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
- {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
- {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
- {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
- {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
- {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
- {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
- {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
- {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
- {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
- {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
- {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
- {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
- {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
- {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
- {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
- {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
- {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
- {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
- {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
- {GRISU_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
- {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
- {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
- {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
- {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
- {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
- {GRISU_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
- {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
- {GRISU_UINT64_C(0xcdb02555, 653131b6), -263, -60},
- {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
- {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
- {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
- {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
- {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
- {GRISU_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
- {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
- {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
- {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
- {GRISU_UINT64_C(0xad78ebc5, ac620000), 3, 20},
- {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
- {GRISU_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
- {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
- {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
- {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
- {GRISU_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
- {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
- {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
- {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
- {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
- {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
- {GRISU_UINT64_C(0xa26da399, 9aef774a), 322, 116},
- {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
- {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
- {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
- {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
- {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
- {GRISU_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
- {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
- {GRISU_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
- {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
- {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
- {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
- {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
- {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
- {GRISU_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
- {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
- {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
- {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
- {GRISU_UINT64_C(0xd01fef10, a657842c), 800, 260},
- {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
- {GRISU_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
- {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
- {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
- {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
- {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
- {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
- {GRISU_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
- {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
- {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(8) = 27;
-// nb elements (8): 82
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(9)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0xd64d3d9d, b981787d), -1057, -299},
- {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
- {GRISU_UINT64_C(0xb9e08a83, a5e34f08), -997, -281},
- {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
- {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
- {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
- {GRISU_UINT64_C(0x8bd6a141, 006042be), -877, -245},
- {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
- {GRISU_UINT64_C(0xf294b943, e17a2bc4), -818, -227},
- {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
- {GRISU_UINT64_C(0xd267caa8, 62a12d67), -758, -209},
- {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
- {GRISU_UINT64_C(0xb67f6455, 292cbf08), -698, -191},
- {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
- {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
- {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
- {GRISU_UINT64_C(0x894bc396, ce5da772), -578, -155},
- {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
- {GRISU_UINT64_C(0xee2ba6c0, 678b597f), -519, -137},
- {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
- {GRISU_UINT64_C(0xce947a3d, a6a9273e), -459, -119},
- {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
- {GRISU_UINT64_C(0xb32df8e9, f3546564), -399, -101},
- {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
- {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
- {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
- {GRISU_UINT64_C(0x86ccbb52, ea94baeb), -279, -65},
- {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
- {GRISU_UINT64_C(0xe9d71b68, 9dde71b0), -220, -47},
- {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
- {GRISU_UINT64_C(0xcad2f7f5, 359a3b3e), -160, -29},
- {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
- {GRISU_UINT64_C(0xafebff0b, cb24aaff), -100, -11},
- {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
- {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
- {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
- {GRISU_UINT64_C(0x84595161, 401484a0), 20, 25},
- {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
- {GRISU_UINT64_C(0xe596b7b0, c643c719), 79, 43},
- {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
- {GRISU_UINT64_C(0xc722f0ef, 9d80aad6), 139, 61},
- {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
- {GRISU_UINT64_C(0xacb92ed9, 397bf996), 199, 79},
- {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
- {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
- {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
- {GRISU_UINT64_C(0x81f14fae, 158c5f6e), 319, 115},
- {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
- {GRISU_UINT64_C(0xe16a1dc9, d8545e95), 378, 133},
- {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
- {GRISU_UINT64_C(0xc38413cf, 25e2d70e), 438, 151},
- {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
- {GRISU_UINT64_C(0xa99541bf, 57452b28), 498, 169},
- {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
- {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
- {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
- {GRISU_UINT64_C(0xff290242, c83396ce), 617, 205},
- {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
- {GRISU_UINT64_C(0xdd50f199, 6b947519), 677, 223},
- {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
- {GRISU_UINT64_C(0xbff610b0, cc6edd3f), 737, 241},
- {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
- {GRISU_UINT64_C(0xa67ff273, b8460357), 797, 259},
- {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
- {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
- {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
- {GRISU_UINT64_C(0xfa856334, 878fc151), 916, 295},
- {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
- {GRISU_UINT64_C(0xd94ad8b1, c7380874), 976, 313},
- {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
- {GRISU_UINT64_C(0xbc789925, 624c5fe1), 1036, 331},
- {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(9) = 30;
-// nb elements (9): 73
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(10)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0x85f04682, 93f0eb4e), -1053, -298},
- {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
- {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
- {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
- {GRISU_UINT64_C(0xf6019da0, 7f549b2b), -921, -258},
- {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
- {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
- {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
- {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
- {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
- {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
- {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
- {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
- {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
- {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
- {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
- {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
- {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
- {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
- {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
- {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
- {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
- {GRISU_UINT64_C(0xed246723, 473e3813), -323, -78},
- {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
- {GRISU_UINT64_C(0xa0b19d2a, b70e6ed6), -256, -58},
- {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
- {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
- {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
- {GRISU_UINT64_C(0x9392ee8e, 921d5d07), -123, -18},
- {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
- {GRISU_UINT64_C(0xc8000000, 00000000), -57, 2},
- {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
- {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
- {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
- {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
- {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
- {GRISU_UINT64_C(0xf8ebad2b, 84e0d58c), 142, 62},
- {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
- {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
- {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
- {GRISU_UINT64_C(0xe498f455, c38b997a), 275, 102},
- {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
- {GRISU_UINT64_C(0x9ae75759, 6946075f), 342, 122},
- {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
- {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
- {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
- {GRISU_UINT64_C(0x8e41ade9, fbebc27d), 475, 162},
- {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
- {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
- {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
- {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
- {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
- {GRISU_UINT64_C(0xb10d8e14, 56105dad), 674, 222},
- {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
- {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
- {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
- {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
- {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
- {GRISU_UINT64_C(0xdc5c5301, c56b75f7), 873, 282},
- {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
- {GRISU_UINT64_C(0x95527a52, 02df0ccb), 940, 302},
- {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
- {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
- {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
- {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(10) = 34;
-// nb elements (10): 66
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(11)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0xa76c5823, 38ed2622), -1050, -297},
- {GRISU_UINT64_C(0xf3a20279, ed56d48a), -1014, -286},
- {GRISU_UINT64_C(0xb1442798, f49ffb4b), -977, -275},
- {GRISU_UINT64_C(0x80fa687f, 881c7f8e), -940, -264},
- {GRISU_UINT64_C(0xbbb01b92, 83253ca3), -904, -253},
- {GRISU_UINT64_C(0x888f9979, 7a5e012d), -867, -242},
- {GRISU_UINT64_C(0xc6b8e9b0, 709f109a), -831, -231},
- {GRISU_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
- {GRISU_UINT64_C(0xd267caa8, 62a12d67), -758, -209},
- {GRISU_UINT64_C(0x99171105, 2d8bf3c5), -721, -198},
- {GRISU_UINT64_C(0xdec681f9, f4c31f31), -685, -187},
- {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
- {GRISU_UINT64_C(0xebdf6617, 91d60f56), -612, -165},
- {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
- {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
- {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
- {GRISU_UINT64_C(0x843610cb, 4bf160cc), -465, -121},
- {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
- {GRISU_UINT64_C(0x8bfbea76, c619ef36), -392, -99},
- {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
- {GRISU_UINT64_C(0x9436c076, 0c86e30c), -319, -77},
- {GRISU_UINT64_C(0xd7adf884, aa879177), -283, -66},
- {GRISU_UINT64_C(0x9ced737b, b6c4183d), -246, -55},
- {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
- {GRISU_UINT64_C(0xa6274bbd, d0fadd62), -173, -33},
- {GRISU_UINT64_C(0xf1c90080, baf72cb1), -137, -22},
- {GRISU_UINT64_C(0xafebff0b, cb24aaff), -100, -11},
- {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
- {GRISU_UINT64_C(0xba43b740, 00000000), -27, 11},
- {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
- {GRISU_UINT64_C(0xc5371912, 364ce305), 46, 33},
- {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
- {GRISU_UINT64_C(0xd0cf4b50, cfe20766), 119, 55},
- {GRISU_UINT64_C(0x97edd871, cfda3a57), 156, 66},
- {GRISU_UINT64_C(0xdd15fe86, affad912), 192, 77},
- {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
- {GRISU_UINT64_C(0xea157514, 3cf97227), 265, 99},
- {GRISU_UINT64_C(0xaa51823e, 34a7eedf), 302, 110},
- {GRISU_UINT64_C(0xf7d88bc2, 4209a565), 338, 121},
- {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
- {GRISU_UINT64_C(0x8335616a, ed761f1f), 412, 143},
- {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
- {GRISU_UINT64_C(0x8aec23d6, 80043bee), 485, 165},
- {GRISU_UINT64_C(0xca28a291, 859bbf93), 521, 176},
- {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
- {GRISU_UINT64_C(0xd60b3bd5, 6a5586f2), 594, 198},
- {GRISU_UINT64_C(0x9bbcc7a1, 42b17ccc), 631, 209},
- {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
- {GRISU_UINT64_C(0xa4e4b66b, 68b65d61), 704, 231},
- {GRISU_UINT64_C(0xeff394dc, ff8a948f), 740, 242},
- {GRISU_UINT64_C(0xae9672ab, a3d0c321), 777, 253},
- {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
- {GRISU_UINT64_C(0xb8da1662, e7b00a17), 850, 275},
- {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
- {GRISU_UINT64_C(0xc3b83581, 09e84f07), 923, 297},
- {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
- {GRISU_UINT64_C(0xcf39e50f, eae16bf0), 996, 319},
- {GRISU_UINT64_C(0x96c6e0ea, b509e64d), 1033, 330},
- {GRISU_UINT64_C(0xdb68c2ca, 82ed2a06), 1069, 341},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(11) = 37;
-// nb elements (11): 60
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(12)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0xd1476e2c, 07286faa), -1047, -296},
- {GRISU_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
- {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
- {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
- {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
- {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
- {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
- {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
- {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
- {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
- {GRISU_UINT64_C(0xa21727db, 38cb0030), -648, -176},
- {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
- {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
- {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
- {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
- {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
- {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
- {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
- {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
- {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
- {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
- {GRISU_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
- {GRISU_UINT64_C(0xcfb11ead, 453994ba), -170, -32},
- {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
- {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
- {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
- {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
- {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
- {GRISU_UINT64_C(0xeb194f8e, 1ae525fd), 69, 40},
- {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
- {GRISU_UINT64_C(0xc2781f49, ffcfa6d5), 149, 64},
- {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
- {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
- {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
- {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
- {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
- {GRISU_UINT64_C(0xdc21a117, 1d42645d), 388, 136},
- {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
- {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
- {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
- {GRISU_UINT64_C(0x969eb7c4, 7859e744), 548, 184},
- {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
- {GRISU_UINT64_C(0xf92e0c35, 37826146), 627, 208},
- {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
- {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
- {GRISU_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
- {GRISU_UINT64_C(0xaa7eebfb, 9df9de8e), 787, 256},
- {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
- {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
- {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
- {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
- {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
- {GRISU_UINT64_C(0xc0fe9088, 95cf3b44), 1026, 328},
- {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(12) = 40;
-// nb elements (12): 55
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(13)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0x82cca4db, 847945ca), -1043, -295},
- {GRISU_UINT64_C(0x94b3a202, eb1c3f39), -1000, -282},
- {GRISU_UINT64_C(0xa90de353, 5aaae202), -957, -269},
- {GRISU_UINT64_C(0xc0314325, 637a193a), -914, -256},
- {GRISU_UINT64_C(0xda7f5bf5, 90966849), -871, -243},
- {GRISU_UINT64_C(0xf867241c, 8cc6d4c1), -828, -230},
- {GRISU_UINT64_C(0x8d3360f0, 9cf6e4bd), -784, -217},
- {GRISU_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
- {GRISU_UINT64_C(0xb67f6455, 292cbf08), -698, -191},
- {GRISU_UINT64_C(0xcf79cc9d, b955c2cc), -655, -178},
- {GRISU_UINT64_C(0xebdf6617, 91d60f56), -612, -165},
- {GRISU_UINT64_C(0x8613fd01, 45877586), -568, -152},
- {GRISU_UINT64_C(0x986ddb5c, 6b3a76b8), -525, -139},
- {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
- {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
- {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
- {GRISU_UINT64_C(0xfea126b7, d78186bd), -353, -87},
- {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
- {GRISU_UINT64_C(0xa48ceaaa, b75a8e2b), -266, -61},
- {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
- {GRISU_UINT64_C(0xd4ad2dbf, c3d07788), -180, -35},
- {GRISU_UINT64_C(0xf1c90080, baf72cb1), -137, -22},
- {GRISU_UINT64_C(0x89705f41, 36b4a597), -93, -9},
- {GRISU_UINT64_C(0x9c400000, 00000000), -50, 4},
- {GRISU_UINT64_C(0xb1a2bc2e, c5000000), -7, 17},
- {GRISU_UINT64_C(0xc9f2c9cd, 04674edf), 36, 30},
- {GRISU_UINT64_C(0xe596b7b0, c643c719), 79, 43},
- {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
- {GRISU_UINT64_C(0x945e455f, 24fb1cf9), 166, 69},
- {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
- {GRISU_UINT64_C(0xbfc2ef45, 6ae276e9), 252, 95},
- {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
- {GRISU_UINT64_C(0xf7d88bc2, 4209a565), 338, 121},
- {GRISU_UINT64_C(0x8ce2529e, 2734bb1d), 382, 134},
- {GRISU_UINT64_C(0xa02aa96b, 06deb0fe), 425, 147},
- {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
- {GRISU_UINT64_C(0xcf02b2c2, 1207ef2f), 511, 173},
- {GRISU_UINT64_C(0xeb57ff22, fc0c795a), 554, 186},
- {GRISU_UINT64_C(0x85c70565, 62757457), 598, 199},
- {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
- {GRISU_UINT64_C(0xace73cbf, dc0bfb7b), 684, 225},
- {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
- {GRISU_UINT64_C(0xdf78e4b2, bd342cf7), 770, 251},
- {GRISU_UINT64_C(0xfe0efb53, d30dd4d8), 813, 264},
- {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
- {GRISU_UINT64_C(0xa42e74f3, d032f526), 900, 290},
- {GRISU_UINT64_C(0xbaa718e6, 8396cffe), 943, 303},
- {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
- {GRISU_UINT64_C(0xf13e34aa, bb430a15), 1029, 329},
- {GRISU_UINT64_C(0x892179be, 91d43a44), 1073, 342},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(13) = 44;
-// nb elements (13): 51
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(14)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0xa37fce12, 6597973d), -1040, -294},
- {GRISU_UINT64_C(0xe858ad24, 8f5c22ca), -994, -280},
- {GRISU_UINT64_C(0xa5178fff, 668ae0b6), -947, -266},
- {GRISU_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
- {GRISU_UINT64_C(0xa6b34ad8, c9dfc070), -854, -238},
- {GRISU_UINT64_C(0xece53cec, 4a314ebe), -808, -224},
- {GRISU_UINT64_C(0xa8530886, b54dbdec), -761, -210},
- {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
- {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
- {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
- {GRISU_UINT64_C(0xab9eb47c, 81f5114f), -575, -154},
- {GRISU_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
- {GRISU_UINT64_C(0xad4ab711, 2eb3929e), -482, -126},
- {GRISU_UINT64_C(0xf64335bc, f065d37d), -436, -112},
- {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
- {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
- {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
- {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
- {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
- {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
- {GRISU_UINT64_C(0xb424dc35, 095cd80f), -110, -14},
- {GRISU_UINT64_C(0x80000000, 00000000), -63, 0},
- {GRISU_UINT64_C(0xb5e620f4, 80000000), -17, 14},
- {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
- {GRISU_UINT64_C(0xb7abc627, 050305ae), 76, 42},
- {GRISU_UINT64_C(0x82818f12, 81ed44a0), 123, 56},
- {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
- {GRISU_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
- {GRISU_UINT64_C(0xbb445da9, ca61281f), 262, 98},
- {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
- {GRISU_UINT64_C(0xbd176620, a501fc00), 355, 126},
- {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
- {GRISU_UINT64_C(0xbeeefb58, 4aff8604), 448, 154},
- {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
- {GRISU_UINT64_C(0xc0cb28a9, 8fcf3c80), 541, 182},
- {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
- {GRISU_UINT64_C(0xc2abf989, 935ddbfe), 634, 210},
- {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
- {GRISU_UINT64_C(0xc491798a, 08a2ad4f), 727, 238},
- {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
- {GRISU_UINT64_C(0xc67bb459, 7ce2ce49), 820, 266},
- {GRISU_UINT64_C(0x8d07e334, 55637eb3), 867, 280},
- {GRISU_UINT64_C(0xc86ab5c3, 9fa63441), 913, 294},
- {GRISU_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
- {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
- {GRISU_UINT64_C(0x8fcac257, 558ee4e6), 1053, 336},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(14) = 47;
-// nb elements (14): 47
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(15)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0xcc5fc196, fefd7d0c), -1037, -293},
- {GRISU_UINT64_C(0xb5854744, 8ffffb2e), -987, -278},
- {GRISU_UINT64_C(0xa139029f, 6a239f72), -937, -263},
- {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
- {GRISU_UINT64_C(0xfe5d5415, 0b090b03), -838, -233},
- {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
- {GRISU_UINT64_C(0xc8a883c0, fdaf7df0), -738, -203},
- {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
- {GRISU_UINT64_C(0x9e4a9cec, 15763e2f), -638, -173},
- {GRISU_UINT64_C(0x8c974f73, 83725573), -588, -158},
- {GRISU_UINT64_C(0xf9bd690a, 1b68637b), -539, -143},
- {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
- {GRISU_UINT64_C(0xc5029163, f384a931), -439, -113},
- {GRISU_UINT64_C(0xaefae514, 77a06b04), -389, -98},
- {GRISU_UINT64_C(0x9b69dbe1, b548ce7d), -339, -83},
- {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
- {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
- {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
- {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
- {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
- {GRISU_UINT64_C(0x98968000, 00000000), -40, 7},
- {GRISU_UINT64_C(0x87867832, 6eac9000), 10, 22},
- {GRISU_UINT64_C(0xf0bdc21a, bb48db20), 59, 37},
- {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
- {GRISU_UINT64_C(0xbde94e8e, 43d0c8ec), 159, 67},
- {GRISU_UINT64_C(0xa8acd7c0, 222311bd), 209, 82},
- {GRISU_UINT64_C(0x95d04aee, 3b80ece6), 259, 97},
- {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
- {GRISU_UINT64_C(0xec5d3fa8, ce427b00), 358, 127},
- {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
- {GRISU_UINT64_C(0xba756174, 393d88e0), 458, 157},
- {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
- {GRISU_UINT64_C(0x9316ff75, dd87cbd8), 558, 187},
- {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
- {GRISU_UINT64_C(0xe8111c87, c5c1ba9a), 657, 217},
- {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
- {GRISU_UINT64_C(0xb7118682, dbb66a77), 757, 247},
- {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
- {GRISU_UINT64_C(0x906a617d, 450187e2), 857, 277},
- {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
- {GRISU_UINT64_C(0xe3d8f9e5, 63a198e5), 956, 307},
- {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
- {GRISU_UINT64_C(0xb3bd72ed, 2af29e20), 1056, 337},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(15) = 50;
-// nb elements (15): 44
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(16)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
- {GRISU_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
- {GRISU_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
- {GRISU_UINT64_C(0xaecc4991, 4078536d), -874, -244},
- {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
- {GRISU_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
- {GRISU_UINT64_C(0xef340a98, 172aace5), -715, -196},
- {GRISU_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
- {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
- {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
- {GRISU_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
- {GRISU_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
- {GRISU_UINT64_C(0xdff97724, 70297ebd), -396, -100},
- {GRISU_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
- {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
- {GRISU_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
- {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
- {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
- {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
- {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
- {GRISU_UINT64_C(0x813f3978, f8940984), 30, 28},
- {GRISU_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
- {GRISU_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
- {GRISU_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
- {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
- {GRISU_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
- {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
- {GRISU_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
- {GRISU_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
- {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
- {GRISU_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
- {GRISU_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
- {GRISU_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
- {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
- {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
- {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
- {GRISU_UINT64_C(0xac2820d9, 623bf429), 880, 284},
- {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
- {GRISU_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
- {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(16) = 54;
-// nb elements (16): 41
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(17)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0x9faacf3d, f73609b1), -1030, -291},
- {GRISU_UINT64_C(0xdd95317f, 31c7fa1d), -974, -274},
- {GRISU_UINT64_C(0x99c10284, 4f94e0fb), -917, -257},
- {GRISU_UINT64_C(0xd5605fcd, cf32e1d7), -861, -240},
- {GRISU_UINT64_C(0x940f4613, ae5ed137), -804, -223},
- {GRISU_UINT64_C(0xcd795be8, 70516656), -748, -206},
- {GRISU_UINT64_C(0x8e938662, 882af53e), -691, -189},
- {GRISU_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
- {GRISU_UINT64_C(0x894bc396, ce5da772), -578, -155},
- {GRISU_UINT64_C(0xbe895233, 86091466), -522, -138},
- {GRISU_UINT64_C(0x843610cb, 4bf160cc), -465, -121},
- {GRISU_UINT64_C(0xb77ada06, 17e3bbcb), -409, -104},
- {GRISU_UINT64_C(0xfea126b7, d78186bd), -353, -87},
- {GRISU_UINT64_C(0xb0af48ec, 79ace837), -296, -70},
- {GRISU_UINT64_C(0xf5330471, 4d9265e0), -240, -53},
- {GRISU_UINT64_C(0xaa242499, 697392d3), -183, -36},
- {GRISU_UINT64_C(0xec1e4a7d, b69561a5), -127, -19},
- {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
- {GRISU_UINT64_C(0xe35fa931, a0000000), -14, 15},
- {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
- {GRISU_UINT64_C(0xdaf3f046, 51d47b4c), 99, 49},
- {GRISU_UINT64_C(0x97edd871, cfda3a57), 156, 66},
- {GRISU_UINT64_C(0xd2d80db0, 2aabd62c), 212, 83},
- {GRISU_UINT64_C(0x924d692c, a61be758), 269, 100},
- {GRISU_UINT64_C(0xcb090c80, 01ab551c), 325, 117},
- {GRISU_UINT64_C(0x8ce2529e, 2734bb1d), 382, 134},
- {GRISU_UINT64_C(0xc38413cf, 25e2d70e), 438, 151},
- {GRISU_UINT64_C(0x87aa9aff, 79042287), 495, 168},
- {GRISU_UINT64_C(0xbc4665b5, 96706115), 551, 185},
- {GRISU_UINT64_C(0x82a45b45, 0226b39d), 608, 202},
- {GRISU_UINT64_C(0xb54d5e4a, 127f59c8), 664, 219},
- {GRISU_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
- {GRISU_UINT64_C(0xae9672ab, a3d0c321), 777, 253},
- {GRISU_UINT64_C(0xf24a01a7, 3cf2dcd0), 833, 270},
- {GRISU_UINT64_C(0xa81f3014, 49ee8c70), 890, 287},
- {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
- {GRISU_UINT64_C(0xa1e53af4, 6f801c53), 1003, 321},
- {GRISU_UINT64_C(0xe0accfa8, 75af45a8), 1059, 338},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(17) = 57;
-// nb elements (17): 39
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(18)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0xc795830d, 75038c1e), -1027, -290},
- {GRISU_UINT64_C(0xad1c8eab, 5ee43b67), -967, -272},
- {GRISU_UINT64_C(0x96267c75, 35b763b5), -907, -254},
- {GRISU_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
- {GRISU_UINT64_C(0xe1ebce4d, c7f16dfc), -788, -218},
- {GRISU_UINT64_C(0xc3f490aa, 77bd60fd), -728, -200},
- {GRISU_UINT64_C(0xa9f6d30a, 038d1dbc), -668, -182},
- {GRISU_UINT64_C(0x936b9fce, bb25c996), -608, -164},
- {GRISU_UINT64_C(0xffbbcfe9, 94e5c620), -549, -146},
- {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
- {GRISU_UINT64_C(0xc06481fb, 9bcf8d3a), -429, -110},
- {GRISU_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
- {GRISU_UINT64_C(0x90bd77f3, 483bb9ba), -309, -74},
- {GRISU_UINT64_C(0xfb158592, be068d2f), -250, -56},
- {GRISU_UINT64_C(0xd9c7dced, 53c72256), -190, -38},
- {GRISU_UINT64_C(0xbce50864, 92111aeb), -130, -20},
- {GRISU_UINT64_C(0xa3d70a3d, 70a3d70a), -70, -2},
- {GRISU_UINT64_C(0x8e1bc9bf, 04000000), -10, 16},
- {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
- {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
- {GRISU_UINT64_C(0xb975d6b6, ee39e437), 169, 70},
- {GRISU_UINT64_C(0xa0dc75f1, 778e39d6), 229, 88},
- {GRISU_UINT64_C(0x8b865b21, 5899f46d), 289, 106},
- {GRISU_UINT64_C(0xf209787b, b47d6b85), 348, 124},
- {GRISU_UINT64_C(0xd1ef0244, af2364ff), 408, 142},
- {GRISU_UINT64_C(0xb616a12b, 7fe617aa), 468, 160},
- {GRISU_UINT64_C(0x9defbf01, b061adab), 528, 178},
- {GRISU_UINT64_C(0x88fcf317, f22241e2), 588, 196},
- {GRISU_UINT64_C(0xeda2ee1c, 7064130c), 647, 214},
- {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
- {GRISU_UINT64_C(0xb2c71d5b, ca9023f8), 767, 250},
- {GRISU_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
- {GRISU_UINT64_C(0x867f59a9, d4bed6c0), 887, 286},
- {GRISU_UINT64_C(0xe950df20, 247c83fd), 946, 304},
- {GRISU_UINT64_C(0xca5e89b1, 8b602368), 1006, 322},
- {GRISU_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(18) = 60;
-// nb elements (18): 37
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(19)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0xf97ae3d0, d2446f25), -1024, -289},
- {GRISU_UINT64_C(0x873e4f75, e2224e68), -960, -270},
- {GRISU_UINT64_C(0x92a1958a, 7675175f), -897, -251},
- {GRISU_UINT64_C(0x9efa548d, 26e5a6e2), -834, -232},
- {GRISU_UINT64_C(0xac5d37d5, b79b6239), -771, -213},
- {GRISU_UINT64_C(0xbae0a846, d2195713), -708, -194},
- {GRISU_UINT64_C(0xca9cf1d2, 06fdc03c), -645, -175},
- {GRISU_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
- {GRISU_UINT64_C(0xee2ba6c0, 678b597f), -519, -137},
- {GRISU_UINT64_C(0x811ccc66, 8829b887), -455, -118},
- {GRISU_UINT64_C(0x8bfbea76, c619ef36), -392, -99},
- {GRISU_UINT64_C(0x97c560ba, 6b0919a6), -329, -80},
- {GRISU_UINT64_C(0xa48ceaaa, b75a8e2b), -266, -61},
- {GRISU_UINT64_C(0xb267ed19, 40f1c61c), -203, -42},
- {GRISU_UINT64_C(0xc16d9a00, 95928a27), -140, -23},
- {GRISU_UINT64_C(0xd1b71758, e219652c), -77, -4},
- {GRISU_UINT64_C(0xe35fa931, a0000000), -14, 15},
- {GRISU_UINT64_C(0xf684df56, c3e01bc7), 49, 34},
- {GRISU_UINT64_C(0x85a36366, eb71f041), 113, 53},
- {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
- {GRISU_UINT64_C(0x9d174b2d, cec0e47b), 239, 91},
- {GRISU_UINT64_C(0xaa51823e, 34a7eedf), 302, 110},
- {GRISU_UINT64_C(0xb8a8d9bb, e123f018), 365, 129},
- {GRISU_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
- {GRISU_UINT64_C(0xd910f7ff, 28069da4), 491, 167},
- {GRISU_UINT64_C(0xeb57ff22, fc0c795a), 554, 186},
- {GRISU_UINT64_C(0xff290242, c83396ce), 617, 205},
- {GRISU_UINT64_C(0x8a5296ff, e33cc930), 681, 224},
- {GRISU_UINT64_C(0x95f83d0a, 1fb69cd9), 744, 243},
- {GRISU_UINT64_C(0xa298f2c5, 01f45f43), 807, 262},
- {GRISU_UINT64_C(0xb049dc01, 6abc5e60), 870, 281},
- {GRISU_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
- {GRISU_UINT64_C(0xcf39e50f, eae16bf0), 996, 319},
- {GRISU_UINT64_C(0xe0accfa8, 75af45a8), 1059, 338},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(19) = 64;
-// nb elements (19): 35
-static const GRISU_CACHE_STRUCT GRISU_CACHE_NAME(20)[] = {
- {GRISU_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
- {GRISU_UINT64_C(0x9becce62, 836ac577), -1020, -288},
- {GRISU_UINT64_C(0xd3515c28, 31559a83), -954, -268},
- {GRISU_UINT64_C(0x8f31cc09, 37ae58d3), -887, -248},
- {GRISU_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
- {GRISU_UINT64_C(0x8380dea9, 3da4bc60), -754, -208},
- {GRISU_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
- {GRISU_UINT64_C(0xf18899b1, bc3f8ca2), -622, -168},
- {GRISU_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
- {GRISU_UINT64_C(0xddd0467c, 64bce4a1), -489, -128},
- {GRISU_UINT64_C(0x964e858c, 91ba2655), -422, -108},
- {GRISU_UINT64_C(0xcbb41ef9, 79346bca), -356, -88},
- {GRISU_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
- {GRISU_UINT64_C(0xbb127c53, b17ec159), -223, -48},
- {GRISU_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
- {GRISU_UINT64_C(0xabcc7711, 8461cefd), -90, -8},
- {GRISU_UINT64_C(0xe8d4a510, 00000000), -24, 12},
- {GRISU_UINT64_C(0x9dc5ada8, 2b70b59e), 43, 32},
- {GRISU_UINT64_C(0xd5d238a4, abe98068), 109, 52},
- {GRISU_UINT64_C(0x90e40fbe, ea1d3a4b), 176, 72},
- {GRISU_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
- {GRISU_UINT64_C(0x850fadc0, 9923329e), 309, 112},
- {GRISU_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
- {GRISU_UINT64_C(0xf46518c2, ef5b8cd1), 441, 152},
- {GRISU_UINT64_C(0xa59bc234, db398c25), 508, 172},
- {GRISU_UINT64_C(0xe070f78d, 3927556b), 574, 192},
- {GRISU_UINT64_C(0x98165af3, 7b2153df), 641, 212},
- {GRISU_UINT64_C(0xce1de406, 42e3f4b9), 707, 232},
- {GRISU_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
- {GRISU_UINT64_C(0xbd49d14a, a79dbc82), 840, 272},
- {GRISU_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
- {GRISU_UINT64_C(0xadd57a27, d29339f6), 973, 312},
- {GRISU_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
- };
-static const int GRISU_CACHE_MAX_DISTANCE(20) = 67;
-// nb elements (20): 33
-static const int GRISU_CACHE_OFFSET = 308;
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 525dea2f..977c67c8 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -94,12 +94,18 @@ StringsStorage::StringsStorage()
}
+static void DeleteIndexName(char** name_ptr) {
+ DeleteArray(*name_ptr);
+}
+
+
StringsStorage::~StringsStorage() {
for (HashMap::Entry* p = names_.Start();
p != NULL;
p = names_.Next(p)) {
DeleteArray(reinterpret_cast<const char*>(p->value));
}
+ index_names_.Iterate(DeleteIndexName);
}
@@ -120,6 +126,22 @@ const char* StringsStorage::GetName(String* name) {
}
+const char* StringsStorage::GetName(int index) {
+ ASSERT(index >= 0);
+ if (index_names_.length() <= index) {
+ index_names_.AddBlock(
+ NULL, index - index_names_.length() + 1);
+ }
+ if (index_names_[index] == NULL) {
+ const int kMaximumNameLength = 32;
+ char* name = NewArray<char>(kMaximumNameLength);
+ OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", index);
+ index_names_[index] = name;
+ }
+ return index_names_[index];
+}
+
+
const char* CodeEntry::kEmptyNamePrefix = "";
@@ -485,11 +507,6 @@ CpuProfilesCollection::CpuProfilesCollection()
}
-static void DeleteArgsCountName(char** name_ptr) {
- DeleteArray(*name_ptr);
-}
-
-
static void DeleteCodeEntry(CodeEntry** entry_ptr) {
delete *entry_ptr;
}
@@ -508,7 +525,6 @@ CpuProfilesCollection::~CpuProfilesCollection() {
current_profiles_.Iterate(DeleteCpuProfile);
profiles_by_token_.Iterate(DeleteProfilesList);
code_entries_.Iterate(DeleteCodeEntry);
- args_count_names_.Iterate(DeleteArgsCountName);
}
@@ -706,22 +722,6 @@ CodeEntry* CpuProfilesCollection::NewCodeEntry(int security_token_id) {
}
-const char* CpuProfilesCollection::GetName(int args_count) {
- ASSERT(args_count >= 0);
- if (args_count_names_.length() <= args_count) {
- args_count_names_.AddBlock(
- NULL, args_count - args_count_names_.length() + 1);
- }
- if (args_count_names_[args_count] == NULL) {
- const int kMaximumNameLength = 32;
- char* name = NewArray<char>(kMaximumNameLength);
- OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", args_count);
- args_count_names_[args_count] = name;
- }
- return args_count_names_[args_count];
-}
-
-
void CpuProfilesCollection::AddPathToCurrentProfiles(
const Vector<CodeEntry*>& path) {
// As starting / stopping profiles is rare relatively to this
@@ -952,7 +952,7 @@ void HeapEntry::PaintAllReachable() {
void HeapEntry::Print(int max_depth, int indent) {
- OS::Print("%6d %6d %6d [%ld] ",
+ OS::Print("%6d %6d %6d [%llu] ",
self_size(), ReachableSize(), RetainedSize(), id_);
if (type() != kString) {
OS::Print("%s %.40s\n", TypeAsString(), name_);
@@ -1001,6 +1001,8 @@ const char* HeapEntry::TypeAsString() {
case kString: return "/string/";
case kCode: return "/code/";
case kArray: return "/array/";
+ case kRegExp: return "/regexp/";
+ case kHeapNumber: return "/number/";
default: return "???";
}
}
@@ -1237,7 +1239,7 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
type_(type),
title_(title),
uid_(uid),
- root_entry_index_(-1),
+ root_entry_(NULL),
raw_entries_(NULL),
entries_sorted_(false) {
STATIC_ASSERT(
@@ -1276,19 +1278,24 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
int children_count,
int retainers_count) {
if (object == kInternalRootObject) {
- ASSERT(root_entry_index_ == -1);
- root_entry_index_ = entries_.length();
+ ASSERT(root_entry_ == NULL);
ASSERT(retainers_count == 0);
- return AddEntry(
+ root_entry_ = AddEntry(
HeapEntry::kInternal, "", 0, 0, children_count, retainers_count);
+ return root_entry_;
} else if (object->IsJSFunction()) {
JSFunction* func = JSFunction::cast(object);
SharedFunctionInfo* shared = func->shared();
- String* name = String::cast(shared->name())->length() > 0 ?
- String::cast(shared->name()) : shared->inferred_name();
return AddEntry(object,
HeapEntry::kClosure,
- collection_->GetFunctionName(name),
+ collection_->GetName(String::cast(shared->name())),
+ children_count,
+ retainers_count);
+ } else if (object->IsJSRegExp()) {
+ JSRegExp* re = JSRegExp::cast(object);
+ return AddEntry(object,
+ HeapEntry::kRegExp,
+ collection_->GetName(re->Pattern()),
children_count,
retainers_count);
} else if (object->IsJSObject()) {
@@ -1333,6 +1340,12 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
"",
children_count,
retainers_count);
+ } else if (object->IsHeapNumber()) {
+ return AddEntry(object,
+ HeapEntry::kHeapNumber,
+ "number",
+ children_count,
+ retainers_count);
}
// No interest in this object.
return NULL;
@@ -1342,12 +1355,14 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
bool HeapSnapshot::WillAddEntry(HeapObject* object) {
return object == kInternalRootObject
|| object->IsJSFunction()
+ || object->IsJSRegExp()
|| object->IsJSObject()
|| object->IsString()
|| object->IsCode()
|| object->IsSharedFunctionInfo()
|| object->IsScript()
- || object->IsFixedArray();
+ || object->IsFixedArray()
+ || object->IsHeapNumber();
}
@@ -1904,13 +1919,21 @@ void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) {
ExtractClosureReferences(js_obj, entry);
ExtractPropertyReferences(js_obj, entry);
ExtractElementReferences(js_obj, entry);
+ ExtractInternalReferences(js_obj, entry);
SetPropertyReference(
- obj, entry, Heap::prototype_symbol(), js_obj->map()->prototype());
+ obj, entry, Heap::Proto_symbol(), js_obj->GetPrototype());
+ if (obj->IsJSFunction()) {
+ JSFunction* js_fun = JSFunction::cast(obj);
+ if (js_fun->has_prototype()) {
+ SetPropertyReference(
+ obj, entry, Heap::prototype_symbol(), js_fun->prototype());
+ }
+ }
} else if (obj->IsString()) {
if (obj->IsConsString()) {
ConsString* cs = ConsString::cast(obj);
- SetElementReference(obj, entry, 0, cs->first());
- SetElementReference(obj, entry, 1, cs->second());
+ SetInternalReference(obj, entry, "1", cs->first());
+ SetInternalReference(obj, entry, "2", cs->second());
}
} else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) {
IndexedReferencesExtractor refs_extractor(this, obj, entry);
@@ -2005,6 +2028,16 @@ void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj,
}
+void HeapSnapshotGenerator::ExtractInternalReferences(JSObject* js_obj,
+ HeapEntry* entry) {
+ int length = js_obj->GetInternalFieldCount();
+ for (int i = 0; i < length; ++i) {
+ Object* o = js_obj->GetInternalField(i);
+ SetInternalReference(js_obj, entry, i, o);
+ }
+}
+
+
void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj,
HeapEntry* parent_entry,
String* reference_name,
@@ -2049,13 +2082,31 @@ void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
}
+void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
+ HeapEntry* parent_entry,
+ int index,
+ Object* child_obj) {
+ HeapEntry* child_entry = GetEntry(child_obj);
+ if (child_entry != NULL) {
+ filler_->SetNamedReference(HeapGraphEdge::kInternal,
+ parent_obj,
+ parent_entry,
+ collection_->GetName(index),
+ child_obj,
+ child_entry);
+ }
+}
+
+
void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj,
HeapEntry* parent_entry,
String* reference_name,
Object* child_obj) {
HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL) {
- filler_->SetNamedReference(HeapGraphEdge::kProperty,
+ HeapGraphEdge::Type type = reference_name->length() > 0 ?
+ HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
+ filler_->SetNamedReference(type,
parent_obj,
parent_entry,
collection_->GetName(reference_name),
@@ -2095,6 +2146,11 @@ HeapSnapshotsComparator::~HeapSnapshotsComparator() {
HeapSnapshotsDiff* HeapSnapshotsComparator::Compare(HeapSnapshot* snapshot1,
HeapSnapshot* snapshot2) {
+ snapshot1->ClearPaint();
+ snapshot1->root()->PaintAllReachable();
+ snapshot2->ClearPaint();
+ snapshot2->root()->PaintAllReachable();
+
List<HeapEntry*>* entries1 = snapshot1->GetSortedEntriesList();
List<HeapEntry*>* entries2 = snapshot2->GetSortedEntriesList();
int i = 0, j = 0;
@@ -2103,8 +2159,14 @@ HeapSnapshotsDiff* HeapSnapshotsComparator::Compare(HeapSnapshot* snapshot1,
uint64_t id1 = entries1->at(i)->id();
uint64_t id2 = entries2->at(j)->id();
if (id1 == id2) {
- i++;
- j++;
+ HeapEntry* entry1 = entries1->at(i++);
+ HeapEntry* entry2 = entries2->at(j++);
+ if (entry1->painted_reachable() != entry2->painted_reachable()) {
+ if (entry1->painted_reachable())
+ deleted_entries.Add(entry1);
+ else
+ added_entries.Add(entry2);
+ }
} else if (id1 < id2) {
HeapEntry* entry = entries1->at(i++);
deleted_entries.Add(entry);
@@ -2122,35 +2184,17 @@ HeapSnapshotsDiff* HeapSnapshotsComparator::Compare(HeapSnapshot* snapshot1,
added_entries.Add(entry);
}
- snapshot1->ClearPaint();
- snapshot1->root()->PaintAllReachable();
- snapshot2->ClearPaint();
- snapshot2->root()->PaintAllReachable();
- int reachable_deleted_entries = 0, reachable_added_entries = 0;
- for (int i = 0; i < deleted_entries.length(); ++i) {
- HeapEntry* entry = deleted_entries[i];
- if (entry->painted_reachable()) ++reachable_deleted_entries;
- }
- for (int i = 0; i < added_entries.length(); ++i) {
- HeapEntry* entry = added_entries[i];
- if (entry->painted_reachable()) ++reachable_added_entries;
- }
-
HeapSnapshotsDiff* diff = new HeapSnapshotsDiff(snapshot1, snapshot2);
diffs_.Add(diff);
- diff->CreateRoots(reachable_added_entries, reachable_deleted_entries);
+ diff->CreateRoots(added_entries.length(), deleted_entries.length());
- int del_child_index = 0, deleted_entry_index = 1;
for (int i = 0; i < deleted_entries.length(); ++i) {
HeapEntry* entry = deleted_entries[i];
- if (entry->painted_reachable())
- diff->AddDeletedEntry(del_child_index++, deleted_entry_index++, entry);
+ diff->AddDeletedEntry(i, i + 1, entry);
}
- int add_child_index = 0, added_entry_index = 1;
for (int i = 0; i < added_entries.length(); ++i) {
HeapEntry* entry = added_entries[i];
- if (entry->painted_reachable())
- diff->AddAddedEntry(add_child_index++, added_entry_index++, entry);
+ diff->AddAddedEntry(i, i + 1, entry);
}
return diff;
}
@@ -2358,7 +2402,9 @@ void HeapSnapshotJSONSerializer::SerializeNodes() {
"," JSON_S("string")
"," JSON_S("object")
"," JSON_S("code")
- "," JSON_S("closure"))
+ "," JSON_S("closure")
+ "," JSON_S("regexp")
+ "," JSON_S("number"))
"," JSON_S("string")
"," JSON_S("number")
"," JSON_S("number")
diff --git a/src/profile-generator.h b/src/profile-generator.h
index 1e949a2c..6f63f6a1 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -67,6 +67,7 @@ class StringsStorage {
~StringsStorage();
const char* GetName(String* name);
+ const char* GetName(int index);
inline const char* GetFunctionName(String* name);
inline const char* GetFunctionName(const char* name);
@@ -78,6 +79,8 @@ class StringsStorage {
// Mapping of strings by String::Hash to const char* strings.
HashMap names_;
+ // Mapping from ints to char* strings.
+ List<char*> index_names_;
DISALLOW_COPY_AND_ASSIGN(StringsStorage);
};
@@ -284,6 +287,9 @@ class CpuProfilesCollection {
const char* GetName(String* name) {
return function_and_resource_names_.GetName(name);
}
+ const char* GetName(int args_count) {
+ return function_and_resource_names_.GetName(args_count);
+ }
CpuProfile* GetProfile(int security_token_id, unsigned uid);
bool IsLastProfile(const char* title);
@@ -302,7 +308,6 @@ class CpuProfilesCollection {
static const int kMaxSimultaneousProfiles = 100;
private:
- const char* GetName(int args_count);
const char* GetFunctionName(String* name) {
return function_and_resource_names_.GetFunctionName(name);
}
@@ -317,8 +322,6 @@ class CpuProfilesCollection {
}
StringsStorage function_and_resource_names_;
- // Mapping from args_count (int) to char* strings.
- List<char*> args_count_names_;
List<CodeEntry*> code_entries_;
List<List<CpuProfile*>* > profiles_by_token_;
// Mapping from profiles' uids to indexes in the second nested list
@@ -502,7 +505,9 @@ class HeapEntry BASE_EMBEDDED {
kString = v8::HeapGraphNode::kString,
kObject = v8::HeapGraphNode::kObject,
kCode = v8::HeapGraphNode::kCode,
- kClosure = v8::HeapGraphNode::kClosure
+ kClosure = v8::HeapGraphNode::kClosure,
+ kRegExp = v8::HeapGraphNode::kRegExp,
+ kHeapNumber = v8::HeapGraphNode::kHeapNumber
};
HeapEntry() { }
@@ -662,7 +667,7 @@ class HeapSnapshot {
Type type() { return type_; }
const char* title() { return title_; }
unsigned uid() { return uid_; }
- HeapEntry* root() { return entries_[root_entry_index_]; }
+ HeapEntry* root() { return root_entry_; }
void AllocateEntries(
int entries_count, int children_count, int retainers_count);
@@ -704,7 +709,7 @@ class HeapSnapshot {
Type type_;
const char* title_;
unsigned uid_;
- int root_entry_index_;
+ HeapEntry* root_entry_;
char* raw_entries_;
List<HeapEntry*> entries_;
bool entries_sorted_;
@@ -824,6 +829,7 @@ class HeapSnapshotsCollection {
HeapSnapshot* GetSnapshot(unsigned uid);
const char* GetName(String* name) { return names_.GetName(name); }
+ const char* GetName(int index) { return names_.GetName(index); }
const char* GetFunctionName(String* name) {
return names_.GetFunctionName(name);
}
@@ -948,6 +954,7 @@ class HeapSnapshotGenerator {
void ExtractClosureReferences(JSObject* js_obj, HeapEntry* entry);
void ExtractPropertyReferences(JSObject* js_obj, HeapEntry* entry);
void ExtractElementReferences(JSObject* js_obj, HeapEntry* entry);
+ void ExtractInternalReferences(JSObject* js_obj, HeapEntry* entry);
void SetClosureReference(HeapObject* parent_obj,
HeapEntry* parent,
String* reference_name,
@@ -960,6 +967,10 @@ class HeapSnapshotGenerator {
HeapEntry* parent,
const char* reference_name,
Object* child);
+ void SetInternalReference(HeapObject* parent_obj,
+ HeapEntry* parent,
+ int index,
+ Object* child);
void SetPropertyReference(HeapObject* parent_obj,
HeapEntry* parent,
String* reference_name,
diff --git a/src/regexp-macro-assembler-irregexp.cc b/src/regexp-macro-assembler-irregexp.cc
index 90abe912..6fbb14ad 100644
--- a/src/regexp-macro-assembler-irregexp.cc
+++ b/src/regexp-macro-assembler-irregexp.cc
@@ -145,6 +145,12 @@ void RegExpMacroAssemblerIrregexp::ReadStackPointerFromRegister(
}
+void RegExpMacroAssemblerIrregexp::SetCurrentPositionFromEnd(int by) {
+ ASSERT(is_uint24(by));
+ Emit(BC_SET_CURRENT_POSITION_FROM_END, by);
+}
+
+
void RegExpMacroAssemblerIrregexp::SetRegister(int register_index, int to) {
ASSERT(register_index >= 0);
ASSERT(register_index <= kMaxRegister);
diff --git a/src/regexp-macro-assembler-irregexp.h b/src/regexp-macro-assembler-irregexp.h
index 3ddbc2fe..6c9c2eb0 100644
--- a/src/regexp-macro-assembler-irregexp.h
+++ b/src/regexp-macro-assembler-irregexp.h
@@ -65,6 +65,7 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
virtual void PushRegister(int register_index,
StackCheckFlag check_stack_limit);
virtual void AdvanceRegister(int reg, int by); // r[reg] += by.
+ virtual void SetCurrentPositionFromEnd(int by);
virtual void SetRegister(int register_index, int to);
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
virtual void ClearRegisters(int reg_from, int reg_to);
diff --git a/src/regexp-macro-assembler-tracer.cc b/src/regexp-macro-assembler-tracer.cc
index c08602eb..463c1a81 100644
--- a/src/regexp-macro-assembler-tracer.cc
+++ b/src/regexp-macro-assembler-tracer.cc
@@ -47,8 +47,15 @@ RegExpMacroAssemblerTracer::~RegExpMacroAssemblerTracer() {
}
+// This is used for printing out debugging information. It makes an integer
+// that is closely related to the address of an object.
+static int LabelToInt(Label* label) {
+ return static_cast<int>(reinterpret_cast<intptr_t>(label));
+}
+
+
void RegExpMacroAssemblerTracer::Bind(Label* label) {
- PrintF("label[%08x]: (Bind)\n", label, label);
+ PrintF("label[%08x]: (Bind)\n", LabelToInt(label));
assembler_->Bind(label);
}
@@ -60,7 +67,7 @@ void RegExpMacroAssemblerTracer::AdvanceCurrentPosition(int by) {
void RegExpMacroAssemblerTracer::CheckGreedyLoop(Label* label) {
- PrintF(" CheckGreedyLoop(label[%08x]);\n\n", label);
+ PrintF(" CheckGreedyLoop(label[%08x]);\n\n", LabelToInt(label));
assembler_->CheckGreedyLoop(label);
}
@@ -84,14 +91,13 @@ void RegExpMacroAssemblerTracer::Backtrack() {
void RegExpMacroAssemblerTracer::GoTo(Label* label) {
- PrintF(" GoTo(label[%08x]);\n\n", label);
+ PrintF(" GoTo(label[%08x]);\n\n", LabelToInt(label));
assembler_->GoTo(label);
}
void RegExpMacroAssemblerTracer::PushBacktrack(Label* label) {
- PrintF(" PushBacktrack(label[%08x]);\n",
- label);
+ PrintF(" PushBacktrack(label[%08x]);\n", LabelToInt(label));
assembler_->PushBacktrack(label);
}
@@ -130,6 +136,12 @@ void RegExpMacroAssemblerTracer::AdvanceRegister(int reg, int by) {
}
+void RegExpMacroAssemblerTracer::SetCurrentPositionFromEnd(int by) {
+ PrintF(" SetCurrentPositionFromEnd(by=%d);\n", by);
+ assembler_->SetCurrentPositionFromEnd(by);
+}
+
+
void RegExpMacroAssemblerTracer::SetRegister(int register_index, int to) {
PrintF(" SetRegister(register=%d, to=%d);\n", register_index, to);
assembler_->SetRegister(register_index, to);
@@ -176,7 +188,7 @@ void RegExpMacroAssemblerTracer::LoadCurrentCharacter(int cp_offset,
const char* check_msg = check_bounds ? "" : " (unchecked)";
PrintF(" LoadCurrentCharacter(cp_offset=%d, label[%08x]%s (%d chars));\n",
cp_offset,
- on_end_of_input,
+ LabelToInt(on_end_of_input),
check_msg,
characters);
assembler_->LoadCurrentCharacter(cp_offset,
@@ -187,39 +199,43 @@ void RegExpMacroAssemblerTracer::LoadCurrentCharacter(int cp_offset,
void RegExpMacroAssemblerTracer::CheckCharacterLT(uc16 limit, Label* on_less) {
- PrintF(" CheckCharacterLT(c='u%04x', label[%08x]);\n", limit, on_less);
+ PrintF(" CheckCharacterLT(c='u%04x', label[%08x]);\n",
+ limit, LabelToInt(on_less));
assembler_->CheckCharacterLT(limit, on_less);
}
void RegExpMacroAssemblerTracer::CheckCharacterGT(uc16 limit,
Label* on_greater) {
- PrintF(" CheckCharacterGT(c='u%04x', label[%08x]);\n", limit, on_greater);
+ PrintF(" CheckCharacterGT(c='u%04x', label[%08x]);\n",
+ limit, LabelToInt(on_greater));
assembler_->CheckCharacterGT(limit, on_greater);
}
void RegExpMacroAssemblerTracer::CheckCharacter(uint32_t c, Label* on_equal) {
- PrintF(" CheckCharacter(c='u%04x', label[%08x]);\n", c, on_equal);
+ PrintF(" CheckCharacter(c='u%04x', label[%08x]);\n",
+ c, LabelToInt(on_equal));
assembler_->CheckCharacter(c, on_equal);
}
void RegExpMacroAssemblerTracer::CheckAtStart(Label* on_at_start) {
- PrintF(" CheckAtStart(label[%08x]);\n", on_at_start);
+ PrintF(" CheckAtStart(label[%08x]);\n", LabelToInt(on_at_start));
assembler_->CheckAtStart(on_at_start);
}
void RegExpMacroAssemblerTracer::CheckNotAtStart(Label* on_not_at_start) {
- PrintF(" CheckNotAtStart(label[%08x]);\n", on_not_at_start);
+ PrintF(" CheckNotAtStart(label[%08x]);\n", LabelToInt(on_not_at_start));
assembler_->CheckNotAtStart(on_not_at_start);
}
void RegExpMacroAssemblerTracer::CheckNotCharacter(uint32_t c,
Label* on_not_equal) {
- PrintF(" CheckNotCharacter(c='u%04x', label[%08x]);\n", c, on_not_equal);
+ PrintF(" CheckNotCharacter(c='u%04x', label[%08x]);\n",
+ c, LabelToInt(on_not_equal));
assembler_->CheckNotCharacter(c, on_not_equal);
}
@@ -231,7 +247,7 @@ void RegExpMacroAssemblerTracer::CheckCharacterAfterAnd(
PrintF(" CheckCharacterAfterAnd(c='u%04x', mask=0x%04x, label[%08x]);\n",
c,
mask,
- on_equal);
+ LabelToInt(on_equal));
assembler_->CheckCharacterAfterAnd(c, mask, on_equal);
}
@@ -243,7 +259,7 @@ void RegExpMacroAssemblerTracer::CheckNotCharacterAfterAnd(
PrintF(" CheckNotCharacterAfterAnd(c='u%04x', mask=0x%04x, label[%08x]);\n",
c,
mask,
- on_not_equal);
+ LabelToInt(on_not_equal));
assembler_->CheckNotCharacterAfterAnd(c, mask, on_not_equal);
}
@@ -258,7 +274,7 @@ void RegExpMacroAssemblerTracer::CheckNotCharacterAfterMinusAnd(
c,
minus,
mask,
- on_not_equal);
+ LabelToInt(on_not_equal));
assembler_->CheckNotCharacterAfterMinusAnd(c, minus, mask, on_not_equal);
}
@@ -266,7 +282,7 @@ void RegExpMacroAssemblerTracer::CheckNotCharacterAfterMinusAnd(
void RegExpMacroAssemblerTracer::CheckNotBackReference(int start_reg,
Label* on_no_match) {
PrintF(" CheckNotBackReference(register=%d, label[%08x]);\n", start_reg,
- on_no_match);
+ LabelToInt(on_no_match));
assembler_->CheckNotBackReference(start_reg, on_no_match);
}
@@ -275,7 +291,7 @@ void RegExpMacroAssemblerTracer::CheckNotBackReferenceIgnoreCase(
int start_reg,
Label* on_no_match) {
PrintF(" CheckNotBackReferenceIgnoreCase(register=%d, label[%08x]);\n",
- start_reg, on_no_match);
+ start_reg, LabelToInt(on_no_match));
assembler_->CheckNotBackReferenceIgnoreCase(start_reg, on_no_match);
}
@@ -286,7 +302,7 @@ void RegExpMacroAssemblerTracer::CheckNotRegistersEqual(int reg1,
PrintF(" CheckNotRegistersEqual(reg1=%d, reg2=%d, label[%08x]);\n",
reg1,
reg2,
- on_not_equal);
+ LabelToInt(on_not_equal));
assembler_->CheckNotRegistersEqual(reg1, reg2, on_not_equal);
}
@@ -300,7 +316,8 @@ void RegExpMacroAssemblerTracer::CheckCharacters(Vector<const uc16> str,
for (int i = 0; i < str.length(); i++) {
PrintF("u%04x", str[i]);
}
- PrintF("\", cp_offset=%d, label[%08x])\n", cp_offset, on_failure);
+ PrintF("\", cp_offset=%d, label[%08x])\n",
+ cp_offset, LabelToInt(on_failure));
assembler_->CheckCharacters(str, cp_offset, on_failure, check_end_of_string);
}
@@ -312,7 +329,7 @@ bool RegExpMacroAssemblerTracer::CheckSpecialCharacterClass(
on_no_match);
PrintF(" CheckSpecialCharacterClass(type='%c', label[%08x]): %s;\n",
type,
- on_no_match,
+ LabelToInt(on_no_match),
supported ? "true" : "false");
return supported;
}
@@ -321,7 +338,7 @@ bool RegExpMacroAssemblerTracer::CheckSpecialCharacterClass(
void RegExpMacroAssemblerTracer::IfRegisterLT(int register_index,
int comparand, Label* if_lt) {
PrintF(" IfRegisterLT(register=%d, number=%d, label[%08x]);\n",
- register_index, comparand, if_lt);
+ register_index, comparand, LabelToInt(if_lt));
assembler_->IfRegisterLT(register_index, comparand, if_lt);
}
@@ -329,7 +346,7 @@ void RegExpMacroAssemblerTracer::IfRegisterLT(int register_index,
void RegExpMacroAssemblerTracer::IfRegisterEqPos(int register_index,
Label* if_eq) {
PrintF(" IfRegisterEqPos(register=%d, label[%08x]);\n",
- register_index, if_eq);
+ register_index, LabelToInt(if_eq));
assembler_->IfRegisterEqPos(register_index, if_eq);
}
@@ -337,7 +354,7 @@ void RegExpMacroAssemblerTracer::IfRegisterEqPos(int register_index,
void RegExpMacroAssemblerTracer::IfRegisterGE(int register_index,
int comparand, Label* if_ge) {
PrintF(" IfRegisterGE(register=%d, number=%d, label[%08x]);\n",
- register_index, comparand, if_ge);
+ register_index, comparand, LabelToInt(if_ge));
assembler_->IfRegisterGE(register_index, comparand, if_ge);
}
diff --git a/src/regexp-macro-assembler-tracer.h b/src/regexp-macro-assembler-tracer.h
index 9608f9e1..6a8f4d47 100644
--- a/src/regexp-macro-assembler-tracer.h
+++ b/src/regexp-macro-assembler-tracer.h
@@ -89,6 +89,7 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler {
StackCheckFlag check_stack_limit);
virtual void ReadCurrentPositionFromRegister(int reg);
virtual void ReadStackPointerFromRegister(int reg);
+ virtual void SetCurrentPositionFromEnd(int by);
virtual void SetRegister(int register_index, int to);
virtual void Succeed();
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
diff --git a/src/regexp-macro-assembler.h b/src/regexp-macro-assembler.h
index 652b690d..dc3bd824 100644
--- a/src/regexp-macro-assembler.h
+++ b/src/regexp-macro-assembler.h
@@ -155,6 +155,7 @@ class RegExpMacroAssembler {
StackCheckFlag check_stack_limit) = 0;
virtual void ReadCurrentPositionFromRegister(int reg) = 0;
virtual void ReadStackPointerFromRegister(int reg) = 0;
+ virtual void SetCurrentPositionFromEnd(int by) = 0;
virtual void SetRegister(int register_index, int to) = 0;
virtual void Succeed() = 0;
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset) = 0;
diff --git a/src/regexp.js b/src/regexp.js
index faa525d6..51f4b094 100644
--- a/src/regexp.js
+++ b/src/regexp.js
@@ -126,11 +126,11 @@ function RegExpCache() {
this.regExp = 0;
this.subject = 0;
this.replaceString = 0;
- this.lastIndex = 0; // Also used for splitLimit when type is "split"
this.answer = 0;
// answerSaved marks whether the contents of answer is valid for a cache
// hit in RegExpExec, StringMatch and StringSplit.
this.answerSaved = false;
+ this.splitLimit = 0; // Used only when type is "split".
}
@@ -181,22 +181,30 @@ function RegExpExec(string) {
var cache = regExpCache;
var saveAnswer = false;
+ var lastIndex = this.lastIndex;
+
+ // Since cache.subject is always a string, a matching input can not
+ // cause visible side-effects when converted to a string, so we can omit
+ // the conversion required by the specification.
+ // Likewise, the regexp.lastIndex and regexp.global properties are value
+ // properties that are not configurable, so reading them can also not cause
+ // any side effects (converting lastIndex to a number can, though).
if (%_ObjectEquals(cache.type, 'exec') &&
- %_ObjectEquals(cache.lastIndex, this.lastIndex) &&
+ %_ObjectEquals(0, lastIndex) &&
%_IsRegExpEquivalent(cache.regExp, this) &&
%_ObjectEquals(cache.subject, string)) {
if (cache.answerSaved) {
- // If this regexp is not global, cache.lastIndex is zero, so we only get
- // here if this.lastIndex is zero, and resulting this.lastIndex
- // must be zero too, so no change is necessary.
- if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
+ // The regexp.lastIndex value must be 0 for non-global RegExps, and for
+ // global RegExps we only cache negative results, which gives a lastIndex
+ // of zero as well.
+ this.lastIndex = 0;
return %_RegExpCloneResult(cache.answer);
} else {
saveAnswer = true;
}
}
- if (%_ArgumentsLength() == 0) {
+ if (%_ArgumentsLength() === 0) {
var regExpInput = LAST_INPUT(lastMatchInfo);
if (IS_UNDEFINED(regExpInput)) {
throw MakeError('no_input_to_regexp', [this]);
@@ -209,41 +217,48 @@ function RegExpExec(string) {
} else {
s = ToString(string);
}
- var lastIndex = this.lastIndex;
-
- var i = this.global ? TO_INTEGER(lastIndex) : 0;
+ var global = this.global;
- if (i < 0 || i > s.length) {
- this.lastIndex = 0;
- return null;
+ // Conversion is required by the ES5 specification (RegExp.prototype.exec
+ // algorithm, step 5) even if the value is discarded for non-global RegExps.
+ var i = TO_INTEGER(lastIndex);
+ if (global) {
+ if (i < 0 || i > s.length) {
+ this.lastIndex = 0;
+ return null;
+ }
+ } else {
+ i = 0;
}
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
// matchIndices is either null or the lastMatchInfo array.
var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
- if (matchIndices == null) {
- if (this.global) {
+ if (matchIndices === null) {
+ if (global) {
+ // Cache negative result only if initial lastIndex was zero.
this.lastIndex = 0;
- if (lastIndex != 0) return matchIndices;
+ if (lastIndex !== 0) return matchIndices;
}
- cache.lastIndex = lastIndex;
cache.regExp = this;
- cache.subject = s;
- cache.answer = matchIndices; // Null.
+ cache.subject = s; // Always a string.
+ cache.answer = null;
cache.answerSaved = true; // Safe since no cloning is needed.
cache.type = 'exec';
return matchIndices; // No match.
}
+
+ // Successful match.
lastMatchInfoOverride = null;
var result = BuildResultFromMatchInfo(matchIndices, s);
- if (this.global) {
+ if (global) {
+ // Don't cache positive results for global regexps.
this.lastIndex = lastMatchInfo[CAPTURE1];
} else {
cache.regExp = this;
cache.subject = s;
- cache.lastIndex = lastIndex;
if (saveAnswer) cache.answer = %_RegExpCloneResult(result);
cache.answerSaved = saveAnswer;
cache.type = 'exec';
@@ -273,32 +288,49 @@ function RegExpTest(string) {
}
string = regExpInput;
}
- var s;
- if (IS_STRING(string)) {
- s = string;
- } else {
- s = ToString(string);
- }
var lastIndex = this.lastIndex;
+
var cache = regExpCache;
if (%_ObjectEquals(cache.type, 'test') &&
%_IsRegExpEquivalent(cache.regExp, this) &&
%_ObjectEquals(cache.subject, string) &&
- %_ObjectEquals(cache.lastIndex, lastIndex)) {
- // If this regexp is not global, cache.lastIndex is zero, so we only get
- // here if this.lastIndex is zero, and resulting this.lastIndex
- // must be zero too, so no change is necessary.
- if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
+ %_ObjectEquals(0, lastIndex)) {
+ // The regexp.lastIndex value must be 0 for non-global RegExps, and for
+ // global RegExps we only cache negative results, which gives a resulting
+ // lastIndex of zero as well.
+ if (global) this.lastIndex = 0;
return cache.answer;
}
+ var s;
+ if (IS_STRING(string)) {
+ s = string;
+ } else {
+ s = ToString(string);
+ }
+ var length = s.length;
+
+ // Conversion is required by the ES5 specification (RegExp.prototype.exec
+ // algorithm, step 5) even if the value is discarded for non-global RegExps.
+ var i = TO_INTEGER(lastIndex);
+ if (global) {
+ if (i < 0 || i > length) {
+ this.lastIndex = 0;
+ return false;
+ }
+ } else {
+ i = 0;
+ }
+
+ var global = this.global;
+
// Remove irrelevant preceeding '.*' in a test regexp. The expression
// checks whether this.source starts with '.*' and that the third
// char is not a '?'
- if (%_StringCharCodeAt(this.source,0) == 46 && // '.'
- %_StringCharCodeAt(this.source,1) == 42 && // '*'
- %_StringCharCodeAt(this.source,2) != 63) { // '?'
+ if (%_StringCharCodeAt(this.source, 0) == 46 && // '.'
+ %_StringCharCodeAt(this.source, 1) == 42 && // '*'
+ %_StringCharCodeAt(this.source, 2) != 63) { // '?'
if (!%_ObjectEquals(regexp_key, this)) {
regexp_key = this;
regexp_val = new $RegExp(this.source.substring(2, this.source.length),
@@ -309,33 +341,28 @@ function RegExpTest(string) {
if (!regexp_val.test(s)) return false;
}
- var length = s.length;
- var i = this.global ? TO_INTEGER(lastIndex) : 0;
-
- cache.type = 'test';
- cache.regExp = this;
- cache.subject = s;
- cache.lastIndex = i;
-
- if (i < 0 || i > length) {
- this.lastIndex = 0;
- cache.answer = false;
- return false;
- }
-
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
// matchIndices is either null or the lastMatchInfo array.
var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
- if (matchIndices == null) {
- if (this.global) this.lastIndex = 0;
- cache.answer = false;
- return false;
+ var result = (matchIndices !== null);
+ if (result) {
+ lastMatchInfoOverride = null;
}
- lastMatchInfoOverride = null;
- if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
- cache.answer = true;
- return true;
+ if (global) {
+ if (result) {
+ this.lastIndex = lastMatchInfo[CAPTURE1];
+ return true;
+ } else {
+ this.lastIndex = 0;
+ if (lastIndex !== 0) return false;
+ }
+ }
+ cache.type = 'test';
+ cache.regExp = this;
+ cache.subject = s;
+ cache.answer = result;
+ return result;
}
@@ -345,12 +372,9 @@ function RegExpToString() {
// ecma_2/RegExp/properties-001.js.
var src = this.source ? this.source : '(?:)';
var result = '/' + src + '/';
- if (this.global)
- result += 'g';
- if (this.ignoreCase)
- result += 'i';
- if (this.multiline)
- result += 'm';
+ if (this.global) result += 'g';
+ if (this.ignoreCase) result += 'i';
+ if (this.multiline) result += 'm';
return result;
}
diff --git a/src/rewriter.cc b/src/rewriter.cc
index f253ec53..b6f82406 100644
--- a/src/rewriter.cc
+++ b/src/rewriter.cc
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// 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:
@@ -27,9 +27,11 @@
#include "v8.h"
+#include "rewriter.h"
+
#include "ast.h"
+#include "compiler.h"
#include "scopes.h"
-#include "rewriter.h"
namespace v8 {
namespace internal {
@@ -986,34 +988,40 @@ void Processor::VisitThisFunction(ThisFunction* node) {
}
-bool Rewriter::Process(FunctionLiteral* function) {
- HistogramTimerScope timer(&Counters::rewriting);
+// Assumes code has been parsed and scopes hve been analyzed. Mutates the
+// AST, so the AST should not continue to be used in the case of failure.
+bool Rewriter::Rewrite(CompilationInfo* info) {
+ FunctionLiteral* function = info->function();
+ ASSERT(function != NULL);
Scope* scope = function->scope();
+ ASSERT(scope != NULL);
if (scope->is_function_scope()) return true;
ZoneList<Statement*>* body = function->body();
- if (body->is_empty()) return true;
+ if (!body->is_empty()) {
+ VariableProxy* result = scope->NewTemporary(Factory::result_symbol());
+ Processor processor(result);
+ processor.Process(body);
+ if (processor.HasStackOverflow()) return false;
- VariableProxy* result = scope->NewTemporary(Factory::result_symbol());
- Processor processor(result);
- processor.Process(body);
- if (processor.HasStackOverflow()) return false;
+ if (processor.result_assigned()) body->Add(new ReturnStatement(result));
+ }
- if (processor.result_assigned()) body->Add(new ReturnStatement(result));
return true;
}
-bool Rewriter::Optimize(FunctionLiteral* function) {
- ZoneList<Statement*>* body = function->body();
+// Assumes code has been parsed and scopes have been analyzed. Mutates the
+// AST, so the AST should not continue to be used in the case of failure.
+bool Rewriter::Analyze(CompilationInfo* info) {
+ FunctionLiteral* function = info->function();
+ ASSERT(function != NULL && function->scope() != NULL);
+ ZoneList<Statement*>* body = function->body();
if (FLAG_optimize_ast && !body->is_empty()) {
- HistogramTimerScope timer(&Counters::ast_optimization);
AstOptimizer optimizer;
optimizer.Optimize(body);
- if (optimizer.HasStackOverflow()) {
- return false;
- }
+ if (optimizer.HasStackOverflow()) return false;
}
return true;
}
diff --git a/src/rewriter.h b/src/rewriter.h
index 8943e75a..62e1b7f7 100644
--- a/src/rewriter.h
+++ b/src/rewriter.h
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// 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:
@@ -31,21 +31,26 @@
namespace v8 {
namespace internal {
-
-// Currently, the rewriter takes function literals (only top-level)
-// and rewrites them to return the value of the last expression in
-// them.
-//
-// The rewriter adds a (hidden) variable, called .result, to the
-// activation, and tries to figure out where it needs to store into
-// this variable. If the variable is ever used, we conclude by adding
-// a return statement that returns the variable to the body of the
-// given function.
+class CompilationInfo;
class Rewriter {
public:
- static bool Process(FunctionLiteral* function);
- static bool Optimize(FunctionLiteral* function);
+ // Rewrite top-level code (ECMA 262 "programs") so as to conservatively
+ // include an assignment of the value of the last statement in the code to
+ // a compiler-generated temporary variable wherever needed.
+ //
+ // Assumes code has been parsed and scopes have been analyzed. Mutates the
+ // AST, so the AST should not continue to be used in the case of failure.
+ static bool Rewrite(CompilationInfo* info);
+
+ // Perform a suite of simple non-iterative analyses of the AST. Mark
+ // expressions that are likely smis, expressions without side effects,
+ // expressions whose value will be converted to Int32, and expressions in a
+ // context where +0 and -0 are treated the same.
+ //
+ // Assumes code has been parsed and scopes have been analyzed. Mutates the
+ // AST, so the AST should not continue to be used in the case of failure.
+ static bool Analyze(CompilationInfo* info);
};
diff --git a/src/runtime.cc b/src/runtime.cc
index 8d58db74..9a604a03 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -2624,15 +2624,15 @@ int Runtime::StringMatch(Handle<String> sub,
if (seq_pat->IsAsciiRepresentation()) {
Vector<const char> pat_vector = seq_pat->ToAsciiVector();
if (seq_sub->IsAsciiRepresentation()) {
- return StringSearch(seq_sub->ToAsciiVector(), pat_vector, start_index);
+ return SearchString(seq_sub->ToAsciiVector(), pat_vector, start_index);
}
- return StringSearch(seq_sub->ToUC16Vector(), pat_vector, start_index);
+ return SearchString(seq_sub->ToUC16Vector(), pat_vector, start_index);
}
Vector<const uc16> pat_vector = seq_pat->ToUC16Vector();
if (seq_sub->IsAsciiRepresentation()) {
- return StringSearch(seq_sub->ToAsciiVector(), pat_vector, start_index);
+ return SearchString(seq_sub->ToAsciiVector(), pat_vector, start_index);
}
- return StringSearch(seq_sub->ToUC16Vector(), pat_vector, start_index);
+ return SearchString(seq_sub->ToUC16Vector(), pat_vector, start_index);
}
@@ -2889,67 +2889,39 @@ static void SetLastMatchInfoNoCaptures(Handle<String> subject,
}
-template <typename schar, typename pchar>
-static bool SearchStringMultiple(Vector<schar> subject,
- String* pattern,
- Vector<pchar> pattern_string,
+template <typename SubjectChar, typename PatternChar>
+static bool SearchStringMultiple(Vector<const SubjectChar> subject,
+ Vector<const PatternChar> pattern,
+ String* pattern_string,
FixedArrayBuilder* builder,
int* match_pos) {
int pos = *match_pos;
int subject_length = subject.length();
- int pattern_length = pattern_string.length();
+ int pattern_length = pattern.length();
int max_search_start = subject_length - pattern_length;
- bool is_ascii = (sizeof(schar) == 1);
- StringSearchStrategy strategy =
- InitializeStringSearch(pattern_string, is_ascii);
- switch (strategy) {
- case SEARCH_FAIL: break;
- case SEARCH_SHORT:
- while (pos <= max_search_start) {
- if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
- *match_pos = pos;
- return false;
- }
- // Position of end of previous match.
- int match_end = pos + pattern_length;
- int new_pos = SimpleIndexOf(subject, pattern_string, match_end);
- if (new_pos >= 0) {
- // A match.
- if (new_pos > match_end) {
- ReplacementStringBuilder::AddSubjectSlice(builder,
- match_end,
- new_pos);
- }
- pos = new_pos;
- builder->Add(pattern);
- } else {
- break;
- }
- }
- break;
- case SEARCH_LONG:
- while (pos <= max_search_start) {
- if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
- *match_pos = pos;
- return false;
- }
- int match_end = pos + pattern_length;
- int new_pos = ComplexIndexOf(subject, pattern_string, match_end);
- if (new_pos >= 0) {
- // A match has been found.
- if (new_pos > match_end) {
- ReplacementStringBuilder::AddSubjectSlice(builder,
- match_end,
- new_pos);
- }
- pos = new_pos;
- builder->Add(pattern);
- } else {
- break;
- }
+ StringSearch<PatternChar, SubjectChar> search(pattern);
+ while (pos <= max_search_start) {
+ if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
+ *match_pos = pos;
+ return false;
+ }
+ // Position of end of previous match.
+ int match_end = pos + pattern_length;
+ int new_pos = search.Search(subject, match_end);
+ if (new_pos >= 0) {
+ // A match.
+ if (new_pos > match_end) {
+ ReplacementStringBuilder::AddSubjectSlice(builder,
+ match_end,
+ new_pos);
}
+ pos = new_pos;
+ builder->Add(pattern_string);
+ } else {
break;
+ }
}
+
if (pos < max_search_start) {
ReplacementStringBuilder::AddSubjectSlice(builder,
pos + pattern_length,
@@ -2977,14 +2949,14 @@ static bool SearchStringMultiple(Handle<String> subject,
Vector<const char> subject_vector = subject->ToAsciiVector();
if (pattern->IsAsciiRepresentation()) {
if (SearchStringMultiple(subject_vector,
- *pattern,
pattern->ToAsciiVector(),
+ *pattern,
builder,
&match_pos)) break;
} else {
if (SearchStringMultiple(subject_vector,
- *pattern,
pattern->ToUC16Vector(),
+ *pattern,
builder,
&match_pos)) break;
}
@@ -2992,14 +2964,14 @@ static bool SearchStringMultiple(Handle<String> subject,
Vector<const uc16> subject_vector = subject->ToUC16Vector();
if (pattern->IsAsciiRepresentation()) {
if (SearchStringMultiple(subject_vector,
- *pattern,
pattern->ToAsciiVector(),
+ *pattern,
builder,
&match_pos)) break;
} else {
if (SearchStringMultiple(subject_vector,
- *pattern,
pattern->ToUC16Vector(),
+ *pattern,
builder,
&match_pos)) break;
}
@@ -4781,51 +4753,23 @@ static Object* Runtime_StringTrim(Arguments args) {
}
-// Define storage for buffers declared in header file.
-// TODO(lrn): Remove these when rewriting search code.
-int BMBuffers::bad_char_occurrence[kBMAlphabetSize];
-BMGoodSuffixBuffers BMBuffers::bmgs_buffers;
-
-
-template <typename schar, typename pchar>
-void FindStringIndices(Vector<const schar> subject,
- Vector<const pchar> pattern,
+template <typename SubjectChar, typename PatternChar>
+void FindStringIndices(Vector<const SubjectChar> subject,
+ Vector<const PatternChar> pattern,
ZoneList<int>* indices,
unsigned int limit) {
ASSERT(limit > 0);
// Collect indices of pattern in subject, and the end-of-string index.
// Stop after finding at most limit values.
- StringSearchStrategy strategy =
- InitializeStringSearch(pattern, sizeof(schar) == 1);
- switch (strategy) {
- case SEARCH_FAIL: return;
- case SEARCH_SHORT: {
- int pattern_length = pattern.length();
- int index = 0;
- while (limit > 0) {
- index = SimpleIndexOf(subject, pattern, index);
- if (index < 0) return;
- indices->Add(index);
- index += pattern_length;
- limit--;
- }
- return;
- }
- case SEARCH_LONG: {
- int pattern_length = pattern.length();
- int index = 0;
- while (limit > 0) {
- index = ComplexIndexOf(subject, pattern, index);
- if (index < 0) return;
- indices->Add(index);
- index += pattern_length;
- limit--;
- }
- return;
- }
- default:
- UNREACHABLE();
- return;
+ StringSearch<PatternChar, SubjectChar> search(pattern);
+ int pattern_length = pattern.length();
+ int index = 0;
+ while (limit > 0) {
+ index = search.Search(subject, index);
+ if (index < 0) return;
+ indices->Add(index);
+ index += pattern_length;
+ limit--;
}
}
@@ -6430,7 +6374,7 @@ static Object* Runtime_LazyCompile(Arguments args) {
// this means that things called through constructors are never known to
// be in loops. We compile them as if they are in loops here just in case.
ASSERT(!function->is_compiled());
- if (!CompileLazyInLoop(function, Handle<Object>::null(), KEEP_EXCEPTION)) {
+ if (!CompileLazyInLoop(function, KEEP_EXCEPTION)) {
return Failure::Exception();
}
@@ -6759,7 +6703,7 @@ static Object* Runtime_StackOverflow(Arguments args) {
static Object* Runtime_StackGuard(Arguments args) {
- ASSERT(args.length() == 1);
+ ASSERT(args.length() == 0);
// First check if this is a real stack overflow.
if (StackGuard::IsStackOverflow()) {
@@ -6801,7 +6745,7 @@ static void PrintObject(Object* obj) {
} else if (obj->IsFalse()) {
PrintF("<false>");
} else {
- PrintF("%p", obj);
+ PrintF("%p", reinterpret_cast<void*>(obj));
}
}
@@ -7253,15 +7197,15 @@ static uint32_t IterateExternalArrayElements(Handle<JSObject> receiver,
Handle<Smi> e(Smi::FromInt(static_cast<int>(val)));
visitor->visit(j, e);
} else {
- Handle<Object> e(
- Heap::AllocateHeapNumber(static_cast<ElementType>(val)));
+ Handle<Object> e =
+ Factory::NewNumber(static_cast<ElementType>(val));
visitor->visit(j, e);
}
}
}
} else {
for (uint32_t j = 0; j < len; j++) {
- Handle<Object> e(Heap::AllocateHeapNumber(array->get(j)));
+ Handle<Object> e = Factory::NewNumber(array->get(j));
visitor->visit(j, e);
}
}
@@ -10209,7 +10153,7 @@ void Runtime::PerformGC(Object* result) {
if (failure->IsRetryAfterGC()) {
// Try to do a garbage collection; ignore it if it fails. The C
// entry stub will throw an out-of-memory exception in that case.
- Heap::CollectGarbage(failure->requested(), failure->allocation_space());
+ Heap::CollectGarbage(failure->allocation_space());
} else {
// Handle last resort GC and make sure to allow future allocations
// to grow the heap without causing GCs (if possible).
diff --git a/src/runtime.h b/src/runtime.h
index 19f41441..2cd95c49 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -267,7 +267,7 @@ namespace internal {
F(Throw, 1, 1) \
F(ReThrow, 1, 1) \
F(ThrowReferenceError, 1, 1) \
- F(StackGuard, 1, 1) \
+ F(StackGuard, 0, 1) \
F(PromoteScheduledException, 0, 1) \
\
/* Contexts */ \
diff --git a/src/scopes.cc b/src/scopes.cc
index c4436fe0..5ff250ff 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// 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:
@@ -27,9 +27,12 @@
#include "v8.h"
+#include "scopes.h"
+
+#include "bootstrapper.h"
+#include "compiler.h"
#include "prettyprinter.h"
#include "scopeinfo.h"
-#include "scopes.h"
namespace v8 {
namespace internal {
@@ -168,6 +171,25 @@ Scope::Scope(Scope* outer_scope, Type type)
}
+bool Scope::Analyze(CompilationInfo* info) {
+ ASSERT(info->function() != NULL);
+ Scope* top = info->function()->scope();
+ while (top->outer_scope() != NULL) top = top->outer_scope();
+ top->AllocateVariables(info->calling_context());
+
+#ifdef DEBUG
+ if (Bootstrapper::IsActive()
+ ? FLAG_print_builtin_scopes
+ : FLAG_print_scopes) {
+ info->function()->scope()->Print();
+ }
+#endif
+
+ info->SetScope(info->function()->scope());
+ return true; // Can not fail.
+}
+
+
void Scope::Initialize(bool inside_with) {
// Add this scope as a new inner scope of the outer scope.
if (outer_scope_ != NULL) {
@@ -201,7 +223,6 @@ void Scope::Initialize(bool inside_with) {
}
-
Variable* Scope::LocalLookup(Handle<String> name) {
return variables_.Lookup(name);
}
diff --git a/src/scopes.h b/src/scopes.h
index 68cf5e51..526c3d34 100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// 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:
@@ -34,6 +34,8 @@
namespace v8 {
namespace internal {
+class CompilationInfo;
+
// A hash map to support fast variable declaration and lookup.
class VariableMap: public HashMap {
@@ -97,11 +99,20 @@ class Scope: public ZoneObject {
virtual ~Scope() { }
+ // Compute top scope and allocate variables. For lazy compilation the top
+ // scope only contains the single lazily compiled function, so this
+ // doesn't re-allocate variables repeatedly.
+ static bool Analyze(CompilationInfo* info);
+
// The scope name is only used for printing/debugging.
void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; }
- void Initialize(bool inside_with);
+ virtual void Initialize(bool inside_with);
+ // Called just before leaving a scope.
+ virtual void Leave() {
+ // No cleanup or fixup necessary.
+ }
// ---------------------------------------------------------------------------
// Declarations
@@ -272,7 +283,7 @@ class Scope: public ZoneObject {
bool AllowsLazyCompilation() const;
// True if the outer context of this scope is always the global context.
- bool HasTrivialOuterContext() const;
+ virtual bool HasTrivialOuterContext() const;
// The number of contexts between this and scope; zero if this == scope.
int ContextChainLength(Scope* scope);
@@ -378,20 +389,53 @@ class Scope: public ZoneObject {
};
+// Scope used during pre-parsing.
class DummyScope : public Scope {
public:
- DummyScope() : Scope(GLOBAL_SCOPE) {
+ DummyScope()
+ : Scope(GLOBAL_SCOPE),
+ nesting_level_(1), // Allows us to Leave the initial scope.
+ inside_with_level_(kNotInsideWith) {
outer_scope_ = this;
+ scope_inside_with_ = false;
}
- virtual Variable* Lookup(Handle<String> name) { return NULL; }
- virtual Variable* Declare(Handle<String> name, Variable::Mode mode) {
- return NULL;
+ virtual void Initialize(bool inside_with) {
+ nesting_level_++;
+ if (inside_with && inside_with_level_ == kNotInsideWith) {
+ inside_with_level_ = nesting_level_;
+ }
+ ASSERT(inside_with_level_ <= nesting_level_);
+ }
+
+ virtual void Leave() {
+ nesting_level_--;
+ ASSERT(nesting_level_ >= 0);
+ if (nesting_level_ < inside_with_level_) {
+ inside_with_level_ = kNotInsideWith;
+ }
+ ASSERT(inside_with_level_ <= nesting_level_);
}
+
+ virtual Variable* Lookup(Handle<String> name) { return NULL; }
+
virtual VariableProxy* NewUnresolved(Handle<String> name, bool inside_with) {
return NULL;
}
+
virtual VariableProxy* NewTemporary(Handle<String> name) { return NULL; }
+
+ virtual bool HasTrivialOuterContext() const {
+ return (nesting_level_ == 0 || inside_with_level_ <= 0);
+ }
+
+ private:
+ static const int kNotInsideWith = -1;
+ // Number of surrounding scopes of the current scope.
+ int nesting_level_;
+ // Nesting level of outermost scope that is contained in a with statement,
+ // or kNotInsideWith if there are no with's around the current scope.
+ int inside_with_level_;
};
diff --git a/src/serialize.cc b/src/serialize.cc
index cde7577c..ccba737d 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -500,7 +500,7 @@ void ExternalReferenceEncoder::Put(Address key, int index) {
ExternalReferenceDecoder::ExternalReferenceDecoder()
- : encodings_(NewArray<Address*>(kTypeCodeCount)) {
+ : encodings_(NewArray<Address*>(kTypeCodeCount)) {
ExternalReferenceTable* external_references =
ExternalReferenceTable::instance();
for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
@@ -619,6 +619,8 @@ void Deserializer::Deserialize() {
external_reference_decoder_ = new ExternalReferenceDecoder();
Heap::IterateStrongRoots(this, VISIT_ONLY_STRONG);
Heap::IterateWeakRoots(this, VISIT_ALL);
+
+ Heap::set_global_contexts_list(Heap::undefined_value());
}
diff --git a/src/spaces-inl.h b/src/spaces-inl.h
index fbb26732..8a0dd07c 100644
--- a/src/spaces-inl.h
+++ b/src/spaces-inl.h
@@ -407,8 +407,7 @@ void MemoryAllocator::UnprotectChunkFromPage(Page* page) {
bool PagedSpace::Contains(Address addr) {
Page* p = Page::FromAddress(addr);
- ASSERT(p->is_valid());
-
+ if (!p->is_valid()) return false;
return MemoryAllocator::IsPageInSpace(p, this);
}
@@ -440,7 +439,7 @@ Object* PagedSpace::AllocateRaw(int size_in_bytes) {
object = SlowAllocateRaw(size_in_bytes);
if (object != NULL) return object;
- return Failure::RetryAfterGC(size_in_bytes, identity());
+ return Failure::RetryAfterGC(identity());
}
@@ -454,7 +453,7 @@ Object* PagedSpace::MCAllocateRaw(int size_in_bytes) {
object = SlowMCAllocateRaw(size_in_bytes);
if (object != NULL) return object;
- return Failure::RetryAfterGC(size_in_bytes, identity());
+ return Failure::RetryAfterGC(identity());
}
@@ -475,7 +474,7 @@ HeapObject* LargeObjectChunk::GetObject() {
Object* NewSpace::AllocateRawInternal(int size_in_bytes,
AllocationInfo* alloc_info) {
Address new_top = alloc_info->top + size_in_bytes;
- if (new_top > alloc_info->limit) return Failure::RetryAfterGC(size_in_bytes);
+ if (new_top > alloc_info->limit) return Failure::RetryAfterGC();
Object* obj = HeapObject::FromAddress(alloc_info->top);
alloc_info->top = new_top;
diff --git a/src/spaces.cc b/src/spaces.cc
index 3d2d42f0..5bdbcc78 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -270,9 +270,9 @@ void CodeRange::TearDown() {
// -----------------------------------------------------------------------------
// MemoryAllocator
//
-int MemoryAllocator::capacity_ = 0;
-int MemoryAllocator::size_ = 0;
-int MemoryAllocator::size_executable_ = 0;
+intptr_t MemoryAllocator::capacity_ = 0;
+intptr_t MemoryAllocator::size_ = 0;
+intptr_t MemoryAllocator::size_executable_ = 0;
List<MemoryAllocator::MemoryAllocationCallbackRegistration>
MemoryAllocator::memory_allocation_callbacks_;
@@ -302,7 +302,7 @@ int MemoryAllocator::Pop() {
}
-bool MemoryAllocator::Setup(int capacity) {
+bool MemoryAllocator::Setup(intptr_t capacity) {
capacity_ = RoundUp(capacity, Page::kPageSize);
// Over-estimate the size of chunks_ array. It assumes the expansion of old
@@ -314,7 +314,8 @@ bool MemoryAllocator::Setup(int capacity) {
//
// Reserve two chunk ids for semispaces, one for map space, one for old
// space, and one for code space.
- max_nof_chunks_ = (capacity_ / (kChunkSize - Page::kPageSize)) + 5;
+ max_nof_chunks_ =
+ static_cast<int>((capacity_ / (kChunkSize - Page::kPageSize))) + 5;
if (max_nof_chunks_ > kMaxNofChunks) return false;
size_ = 0;
@@ -691,7 +692,9 @@ Page* MemoryAllocator::FindLastPageInSameChunk(Page* p) {
#ifdef DEBUG
void MemoryAllocator::ReportStatistics() {
float pct = static_cast<float>(capacity_ - size_) / capacity_;
- PrintF(" capacity: %d, used: %d, available: %%%d\n\n",
+ PrintF(" capacity: %" V8_PTR_PREFIX "d"
+ ", used: %" V8_PTR_PREFIX "d"
+ ", available: %%%d\n\n",
capacity_, size_, static_cast<int>(pct*100));
}
#endif
@@ -769,7 +772,7 @@ Page* MemoryAllocator::RelinkPagesInChunk(int chunk_id,
// -----------------------------------------------------------------------------
// PagedSpace implementation
-PagedSpace::PagedSpace(int max_capacity,
+PagedSpace::PagedSpace(intptr_t max_capacity,
AllocationSpace id,
Executability executable)
: Space(id, executable) {
@@ -797,8 +800,9 @@ bool PagedSpace::Setup(Address start, size_t size) {
Page::kPageSize * pages_in_chunk,
this, &num_pages);
} else {
- int requested_pages = Min(MemoryAllocator::kPagesPerChunk,
- max_capacity_ / Page::kObjectAreaSize);
+ int requested_pages =
+ Min(MemoryAllocator::kPagesPerChunk,
+ static_cast<int>(max_capacity_ / Page::kObjectAreaSize));
first_page_ =
MemoryAllocator::AllocatePages(requested_pages, &num_pages, this);
if (!first_page_->is_valid()) return false;
@@ -984,7 +988,8 @@ bool PagedSpace::Expand(Page* last_page) {
// Last page must be valid and its next page is invalid.
ASSERT(last_page->is_valid() && !last_page->next_page()->is_valid());
- int available_pages = (max_capacity_ - Capacity()) / Page::kObjectAreaSize;
+ int available_pages =
+ static_cast<int>((max_capacity_ - Capacity()) / Page::kObjectAreaSize);
if (available_pages <= 0) return false;
int desired_pages = Min(available_pages, MemoryAllocator::kPagesPerChunk);
@@ -1264,7 +1269,7 @@ void NewSpace::Grow() {
void NewSpace::Shrink() {
- int new_capacity = Max(InitialCapacity(), 2 * Size());
+ int new_capacity = Max(InitialCapacity(), 2 * SizeAsInt());
int rounded_new_capacity =
RoundUp(new_capacity, static_cast<int>(OS::AllocateAlignment()));
if (rounded_new_capacity < Capacity() &&
@@ -1643,7 +1648,8 @@ void NewSpace::ReportStatistics() {
#ifdef DEBUG
if (FLAG_heap_stats) {
float pct = static_cast<float>(Available()) / Capacity();
- PrintF(" capacity: %d, available: %d, %%%d\n",
+ PrintF(" capacity: %" V8_PTR_PREFIX "d"
+ ", available: %" V8_PTR_PREFIX "d, %%%d\n",
Capacity(), Available(), static_cast<int>(pct*100));
PrintF("\n Object Histogram:\n");
for (int i = 0; i <= LAST_TYPE; i++) {
@@ -1822,7 +1828,7 @@ Object* OldSpaceFreeList::Allocate(int size_in_bytes, int* wasted_bytes) {
if (cur == kEnd) {
// No large enough size in list.
*wasted_bytes = 0;
- return Failure::RetryAfterGC(size_in_bytes, owner_);
+ return Failure::RetryAfterGC(owner_);
}
ASSERT(!FLAG_always_compact); // We only use the freelists with mark-sweep.
int rem = cur - index;
@@ -1920,7 +1926,7 @@ void FixedSizeFreeList::Free(Address start) {
Object* FixedSizeFreeList::Allocate() {
if (head_ == NULL) {
- return Failure::RetryAfterGC(object_size_, owner_);
+ return Failure::RetryAfterGC(owner_);
}
ASSERT(!FLAG_always_compact); // We only use the freelists with mark-sweep.
@@ -2401,8 +2407,10 @@ void PagedSpace::CollectCodeStatistics() {
void OldSpace::ReportStatistics() {
- int pct = Available() * 100 / Capacity();
- PrintF(" capacity: %d, waste: %d, available: %d, %%%d\n",
+ int pct = static_cast<int>(Available() * 100 / Capacity());
+ PrintF(" capacity: %" V8_PTR_PREFIX "d"
+ ", waste: %" V8_PTR_PREFIX "d"
+ ", available: %" V8_PTR_PREFIX "d, %%%d\n",
Capacity(), Waste(), Available(), pct);
ClearHistograms();
@@ -2558,8 +2566,10 @@ void FixedSpace::DeallocateBlock(Address start,
#ifdef DEBUG
void FixedSpace::ReportStatistics() {
- int pct = Available() * 100 / Capacity();
- PrintF(" capacity: %d, waste: %d, available: %d, %%%d\n",
+ int pct = static_cast<int>(Available() * 100 / Capacity());
+ PrintF(" capacity: %" V8_PTR_PREFIX "d"
+ ", waste: %" V8_PTR_PREFIX "d"
+ ", available: %" V8_PTR_PREFIX "d, %%%d\n",
Capacity(), Waste(), Available(), pct);
ClearHistograms();
@@ -2743,14 +2753,14 @@ Object* LargeObjectSpace::AllocateRawInternal(int requested_size,
// Check if we want to force a GC before growing the old space further.
// If so, fail the allocation.
if (!Heap::always_allocate() && Heap::OldGenerationAllocationLimitReached()) {
- return Failure::RetryAfterGC(requested_size, identity());
+ return Failure::RetryAfterGC(identity());
}
size_t chunk_size;
LargeObjectChunk* chunk =
LargeObjectChunk::New(requested_size, &chunk_size, executable);
if (chunk == NULL) {
- return Failure::RetryAfterGC(requested_size, identity());
+ return Failure::RetryAfterGC(identity());
}
size_ += static_cast<int>(chunk_size);
@@ -3011,7 +3021,7 @@ void LargeObjectSpace::Print() {
void LargeObjectSpace::ReportStatistics() {
- PrintF(" size: %d\n", size_);
+ PrintF(" size: %" V8_PTR_PREFIX "d\n", size_);
int num_objects = 0;
ClearHistograms();
LargeObjectIterator it(this);
diff --git a/src/spaces.h b/src/spaces.h
index 94e0cd24..0e6a91e2 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -371,7 +371,7 @@ class Space : public Malloced {
// Identity used in error reporting.
AllocationSpace identity() { return id_; }
- virtual int Size() = 0;
+ virtual intptr_t Size() = 0;
#ifdef ENABLE_HEAP_PROTECTION
// Protect/unprotect the space by marking it read-only/writable.
@@ -491,7 +491,7 @@ class MemoryAllocator : public AllStatic {
public:
// Initializes its internal bookkeeping structures.
// Max capacity of the total space.
- static bool Setup(int max_capacity);
+ static bool Setup(intptr_t max_capacity);
// Deletes valid chunks.
static void TearDown();
@@ -582,16 +582,18 @@ class MemoryAllocator : public AllStatic {
MemoryAllocationCallback callback);
// Returns the maximum available bytes of heaps.
- static int Available() { return capacity_ < size_ ? 0 : capacity_ - size_; }
+ static intptr_t Available() {
+ return capacity_ < size_ ? 0 : capacity_ - size_;
+ }
// Returns allocated spaces in bytes.
- static int Size() { return size_; }
+ static intptr_t Size() { return size_; }
// Returns allocated executable spaces in bytes.
- static int SizeExecutable() { return size_executable_; }
+ static intptr_t SizeExecutable() { return size_executable_; }
// Returns maximum available bytes that the old space can have.
- static int MaxAvailable() {
+ static intptr_t MaxAvailable() {
return (Available() / Page::kPageSize) * Page::kObjectAreaSize;
}
@@ -649,12 +651,12 @@ class MemoryAllocator : public AllStatic {
private:
// Maximum space size in bytes.
- static int capacity_;
+ static intptr_t capacity_;
// Allocated space size in bytes.
- static int size_;
+ static intptr_t size_;
// Allocated executable space size in bytes.
- static int size_executable_;
+ static intptr_t size_executable_;
struct MemoryAllocationCallbackRegistration {
MemoryAllocationCallbackRegistration(MemoryAllocationCallback callback,
@@ -927,10 +929,10 @@ class AllocationStats BASE_EMBEDDED {
}
// Accessors for the allocation statistics.
- int Capacity() { return capacity_; }
- int Available() { return available_; }
- int Size() { return size_; }
- int Waste() { return waste_; }
+ intptr_t Capacity() { return capacity_; }
+ intptr_t Available() { return available_; }
+ intptr_t Size() { return size_; }
+ intptr_t Waste() { return waste_; }
// Grow the space by adding available bytes.
void ExpandSpace(int size_in_bytes) {
@@ -945,13 +947,13 @@ class AllocationStats BASE_EMBEDDED {
}
// Allocate from available bytes (available -> size).
- void AllocateBytes(int size_in_bytes) {
+ void AllocateBytes(intptr_t size_in_bytes) {
available_ -= size_in_bytes;
size_ += size_in_bytes;
}
// Free allocated bytes, making them available (size -> available).
- void DeallocateBytes(int size_in_bytes) {
+ void DeallocateBytes(intptr_t size_in_bytes) {
size_ -= size_in_bytes;
available_ += size_in_bytes;
}
@@ -964,23 +966,25 @@ class AllocationStats BASE_EMBEDDED {
// Consider the wasted bytes to be allocated, as they contain filler
// objects (waste -> size).
- void FillWastedBytes(int size_in_bytes) {
+ void FillWastedBytes(intptr_t size_in_bytes) {
waste_ -= size_in_bytes;
size_ += size_in_bytes;
}
private:
- int capacity_;
- int available_;
- int size_;
- int waste_;
+ intptr_t capacity_;
+ intptr_t available_;
+ intptr_t size_;
+ intptr_t waste_;
};
class PagedSpace : public Space {
public:
// Creates a space with a maximum capacity, and an id.
- PagedSpace(int max_capacity, AllocationSpace id, Executability executable);
+ PagedSpace(intptr_t max_capacity,
+ AllocationSpace id,
+ Executability executable);
virtual ~PagedSpace() {}
@@ -1031,21 +1035,21 @@ class PagedSpace : public Space {
}
// Current capacity without growing (Size() + Available() + Waste()).
- int Capacity() { return accounting_stats_.Capacity(); }
+ intptr_t Capacity() { return accounting_stats_.Capacity(); }
// Total amount of memory committed for this space. For paged
// spaces this equals the capacity.
- int CommittedMemory() { return Capacity(); }
+ intptr_t CommittedMemory() { return Capacity(); }
// Available bytes without growing.
- int Available() { return accounting_stats_.Available(); }
+ intptr_t Available() { return accounting_stats_.Available(); }
// Allocated bytes in this space.
- virtual int Size() { return accounting_stats_.Size(); }
+ virtual intptr_t Size() { return accounting_stats_.Size(); }
// Wasted bytes due to fragmentation and not recoverable until the
// next GC of this space.
- int Waste() { return accounting_stats_.Waste(); }
+ intptr_t Waste() { return accounting_stats_.Waste(); }
// Returns the address of the first object in this space.
Address bottom() { return first_page_->ObjectAreaStart(); }
@@ -1137,7 +1141,7 @@ class PagedSpace : public Space {
protected:
// Maximum capacity of this space.
- int max_capacity_;
+ intptr_t max_capacity_;
// Accounting information for this space.
AllocationStats accounting_stats_;
@@ -1328,7 +1332,7 @@ class SemiSpace : public Space {
// If we don't have these here then SemiSpace will be abstract. However
// they should never be called.
- virtual int Size() {
+ virtual intptr_t Size() {
UNREACHABLE();
return 0;
}
@@ -1471,22 +1475,26 @@ class NewSpace : public Space {
}
// Return the allocated bytes in the active semispace.
- virtual int Size() { return static_cast<int>(top() - bottom()); }
+ virtual intptr_t Size() { return static_cast<int>(top() - bottom()); }
+ // The same, but returning an int. We have to have the one that returns
+ // intptr_t because it is inherited, but if we know we are dealing with the
+ // new space, which can't get as big as the other spaces then this is useful:
+ int SizeAsInt() { return static_cast<int>(Size()); }
// Return the current capacity of a semispace.
- int Capacity() {
+ intptr_t Capacity() {
ASSERT(to_space_.Capacity() == from_space_.Capacity());
return to_space_.Capacity();
}
// Return the total amount of memory committed for new space.
- int CommittedMemory() {
+ intptr_t CommittedMemory() {
if (from_space_.is_committed()) return 2 * Capacity();
return Capacity();
}
// Return the available bytes without growing in the active semispace.
- int Available() { return Capacity() - Size(); }
+ intptr_t Available() { return Capacity() - Size(); }
// Return the maximum capacity of a semispace.
int MaximumCapacity() {
@@ -1681,7 +1689,7 @@ class OldSpaceFreeList BASE_EMBEDDED {
void Reset();
// Return the number of bytes available on the free list.
- int available() { return available_; }
+ intptr_t available() { return available_; }
// Place a node on the free list. The block of size 'size_in_bytes'
// starting at 'start' is placed on the free list. The return value is the
@@ -1783,7 +1791,7 @@ class FixedSizeFreeList BASE_EMBEDDED {
void Reset();
// Return the number of bytes available on the free list.
- int available() { return available_; }
+ intptr_t available() { return available_; }
// Place a node on the free list. The block starting at 'start' (assumed to
// have size object_size_) is placed on the free list. Bookkeeping
@@ -1797,7 +1805,7 @@ class FixedSizeFreeList BASE_EMBEDDED {
private:
// Available bytes on the free list.
- int available_;
+ intptr_t available_;
// The head of the free list.
Address head_;
@@ -1823,7 +1831,7 @@ class OldSpace : public PagedSpace {
public:
// Creates an old space object with a given maximum capacity.
// The constructor does not allocate pages from OS.
- explicit OldSpace(int max_capacity,
+ explicit OldSpace(intptr_t max_capacity,
AllocationSpace id,
Executability executable)
: PagedSpace(max_capacity, id, executable), free_list_(id) {
@@ -1832,7 +1840,7 @@ class OldSpace : public PagedSpace {
// The bytes available on the free list (ie, not above the linear allocation
// pointer).
- int AvailableFree() { return free_list_.available(); }
+ intptr_t AvailableFree() { return free_list_.available(); }
// The limit of allocation for a page in this space.
virtual Address PageAllocationLimit(Page* page) {
@@ -1893,7 +1901,7 @@ class OldSpace : public PagedSpace {
class FixedSpace : public PagedSpace {
public:
- FixedSpace(int max_capacity,
+ FixedSpace(intptr_t max_capacity,
AllocationSpace id,
int object_size_in_bytes,
const char* name)
@@ -1968,7 +1976,7 @@ class FixedSpace : public PagedSpace {
class MapSpace : public FixedSpace {
public:
// Creates a map space object with a maximum capacity.
- MapSpace(int max_capacity, int max_map_space_pages, AllocationSpace id)
+ MapSpace(intptr_t max_capacity, int max_map_space_pages, AllocationSpace id)
: FixedSpace(max_capacity, id, Map::kSize, "map"),
max_map_space_pages_(max_map_space_pages) {
ASSERT(max_map_space_pages < kMaxMapPageIndex);
@@ -2073,7 +2081,7 @@ class MapSpace : public FixedSpace {
class CellSpace : public FixedSpace {
public:
// Creates a property cell space object with a maximum capacity.
- CellSpace(int max_capacity, AllocationSpace id)
+ CellSpace(intptr_t max_capacity, AllocationSpace id)
: FixedSpace(max_capacity, id, JSGlobalPropertyCell::kSize, "cell") {}
protected:
@@ -2129,7 +2137,7 @@ class LargeObjectChunk {
// Given a chunk size, returns the object size it can accommodate. Used by
// LargeObjectSpace::Available.
- static int ObjectSizeFor(int chunk_size) {
+ static intptr_t ObjectSizeFor(intptr_t chunk_size) {
if (chunk_size <= (Page::kPageSize + Page::kObjectStartOffset)) return 0;
return chunk_size - Page::kPageSize - Page::kObjectStartOffset;
}
@@ -2165,11 +2173,11 @@ class LargeObjectSpace : public Space {
Object* AllocateRawFixedArray(int size_in_bytes);
// Available bytes for objects in this space.
- int Available() {
+ intptr_t Available() {
return LargeObjectChunk::ObjectSizeFor(MemoryAllocator::Available());
}
- virtual int Size() {
+ virtual intptr_t Size() {
return size_;
}
@@ -2186,7 +2194,6 @@ class LargeObjectSpace : public Space {
// if such a page doesn't exist.
LargeObjectChunk* FindChunkContainingPc(Address pc);
-
// Iterates objects covered by dirty regions.
void IterateDirtyRegions(ObjectSlotCallback func);
@@ -2223,7 +2230,7 @@ class LargeObjectSpace : public Space {
private:
// The head of the linked list of large object chunks.
LargeObjectChunk* first_chunk_;
- int size_; // allocated bytes
+ intptr_t size_; // allocated bytes
int page_count_; // number of chunks
diff --git a/src/string-search.cc b/src/string-search.cc
new file mode 100644
index 00000000..56874432
--- /dev/null
+++ b/src/string-search.cc
@@ -0,0 +1,40 @@
+// 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 "string-search.h"
+
+namespace v8 {
+namespace internal {
+
+// Storage for constants used by string-search.
+
+int StringSearchBase::kBadCharShiftTable[kUC16AlphabetSize];
+int StringSearchBase::kGoodSuffixShiftTable[kBMMaxShift + 1];
+int StringSearchBase::kSuffixTable[kBMMaxShift + 1];
+
+}} // namespace v8::internal
diff --git a/src/string-search.h b/src/string-search.h
index d7959c0b..eac84757 100644
--- a/src/string-search.h
+++ b/src/string-search.h
@@ -32,278 +32,484 @@ namespace v8 {
namespace internal {
-// Cap on the maximal shift in the Boyer-Moore implementation. By setting a
-// limit, we can fix the size of tables. For a needle longer than this limit,
-// search will not be optimal, since we only build tables for a smaller suffix
-// of the string, which is a safe approximation.
-static const int kBMMaxShift = 250;
-// Reduce alphabet to this size.
-// One of the tables used by Boyer-Moore and Boyer-Moore-Horspool has size
-// proportional to the input alphabet. We reduce the alphabet size by
-// equating input characters modulo a smaller alphabet size. This gives
-// a potentially less efficient searching, but is a safe approximation.
-// For needles using only characters in the same Unicode 256-code point page,
-// there is no search speed degradation.
-static const int kBMAlphabetSize = 256;
-// For patterns below this length, the skip length of Boyer-Moore is too short
-// to compensate for the algorithmic overhead compared to simple brute force.
-static const int kBMMinPatternLength = 7;
-
-// Holds the two buffers used by Boyer-Moore string search's Good Suffix
-// shift. Only allows the last kBMMaxShift characters of the needle
-// to be indexed.
-class BMGoodSuffixBuffers {
+//---------------------------------------------------------------------
+// String Search object.
+//---------------------------------------------------------------------
+
+// Class holding constants and methods that apply to all string search variants,
+// independently of subject and pattern char size.
+class StringSearchBase {
+ protected:
+ // Cap on the maximal shift in the Boyer-Moore implementation. By setting a
+ // limit, we can fix the size of tables. For a needle longer than this limit,
+ // search will not be optimal, since we only build tables for a suffix
+ // of the string, but it is a safe approximation.
+ static const int kBMMaxShift = 250;
+
+ // Reduce alphabet to this size.
+ // One of the tables used by Boyer-Moore and Boyer-Moore-Horspool has size
+ // proportional to the input alphabet. We reduce the alphabet size by
+ // equating input characters modulo a smaller alphabet size. This gives
+ // a potentially less efficient searching, but is a safe approximation.
+ // For needles using only characters in the same Unicode 256-code point page,
+ // there is no search speed degradation.
+ static const int kAsciiAlphabetSize = 128;
+ static const int kUC16AlphabetSize = 256;
+
+ // Bad-char shift table stored in the state. It's length is the alphabet size.
+ // For patterns below this length, the skip length of Boyer-Moore is too short
+ // to compensate for the algorithmic overhead compared to simple brute force.
+ static const int kBMMinPatternLength = 7;
+
+ static inline bool IsAsciiString(Vector<const char>) {
+ return true;
+ }
+
+ static inline bool IsAsciiString(Vector<const uc16> string) {
+ for (int i = 0, n = string.length(); i < n; i++) {
+ if (static_cast<unsigned>(string[i]) > String::kMaxAsciiCharCodeU) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // The following tables are shared by all searches.
+ // TODO(lrn): Introduce a way for a pattern to keep its tables
+ // between searches (e.g., for an Atom RegExp).
+
+ // Store for the BoyerMoore(Horspool) bad char shift table.
+ static int kBadCharShiftTable[kUC16AlphabetSize];
+ // Store for the BoyerMoore good suffix shift table.
+ static int kGoodSuffixShiftTable[kBMMaxShift + 1];
+ // Table used temporarily while building the BoyerMoore good suffix
+ // shift table.
+ static int kSuffixTable[kBMMaxShift + 1];
+};
+
+
+template <typename PatternChar, typename SubjectChar>
+class StringSearch : private StringSearchBase {
public:
- BMGoodSuffixBuffers() {}
- inline void Initialize(int needle_length) {
- ASSERT(needle_length > 1);
- int start = needle_length < kBMMaxShift ? 0 : needle_length - kBMMaxShift;
- int len = needle_length - start;
- biased_suffixes_ = suffixes_ - start;
- biased_good_suffix_shift_ = good_suffix_shift_ - start;
- for (int i = 0; i <= len; i++) {
- good_suffix_shift_[i] = len;
+ explicit StringSearch(Vector<const PatternChar> pattern)
+ : pattern_(pattern),
+ start_(Max(0, pattern.length() - kBMMaxShift)) {
+ if (sizeof(PatternChar) > sizeof(SubjectChar)) {
+ if (!IsAsciiString(pattern_)) {
+ strategy_ = &FailSearch;
+ return;
+ }
+ }
+ int pattern_length = pattern_.length();
+ if (pattern_length < kBMMinPatternLength) {
+ if (pattern_length == 1) {
+ strategy_ = &SingleCharSearch;
+ return;
+ }
+ strategy_ = &LinearSearch;
+ return;
}
+ strategy_ = &InitialSearch;
}
- inline int& suffix(int index) {
- ASSERT(biased_suffixes_ + index >= suffixes_);
- return biased_suffixes_[index];
+
+ int Search(Vector<const SubjectChar> subject, int index) {
+ return strategy_(this, subject, index);
}
- inline int& shift(int index) {
- ASSERT(biased_good_suffix_shift_ + index >= good_suffix_shift_);
- return biased_good_suffix_shift_[index];
+
+ static inline int AlphabetSize() {
+ if (sizeof(PatternChar) == 1) {
+ // ASCII needle.
+ return kAsciiAlphabetSize;
+ } else {
+ ASSERT(sizeof(PatternChar) == 2);
+ // UC16 needle.
+ return kUC16AlphabetSize;
+ }
}
+
private:
- int suffixes_[kBMMaxShift + 1];
- int good_suffix_shift_[kBMMaxShift + 1];
- int* biased_suffixes_;
- int* biased_good_suffix_shift_;
- DISALLOW_COPY_AND_ASSIGN(BMGoodSuffixBuffers);
-};
+ typedef int (*SearchFunction)( // NOLINT - it's not a cast!
+ StringSearch<PatternChar, SubjectChar>*,
+ Vector<const SubjectChar>,
+ int);
+
+ static int FailSearch(StringSearch<PatternChar, SubjectChar>*,
+ Vector<const SubjectChar>,
+ int) {
+ return -1;
+ }
-// buffers reused by BoyerMoore
-struct BMBuffers {
- public:
- static int bad_char_occurrence[kBMAlphabetSize];
- static BMGoodSuffixBuffers bmgs_buffers;
+ static int SingleCharSearch(StringSearch<PatternChar, SubjectChar>* search,
+ Vector<const SubjectChar> subject,
+ int start_index);
+
+ static int LinearSearch(StringSearch<PatternChar, SubjectChar>* search,
+ Vector<const SubjectChar> subject,
+ int start_index);
+
+ static int InitialSearch(StringSearch<PatternChar, SubjectChar>* search,
+ Vector<const SubjectChar> subject,
+ int start_index);
+
+ static int BoyerMooreHorspoolSearch(
+ StringSearch<PatternChar, SubjectChar>* search,
+ Vector<const SubjectChar> subject,
+ int start_index);
+
+ static int BoyerMooreSearch(StringSearch<PatternChar, SubjectChar>* search,
+ Vector<const SubjectChar> subject,
+ int start_index);
+
+ void PopulateBoyerMooreHorspoolTable();
+
+ void PopulateBoyerMooreTable();
+
+ static inline int CharOccurrence(int* bad_char_occurrence,
+ SubjectChar char_code) {
+ if (sizeof(SubjectChar) == 1) {
+ return bad_char_occurrence[static_cast<int>(char_code)];
+ }
+ if (sizeof(PatternChar) == 1) {
+ if (static_cast<unsigned int>(char_code) > String::kMaxAsciiCharCodeU) {
+ return -1;
+ }
+ return bad_char_occurrence[static_cast<unsigned int>(char_code)];
+ }
+ // Both pattern and subject are UC16. Reduce character to equivalence class.
+ int equiv_class = char_code % kUC16AlphabetSize;
+ return bad_char_occurrence[equiv_class];
+ }
+
+ // Return a table covering the last kBMMaxShift+1 positions of
+ // pattern.
+ int* bad_char_table() {
+ return kBadCharShiftTable;
+ }
+
+ int* good_suffix_shift_table() {
+ // Return biased pointer that maps the range [start_..pattern_.length()
+ // to the kGoodSuffixShiftTable array.
+ return kGoodSuffixShiftTable - start_;
+ }
+
+ int* suffix_table() {
+ // Return biased pointer that maps the range [start_..pattern_.length()
+ // to the kSuffixTable array.
+ return kSuffixTable - start_;
+ }
+
+ // The pattern to search for.
+ Vector<const PatternChar> pattern_;
+ // Pointer to implementation of the search.
+ SearchFunction strategy_;
+ // Cache value of Max(0, pattern_length() - kBMMaxShift)
+ int start_;
};
-// State of the string match tables.
-// SIMPLE: No usable content in the buffers.
-// BOYER_MOORE_HORSPOOL: The bad_char_occurence table has been populated.
-// BOYER_MOORE: The bmgs_buffers tables have also been populated.
-// Whenever starting with a new needle, one should call InitializeStringSearch
-// to determine which search strategy to use, and in the case of a long-needle
-// strategy, the call also initializes the algorithm to SIMPLE.
-enum StringSearchAlgorithm { SIMPLE_SEARCH, BOYER_MOORE_HORSPOOL, BOYER_MOORE };
-static StringSearchAlgorithm algorithm;
+//---------------------------------------------------------------------
+// Single Character Pattern Search Strategy
+//---------------------------------------------------------------------
-// Compute the bad-char table for Boyer-Moore in the static buffer.
-template <typename PatternChar>
-static void BoyerMoorePopulateBadCharTable(Vector<const PatternChar> pattern) {
- // Only preprocess at most kBMMaxShift last characters of pattern.
- int start = Max(pattern.length() - kBMMaxShift, 0);
- // Run forwards to populate bad_char_table, so that *last* instance
- // of character equivalence class is the one registered.
- // Notice: Doesn't include the last character.
- int table_size = (sizeof(PatternChar) == 1) ? String::kMaxAsciiCharCode + 1
- : kBMAlphabetSize;
- if (start == 0) { // All patterns less than kBMMaxShift in length.
- memset(BMBuffers::bad_char_occurrence,
- -1,
- table_size * sizeof(*BMBuffers::bad_char_occurrence));
+template <typename PatternChar, typename SubjectChar>
+int StringSearch<PatternChar, SubjectChar>::SingleCharSearch(
+ StringSearch<PatternChar, SubjectChar>* search,
+ Vector<const SubjectChar> subject,
+ int index) {
+ ASSERT_EQ(1, search->pattern_.length());
+ PatternChar pattern_first_char = search->pattern_[0];
+ int i = index;
+ if (sizeof(SubjectChar) == 1 && sizeof(PatternChar) == 1) {
+ const SubjectChar* pos = reinterpret_cast<const SubjectChar*>(
+ memchr(subject.start() + i,
+ pattern_first_char,
+ subject.length() - i));
+ if (pos == NULL) return -1;
+ return static_cast<int>(pos - subject.start());
} else {
- for (int i = 0; i < table_size; i++) {
- BMBuffers::bad_char_occurrence[i] = start - 1;
+ if (sizeof(PatternChar) > sizeof(SubjectChar)) {
+ if (static_cast<uc16>(pattern_first_char) > String::kMaxAsciiCharCodeU) {
+ return -1;
+ }
}
+ SubjectChar search_char = static_cast<SubjectChar>(pattern_first_char);
+ int n = subject.length();
+ while (i < n) {
+ if (subject[i++] == search_char) return i - 1;
+ }
+ return -1;
}
- for (int i = start; i < pattern.length() - 1; i++) {
- PatternChar c = pattern[i];
- int bucket = (sizeof(PatternChar) ==1) ? c : c % kBMAlphabetSize;
- BMBuffers::bad_char_occurrence[bucket] = i;
+}
+
+//---------------------------------------------------------------------
+// Linear Search Strategy
+//---------------------------------------------------------------------
+
+
+template <typename PatternChar, typename SubjectChar>
+static inline bool CharCompare(const PatternChar* pattern,
+ const SubjectChar* subject,
+ int length) {
+ ASSERT(length > 0);
+ int pos = 0;
+ do {
+ if (pattern[pos] != subject[pos]) {
+ return false;
+ }
+ pos++;
+ } while (pos < length);
+ return true;
+}
+
+
+// Simple linear search for short patterns. Never bails out.
+template <typename PatternChar, typename SubjectChar>
+int StringSearch<PatternChar, SubjectChar>::LinearSearch(
+ StringSearch<PatternChar, SubjectChar>* search,
+ Vector<const SubjectChar> subject,
+ int index) {
+ Vector<const PatternChar> pattern = search->pattern_;
+ ASSERT(pattern.length() > 1);
+ int pattern_length = pattern.length();
+ PatternChar pattern_first_char = pattern[0];
+ int i = index;
+ int n = subject.length() - pattern_length;
+ while (i <= n) {
+ if (sizeof(SubjectChar) == 1 && sizeof(PatternChar) == 1) {
+ const SubjectChar* pos = reinterpret_cast<const SubjectChar*>(
+ memchr(subject.start() + i,
+ pattern_first_char,
+ n - i + 1));
+ if (pos == NULL) return -1;
+ i = static_cast<int>(pos - subject.start()) + 1;
+ } else {
+ if (subject[i++] != pattern_first_char) continue;
+ }
+ // Loop extracted to separate function to allow using return to do
+ // a deeper break.
+ if (CharCompare(pattern.start() + 1,
+ subject.start() + i,
+ pattern_length - 1)) {
+ return i - 1;
+ }
+ }
+ return -1;
+}
+
+//---------------------------------------------------------------------
+// Boyer-Moore string search
+//---------------------------------------------------------------------
+
+template <typename PatternChar, typename SubjectChar>
+int StringSearch<PatternChar, SubjectChar>::BoyerMooreSearch(
+ StringSearch<PatternChar, SubjectChar>* search,
+ Vector<const SubjectChar> subject,
+ int start_index) {
+ Vector<const PatternChar> pattern = search->pattern_;
+ int subject_length = subject.length();
+ int pattern_length = pattern.length();
+ // Only preprocess at most kBMMaxShift last characters of pattern.
+ int start = search->start_;
+
+ int* bad_char_occurence = search->bad_char_table();
+ int* good_suffix_shift = search->good_suffix_shift_table();
+
+ PatternChar last_char = pattern[pattern_length - 1];
+ int index = start_index;
+ // Continue search from i.
+ while (index <= subject_length - pattern_length) {
+ int j = pattern_length - 1;
+ int c;
+ while (last_char != (c = subject[index + j])) {
+ int shift =
+ j - CharOccurrence(bad_char_occurence, c);
+ index += shift;
+ if (index > subject_length - pattern_length) {
+ return -1;
+ }
+ }
+ while (j >= 0 && pattern[j] == (c = subject[index + j])) j--;
+ if (j < 0) {
+ return index;
+ } else if (j < start) {
+ // we have matched more than our tables allow us to be smart about.
+ // Fall back on BMH shift.
+ index += pattern_length - 1
+ - CharOccurrence(bad_char_occurence,
+ static_cast<SubjectChar>(last_char));
+ } else {
+ int gs_shift = good_suffix_shift[j + 1];
+ int bc_occ =
+ CharOccurrence(bad_char_occurence, c);
+ int shift = j - bc_occ;
+ if (gs_shift > shift) {
+ shift = gs_shift;
+ }
+ index += shift;
+ }
}
+
+ return -1;
}
-template <typename PatternChar>
-static void BoyerMoorePopulateGoodSuffixTable(
- Vector<const PatternChar> pattern) {
- int m = pattern.length();
- int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
- int len = m - start;
- // Compute Good Suffix tables.
- BMBuffers::bmgs_buffers.Initialize(m);
+template <typename PatternChar, typename SubjectChar>
+void StringSearch<PatternChar, SubjectChar>::PopulateBoyerMooreTable() {
+ int pattern_length = pattern_.length();
+ const PatternChar* pattern = pattern_.start();
+ // Only look at the last kBMMaxShift characters of pattern (from start_
+ // to pattern_length).
+ int start = start_;
+ int length = pattern_length - start;
+
+ // Biased tables so that we can use pattern indices as table indices,
+ // even if we only cover the part of the pattern from offset start.
+ int* shift_table = good_suffix_shift_table();
+ int* suffix_table = this->suffix_table();
+
+ // Initialize table.
+ for (int i = start; i < pattern_length; i++) {
+ shift_table[i] = length;
+ }
+ shift_table[pattern_length] = 1;
+ suffix_table[pattern_length] = pattern_length + 1;
- BMBuffers::bmgs_buffers.shift(m-1) = 1;
- BMBuffers::bmgs_buffers.suffix(m) = m + 1;
- PatternChar last_char = pattern[m - 1];
- int suffix = m + 1;
+ // Find suffixes.
+ PatternChar last_char = pattern[pattern_length - 1];
+ int suffix = pattern_length + 1;
{
- int i = m;
+ int i = pattern_length;
while (i > start) {
PatternChar c = pattern[i - 1];
- while (suffix <= m && c != pattern[suffix - 1]) {
- if (BMBuffers::bmgs_buffers.shift(suffix) == len) {
- BMBuffers::bmgs_buffers.shift(suffix) = suffix - i;
+ while (suffix <= pattern_length && c != pattern[suffix - 1]) {
+ if (shift_table[suffix] == length) {
+ shift_table[suffix] = suffix - i;
}
- suffix = BMBuffers::bmgs_buffers.suffix(suffix);
+ suffix = suffix_table[suffix];
}
- BMBuffers::bmgs_buffers.suffix(--i) = --suffix;
- if (suffix == m) {
+ suffix_table[--i] = --suffix;
+ if (suffix == pattern_length) {
// No suffix to extend, so we check against last_char only.
while ((i > start) && (pattern[i - 1] != last_char)) {
- if (BMBuffers::bmgs_buffers.shift(m) == len) {
- BMBuffers::bmgs_buffers.shift(m) = m - i;
+ if (shift_table[pattern_length] == length) {
+ shift_table[pattern_length] = pattern_length - i;
}
- BMBuffers::bmgs_buffers.suffix(--i) = m;
+ suffix_table[--i] = pattern_length;
}
if (i > start) {
- BMBuffers::bmgs_buffers.suffix(--i) = --suffix;
+ suffix_table[--i] = --suffix;
}
}
}
}
- if (suffix < m) {
- for (int i = start; i <= m; i++) {
- if (BMBuffers::bmgs_buffers.shift(i) == len) {
- BMBuffers::bmgs_buffers.shift(i) = suffix - start;
+ // Build shift table using suffixes.
+ if (suffix < pattern_length) {
+ for (int i = start; i <= pattern_length; i++) {
+ if (shift_table[i] == length) {
+ shift_table[i] = suffix - start;
}
if (i == suffix) {
- suffix = BMBuffers::bmgs_buffers.suffix(suffix);
+ suffix = suffix_table[suffix];
}
}
}
}
+//---------------------------------------------------------------------
+// Boyer-Moore-Horspool string search.
+//---------------------------------------------------------------------
-template <typename SubjectChar, typename PatternChar>
-static inline int CharOccurrence(int char_code) {
- if (sizeof(SubjectChar) == 1) {
- return BMBuffers::bad_char_occurrence[char_code];
- }
- if (sizeof(PatternChar) == 1) {
- if (char_code > String::kMaxAsciiCharCode) {
- return -1;
- }
- return BMBuffers::bad_char_occurrence[char_code];
- }
- return BMBuffers::bad_char_occurrence[char_code % kBMAlphabetSize];
-}
-
-
-// Restricted simplified Boyer-Moore string matching.
-// Uses only the bad-shift table of Boyer-Moore and only uses it
-// for the character compared to the last character of the needle.
-template <typename SubjectChar, typename PatternChar>
-static int BoyerMooreHorspool(Vector<const SubjectChar> subject,
- Vector<const PatternChar> pattern,
- int start_index,
- bool* complete) {
- ASSERT(algorithm <= BOYER_MOORE_HORSPOOL);
- int n = subject.length();
- int m = pattern.length();
-
- int badness = -m;
+template <typename PatternChar, typename SubjectChar>
+int StringSearch<PatternChar, SubjectChar>::BoyerMooreHorspoolSearch(
+ StringSearch<PatternChar, SubjectChar>* search,
+ Vector<const SubjectChar> subject,
+ int start_index) {
+ Vector<const PatternChar> pattern = search->pattern_;
+ int subject_length = subject.length();
+ int pattern_length = pattern.length();
+ int* char_occurrences = search->bad_char_table();
+ int badness = -pattern_length;
// How bad we are doing without a good-suffix table.
- int idx; // No matches found prior to this index.
- PatternChar last_char = pattern[m - 1];
- int last_char_shift =
- m - 1 - CharOccurrence<SubjectChar, PatternChar>(last_char);
+ PatternChar last_char = pattern[pattern_length - 1];
+ int last_char_shift = pattern_length - 1 -
+ CharOccurrence(char_occurrences, static_cast<SubjectChar>(last_char));
// Perform search
- for (idx = start_index; idx <= n - m;) {
- int j = m - 1;
- int c;
- while (last_char != (c = subject[idx + j])) {
- int bc_occ = CharOccurrence<SubjectChar, PatternChar>(c);
+ int index = start_index; // No matches found prior to this index.
+ while (index <= subject_length - pattern_length) {
+ int j = pattern_length - 1;
+ int subject_char;
+ while (last_char != (subject_char = subject[index + j])) {
+ int bc_occ = CharOccurrence(char_occurrences, subject_char);
int shift = j - bc_occ;
- idx += shift;
+ index += shift;
badness += 1 - shift; // at most zero, so badness cannot increase.
- if (idx > n - m) {
- *complete = true;
+ if (index > subject_length - pattern_length) {
return -1;
}
}
j--;
- while (j >= 0 && pattern[j] == (subject[idx + j])) j--;
+ while (j >= 0 && pattern[j] == (subject[index + j])) j--;
if (j < 0) {
- *complete = true;
- return idx;
+ return index;
} else {
- idx += last_char_shift;
+ index += last_char_shift;
// Badness increases by the number of characters we have
// checked, and decreases by the number of characters we
// can skip by shifting. It's a measure of how we are doing
// compared to reading each character exactly once.
- badness += (m - j) - last_char_shift;
+ badness += (pattern_length - j) - last_char_shift;
if (badness > 0) {
- *complete = false;
- return idx;
+ search->PopulateBoyerMooreTable();
+ search->strategy_ = &BoyerMooreSearch;
+ return BoyerMooreSearch(search, subject, index);
}
}
}
- *complete = true;
return -1;
}
-template <typename SubjectChar, typename PatternChar>
-static int BoyerMooreIndexOf(Vector<const SubjectChar> subject,
- Vector<const PatternChar> pattern,
- int idx) {
- ASSERT(algorithm <= BOYER_MOORE);
- int n = subject.length();
- int m = pattern.length();
- // Only preprocess at most kBMMaxShift last characters of pattern.
- int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
+template <typename PatternChar, typename SubjectChar>
+void StringSearch<PatternChar, SubjectChar>::PopulateBoyerMooreHorspoolTable() {
+ int pattern_length = pattern_.length();
- PatternChar last_char = pattern[m - 1];
- // Continue search from i.
- while (idx <= n - m) {
- int j = m - 1;
- SubjectChar c;
- while (last_char != (c = subject[idx + j])) {
- int shift = j - CharOccurrence<SubjectChar, PatternChar>(c);
- idx += shift;
- if (idx > n - m) {
- return -1;
- }
- }
- while (j >= 0 && pattern[j] == (c = subject[idx + j])) j--;
- if (j < 0) {
- return idx;
- } else if (j < start) {
- // we have matched more than our tables allow us to be smart about.
- // Fall back on BMH shift.
- idx += m - 1 - CharOccurrence<SubjectChar, PatternChar>(last_char);
- } else {
- int gs_shift = BMBuffers::bmgs_buffers.shift(j + 1);
- int bc_occ = CharOccurrence<SubjectChar, PatternChar>(c);
- int shift = j - bc_occ;
- if (gs_shift > shift) {
- shift = gs_shift;
- }
- idx += shift;
+ int* bad_char_occurrence = bad_char_table();
+
+ // Only preprocess at most kBMMaxShift last characters of pattern.
+ int start = start_;
+ // Run forwards to populate bad_char_table, so that *last* instance
+ // of character equivalence class is the one registered.
+ // Notice: Doesn't include the last character.
+ int table_size = AlphabetSize();
+ if (start == 0) { // All patterns less than kBMMaxShift in length.
+ memset(bad_char_occurrence,
+ -1,
+ table_size * sizeof(*bad_char_occurrence));
+ } else {
+ for (int i = 0; i < table_size; i++) {
+ bad_char_occurrence[i] = start - 1;
}
}
-
- return -1;
+ for (int i = start; i < pattern_length - 1; i++) {
+ PatternChar c = pattern_[i];
+ int bucket = (sizeof(PatternChar) == 1) ? c : c % AlphabetSize();
+ bad_char_occurrence[bucket] = i;
+ }
}
+//---------------------------------------------------------------------
+// Linear string search with bailout to BMH.
+//---------------------------------------------------------------------
-// Trivial string search for shorter strings.
-// On return, if "complete" is set to true, the return value is the
-// final result of searching for the patter in the subject.
-// If "complete" is set to false, the return value is the index where
-// further checking should start, i.e., it's guaranteed that the pattern
-// does not occur at a position prior to the returned index.
+// Simple linear search for short patterns, which bails out if the string
+// isn't found very early in the subject. Upgrades to BoyerMooreHorspool.
template <typename PatternChar, typename SubjectChar>
-static int SimpleIndexOf(Vector<const SubjectChar> subject,
- Vector<const PatternChar> pattern,
- int idx,
- bool* complete) {
- ASSERT(pattern.length() > 1);
+int StringSearch<PatternChar, SubjectChar>::InitialSearch(
+ StringSearch<PatternChar, SubjectChar>* search,
+ Vector<const SubjectChar> subject,
+ int index) {
+ Vector<const PatternChar> pattern = search->pattern_;
int pattern_length = pattern.length();
// Badness is a count of how much work we have done. When we have
// done enough work we decide it's probably worth switching to a better
@@ -313,149 +519,52 @@ static int SimpleIndexOf(Vector<const SubjectChar> subject,
// We know our pattern is at least 2 characters, we cache the first so
// the common case of the first character not matching is faster.
PatternChar pattern_first_char = pattern[0];
- for (int i = idx, n = subject.length() - pattern_length; i <= n; i++) {
+ for (int i = index, n = subject.length() - pattern_length; i <= n; i++) {
badness++;
- if (badness > 0) {
- *complete = false;
- return i;
- }
- if (sizeof(SubjectChar) == 1 && sizeof(PatternChar) == 1) {
- const SubjectChar* pos = reinterpret_cast<const SubjectChar*>(
- memchr(subject.start() + i,
- pattern_first_char,
- n - i + 1));
- if (pos == NULL) {
- *complete = true;
- return -1;
+ if (badness <= 0) {
+ if (sizeof(SubjectChar) == 1 && sizeof(PatternChar) == 1) {
+ const SubjectChar* pos = reinterpret_cast<const SubjectChar*>(
+ memchr(subject.start() + i,
+ pattern_first_char,
+ n - i + 1));
+ if (pos == NULL) {
+ return -1;
+ }
+ i = static_cast<int>(pos - subject.start());
+ } else {
+ if (subject[i] != pattern_first_char) continue;
}
- i = static_cast<int>(pos - subject.start());
- } else {
- if (subject[i] != pattern_first_char) continue;
- }
- int j = 1;
- do {
- if (pattern[j] != subject[i+j]) {
- break;
+ int j = 1;
+ do {
+ if (pattern[j] != subject[i + j]) {
+ break;
+ }
+ j++;
+ } while (j < pattern_length);
+ if (j == pattern_length) {
+ return i;
}
- j++;
- } while (j < pattern_length);
- if (j == pattern_length) {
- *complete = true;
- return i;
- }
- badness += j;
- }
- *complete = true;
- return -1;
-}
-
-// Simple indexOf that never bails out. For short patterns only.
-template <typename PatternChar, typename SubjectChar>
-static int SimpleIndexOf(Vector<const SubjectChar> subject,
- Vector<const PatternChar> pattern,
- int idx) {
- int pattern_length = pattern.length();
- PatternChar pattern_first_char = pattern[0];
- for (int i = idx, n = subject.length() - pattern_length; i <= n; i++) {
- if (sizeof(SubjectChar) == 1 && sizeof(PatternChar) == 1) {
- const SubjectChar* pos = reinterpret_cast<const SubjectChar*>(
- memchr(subject.start() + i,
- pattern_first_char,
- n - i + 1));
- if (pos == NULL) return -1;
- i = static_cast<int>(pos - subject.start());
+ badness += j;
} else {
- if (subject[i] != pattern_first_char) continue;
- }
- int j = 1;
- while (j < pattern_length) {
- if (pattern[j] != subject[i+j]) {
- break;
- }
- j++;
- }
- if (j == pattern_length) {
- return i;
+ search->PopulateBoyerMooreHorspoolTable();
+ search->strategy_ = &BoyerMooreHorspoolSearch;
+ return BoyerMooreHorspoolSearch(search, subject, i);
}
}
return -1;
}
-// Strategy for searching for a string in another string.
-enum StringSearchStrategy { SEARCH_FAIL, SEARCH_SHORT, SEARCH_LONG };
-
-
-template <typename PatternChar>
-static inline StringSearchStrategy InitializeStringSearch(
- Vector<const PatternChar> pat, bool ascii_subject) {
- // We have an ASCII haystack and a non-ASCII needle. Check if there
- // really is a non-ASCII character in the needle and bail out if there
- // is.
- if (ascii_subject && sizeof(PatternChar) > 1) {
- for (int i = 0; i < pat.length(); i++) {
- uc16 c = pat[i];
- if (c > String::kMaxAsciiCharCode) {
- return SEARCH_FAIL;
- }
- }
- }
- if (pat.length() < kBMMinPatternLength) {
- return SEARCH_SHORT;
- }
- algorithm = SIMPLE_SEARCH;
- return SEARCH_LONG;
-}
-
-
-// Dispatch long needle searches to different algorithms.
+// Perform a a single stand-alone search.
+// If searching multiple times for the same pattern, a search
+// object should be constructed once and the Search function then called
+// for each search.
template <typename SubjectChar, typename PatternChar>
-static int ComplexIndexOf(Vector<const SubjectChar> sub,
- Vector<const PatternChar> pat,
- int start_index) {
- ASSERT(pat.length() >= kBMMinPatternLength);
- // Try algorithms in order of increasing setup cost and expected performance.
- bool complete;
- int idx = start_index;
- switch (algorithm) {
- case SIMPLE_SEARCH:
- idx = SimpleIndexOf(sub, pat, idx, &complete);
- if (complete) return idx;
- BoyerMoorePopulateBadCharTable(pat);
- algorithm = BOYER_MOORE_HORSPOOL;
- // FALLTHROUGH.
- case BOYER_MOORE_HORSPOOL:
- idx = BoyerMooreHorspool(sub, pat, idx, &complete);
- if (complete) return idx;
- // Build the Good Suffix table and continue searching.
- BoyerMoorePopulateGoodSuffixTable(pat);
- algorithm = BOYER_MOORE;
- // FALLTHROUGH.
- case BOYER_MOORE:
- return BoyerMooreIndexOf(sub, pat, idx);
- }
- UNREACHABLE();
- return -1;
-}
-
-
-// Dispatch to different search strategies for a single search.
-// If searching multiple times on the same needle, the search
-// strategy should only be computed once and then dispatch to different
-// loops.
-template <typename SubjectChar, typename PatternChar>
-static int StringSearch(Vector<const SubjectChar> sub,
- Vector<const PatternChar> pat,
+static int SearchString(Vector<const SubjectChar> subject,
+ Vector<const PatternChar> pattern,
int start_index) {
- bool ascii_subject = (sizeof(SubjectChar) == 1);
- StringSearchStrategy strategy = InitializeStringSearch(pat, ascii_subject);
- switch (strategy) {
- case SEARCH_FAIL: return -1;
- case SEARCH_SHORT: return SimpleIndexOf(sub, pat, start_index);
- case SEARCH_LONG: return ComplexIndexOf(sub, pat, start_index);
- }
- UNREACHABLE();
- return -1;
+ StringSearch<PatternChar, SubjectChar> search(pattern);
+ return search.Search(subject, start_index);
}
}} // namespace v8::internal
diff --git a/src/string.js b/src/string.js
index 30eedb3c..d97f632b 100644
--- a/src/string.js
+++ b/src/string.js
@@ -611,7 +611,7 @@ function StringSplit(separator, limit) {
if (%_ObjectEquals(cache.type, 'split') &&
%_IsRegExpEquivalent(cache.regExp, separator) &&
%_ObjectEquals(cache.subject, subject) &&
- %_ObjectEquals(cache.lastIndex, limit)) {
+ %_ObjectEquals(cache.splitLimit, limit)) {
if (cache.answerSaved) {
return CloneDenseArray(cache.answer);
} else {
@@ -622,8 +622,7 @@ function StringSplit(separator, limit) {
cache.type = 'split';
cache.regExp = separator;
cache.subject = subject;
- // Reuse lastIndex field for split limit when type is "split".
- cache.lastIndex = limit;
+ cache.splitLimit = limit;
%_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]);
diff --git a/src/strtod.cc b/src/strtod.cc
new file mode 100644
index 00000000..ae278bd9
--- /dev/null
+++ b/src/strtod.cc
@@ -0,0 +1,214 @@
+// 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 <stdarg.h>
+#include <limits.h>
+
+#include "v8.h"
+
+#include "strtod.h"
+// #include "cached-powers.h"
+
+namespace v8 {
+namespace internal {
+
+// 2^53 = 9007199254740992.
+// Any integer with at most 15 decimal digits will hence fit into a double
+// (which has a 53bit significand) without loss of precision.
+static const int kMaxExactDoubleIntegerDecimalDigits = 15;
+// 2^64 = 18446744073709551616
+// Any integer with at most 19 digits will hence fit into a 64bit datatype.
+static const int kMaxUint64DecimalDigits = 19;
+// Max double: 1.7976931348623157 x 10^308
+// Min non-zero double: 4.9406564584124654 x 10^-324
+// Any x >= 10^309 is interpreted as +infinity.
+// Any x <= 10^-324 is interpreted as 0.
+// Note that 2.5e-324 (despite being smaller than the min double) will be read
+// as non-zero (equal to the min non-zero double).
+static const int kMaxDecimalPower = 309;
+static const int kMinDecimalPower = -324;
+
+static const double exact_powers_of_ten[] = {
+ 1.0, // 10^0
+ 10.0,
+ 100.0,
+ 1000.0,
+ 10000.0,
+ 100000.0,
+ 1000000.0,
+ 10000000.0,
+ 100000000.0,
+ 1000000000.0,
+ 10000000000.0, // 10^10
+ 100000000000.0,
+ 1000000000000.0,
+ 10000000000000.0,
+ 100000000000000.0,
+ 1000000000000000.0,
+ 10000000000000000.0,
+ 100000000000000000.0,
+ 1000000000000000000.0,
+ 10000000000000000000.0,
+ 100000000000000000000.0, // 10^20
+ 1000000000000000000000.0,
+ // 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22
+ 10000000000000000000000.0
+};
+
+static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten);
+
+
+extern "C" double gay_strtod(const char* s00, const char** se);
+
+static double old_strtod(Vector<const char> buffer, int exponent) {
+ // gay_strtod is broken on Linux,x86. For numbers with few decimal digits
+ // the computation is done using floating-point operations which (on Linux)
+ // are prone to double-rounding errors.
+ // By adding several zeroes to the buffer gay_strtod falls back to a slower
+ // (but correct) algorithm.
+ const int kInsertedZeroesCount = 20;
+ char gay_buffer[1024];
+ Vector<char> gay_buffer_vector(gay_buffer, sizeof(gay_buffer));
+ int pos = 0;
+ for (int i = 0; i < buffer.length(); ++i) {
+ gay_buffer_vector[pos++] = buffer[i];
+ }
+ for (int i = 0; i < kInsertedZeroesCount; ++i) {
+ gay_buffer_vector[pos++] = '0';
+ }
+ exponent -= kInsertedZeroesCount;
+ gay_buffer_vector[pos++] = 'e';
+ if (exponent < 0) {
+ gay_buffer_vector[pos++] = '-';
+ exponent = -exponent;
+ }
+ const int kNumberOfExponentDigits = 5;
+ for (int i = kNumberOfExponentDigits - 1; i >= 0; i--) {
+ gay_buffer_vector[pos + i] = exponent % 10 + '0';
+ exponent /= 10;
+ }
+ pos += kNumberOfExponentDigits;
+ gay_buffer_vector[pos] = '\0';
+ return gay_strtod(gay_buffer, NULL);
+}
+
+
+static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) {
+ for (int i = 0; i < buffer.length(); i++) {
+ if (buffer[i] != '0') {
+ return Vector<const char>(buffer.start() + i, buffer.length() - i);
+ }
+ }
+ return Vector<const char>(buffer.start(), 0);
+}
+
+
+static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
+ for (int i = buffer.length() - 1; i >= 0; --i) {
+ if (buffer[i] != '0') {
+ return Vector<const char>(buffer.start(), i + 1);
+ }
+ }
+ return Vector<const char>(buffer.start(), 0);
+}
+
+
+uint64_t ReadUint64(Vector<const char> buffer) {
+ ASSERT(buffer.length() <= kMaxUint64DecimalDigits);
+ uint64_t result = 0;
+ for (int i = 0; i < buffer.length(); ++i) {
+ int digit = buffer[i] - '0';
+ ASSERT(0 <= digit && digit <= 9);
+ result = 10 * result + digit;
+ }
+ return result;
+}
+
+
+static bool DoubleStrtod(Vector<const char> trimmed,
+ int exponent,
+ double* result) {
+#if (defined(V8_TARGET_ARCH_IA32) || defined(USE_SIMULATOR)) && !defined(WIN32)
+ // On x86 the floating-point stack can be 64 or 80 bits wide. If it is
+ // 80 bits wide (as is the case on Linux) then double-rounding occurs and the
+ // result is not accurate.
+ // We know that Windows32 uses 64 bits and is therefore accurate.
+ // Note that the ARM simulator is compiled for 32bits. It therefore exhibits
+ // the same problem.
+ return false;
+#endif
+ if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
+ // The trimmed input fits into a double.
+ // If the 10^exponent (resp. 10^-exponent) fits into a double too then we
+ // can compute the result-double simply by multiplying (resp. dividing) the
+ // two numbers.
+ // This is possible because IEEE guarantees that floating-point operations
+ // return the best possible approximation.
+ if (exponent < 0 && -exponent < kExactPowersOfTenSize) {
+ // 10^-exponent fits into a double.
+ *result = static_cast<double>(ReadUint64(trimmed));
+ *result /= exact_powers_of_ten[-exponent];
+ return true;
+ }
+ if (0 <= exponent && exponent < kExactPowersOfTenSize) {
+ // 10^exponent fits into a double.
+ *result = static_cast<double>(ReadUint64(trimmed));
+ *result *= exact_powers_of_ten[exponent];
+ return true;
+ }
+ int remaining_digits =
+ kMaxExactDoubleIntegerDecimalDigits - trimmed.length();
+ if ((0 <= exponent) &&
+ (exponent - remaining_digits < kExactPowersOfTenSize)) {
+ // The trimmed string was short and we can multiply it with
+ // 10^remaining_digits. As a result the remaining exponent now fits
+ // into a double too.
+ *result = static_cast<double>(ReadUint64(trimmed));
+ *result *= exact_powers_of_ten[remaining_digits];
+ *result *= exact_powers_of_ten[exponent - remaining_digits];
+ return true;
+ }
+ }
+ return false;
+}
+
+
+double Strtod(Vector<const char> buffer, int exponent) {
+ Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
+ Vector<const char> trimmed = TrimTrailingZeros(left_trimmed);
+ exponent += left_trimmed.length() - trimmed.length();
+ if (trimmed.length() == 0) return 0.0;
+ if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) return V8_INFINITY;
+ if (exponent + trimmed.length() <= kMinDecimalPower) return 0.0;
+ double result;
+ if (DoubleStrtod(trimmed, exponent, &result)) {
+ return result;
+ }
+ return old_strtod(trimmed, exponent);
+}
+
+} } // namespace v8::internal
diff --git a/src/vm-state.cc b/src/strtod.h
index 6bd737df..1a5a96c8 100644
--- a/src/vm-state.cc
+++ b/src/strtod.h
@@ -25,15 +25,16 @@
// (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 "vm-state.h"
+#ifndef V8_STRTOD_H_
+#define V8_STRTOD_H_
namespace v8 {
namespace internal {
-#ifdef ENABLE_VMSTATE_TRACKING
-AtomicWord VMState::current_state_ = 0;
-#endif
+// The buffer must only contain digits in the range [0-9]. It must not
+// contain a dot or a sign. It must not start with '0', and must not be empty.
+double Strtod(Vector<const char> buffer, int exponent);
} } // namespace v8::internal
+
+#endif // V8_STRTOD_H_
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 6b41577e..e6df1b49 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -988,6 +988,7 @@ Object* StoreInterceptorProperty(Arguments args) {
Object* KeyedLoadPropertyWithInterceptor(Arguments args) {
JSObject* receiver = JSObject::cast(args[0]);
+ ASSERT(Smi::cast(args[1])->value() >= 0);
uint32_t index = Smi::cast(args[1])->value();
return receiver->GetElementWithInterceptor(receiver, index);
}
diff --git a/src/stub-cache.h b/src/stub-cache.h
index c47cab71..e4a9e955 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -626,7 +626,8 @@ class KeyedStoreStubCompiler: public StubCompiler {
V(String.prototype, charCodeAt, StringCharCodeAt) \
V(String.prototype, charAt, StringCharAt) \
V(String, fromCharCode, StringFromCharCode) \
- V(Math, floor, MathFloor)
+ V(Math, floor, MathFloor) \
+ V(Math, abs, MathAbs)
class CallStubCompiler: public StubCompiler {
diff --git a/src/top.cc b/src/top.cc
index e172cb86..9ce65429 100644
--- a/src/top.cc
+++ b/src/top.cc
@@ -69,6 +69,9 @@ void ThreadLocalTop::Initialize() {
#ifdef ENABLE_LOGGING_AND_PROFILING
js_entry_sp_ = 0;
#endif
+#ifdef ENABLE_VMSTATE_TRACKING
+ current_vm_state_ = NULL;
+#endif
try_catch_handler_address_ = NULL;
context_ = NULL;
int id = ThreadManager::CurrentId();
@@ -344,6 +347,10 @@ Handle<JSArray> Top::CaptureCurrentStackTrace(
Handle<String> column_key = Factory::LookupAsciiSymbol("column");
Handle<String> line_key = Factory::LookupAsciiSymbol("lineNumber");
Handle<String> script_key = Factory::LookupAsciiSymbol("scriptName");
+ Handle<String> name_or_source_url_key =
+ Factory::LookupAsciiSymbol("nameOrSourceURL");
+ Handle<String> script_name_or_source_url_key =
+ Factory::LookupAsciiSymbol("scriptNameOrSourceURL");
Handle<String> function_key = Factory::LookupAsciiSymbol("functionName");
Handle<String> eval_key = Factory::LookupAsciiSymbol("isEval");
Handle<String> constructor_key = Factory::LookupAsciiSymbol("isConstructor");
@@ -355,13 +362,13 @@ Handle<JSArray> Top::CaptureCurrentStackTrace(
Handle<JSObject> stackFrame = Factory::NewJSObject(object_function());
JavaScriptFrame* frame = it.frame();
- JSFunction* fun(JSFunction::cast(frame->function()));
- Script* script = Script::cast(fun->shared()->script());
+ Handle<JSFunction> fun(JSFunction::cast(frame->function()));
+ Handle<Script> script(Script::cast(fun->shared()->script()));
if (options & StackTrace::kLineNumber) {
int script_line_offset = script->line_offset()->value();
int position = frame->code()->SourcePosition(frame->pc());
- int line_number = GetScriptLineNumber(Handle<Script>(script), position);
+ int line_number = GetScriptLineNumber(script, position);
// line_number is already shifted by the script_line_offset.
int relative_line_number = line_number - script_line_offset;
if (options & StackTrace::kColumnOffset && relative_line_number >= 0) {
@@ -385,6 +392,22 @@ Handle<JSArray> Top::CaptureCurrentStackTrace(
SetProperty(stackFrame, script_key, script_name, NONE);
}
+ if (options & StackTrace::kScriptNameOrSourceURL) {
+ Handle<Object> script_name(script->name());
+ Handle<JSValue> script_wrapper = GetScriptWrapper(script);
+ Handle<Object> property = GetProperty(script_wrapper,
+ name_or_source_url_key);
+ ASSERT(property->IsJSFunction());
+ Handle<JSFunction> method = Handle<JSFunction>::cast(property);
+ bool caught_exception;
+ Handle<Object> result = Execution::TryCall(method, script_wrapper, 0,
+ NULL, &caught_exception);
+ if (caught_exception) {
+ result = Factory::undefined_value();
+ }
+ SetProperty(stackFrame, script_name_or_source_url_key, result, NONE);
+ }
+
if (options & StackTrace::kFunctionName) {
Handle<Object> fun_name(fun->shared()->name());
if (fun_name->ToBoolean()->IsFalse()) {
diff --git a/src/top.h b/src/top.h
index 776c43e3..a2ba3ddd 100644
--- a/src/top.h
+++ b/src/top.h
@@ -41,6 +41,7 @@ namespace internal {
class SaveContext; // Forward declaration.
class ThreadVisitor; // Defined in v8threads.h
+class VMState; // Defined in vm-state.h
class ThreadLocalTop BASE_EMBEDDED {
public:
@@ -101,10 +102,15 @@ class ThreadLocalTop BASE_EMBEDDED {
// Stack.
Address c_entry_fp_; // the frame pointer of the top c entry frame
Address handler_; // try-blocks are chained through the stack
+
#ifdef ENABLE_LOGGING_AND_PROFILING
Address js_entry_sp_; // the stack pointer of the bottom js entry frame
#endif
+#ifdef ENABLE_VMSTATE_TRACKING
+ VMState* current_vm_state_;
+#endif
+
// Generated code scratch locations.
int32_t formal_count_;
@@ -254,6 +260,16 @@ class Top {
}
#endif
+#ifdef ENABLE_VMSTATE_TRACKING
+ static VMState* current_vm_state() {
+ return thread_local_.current_vm_state_;
+ }
+
+ static void set_current_vm_state(VMState* state) {
+ thread_local_.current_vm_state_ = state;
+ }
+#endif
+
// Generated code scratch locations.
static void* formal_count_address() { return &thread_local_.formal_count_; }
diff --git a/src/utils.h b/src/utils.h
index fefbfe9a..ffdb639e 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -222,11 +222,21 @@ uint32_t ComputeIntegerHash(uint32_t key);
// ----------------------------------------------------------------------------
// I/O support.
-// Our version of printf(). Avoids compilation errors that we get
-// with standard printf when attempting to print pointers, etc.
-// (the errors are due to the extra compilation flags, which we
-// want elsewhere).
-void PrintF(const char* format, ...);
+#if __GNUC__ >= 4
+// On gcc we can ask the compiler to check the types of %d-style format
+// specifiers and their associated arguments. TODO(erikcorry) fix this
+// so it works on MacOSX.
+#if defined(__MACH__) && defined(__APPLE__)
+#define PRINTF_CHECKING
+#else // MacOsX.
+#define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2)))
+#endif
+#else
+#define PRINTF_CHECKING
+#endif
+
+// Our version of printf().
+void PRINTF_CHECKING PrintF(const char* format, ...);
// Our version of fflush.
void Flush();
diff --git a/src/v8-counters.h b/src/v8-counters.h
index a8eb9d2a..60e8741d 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -1,4 +1,4 @@
-// Copyright 2007-2008 the V8 project authors. All rights reserved.
+// 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:
@@ -45,14 +45,7 @@ namespace internal {
/* Total compilation times. */ \
HT(compile, V8.Compile) \
HT(compile_eval, V8.CompileEval) \
- HT(compile_lazy, V8.CompileLazy) \
- /* Individual compiler passes. */ \
- HT(rewriting, V8.Rewriting) \
- HT(usage_analysis, V8.UsageAnalysis) \
- HT(variable_allocation, V8.VariableAllocation) \
- HT(ast_optimization, V8.ASTOptimization) \
- HT(code_generation, V8.CodeGeneration) \
- HT(deferred_code_generation, V8.DeferredCodeGeneration)
+ HT(compile_lazy, V8.CompileLazy)
// WARNING: STATS_COUNTER_LIST_* is a very large macro that is causing MSVC
@@ -161,6 +154,8 @@ namespace internal {
SC(named_load_inline_miss, V8.NamedLoadInlineMiss) \
SC(named_load_global_inline, V8.NamedLoadGlobalInline) \
SC(named_load_global_inline_miss, V8.NamedLoadGlobalInlineMiss) \
+ SC(dont_delete_hint_hit, V8.DontDeleteHintHit) \
+ SC(dont_delete_hint_miss, V8.DontDeleteHintMiss) \
SC(named_load_global_stub, V8.NamedLoadGlobalStub) \
SC(named_load_global_stub_miss, V8.NamedLoadGlobalStubMiss) \
SC(keyed_store_field, V8.KeyedStoreField) \
diff --git a/src/v8.cc b/src/v8.cc
index 23139670..b30564a3 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -68,7 +68,7 @@ bool V8::Initialize(Deserializer* des) {
OS::Setup();
// Initialize other runtime facilities
-#if !V8_HOST_ARCH_ARM && V8_TARGET_ARCH_ARM
+#if (defined(USE_SIMULATOR) || !V8_HOST_ARCH_ARM) && V8_TARGET_ARCH_ARM
::assembler::arm::Simulator::Initialize();
#endif
diff --git a/src/v8natives.js b/src/v8natives.js
index ca1c99d4..88aea9c1 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -547,11 +547,11 @@ function DefineOwnProperty(obj, p, desc, should_throw) {
if (!IS_UNDEFINED(current) && !current.isConfigurable()) {
// Step 5 and 6
- if ((!desc.hasEnumerable() ||
+ if ((!desc.hasEnumerable() ||
SameValue(desc.isEnumerable() && current.isEnumerable())) &&
- (!desc.hasConfigurable() ||
+ (!desc.hasConfigurable() ||
SameValue(desc.isConfigurable(), current.isConfigurable())) &&
- (!desc.hasWritable() ||
+ (!desc.hasWritable() ||
SameValue(desc.isWritable(), current.isWritable())) &&
(!desc.hasValue() ||
SameValue(desc.getValue(), current.getValue())) &&
@@ -755,7 +755,7 @@ function ObjectSeal(obj) {
var desc = GetOwnProperty(obj, name);
if (desc.isConfigurable()) desc.setConfigurable(false);
DefineOwnProperty(obj, name, desc, true);
- }
+ }
return ObjectPreventExtension(obj);
}
@@ -772,7 +772,7 @@ function ObjectFreeze(obj) {
if (IsDataDescriptor(desc)) desc.setWritable(false);
if (desc.isConfigurable()) desc.setConfigurable(false);
DefineOwnProperty(obj, name, desc, true);
- }
+ }
return ObjectPreventExtension(obj);
}
@@ -1118,12 +1118,12 @@ function FunctionBind(this_arg) { // Length is 1.
var bound_args = new $Array(argc_bound);
for(var i = 0; i < argc_bound; i++) {
bound_args[i] = %_Arguments(i+1);
- }
+ }
}
var fn = this;
var result = function() {
// Combine the args we got from the bind call with the args
- // given as argument to the invocation.
+ // given as argument to the invocation.
var argc = %_ArgumentsLength();
var args = new $Array(argc + argc_bound);
// Add bound arguments.
@@ -1132,7 +1132,7 @@ function FunctionBind(this_arg) { // Length is 1.
}
// Add arguments from call.
for (var i = 0; i < argc; i++) {
- args[argc_bound + i] = %_Arguments(i);
+ args[argc_bound + i] = %_Arguments(i);
}
// If this is a construct call we use a special runtime method
// to generate the actual object using the bound function.
@@ -1147,7 +1147,7 @@ function FunctionBind(this_arg) { // Length is 1.
// try to redefine these as defined by the spec. The spec says
// that bind should make these throw a TypeError if get or set
// is called and make them non-enumerable and non-configurable.
- // To be consistent with our normal functions we leave this as it is.
+ // To be consistent with our normal functions we leave this as it is.
// Set the correct length.
var length = (this.length - argc_bound) > 0 ? this.length - argc_bound : 0;
diff --git a/src/version.cc b/src/version.cc
index 5be1e822..6d98b044 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -33,10 +33,10 @@
// NOTE these macros are used by the SCons build script so their names
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 2
-#define MINOR_VERSION 4
-#define BUILD_NUMBER 7
+#define MINOR_VERSION 5
+#define BUILD_NUMBER 1
#define PATCH_LEVEL 0
-#define CANDIDATE_VERSION true
+#define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the
// shared library instead the generic SONAME generated from the V8 version
diff --git a/src/vm-state-inl.h b/src/vm-state-inl.h
index aa4cedbb..74f4a6a7 100644
--- a/src/vm-state-inl.h
+++ b/src/vm-state-inl.h
@@ -75,9 +75,9 @@ VMState::VMState(StateTag state)
#endif
state_ = state;
// Save the previous state.
- previous_ = reinterpret_cast<VMState*>(current_state_);
+ previous_ = Top::current_vm_state();
// Install the new state.
- OS::ReleaseStore(&current_state_, reinterpret_cast<AtomicWord>(this));
+ Top::set_current_vm_state(this);
#ifdef ENABLE_LOGGING_AND_PROFILING
if (FLAG_log_state_changes) {
@@ -106,7 +106,7 @@ VMState::VMState(StateTag state)
VMState::~VMState() {
if (disabled_) return;
// Return to the previous state.
- OS::ReleaseStore(&current_state_, reinterpret_cast<AtomicWord>(previous_));
+ Top::set_current_vm_state(previous_);
#ifdef ENABLE_LOGGING_AND_PROFILING
if (FLAG_log_state_changes) {
diff --git a/src/vm-state.h b/src/vm-state.h
index 080eb8de..cc91e837 100644
--- a/src/vm-state.h
+++ b/src/vm-state.h
@@ -28,6 +28,8 @@
#ifndef V8_VM_STATE_H_
#define V8_VM_STATE_H_
+#include "top.h"
+
namespace v8 {
namespace internal {
@@ -44,16 +46,16 @@ class VMState BASE_EMBEDDED {
// Used for debug asserts.
static bool is_outermost_external() {
- return current_state_ == 0;
+ return Top::current_vm_state() == 0;
}
static StateTag current_state() {
- VMState* state = reinterpret_cast<VMState*>(current_state_);
+ VMState* state = Top::current_vm_state();
return state ? state->state() : EXTERNAL;
}
static Address external_callback() {
- VMState* state = reinterpret_cast<VMState*>(current_state_);
+ VMState* state = Top::current_vm_state();
return state ? state->external_callback_ : NULL;
}
@@ -63,8 +65,6 @@ class VMState BASE_EMBEDDED {
VMState* previous_;
Address external_callback_;
- // A stack of VM states.
- static AtomicWord current_state_;
#else
public:
explicit VMState(StateTag state) {}
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index 08c19ba6..0dead6b7 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -715,7 +715,7 @@ static void ArrayNativeCode(MacroAssembler* masm,
__ cmpq(rax, Immediate(1));
__ j(not_equal, &argc_two_or_more);
__ movq(rdx, Operand(rsp, kPointerSize)); // Get the argument from the stack.
- __ JumpIfNotPositiveSmi(rdx, call_generic_code);
+ __ JumpUnlessNonNegativeSmi(rdx, call_generic_code);
// Handle construction of an empty array of a certain size. Bail out if size
// is to large to actually allocate an elements array.
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 9d82e0e3..2d87667b 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -1413,20 +1413,8 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
__ j(equal, &done);
}
__ SmiNeg(rax, rax, &done);
+ __ jmp(&slow); // zero, if not handled above, and Smi::kMinValue.
- // Either zero or Smi::kMinValue, neither of which become a smi when
- // negated. We handle negative zero here if required. We always enter
- // the runtime system if we have Smi::kMinValue.
- if (negative_zero_ == kStrictNegativeZero) {
- __ SmiCompare(rax, Smi::FromInt(0));
- __ j(not_equal, &slow);
- __ Move(rax, Factory::minus_zero_value());
- __ jmp(&done);
- } else {
- __ SmiCompare(rax, Smi::FromInt(Smi::kMinValue));
- __ j(equal, &slow);
- __ jmp(&done);
- }
// Try floating point case.
__ bind(&try_float);
} else if (FLAG_debug_code) {
@@ -2135,7 +2123,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ JumpIfNotBothSmi(rax, rdx, &non_smi);
__ subq(rdx, rax);
__ j(no_overflow, &smi_done);
- __ neg(rdx); // Correct sign in case of overflow.
+ __ not_(rdx); // Correct sign in case of overflow. rdx cannot be 0 here.
__ bind(&smi_done);
__ movq(rax, rdx);
__ ret(0);
@@ -2406,16 +2394,7 @@ void CompareStub::BranchIfNonSymbol(MacroAssembler* masm,
void StackCheckStub::Generate(MacroAssembler* masm) {
- // Because builtins always remove the receiver from the stack, we
- // have to fake one to avoid underflowing the stack. The receiver
- // must be inserted below the return address on the stack so we
- // temporarily store that in a register.
- __ pop(rax);
- __ Push(Smi::FromInt(0));
- __ push(rax);
-
- // Do tail-call to runtime routine.
- __ TailCallRuntime(Runtime::kStackGuard, 1, 1);
+ __ TailCallRuntime(Runtime::kStackGuard, 0, 1);
}
@@ -3801,7 +3780,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
Label result_longer_than_two;
__ movq(rcx, Operand(rsp, kToOffset));
__ movq(rdx, Operand(rsp, kFromOffset));
- __ JumpIfNotBothPositiveSmi(rcx, rdx, &runtime);
+ __ JumpUnlessBothNonNegativeSmi(rcx, rdx, &runtime);
__ SmiSub(rcx, rcx, rdx); // Overflow doesn't happen.
__ cmpq(FieldOperand(rax, String::kLengthOffset), rcx);
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index 0d8b827d..9e6ef3b5 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -178,22 +178,12 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Adjust for function-level loop nesting.
ASSERT_EQ(0, loop_nesting_);
- loop_nesting_ = info->loop_nesting();
+ loop_nesting_ = info->is_in_loop() ? 1 : 0;
JumpTarget::set_compiling_deferred_code(false);
-#ifdef DEBUG
- if (strlen(FLAG_stop_at) > 0 &&
- info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
- frame_->SpillAll();
- __ int3();
- }
-#endif
-
- // New scope to get automatic timing calculation.
- { HistogramTimerScope codegen_timer(&Counters::code_generation);
+ {
CodeGenState state(this);
-
// Entry:
// Stack: receiver, arguments, return address.
// rbp: caller's frame pointer
@@ -202,6 +192,14 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// rsi: callee's context
allocator_->Initialize();
+#ifdef DEBUG
+ if (strlen(FLAG_stop_at) > 0 &&
+ info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+ frame_->SpillAll();
+ __ int3();
+ }
+#endif
+
frame_->Enter();
// Allocate space for locals and initialize them.
@@ -356,7 +354,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
}
// Adjust for function-level loop nesting.
- ASSERT_EQ(loop_nesting_, info->loop_nesting());
+ ASSERT_EQ(loop_nesting_, info->is_in_loop() ? 1 : 0);
loop_nesting_ = 0;
// Code generation state must be reset.
@@ -367,7 +365,6 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Process any deferred code using the register allocator.
if (!HasStackOverflow()) {
- HistogramTimerScope deferred_timer(&Counters::deferred_code_generation);
JumpTarget::set_compiling_deferred_code(true);
ProcessDeferred();
JumpTarget::set_compiling_deferred_code(false);
@@ -1884,8 +1881,7 @@ Result CodeGenerator::ConstantSmiBinaryOperation(BinaryOperation* expr,
operand->reg(),
smi_value,
overwrite_mode);
- // Check for negative or non-Smi left hand side.
- __ JumpIfNotPositiveSmi(operand->reg(), deferred->entry_label());
+ __ JumpUnlessNonNegativeSmi(operand->reg(), deferred->entry_label());
if (int_value < 0) int_value = -int_value;
if (int_value == 1) {
__ Move(operand->reg(), Smi::FromInt(0));
@@ -4277,9 +4273,12 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
// Build the function info and instantiate it.
Handle<SharedFunctionInfo> function_info =
- Compiler::BuildFunctionInfo(node, script(), this);
+ Compiler::BuildFunctionInfo(node, script());
// Check for stack-overflow exception.
- if (HasStackOverflow()) return;
+ if (function_info.is_null()) {
+ SetStackOverflow();
+ return;
+ }
InstantiateFunction(function_info);
}
@@ -5684,9 +5683,9 @@ void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
Result value = frame_->Pop();
value.ToRegister();
ASSERT(value.is_valid());
- Condition positive_smi = masm_->CheckPositiveSmi(value.reg());
+ Condition non_negative_smi = masm_->CheckNonNegativeSmi(value.reg());
value.Unuse();
- destination()->Split(positive_smi);
+ destination()->Split(non_negative_smi);
}
@@ -6911,7 +6910,7 @@ void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) {
deferred->Branch(not_equal);
// Check that both indices are smis.
- Condition both_smi = __ CheckBothSmi(index1.reg(), index2.reg());
+ Condition both_smi = masm()->CheckBothSmi(index1.reg(), index2.reg());
deferred->Branch(NegateCondition(both_smi));
// Bring addresses into index1 and index2.
@@ -8377,7 +8376,7 @@ Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
}
// Check that the receiver is a heap object.
- Condition is_smi = __ CheckSmi(receiver.reg());
+ Condition is_smi = masm()->CheckSmi(receiver.reg());
slow.Branch(is_smi, &value, &receiver);
// This is the map check instruction that will be patched.
@@ -8506,8 +8505,7 @@ Result CodeGenerator::EmitKeyedLoad() {
kScratchRegister);
deferred->Branch(not_equal);
- // Check that the key is a non-negative smi.
- __ JumpIfNotPositiveSmi(key.reg(), deferred->entry_label());
+ __ JumpUnlessNonNegativeSmi(key.reg(), deferred->entry_label());
// Get the elements array from the receiver.
__ movq(elements.reg(),
diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h
index 6e1dd727..79573245 100644
--- a/src/x64/codegen-x64.h
+++ b/src/x64/codegen-x64.h
@@ -298,9 +298,7 @@ enum ArgumentsAllocationMode {
class CodeGenerator: public AstVisitor {
public:
- // Takes a function literal, generates code for it. This function should only
- // be called by compiler.cc.
- static Handle<Code> MakeCode(CompilationInfo* info);
+ static bool MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(CompilationInfo* info);
@@ -586,9 +584,6 @@ class CodeGenerator: public AstVisitor {
void CheckStack();
- static InlineFunctionGenerator FindInlineFunctionGenerator(
- Runtime::FunctionId function_id);
-
bool CheckForInlineRuntimeCall(CallRuntime* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index c15860c7..32d62426 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -61,6 +61,12 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator");
+#ifdef DEBUG
+ if (strlen(FLAG_stop_at) > 0 &&
+ info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+ __ int3();
+ }
+#endif
__ push(rbp); // Caller's frame pointer.
__ movq(rbp, rsp);
__ push(rsi); // Callee's context.
@@ -767,7 +773,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Get the current entry of the array into register rbx.
__ movq(rbx, Operand(rsp, 2 * kPointerSize));
- SmiIndex index = __ SmiToIndex(rax, rax, kPointerSizeLog2);
+ SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2);
__ movq(rbx, FieldOperand(rbx,
index.reg,
index.scale,
@@ -1407,7 +1413,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
Label done, stub_call, smi_case;
__ pop(rdx);
__ movq(rcx, rax);
- Condition smi = __ CheckBothSmi(rdx, rax);
+ Condition smi = masm()->CheckBothSmi(rdx, rax);
__ j(smi, &smi_case);
__ bind(&stub_call);
@@ -1965,8 +1971,8 @@ void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through);
- Condition positive_smi = __ CheckPositiveSmi(rax);
- Split(positive_smi, if_true, if_false, fall_through);
+ Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
+ Split(non_negative_smi, if_true, if_false, fall_through);
context()->Plug(if_true, if_false);
}
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index 62e76912..1d95b7f6 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -893,8 +893,9 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
// Check that the receiver isn't a smi.
__ JumpIfSmi(rdx, &slow);
- // Check that the key is a smi.
- __ JumpIfNotSmi(rax, &slow);
+ // Check that the key is an array index, that is Uint32.
+ STATIC_ASSERT(kSmiValueSize <= 32);
+ __ JumpUnlessNonNegativeSmi(rax, &slow);
// Get the map of the receiver.
__ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
@@ -1728,7 +1729,8 @@ bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
bool LoadIC::PatchInlinedContextualLoad(Address address,
Object* map,
- Object* cell) {
+ Object* cell,
+ bool is_dont_delete) {
// TODO(<bug#>): implement this.
return false;
}
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 869986eb..2c946f56 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -825,7 +825,7 @@ Condition MacroAssembler::CheckSmi(Register src) {
}
-Condition MacroAssembler::CheckPositiveSmi(Register src) {
+Condition MacroAssembler::CheckNonNegativeSmi(Register src) {
ASSERT_EQ(0, kSmiTag);
// Make mask 0x8000000000000001 and test that both bits are zero.
movq(kScratchRegister, src);
@@ -846,15 +846,15 @@ Condition MacroAssembler::CheckBothSmi(Register first, Register second) {
}
-Condition MacroAssembler::CheckBothPositiveSmi(Register first,
- Register second) {
+Condition MacroAssembler::CheckBothNonNegativeSmi(Register first,
+ Register second) {
if (first.is(second)) {
- return CheckPositiveSmi(first);
+ return CheckNonNegativeSmi(first);
}
movq(kScratchRegister, first);
or_(kScratchRegister, second);
rol(kScratchRegister, Immediate(1));
- testl(kScratchRegister, Immediate(0x03));
+ testl(kScratchRegister, Immediate(3));
return zero;
}
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index a8ffca91..cb910675 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -101,9 +101,9 @@ class MacroAssembler: public Assembler {
// dirty. |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 the elements array
- // represented as a Smi. All registers are clobbered by the
- // operation. RecordWrite filters out smis so it does not update the
- // write barrier if the value is a smi.
+ // represented as an untagged 32-bit integer. All registers are
+ // clobbered by the operation. RecordWrite filters out smis so it
+ // does not update the write barrier if the value is a smi.
void RecordWrite(Register object,
int offset,
Register value,
@@ -122,7 +122,7 @@ class MacroAssembler: public Assembler {
// The value is known to not be a smi.
// 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
- // the elements array represented as a Smi.
+ // the elements array represented as an untagged 32-bit integer.
// All registers are clobbered by the operation.
void RecordWriteNonSmi(Register object,
int offset,
@@ -265,14 +265,14 @@ class MacroAssembler: public Assembler {
// Is the value a tagged smi.
Condition CheckSmi(Register src);
- // Is the value a positive tagged smi.
- Condition CheckPositiveSmi(Register src);
+ // Is the value a non-negative tagged smi.
+ Condition CheckNonNegativeSmi(Register src);
// Are both values tagged smis.
Condition CheckBothSmi(Register first, Register second);
- // Are both values tagged smis.
- Condition CheckBothPositiveSmi(Register first, Register second);
+ // Are both values non-negative tagged smis.
+ Condition CheckBothNonNegativeSmi(Register first, Register second);
// Are either value a tagged smi.
Condition CheckEitherSmi(Register first,
@@ -311,9 +311,9 @@ class MacroAssembler: public Assembler {
template <typename LabelType>
void JumpIfNotSmi(Register src, LabelType* on_not_smi);
- // Jump to label if the value is not a positive tagged smi.
+ // Jump to label if the value is not a non-negative tagged smi.
template <typename LabelType>
- void JumpIfNotPositiveSmi(Register src, LabelType* on_not_smi);
+ void JumpUnlessNonNegativeSmi(Register src, LabelType* on_not_smi);
// Jump to label if the value, which must be a tagged smi, has value equal
// to the constant.
@@ -328,10 +328,10 @@ class MacroAssembler: public Assembler {
Register src2,
LabelType* on_not_both_smi);
- // Jump if either or both register are not positive smi values.
+ // Jump if either or both register are not non-negative smi values.
template <typename LabelType>
- void JumpIfNotBothPositiveSmi(Register src1, Register src2,
- LabelType* on_not_both_smi);
+ void JumpUnlessBothNonNegativeSmi(Register src1, Register src2,
+ LabelType* on_not_both_smi);
// Operations on tagged smi values.
@@ -1463,10 +1463,10 @@ void MacroAssembler::JumpIfNotSmi(Register src, LabelType* on_not_smi) {
template <typename LabelType>
-void MacroAssembler::JumpIfNotPositiveSmi(Register src,
- LabelType* on_not_positive_smi) {
- Condition positive_smi = CheckPositiveSmi(src);
- j(NegateCondition(positive_smi), on_not_positive_smi);
+void MacroAssembler::JumpUnlessNonNegativeSmi(
+ Register src, LabelType* on_not_smi_or_negative) {
+ Condition non_negative_smi = CheckNonNegativeSmi(src);
+ j(NegateCondition(non_negative_smi), on_not_smi_or_negative);
}
@@ -1505,10 +1505,10 @@ void MacroAssembler::JumpIfNotBothSmi(Register src1,
template <typename LabelType>
-void MacroAssembler::JumpIfNotBothPositiveSmi(Register src1,
- Register src2,
- LabelType* on_not_both_smi) {
- Condition both_smi = CheckBothPositiveSmi(src1, src2);
+void MacroAssembler::JumpUnlessBothNonNegativeSmi(Register src1,
+ Register src2,
+ LabelType* on_not_both_smi) {
+ Condition both_smi = CheckBothNonNegativeSmi(src1, src2);
j(NegateCondition(both_smi), on_not_both_smi);
}
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index 91e2b449..47c19c7e 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -145,7 +145,6 @@ int RegExpMacroAssemblerX64::stack_limit_slack() {
void RegExpMacroAssemblerX64::AdvanceCurrentPosition(int by) {
if (by != 0) {
- Label inside_string;
__ addq(rdi, Immediate(by * char_size()));
}
}
@@ -1053,6 +1052,19 @@ void RegExpMacroAssemblerX64::ReadStackPointerFromRegister(int reg) {
}
+void RegExpMacroAssemblerX64::SetCurrentPositionFromEnd(int by) {
+ NearLabel after_position;
+ __ cmpq(rdi, Immediate(-by * char_size()));
+ __ j(greater_equal, &after_position);
+ __ movq(rdi, Immediate(-by * char_size()));
+ // On RegExp code entry (where this operation is used), the character before
+ // the current position is expected to be already loaded.
+ // We have advanced the position, so it's safe to read backwards.
+ LoadCurrentCharacterUnchecked(-1, 1);
+ __ bind(&after_position);
+}
+
+
void RegExpMacroAssemblerX64::SetRegister(int register_index, int to) {
ASSERT(register_index >= num_saved_registers_); // Reserved for positions!
__ movq(register_location(register_index), Immediate(to));
diff --git a/src/x64/regexp-macro-assembler-x64.h b/src/x64/regexp-macro-assembler-x64.h
index 3bcc3ac1..182bc552 100644
--- a/src/x64/regexp-macro-assembler-x64.h
+++ b/src/x64/regexp-macro-assembler-x64.h
@@ -93,6 +93,7 @@ class RegExpMacroAssemblerX64: public NativeRegExpMacroAssembler {
StackCheckFlag check_stack_limit);
virtual void ReadCurrentPositionFromRegister(int reg);
virtual void ReadStackPointerFromRegister(int reg);
+ virtual void SetCurrentPositionFromEnd(int by);
virtual void SetRegister(int register_index, int to);
virtual void Succeed();
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 68b18a24..eb48da9a 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -1558,6 +1558,109 @@ Object* CallStubCompiler::CompileMathFloorCall(Object* object,
}
+Object* CallStubCompiler::CompileMathAbsCall(Object* object,
+ JSObject* holder,
+ JSGlobalPropertyCell* cell,
+ JSFunction* function,
+ String* name) {
+ // ----------- S t a t e -------------
+ // -- rcx : function name
+ // -- rsp[0] : return address
+ // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
+ // -- ...
+ // -- rsp[(argc + 1) * 8] : receiver
+ // -----------------------------------
+
+ const int argc = arguments().immediate();
+
+ // If the object is not a JSObject or we got an unexpected number of
+ // arguments, bail out to the regular call.
+ if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
+
+ Label miss;
+ GenerateNameCheck(name, &miss);
+
+ if (cell == NULL) {
+ __ movq(rdx, Operand(rsp, 2 * kPointerSize));
+
+ __ JumpIfSmi(rdx, &miss);
+
+ CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name,
+ &miss);
+ } else {
+ ASSERT(cell->value() == function);
+ GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
+ GenerateLoadFunctionFromCell(cell, function, &miss);
+ }
+
+ // Load the (only) argument into rax.
+ __ movq(rax, Operand(rsp, 1 * kPointerSize));
+
+ // Check if the argument is a smi.
+ Label not_smi;
+ STATIC_ASSERT(kSmiTag == 0);
+ __ JumpIfNotSmi(rax, &not_smi);
+ __ SmiToInteger32(rax, rax);
+
+ // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
+ // otherwise.
+ __ movl(rbx, rax);
+ __ sarl(rbx, Immediate(kBitsPerInt - 1));
+
+ // Do bitwise not or do nothing depending on ebx.
+ __ xorl(rax, rbx);
+
+ // Add 1 or do nothing depending on ebx.
+ __ subl(rax, rbx);
+
+ // If the result is still negative, go to the slow case.
+ // This only happens for the most negative smi.
+ Label slow;
+ __ j(negative, &slow);
+
+ // Smi case done.
+ __ Integer32ToSmi(rax, rax);
+ __ ret(2 * kPointerSize);
+
+ // Check if the argument is a heap number and load its value.
+ __ bind(&not_smi);
+ __ CheckMap(rax, Factory::heap_number_map(), &slow, true);
+ __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
+
+ // Check the sign of the argument. If the argument is positive,
+ // just return it.
+ Label negative_sign;
+ const int sign_mask_shift =
+ (HeapNumber::kExponentOffset - HeapNumber::kValueOffset) * kBitsPerByte;
+ __ movq(rdi, static_cast<int64_t>(HeapNumber::kSignMask) << sign_mask_shift,
+ RelocInfo::NONE);
+ __ testq(rbx, rdi);
+ __ j(not_zero, &negative_sign);
+ __ ret(2 * kPointerSize);
+
+ // If the argument is negative, clear the sign, and return a new
+ // number. We still have the sign mask in rdi.
+ __ bind(&negative_sign);
+ __ xor_(rbx, rdi);
+ __ AllocateHeapNumber(rax, rdx, &slow);
+ __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx);
+ __ ret(2 * kPointerSize);
+
+ // Tail call the full function. We do not have to patch the receiver
+ // because the function makes no use of it.
+ __ bind(&slow);
+ __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
+
+ __ bind(&miss);
+ // rcx: function name.
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
+
+ // Return the generated code.
+ return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
+}
+
+
Object* CallStubCompiler::CompileCallInterceptor(JSObject* object,
JSObject* holder,
String* name) {