Commit 22e6958d authored by yangguo's avatar yangguo Committed by Commit bot

Fix remaining issues in the custom snapshot.

Math functions:
Some Math functions require typed arrays for their implementation. The embedded
script may call those Math functions. The serializer needs to deal with this.
Added assertion to make sure no other typed array is created when snapshotting.

Number-string cache:
We assume that the initial snapshot does not expand the number-string cache.
This is no longer true for custom heap snapshots.

Bound functions:
Bound functions store the bound arguments in a COW fixed array, including the
bindee function. COW arrays are serialized into the startup snapshot and
referenced in the partial snapshot via partial snapshot cache. However, the
bindee function is context-dependent and must not be part of the startup
snapshot. There is no need for bound functions to use a COW array though.

R=jochen@chromium.org

Review URL: https://codereview.chromium.org/851073002

Cr-Commit-Position: refs/heads/master@{#26072}
parent 1a5db24e
......@@ -2791,10 +2791,9 @@ Genesis::Genesis(Isolate* isolate,
if (!InstallExperimentalNatives()) return;
InitializeExperimentalGlobal();
// We can't (de-)serialize typed arrays currently, but we are lucky: The state
// of the random number generator needs no initialization during snapshot
// creation time and we don't need trigonometric functions then.
if (!isolate->serializer_enabled()) {
// The serializer cannot serialize typed arrays. Reset those typed arrays
// for each new context.
{
// Initially seed the per-context random number generator using the
// per-isolate random number generator.
const int num_elems = 2;
......
......@@ -2149,12 +2149,6 @@ void Factory::SetNumberStringCache(Handle<Object> number,
if (number_string_cache()->get(hash * 2) != *undefined_value()) {
int full_size = isolate()->heap()->FullSizeNumberStringCacheLength();
if (number_string_cache()->length() != full_size) {
// The first time we have a hash collision, we move to the full sized
// number string cache. The idea is to have a small number string
// cache in the snapshot to keep boot-time memory usage down.
// If we expand the number string cache already while creating
// the snapshot then that didn't work out.
DCHECK(!isolate()->serializer_enabled());
Handle<FixedArray> new_cache = NewFixedArray(full_size, TENURED);
isolate()->heap()->set_number_string_cache(*new_cache);
return;
......
......@@ -1486,6 +1486,10 @@ class Heap {
MUST_USE_RESULT AllocationResult
AllocateFixedArray(int length, PretenureFlag pretenure = NOT_TENURED);
static const int kInitialStringTableSize = 2048;
static const int kInitialEvalCacheSize = 64;
static const int kInitialNumberStringCacheSize = 256;
private:
Heap();
......@@ -2043,10 +2047,6 @@ class Heap {
inline void UpdateAllocationsHash(uint32_t value);
inline void PrintAlloctionsHash();
static const int kInitialStringTableSize = 2048;
static const int kInitialEvalCacheSize = 64;
static const int kInitialNumberStringCacheSize = 256;
// Object counts and used memory by InstanceType
size_t object_counts_[OBJECT_STATS_COUNT];
size_t object_counts_last_time_[OBJECT_STATS_COUNT];
......
......@@ -6186,7 +6186,7 @@ void JSFunction::set_function_bindings(FixedArray* bindings) {
// Bound function literal may be initialized to the empty fixed array
// before the bindings are set.
DCHECK(bindings == GetHeap()->empty_fixed_array() ||
bindings->map() == GetHeap()->fixed_cow_array_map());
bindings->map() == GetHeap()->fixed_array_map());
set_literals_or_bindings(bindings);
}
......
......@@ -435,8 +435,7 @@ RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
for (int j = 0; j < argc; j++, i++) {
new_bindings->set(i, *arguments[j + 1]);
}
new_bindings->set_map_no_write_barrier(
isolate->heap()->fixed_cow_array_map());
new_bindings->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
bound_function->set_function_bindings(*new_bindings);
// Update length. Have to remove the prototype first so that map migration
......@@ -462,8 +461,8 @@ RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) {
if (callable->IsJSFunction()) {
Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
if (function->shared()->bound()) {
RUNTIME_ASSERT(function->function_bindings()->IsFixedArray());
Handle<FixedArray> bindings(function->function_bindings());
RUNTIME_ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
return *isolate->factory()->NewJSArrayWithElements(bindings);
}
}
......
......@@ -63,6 +63,8 @@ bool Runtime::SetupArrayBufferAllocatingData(Isolate* isolate,
bool initialize) {
void* data;
CHECK(V8::ArrayBufferAllocator() != NULL);
// Prevent creating array buffers when serializing.
DCHECK(!isolate->serializer_enabled());
if (allocated_length != 0) {
if (initialize) {
data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
......
......@@ -1665,6 +1665,9 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
DCHECK(Map::cast(obj)->code_cache() == obj->GetHeap()->empty_fixed_array());
}
// Replace typed arrays by undefined.
if (obj->IsJSTypedArray()) obj = isolate_->heap()->undefined_value();
int root_index = root_index_map_.Lookup(obj);
if (root_index != RootIndexMap::kInvalidRootIndex) {
PutRoot(root_index, obj, how_to_code, where_to_point, skip);
......@@ -1832,6 +1835,9 @@ void Serializer::ObjectSerializer::Serialize() {
PrintF("\n");
}
// We cannot serialize typed array objects correctly.
DCHECK(!object_->IsJSTypedArray());
if (object_->IsScript()) {
// Clear cached line ends.
Object* undefined = serializer_->isolate()->heap()->undefined_value();
......
......@@ -99,6 +99,7 @@ class TestHeap : public i::Heap {
using i::Heap::AllocateJSObjectFromMap;
using i::Heap::AllocateMap;
using i::Heap::CopyCode;
using i::Heap::kInitialNumberStringCacheSize;
};
......
......@@ -261,7 +261,7 @@ TEST(BoundFunctionInSnapshot) {
GetProperty(f, v8::HeapGraphEdge::kInternal, "bindings");
CHECK_NE(NULL, bindings);
CHECK_EQ(v8::HeapGraphNode::kArray, bindings->GetType());
CHECK_EQ(4, bindings->GetChildrenCount());
CHECK_EQ(3, bindings->GetChildrenCount());
const v8::HeapGraphNode* bound_this = GetProperty(
f, v8::HeapGraphEdge::kShortcut, "bound_this");
......
......@@ -5089,6 +5089,16 @@ TEST(Regress442710) {
}
TEST(NumberStringCacheSize) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
// Test that the number-string cache has not been resized.
CHECK_EQ(TestHeap::kInitialNumberStringCacheSize * 2,
heap->number_string_cache()->length());
}
#ifdef DEBUG
TEST(PathTracer) {
CcTest::InitializeVM();
......
......@@ -565,7 +565,9 @@ UNINITIALIZED_TEST(CustomContextSerialization) {
"(function() {"
" e = function(s) { eval (s); }"
"})();"
"var o = this;");
"var o = this;"
"var r = Math.random();"
"var f = (function(a, b) {}).bind(1, 2, 3);");
}
// Make sure all builtin scripts are cached.
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment