From 458e87fd05080071622b161cb861ff4ee4a20f0f Mon Sep 17 00:00:00 2001 From: erikcorry Date: Tue, 19 Jun 2012 18:38:03 +0000 Subject: [PATCH] Snapshots: Add --extra-code flag to mksnapshot which lets you specify a file with more JS code that is loaded into the VM before writing the snapshot. Get rid of the hard coded limit on the partial snapshot cache size. This change disables most of the serializer tests for the snapshot build of the VM: It's getting too complicated to support both booting from a snapshot and then creating a new snapshot from the same VM or loading more code with another snapshot in the same VM. Review URL: http://codereview.chromium.org/10574013 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11871 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/flag-definitions.h | 5 ++ src/heap.cc | 2 +- src/isolate.cc | 36 ++++++++- src/isolate.h | 6 +- src/mksnapshot.cc | 59 ++++++++++++++ src/serialize.cc | 83 ++++++++----------- src/serialize.h | 1 - src/snapshot-common.cc | 5 ++ src/snapshot.h | 2 + test/cctest/test-serialize.cc | 184 ++++++++++++++++++++++-------------------- 10 files changed, 240 insertions(+), 143 deletions(-) diff --git a/src/flag-definitions.h b/src/flag-definitions.h index e9d8d5d..125d151 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -451,6 +451,10 @@ DEFINE_string(testing_serialization_file, "/tmp/serdes", "file in which to serialize heap") #endif +// mksnapshot.cc +DEFINE_string(extra_code, NULL, "A filename with extra code to be included in" + " the snapshot (mksnapshot only)") + // // Dev shell flags // @@ -610,6 +614,7 @@ DEFINE_bool(sliding_state_window, false, DEFINE_string(logfile, "v8.log", "Specify the name of the log file.") DEFINE_bool(ll_prof, false, "Enable low-level linux profiler.") + // // Disassembler only flags // diff --git a/src/heap.cc b/src/heap.cc index 914e21a..df8dde6 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -2822,7 +2822,7 @@ void Heap::AllocateFullSizeNumberStringCache() { // 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. - ASSERT(!Serializer::enabled()); + ASSERT(!Serializer::enabled() || FLAG_extra_code != NULL); MaybeObject* maybe_obj = AllocateFixedArray(FullSizeNumberStringCacheLength(), TENURED); Object* new_cache; diff --git a/src/isolate.cc b/src/isolate.cc index 54a72d3..dae2504 100644 --- a/src/isolate.cc +++ b/src/isolate.cc @@ -1550,6 +1550,11 @@ void Isolate::TearDown() { thread_data_table_->RemoveAllThreads(this); } + if (serialize_partial_snapshot_cache_ != NULL) { + delete[] serialize_partial_snapshot_cache_; + serialize_partial_snapshot_cache_ = NULL; + } + if (!IsDefaultIsolate()) { delete this; } @@ -1598,6 +1603,26 @@ void Isolate::Deinit() { } +void Isolate::PushToPartialSnapshotCache(Object* obj) { + int length = serialize_partial_snapshot_cache_length(); + int capacity = serialize_partial_snapshot_cache_capacity(); + + if (length >= capacity) { + int new_capacity = (capacity + 10) * 1.2; + Object** new_array = new Object*[new_capacity]; + for (int i = 0; i < length; i++) { + new_array[i] = serialize_partial_snapshot_cache()[i]; + } + if (capacity != 0) delete[] serialize_partial_snapshot_cache(); + set_serialize_partial_snapshot_cache(new_array); + set_serialize_partial_snapshot_cache_capacity(new_capacity); + } + + serialize_partial_snapshot_cache()[length] = obj; + set_serialize_partial_snapshot_cache_length(length + 1); +} + + void Isolate::SetIsolateThreadLocals(Isolate* isolate, PerIsolateThreadData* data) { Thread::SetThreadLocal(isolate_key_, isolate); @@ -1815,6 +1840,11 @@ bool Isolate::Init(Deserializer* des) { return false; } + if (create_heap_objects) { + // Terminate the cache array with the sentinel so we can iterate. + PushToPartialSnapshotCache(heap_.undefined_value()); + } + InitializeThreadLocal(); bootstrapper_->Initialize(create_heap_objects); @@ -1841,7 +1871,7 @@ bool Isolate::Init(Deserializer* des) { #endif // If we are deserializing, read the state into the now-empty heap. - if (des != NULL) { + if (!create_heap_objects) { des->Deserialize(); } stub_cache_->Initialize(); @@ -1856,7 +1886,7 @@ bool Isolate::Init(Deserializer* des) { heap_.SetStackLimits(); // Quiet the heap NaN if needed on target platform. - if (des != NULL) Assembler::QuietNaN(heap_.nan_value()); + if (create_heap_objects) Assembler::QuietNaN(heap_.nan_value()); deoptimizer_data_ = new DeoptimizerData; runtime_profiler_ = new RuntimeProfiler(this); @@ -1864,7 +1894,7 @@ bool Isolate::Init(Deserializer* des) { // If we are deserializing, log non-function code objects and compiled // functions found in the snapshot. - if (des != NULL && (FLAG_log_code || FLAG_ll_prof)) { + if (create_heap_objects && (FLAG_log_code || FLAG_ll_prof)) { HandleScope scope; LOG(this, LogCodeObjects()); LOG(this, LogCompiledFunctions()); diff --git a/src/isolate.h b/src/isolate.h index 5ca2b87..8cd0745 100644 --- a/src/isolate.h +++ b/src/isolate.h @@ -307,7 +307,6 @@ class ThreadLocalTop BASE_EMBEDDED { #define ISOLATE_INIT_ARRAY_LIST(V) \ /* SerializerDeserializer state. */ \ - V(Object*, serialize_partial_snapshot_cache, kPartialSnapshotCacheCapacity) \ V(int, jsregexp_static_offsets_vector, kJSRegexpStaticOffsetsVectorSize) \ V(int, bad_char_shift_table, kUC16AlphabetSize) \ V(int, good_suffix_shift_table, (kBMMaxShift + 1)) \ @@ -320,6 +319,8 @@ typedef List DebugObjectCache; #define ISOLATE_INIT_LIST(V) \ /* SerializerDeserializer state. */ \ V(int, serialize_partial_snapshot_cache_length, 0) \ + V(int, serialize_partial_snapshot_cache_capacity, 0) \ + V(Object**, serialize_partial_snapshot_cache, NULL) \ /* Assembler state. */ \ /* A previously allocated buffer of kMinimalBufferSize bytes, or NULL. */ \ V(byte*, assembler_spare_buffer, NULL) \ @@ -610,6 +611,9 @@ class Isolate { (exception != heap()->termination_exception()); } + // Serializer. + void PushToPartialSnapshotCache(Object* obj); + // JS execution stack (see frames.h). static Address c_entry_fp(ThreadLocalTop* thread) { return thread->c_entry_fp_; diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc index e426a58..7bdad84 100644 --- a/src/mksnapshot.cc +++ b/src/mksnapshot.cc @@ -25,6 +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. +#include +#include #ifdef COMPRESS_STARTUP_DATA_BZ2 #include #endif @@ -33,6 +35,7 @@ #include "v8.h" #include "bootstrapper.h" +#include "flags.h" #include "natives.h" #include "platform.h" #include "serialize.h" @@ -308,6 +311,62 @@ int main(int argc, char** argv) { "\nException thrown while compiling natives - see above.\n\n"); exit(1); } + if (i::FLAG_extra_code != NULL) { + context->Enter(); + // Capture 100 frames if anything happens. + V8::SetCaptureStackTraceForUncaughtExceptions(true, 100); + HandleScope scope; + const char* name = i::FLAG_extra_code; + FILE* file = i::OS::FOpen(name, "rb"); + if (file == NULL) { + fprintf(stderr, "Failed to open '%s': errno %d\n", name, errno); + exit(1); + } + + fseek(file, 0, SEEK_END); + int size = ftell(file); + rewind(file); + + char* chars = new char[size + 1]; + chars[size] = '\0'; + for (int i = 0; i < size;) { + int read = static_cast(fread(&chars[i], 1, size - i, file)); + if (read < 0) { + fprintf(stderr, "Failed to read '%s': errno %d\n", name, errno); + exit(1); + } + i += read; + } + fclose(file); + Local source = String::New(chars); + TryCatch try_catch; + Local