Revision: 3792
Author: [email protected]
Date: Thu Feb 4 00:02:41 2010
Log: * Add the partial context snapshot to the VM executable if
running with snapshots.
* Create contexts from partial snapshot if they contain no
extensions or global object templates. Add counters to track
when this happens.
* Remove debugging (logging code).
* Some lint fixes.
Review URL: http://codereview.chromium.org/565047
http://code.google.com/p/v8/source/detail?r=3792
Modified:
/branches/experimental/partial_snapshots/include/v8.h
/branches/experimental/partial_snapshots/src/api.cc
/branches/experimental/partial_snapshots/src/bootstrapper.cc
/branches/experimental/partial_snapshots/src/bootstrapper.h
/branches/experimental/partial_snapshots/src/frames.cc
/branches/experimental/partial_snapshots/src/heap.h
/branches/experimental/partial_snapshots/src/mksnapshot.cc
/branches/experimental/partial_snapshots/src/serialize.cc
/branches/experimental/partial_snapshots/src/serialize.h
/branches/experimental/partial_snapshots/src/snapshot-common.cc
/branches/experimental/partial_snapshots/src/snapshot-empty.cc
/branches/experimental/partial_snapshots/src/snapshot.h
/branches/experimental/partial_snapshots/src/v8-counters.h
/branches/experimental/partial_snapshots/src/v8threads.cc
/branches/experimental/partial_snapshots/test/cctest/test-serialize.cc
=======================================
--- /branches/experimental/partial_snapshots/include/v8.h Mon Jan 11
04:13:24 2010
+++ /branches/experimental/partial_snapshots/include/v8.h Thu Feb 4
00:02:41 2010
@@ -2586,8 +2586,9 @@
void DetachGlobal();
/** Creates a new context. */
+ static Persistent<Context> New();
static Persistent<Context> New(
- ExtensionConfiguration* extensions = 0,
+ ExtensionConfiguration* extensions,
Handle<ObjectTemplate> global_template = Handle<ObjectTemplate>(),
Handle<Value> global_object = Handle<Value>());
=======================================
--- /branches/experimental/partial_snapshots/src/api.cc Wed Feb 3 02:52:22
2010
+++ /branches/experimental/partial_snapshots/src/api.cc Thu Feb 4 00:02:41
2010
@@ -2732,6 +2732,37 @@
return i::Handle<i::FunctionTemplateInfo>(
i::FunctionTemplateInfo::cast(templ->constructor()));
}
+
+
+Persistent<Context> v8::Context::New() {
+ EnsureInitialized("v8::Context::New()");
+ LOG_API("Context::New");
+ ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
+
+ if (i::Bootstrapper::AutoExtensionsExist()) {
+ return New(0);
+ }
+
+ // Enter V8 via an ENTER_V8 scope.
+ Persistent<Context> result;
+ {
+ ENTER_V8;
+ HandleScope scope;
+#if defined(ANDROID)
+ // On mobile device, full GC is expensive, leave it to the system to
+ // decide when should make a full GC.
+#else
+ // Give the heap a chance to cleanup if we've disposed contexts.
+ i::Heap::CollectAllGarbageIfContextDisposed();
+#endif
+ i::Handle<i::Context> env = i::Snapshot::NewContextFromSnapshot();
+ if (env.is_null()) {
+ return New(0);
+ }
+ i::Counters::contexts_created_by_snapshot.Increment();
+ return Persistent<Context>::New(Utils::ToLocal(env));
+ }
+}
Persistent<Context> v8::Context::New(
@@ -2741,6 +2772,7 @@
EnsureInitialized("v8::Context::New()");
LOG_API("Context::New");
ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
+ i::Counters::contexts_created_from_scratch.Increment();
// Enter V8 via an ENTER_V8 scope.
i::Handle<i::Context> env;
=======================================
--- /branches/experimental/partial_snapshots/src/bootstrapper.cc Wed Feb 3
02:52:22 2010
+++ /branches/experimental/partial_snapshots/src/bootstrapper.cc Thu Feb 4
00:02:41 2010
@@ -1262,7 +1262,7 @@
current->set_state(v8::UNVISITED);
current = current->next();
}
- // Install auto extensions
+ // Install auto extensions. Coordinate with AutoExtensionsExist below.
current = v8::RegisteredExtension::first_extension();
while (current != NULL) {
if (current->extension()->auto_enable())
@@ -1613,6 +1613,19 @@
void Bootstrapper::FreeThreadResources() {
ASSERT(Genesis::current() == NULL);
}
+
+
+// Are there extensions that should be installed even if no extension was
+// specified?
+bool Bootstrapper::AutoExtensionsExist() {
+ // Find auto extensions.
+ v8::RegisteredExtension* current =
v8::RegisteredExtension::first_extension();
+ while (current != NULL) {
+ if (current->extension()->auto_enable()) return true;
+ current = current->next();
+ }
+ return FLAG_expose_gc;
+}
// Reserve space for statics needing saving and restoring.
=======================================
--- /branches/experimental/partial_snapshots/src/bootstrapper.h Wed Feb 3
02:52:22 2010
+++ /branches/experimental/partial_snapshots/src/bootstrapper.h Thu Feb 4
00:02:41 2010
@@ -75,6 +75,9 @@
// This will allocate a char array that is deleted when V8 is shut down.
// It should only be used for strictly finite allocations.
static char* AllocateAutoDeletedArray(int bytes);
+
+ // Used for new context creation.
+ static bool AutoExtensionsExist();
};
=======================================
--- /branches/experimental/partial_snapshots/src/frames.cc Wed Feb 3
02:52:22 2010
+++ /branches/experimental/partial_snapshots/src/frames.cc Thu Feb 4
00:02:41 2010
@@ -359,7 +359,6 @@
for (StackHandlerIterator it(this, top_handler()); !it.done();
it.Advance()) {
it.handler()->Cook(code);
}
- printf("Cook %p (%d)\n", (void*)(pc()), code->kind());
ASSERT(code->contains(pc()));
set_pc(AddressFrom<Address>(pc() - code->instruction_start()));
}
@@ -372,7 +371,6 @@
it.handler()->Uncook(code);
}
set_pc(code->instruction_start() + OffsetFrom(pc()));
- printf("Uncook %p (%d)\n", (void*)(pc()), code->kind());
ASSERT(code->contains(pc()));
}
=======================================
--- /branches/experimental/partial_snapshots/src/heap.h Wed Feb 3 02:52:22
2010
+++ /branches/experimental/partial_snapshots/src/heap.h Thu Feb 4 00:02:41
2010
@@ -1477,12 +1477,10 @@
public:
AssertNoAllocation() {
old_state_ = Heap::allow_allocation(false);
- //printf("No allocation\n");
}
~AssertNoAllocation() {
Heap::allow_allocation(old_state_);
- //printf("Allocation\n");
}
private:
=======================================
--- /branches/experimental/partial_snapshots/src/mksnapshot.cc Wed Feb 3
02:52:22 2010
+++ /branches/experimental/partial_snapshots/src/mksnapshot.cc Thu Feb 4
00:02:41 2010
@@ -35,6 +35,7 @@
#include "natives.h"
#include "platform.h"
#include "serialize.h"
+#include "list.h"
// use explicit namespace to avoid clashing with types in namespace v8
namespace i = v8::internal;
@@ -96,7 +97,9 @@
class CppByteSink : public i::SnapshotByteSink {
public:
- explicit CppByteSink(const char* snapshot_file) : bytes_written_(0) {
+ explicit CppByteSink(const char* snapshot_file)
+ : bytes_written_(0),
+ partial_sink_(this) {
fp_ = i::OS::FOpen(snapshot_file, "wb");
if (fp_ == NULL) {
i::PrintF("Unable to write to snapshot file \"%s\"\n",
snapshot_file);
@@ -111,22 +114,63 @@
}
virtual ~CppByteSink() {
- if (fp_ != NULL) {
- fprintf(fp_, "};\n\n");
- fprintf(fp_, "int Snapshot::size_ = %d;\n\n", bytes_written_);
- fprintf(fp_, "} } // namespace v8::internal\n");
- fclose(fp_);
+ fprintf(fp_, "const int Snapshot::size_ = %d;\n\n", bytes_written_);
+ fprintf(fp_, "} } // namespace v8::internal\n");
+ fclose(fp_);
+ }
+
+ void WriteSpaceUsed(
+ int new_space_used,
+ int pointer_space_used,
+ int data_space_used,
+ int code_space_used,
+ int map_space_used,
+ int cell_space_used,
+ int large_space_used) {
+ fprintf(fp_, "};\n\n");
+ fprintf(fp_, "const int Snapshot::new_space_used_ = %d;\n",
new_space_used);
+ fprintf(fp_,
+ "const int Snapshot::pointer_space_used_ = %d;\n",
+ pointer_space_used);
+ fprintf(fp_,
+ "const int Snapshot::data_space_used_ = %d;\n",
+ data_space_used);
+ fprintf(fp_,
+ "const int Snapshot::code_space_used_ = %d;\n",
+ code_space_used);
+ fprintf(fp_, "const int Snapshot::map_space_used_ = %d;\n",
map_space_used);
+ fprintf(fp_,
+ "const int Snapshot::cell_space_used_ = %d;\n",
+ cell_space_used);
+ fprintf(fp_,
+ "const int Snapshot::large_space_used_ = %d;\n",
+ large_space_used);
+ }
+
+ void WritePartialSnapshot() {
+ int length = partial_sink_.Position();
+ fprintf(fp_, "};\n\n");
+ fprintf(fp_, "const int Snapshot::context_size_ = %d;\n", length);
+ fprintf(fp_, "const byte Snapshot::context_data_[] = {\n");
+ for (int j = 0; j < length; j++) {
+ if ((j & 0x1f) == 0x1f) {
+ fprintf(fp_, "\n");
+ }
+ char byte = partial_sink_.at(j);
+ if (j != 0) {
+ fprintf(fp_, ",");
+ }
+ fprintf(fp_, "%d", byte);
}
}
virtual void Put(int byte, const char* description) {
- i::SerializerDeserializer::Trace("Put %s: %d\n", description, byte);
if (bytes_written_ != 0) {
fprintf(fp_, ",");
}
fprintf(fp_, "%d", byte);
bytes_written_++;
- if ((bytes_written_ & 0x3f) == 0) {
+ if ((bytes_written_ & 0x1f) == 0) {
fprintf(fp_, "\n");
}
}
@@ -134,10 +178,29 @@
virtual int Position() {
return bytes_written_;
}
+
+ i::SnapshotByteSink* partial_sink() { return &partial_sink_; }
+
+ class PartialSnapshotSink : public i::SnapshotByteSink {
+ public:
+ explicit PartialSnapshotSink(CppByteSink* parent)
+ : parent_(parent),
+ data_() { }
+ virtual ~PartialSnapshotSink() { data_.Free(); }
+ virtual void Put(int byte, const char* description) {
+ data_.Add(byte);
+ }
+ virtual int Position() { return data_.length(); }
+ char at(int i) { return data_[i]; }
+ private:
+ CppByteSink* parent_;
+ i::List<char> data_;
+ };
private:
FILE* fp_;
int bytes_written_;
+ PartialSnapshotSink partial_sink_;
};
@@ -163,12 +226,32 @@
i::Bootstrapper::NativesSourceLookup(i);
}
}
+ // If we don't do this then we end up with a stray root pointing at the
+ // context even after we have disposed of the context.
+ i::Heap::CollectAllGarbage(true);
+ i::AssertNoAllocation we_have_raw_pointers_here;
+ i::Object* raw_context = *(v8::Utils::OpenHandle(*context));
context.Dispose();
CppByteSink sink(argv[1]);
// This results in a somewhat smaller snapshot, probably because it gets
rid
// of some things that are cached between garbage collections.
- i::Heap::CollectAllGarbage(true);
i::StartupSerializer ser(&sink);
- ser.Serialize();
+ ser.SerializeStrongReferences();
+
+ i::PartialSerializer partial_ser(&ser, sink.partial_sink());
+ partial_ser.Serialize(&raw_context);
+
+ ser.SerializeWeakReferences();
+
+ sink.WritePartialSnapshot();
+
+ sink.WriteSpaceUsed(
+ partial_ser.CurrentAllocationAddress(i::NEW_SPACE),
+ partial_ser.CurrentAllocationAddress(i::OLD_POINTER_SPACE),
+ partial_ser.CurrentAllocationAddress(i::OLD_DATA_SPACE),
+ partial_ser.CurrentAllocationAddress(i::CODE_SPACE),
+ partial_ser.CurrentAllocationAddress(i::MAP_SPACE),
+ partial_ser.CurrentAllocationAddress(i::CELL_SPACE),
+ partial_ser.CurrentAllocationAddress(i::LO_SPACE));
return 0;
}
=======================================
--- /branches/experimental/partial_snapshots/src/serialize.cc Wed Feb 3
04:58:31 2010
+++ /branches/experimental/partial_snapshots/src/serialize.cc Thu Feb 4
00:02:41 2010
@@ -665,7 +665,6 @@
Address address) {
while (current < limit) {
int data = source_->Get();
- Trace("Tag", data);
switch (data) {
#define RAW_CASE(index, size) \
case RAW_DATA_SERIALIZATION + index: { \
@@ -1358,8 +1357,6 @@
fullness_[space] = allocation_address + size;
return allocation_address;
}
-
-bool SerializerDeserializer::tracing_;
} } // namespace v8::internal
=======================================
--- /branches/experimental/partial_snapshots/src/serialize.h Wed Feb 3
04:58:31 2010
+++ /branches/experimental/partial_snapshots/src/serialize.h Thu Feb 4
00:02:41 2010
@@ -173,21 +173,6 @@
public:
static void Iterate(ObjectVisitor* visitor);
static void SetSnapshotCacheSize(int size);
-#ifdef DEBUG
- static void StartTracing() { tracing_ = true; }
- static void StopTracing() { tracing_ = false; }
- static void Trace(const char *msg, int arg) { if (tracing_)
printf("%s %d\n", msg, arg); }
- static void Trace(const char *msg, const char* arg) { if (tracing_)
printf("%s %s\n", msg, arg); }
- static void Trace(const char *msg, const char* arg1, int arg2) { if
(tracing_) printf("%s %s %d\n", msg, arg1, arg2); }
- static bool tracing() { return tracing_; }
-#else
- static void StartTracing() { }
- static void StopTracing() { }
- static void Trace(const char *msg, int arg) { }
- static void Trace(const char *msg, const char* arg) { }
- static void Trace(const char *msg, const char* arg1, int arg2) { }
- static bool tracing() { return false; }
-#endif
protected:
enum DataType {
@@ -233,7 +218,6 @@
static int partial_snapshot_cache_length_;
static const int kPartialSnapshotCacheCapacity = 1300;
static Object* partial_snapshot_cache_[];
- static bool tracing_;
};
@@ -241,18 +225,14 @@
// A little unwind to catch the really small ints.
int snapshot_byte = Get();
if ((snapshot_byte & 0x80) == 0) {
- SerializerDeserializer::Trace("Tag IntLastPart", snapshot_byte);
return snapshot_byte;
}
- SerializerDeserializer::Trace("Tag IntPart", snapshot_byte);
int accumulator = (snapshot_byte & 0x7f) << 7;
while (true) {
snapshot_byte = Get();
if ((snapshot_byte & 0x80) == 0) {
- SerializerDeserializer::Trace("Tag IntLastPart", snapshot_byte);
return accumulator | snapshot_byte;
}
- SerializerDeserializer::Trace("Tag IntPart", snapshot_byte);
accumulator = (accumulator | (snapshot_byte & 0x7f)) << 7;
}
UNREACHABLE();
@@ -261,11 +241,6 @@
void SnapshotByteSource::CopyRaw(byte* to, int number_of_bytes) {
- if (SerializerDeserializer::tracing()) {
- for (int i = 0; i < number_of_bytes; i++) {
- SerializerDeserializer::Trace("Tag Byte", data_[position_ + i]);
- }
- }
memcpy(to, data_ + position_, number_of_bytes);
position_ += number_of_bytes;
}
=======================================
--- /branches/experimental/partial_snapshots/src/snapshot-common.cc Wed Jan
27 00:25:48 2010
+++ /branches/experimental/partial_snapshots/src/snapshot-common.cc Thu
Feb 4 00:02:41 2010
@@ -58,5 +58,25 @@
}
return false;
}
+
+
+Handle<Context> Snapshot::NewContextFromSnapshot() {
+ if (context_size_ == 0) {
+ return Handle<Context>();
+ }
+ Heap::ReserveSpace(new_space_used_,
+ pointer_space_used_,
+ data_space_used_,
+ code_space_used_,
+ map_space_used_,
+ cell_space_used_,
+ large_space_used_);
+ SnapshotByteSource source(context_data_, context_size_);
+ Deserializer deserializer(&source);
+ Object* root;
+ deserializer.DeserializePartial(&root);
+ CHECK(root->IsContext());
+ return Handle<Context>(Context::cast(root));
+}
} } // namespace v8::internal
=======================================
--- /branches/experimental/partial_snapshots/src/snapshot-empty.cc Mon May
25 03:05:56 2009
+++ /branches/experimental/partial_snapshots/src/snapshot-empty.cc Thu Feb
4 00:02:41 2010
@@ -35,6 +35,16 @@
namespace internal {
const byte Snapshot::data_[] = { 0 };
-int Snapshot::size_ = 0;
+const int Snapshot::size_ = 0;
+const byte Snapshot::context_data_[] = { 0 };
+const int Snapshot::context_size_ = 0;
+
+const int Snapshot::new_space_used_ = 0;
+const int Snapshot::pointer_space_used_ = 0;
+const int Snapshot::data_space_used_ = 0;
+const int Snapshot::code_space_used_ = 0;
+const int Snapshot::map_space_used_ = 0;
+const int Snapshot::cell_space_used_ = 0;
+const int Snapshot::large_space_used_ = 0;
} } // namespace v8::internal
=======================================
--- /branches/experimental/partial_snapshots/src/snapshot.h Mon Nov 16
04:08:40 2009
+++ /branches/experimental/partial_snapshots/src/snapshot.h Thu Feb 4
00:02:41 2010
@@ -38,6 +38,9 @@
// could be found.
static bool Initialize(const char* snapshot_file = NULL);
+ // Create a new context using the internal partial snapshot.
+ static Handle<Context> NewContextFromSnapshot();
+
// Returns whether or not the snapshot is enabled.
static bool IsEnabled() { return size_ != 0; }
@@ -47,7 +50,16 @@
private:
static const byte data_[];
- static int size_;
+ static const byte context_data_[];
+ static const int new_space_used_;
+ static const int pointer_space_used_;
+ static const int data_space_used_;
+ static const int code_space_used_;
+ static const int map_space_used_;
+ static const int cell_space_used_;
+ static const int large_space_used_;
+ static const int size_;
+ static const int context_size_;
static bool Deserialize(const byte* content, int len);
=======================================
--- /branches/experimental/partial_snapshots/src/v8-counters.h Wed Jan 27
03:08:32 2010
+++ /branches/experimental/partial_snapshots/src/v8-counters.h Thu Feb 4
00:02:41 2010
@@ -97,7 +97,12 @@
/* Amount of source code compiled with the old codegen. */ \
SC(total_old_codegen_source_size, V8.TotalOldCodegenSourceSize) \
/* Amount of source code compiled with the full codegen. */ \
- SC(total_full_codegen_source_size, V8.TotalFullCodegenSourceSize)
+ SC(total_full_codegen_source_size, V8.TotalFullCodegenSourceSize) \
+ /* Number of contexts created from scratch. */ \
+ SC(contexts_created_from_scratch, V8.ContextsCreatedFromScratch) \
+ /* Number of contexts created by partial snapshot. */ \
+ SC(contexts_created_by_snapshot, V8.ContextsCreatedBySnapshot)
+
#define STATS_COUNTER_LIST_2(SC) \
=======================================
--- /branches/experimental/partial_snapshots/src/v8threads.cc Wed Feb 3
02:52:22 2010
+++ /branches/experimental/partial_snapshots/src/v8threads.cc Thu Feb 4
00:02:41 2010
@@ -156,7 +156,6 @@
return false;
}
char* from = state->data();
- printf("Restore from %p\n", (void*)state->data());
from = HandleScopeImplementer::RestoreThread(from);
from = Top::RestoreThread(from);
from = Relocatable::RestoreState(from);
@@ -285,7 +284,6 @@
void ThreadManager::EagerlyArchiveThread() {
ThreadState* state = lazily_archived_thread_state_;
state->LinkInto(ThreadState::IN_USE_LIST);
- printf("Archive into %p\n", (void*)state->data());
char* to = state->data();
// Ensure that data containing GC roots are archived first, and handle
them
// in ThreadManager::Iterate(ObjectVisitor*).
@@ -326,7 +324,6 @@
state != NULL;
state = state->Next()) {
char* data = state->data();
- printf("Iterate over %p\n", (void*)state->data());
data = HandleScopeImplementer::Iterate(v, data);
data = Top::Iterate(v, data);
data = Relocatable::Iterate(v, data);
@@ -339,7 +336,6 @@
state != NULL;
state = state->Next()) {
char* data = state->data();
- printf("Mark compact prologue %p\n", (void*)state->data());
data += HandleScopeImplementer::ArchiveSpacePerThread();
Top::MarkCompactPrologue(is_compacting, data);
}
@@ -351,7 +347,6 @@
state != NULL;
state = state->Next()) {
char* data = state->data();
- printf("Mark compact epilogue %p\n", (void*)state->data());
data += HandleScopeImplementer::ArchiveSpacePerThread();
Top::MarkCompactEpilogue(is_compacting, data);
}
=======================================
--- /branches/experimental/partial_snapshots/test/cctest/test-serialize.cc
Wed Feb 3 04:58:31 2010
+++ /branches/experimental/partial_snapshots/test/cctest/test-serialize.cc
Thu Feb 4 00:02:41 2010
@@ -187,7 +187,6 @@
}
}
virtual void Put(int byte, const char* description) {
- SerializerDeserializer::Trace("Tag", description, byte);
if (fp_ != NULL) {
fputc(byte, fp_);
}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev