blob: f3205983d0cff985629b09be5c317fec5475f941 [file] [log] [blame]
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001// Copyright 2007-2010 the V8 project authors. All rights reserved.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <signal.h>
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000029
machenbach@chromium.org196eb602014-06-04 00:06:13 +000030#include <sys/stat.h>
ulan@chromium.org57ff8812013-05-10 08:16:55 +000031
machenbach@chromium.org196eb602014-06-04 00:06:13 +000032#include "src/v8.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000033
machenbach@chromium.org196eb602014-06-04 00:06:13 +000034#include "src/bootstrapper.h"
35#include "src/debug.h"
36#include "src/ic-inl.h"
37#include "src/natives.h"
38#include "src/objects.h"
39#include "src/runtime.h"
40#include "src/scopeinfo.h"
41#include "src/serialize.h"
42#include "src/snapshot.h"
43#include "src/spaces.h"
44#include "test/cctest/cctest.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000045
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000046using namespace v8::internal;
47
ager@chromium.org5ec48922009-05-05 07:25:34 +000048static const unsigned kCounters = 256;
49static int local_counters[kCounters];
50static const char* local_counter_names[kCounters];
51
52
53static unsigned CounterHash(const char* s) {
54 unsigned hash = 0;
55 while (*++s) {
56 hash |= hash << 5;
57 hash += *s;
58 }
59 return hash;
60}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000061
62
63// Callback receiver to track counters in test.
ager@chromium.orga74f0da2008-12-03 16:05:52 +000064static int* counter_function(const char* name) {
ager@chromium.org5ec48922009-05-05 07:25:34 +000065 unsigned hash = CounterHash(name) % kCounters;
66 unsigned original_hash = hash;
67 USE(original_hash);
68 while (true) {
69 if (local_counter_names[hash] == name) {
70 return &local_counters[hash];
71 }
72 if (local_counter_names[hash] == 0) {
73 local_counter_names[hash] = name;
74 return &local_counters[hash];
75 }
76 if (strcmp(local_counter_names[hash], name) == 0) {
77 return &local_counters[hash];
78 }
79 hash = (hash + 1) % kCounters;
80 ASSERT(hash != original_hash); // Hash table has been filled up.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000081 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000082}
83
84
85template <class T>
86static Address AddressOf(T id) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000087 return ExternalReference(id, CcTest::i_isolate()).address();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000088}
89
90
91template <class T>
92static uint32_t Encode(const ExternalReferenceEncoder& encoder, T id) {
93 return encoder.Encode(AddressOf(id));
94}
95
96
97static int make_code(TypeCode type, int id) {
98 return static_cast<uint32_t>(type) << kReferenceTypeShift | id;
99}
100
101
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000102TEST(ExternalReferenceEncoder) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000103 Isolate* isolate = CcTest::i_isolate();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000104 isolate->stats_table()->SetCounterFunction(counter_function);
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000105 v8::V8::Initialize();
106
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000107 ExternalReferenceEncoder encoder(isolate);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000108 CHECK_EQ(make_code(BUILTIN, Builtins::kArrayCode),
109 Encode(encoder, Builtins::kArrayCode));
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000110 CHECK_EQ(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort),
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000111 Encode(encoder, Runtime::kAbort));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000112 ExternalReference total_compile_size =
113 ExternalReference(isolate->counters()->total_compile_size());
114 CHECK_EQ(make_code(STATS_COUNTER, Counters::k_total_compile_size),
115 encoder.Encode(total_compile_size.address()));
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000116 ExternalReference stack_limit_address =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000117 ExternalReference::address_of_stack_limit(isolate);
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000118 CHECK_EQ(make_code(UNCLASSIFIED, 4),
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000119 encoder.Encode(stack_limit_address.address()));
120 ExternalReference real_stack_limit_address =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000121 ExternalReference::address_of_real_stack_limit(isolate);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000122 CHECK_EQ(make_code(UNCLASSIFIED, 5),
123 encoder.Encode(real_stack_limit_address.address()));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000124 CHECK_EQ(make_code(UNCLASSIFIED, 16),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000125 encoder.Encode(ExternalReference::debug_break(isolate).address()));
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000126 CHECK_EQ(make_code(UNCLASSIFIED, 10),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000127 encoder.Encode(
128 ExternalReference::new_space_start(isolate).address()));
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000129 CHECK_EQ(make_code(UNCLASSIFIED, 3),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000130 encoder.Encode(
131 ExternalReference::roots_array_start(isolate).address()));
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000132 CHECK_EQ(make_code(UNCLASSIFIED, 52),
133 encoder.Encode(ExternalReference::cpu_features().address()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000134}
135
136
137TEST(ExternalReferenceDecoder) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000138 Isolate* isolate = CcTest::i_isolate();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000139 isolate->stats_table()->SetCounterFunction(counter_function);
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000140 v8::V8::Initialize();
141
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000142 ExternalReferenceDecoder decoder(isolate);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000143 CHECK_EQ(AddressOf(Builtins::kArrayCode),
144 decoder.Decode(make_code(BUILTIN, Builtins::kArrayCode)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000145 CHECK_EQ(AddressOf(Runtime::kAbort),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000146 decoder.Decode(make_code(v8::internal::RUNTIME_FUNCTION,
147 Runtime::kAbort)));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000148 ExternalReference total_compile_size =
149 ExternalReference(isolate->counters()->total_compile_size());
150 CHECK_EQ(total_compile_size.address(),
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000151 decoder.Decode(
152 make_code(STATS_COUNTER,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000153 Counters::k_total_compile_size)));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000154 CHECK_EQ(ExternalReference::address_of_stack_limit(isolate).address(),
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000155 decoder.Decode(make_code(UNCLASSIFIED, 4)));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000156 CHECK_EQ(ExternalReference::address_of_real_stack_limit(isolate).address(),
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000157 decoder.Decode(make_code(UNCLASSIFIED, 5)));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000158 CHECK_EQ(ExternalReference::debug_break(isolate).address(),
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000159 decoder.Decode(make_code(UNCLASSIFIED, 16)));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000160 CHECK_EQ(ExternalReference::new_space_start(isolate).address(),
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000161 decoder.Decode(make_code(UNCLASSIFIED, 10)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000162}
163
164
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000165class FileByteSink : public SnapshotByteSink {
166 public:
167 explicit FileByteSink(const char* snapshot_file) {
168 fp_ = OS::FOpen(snapshot_file, "wb");
169 file_name_ = snapshot_file;
170 if (fp_ == NULL) {
171 PrintF("Unable to write to snapshot file \"%s\"\n", snapshot_file);
172 exit(1);
173 }
174 }
175 virtual ~FileByteSink() {
176 if (fp_ != NULL) {
177 fclose(fp_);
178 }
179 }
180 virtual void Put(int byte, const char* description) {
181 if (fp_ != NULL) {
182 fputc(byte, fp_);
183 }
184 }
185 virtual int Position() {
186 return ftell(fp_);
187 }
188 void WriteSpaceUsed(
189 int new_space_used,
190 int pointer_space_used,
191 int data_space_used,
192 int code_space_used,
193 int map_space_used,
danno@chromium.org41728482013-06-12 22:31:22 +0000194 int cell_space_used,
195 int property_cell_space_used);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000196
197 private:
198 FILE* fp_;
199 const char* file_name_;
200};
201
202
203void FileByteSink::WriteSpaceUsed(
204 int new_space_used,
205 int pointer_space_used,
206 int data_space_used,
207 int code_space_used,
208 int map_space_used,
danno@chromium.org41728482013-06-12 22:31:22 +0000209 int cell_space_used,
210 int property_cell_space_used) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000211 int file_name_length = StrLength(file_name_) + 10;
212 Vector<char> name = Vector<char>::New(file_name_length + 1);
bmeurer@chromium.org70ec1a22014-06-16 11:20:10 +0000213 SNPrintF(name, "%s.size", file_name_);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000214 FILE* fp = OS::FOpen(name.start(), "w");
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000215 name.Dispose();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000216 fprintf(fp, "new %d\n", new_space_used);
217 fprintf(fp, "pointer %d\n", pointer_space_used);
218 fprintf(fp, "data %d\n", data_space_used);
219 fprintf(fp, "code %d\n", code_space_used);
220 fprintf(fp, "map %d\n", map_space_used);
221 fprintf(fp, "cell %d\n", cell_space_used);
danno@chromium.org41728482013-06-12 22:31:22 +0000222 fprintf(fp, "property cell %d\n", property_cell_space_used);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000223 fclose(fp);
224}
225
226
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000227static bool WriteToFile(Isolate* isolate, const char* snapshot_file) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000228 FileByteSink file(snapshot_file);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000229 StartupSerializer ser(isolate, &file);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000230 ser.Serialize();
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000231
232 file.WriteSpaceUsed(
233 ser.CurrentAllocationAddress(NEW_SPACE),
234 ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
235 ser.CurrentAllocationAddress(OLD_DATA_SPACE),
236 ser.CurrentAllocationAddress(CODE_SPACE),
237 ser.CurrentAllocationAddress(MAP_SPACE),
danno@chromium.org41728482013-06-12 22:31:22 +0000238 ser.CurrentAllocationAddress(CELL_SPACE),
239 ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000240
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000241 return true;
242}
243
244
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000245static void Serialize() {
ager@chromium.org3811b432009-10-28 14:53:37 +0000246 // We have to create one context. One reason for this is so that the builtins
247 // can be loaded from v8natives.js and their addresses can be processed. This
248 // will clear the pending fixups array, which would otherwise contain GC roots
249 // that would confuse the serialization/deserialization process.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000250 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000251 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000252 v8::HandleScope scope(isolate);
253 v8::Context::New(isolate);
254 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000255
256 Isolate* internal_isolate = CcTest::i_isolate();
257 internal_isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "serialize");
258 WriteToFile(internal_isolate, FLAG_testing_serialization_file);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000259}
260
261
ager@chromium.org3811b432009-10-28 14:53:37 +0000262// Test that the whole heap can be serialized.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000263TEST(Serialize) {
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000264 if (!Snapshot::HaveASnapshotToStartFrom()) {
machenbach@chromium.orgfb547e02014-05-23 00:04:50 +0000265 CcTest::i_isolate()->enable_serializer();
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000266 v8::V8::Initialize();
267 Serialize();
268 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000269}
270
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000271
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000272// Test that heap serialization is non-destructive.
273TEST(SerializeTwice) {
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000274 if (!Snapshot::HaveASnapshotToStartFrom()) {
machenbach@chromium.orgfb547e02014-05-23 00:04:50 +0000275 CcTest::i_isolate()->enable_serializer();
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000276 v8::V8::Initialize();
277 Serialize();
278 Serialize();
279 }
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000280}
281
282
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000283//----------------------------------------------------------------------------
284// Tests that the heap can be deserialized.
285
286static void Deserialize() {
machenbach@chromium.orge3a73ec2014-06-10 10:57:45 +0000287 CHECK(Snapshot::Initialize(FLAG_testing_serialization_file));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000288}
289
290
291static void SanityCheck() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000292 Isolate* isolate = CcTest::i_isolate();
293 v8::HandleScope scope(CcTest::isolate());
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +0000294#ifdef VERIFY_HEAP
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000295 CcTest::heap()->Verify();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000296#endif
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000297 CHECK(isolate->global_object()->IsJSObject());
298 CHECK(isolate->native_context()->IsContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000299 CHECK(CcTest::heap()->string_table()->IsStringTable());
machenbach@chromium.orga86d4162014-05-01 00:05:11 +0000300 isolate->factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("Empty"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000301}
302
303
iposva@chromium.org245aa852009-02-10 00:49:54 +0000304DEPENDENT_TEST(Deserialize, Serialize) {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000305 // The serialize-deserialize tests only work if the VM is built without
306 // serialization. That doesn't matter. We don't need to be able to
307 // serialize a snapshot in a VM that is booted from a snapshot.
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000308 if (!Snapshot::HaveASnapshotToStartFrom()) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000309 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000310 v8::HandleScope scope(isolate);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000311 Deserialize();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000312
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000313 v8::Local<v8::Context> env = v8::Context::New(isolate);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000314 env->Enter();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000315
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000316 SanityCheck();
317 }
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000318}
319
320
321DEPENDENT_TEST(DeserializeFromSecondSerialization, SerializeTwice) {
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000322 if (!Snapshot::HaveASnapshotToStartFrom()) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000323 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000324 v8::HandleScope scope(isolate);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000325 Deserialize();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000326
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000327 v8::Local<v8::Context> env = v8::Context::New(isolate);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000328 env->Enter();
ager@chromium.org3811b432009-10-28 14:53:37 +0000329
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000330 SanityCheck();
331 }
ager@chromium.org3811b432009-10-28 14:53:37 +0000332}
333
334
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000335DEPENDENT_TEST(DeserializeAndRunScript2, Serialize) {
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000336 if (!Snapshot::HaveASnapshotToStartFrom()) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000337 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000338 v8::HandleScope scope(isolate);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000339 Deserialize();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000340
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000341 v8::Local<v8::Context> env = v8::Context::New(isolate);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000342 env->Enter();
ager@chromium.org3811b432009-10-28 14:53:37 +0000343
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000344 const char* c_source = "\"1234\".length";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000345 v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, c_source);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000346 v8::Local<v8::Script> script = v8::Script::Compile(source);
347 CHECK_EQ(4, script->Run()->Int32Value());
348 }
ager@chromium.org3811b432009-10-28 14:53:37 +0000349}
350
351
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000352DEPENDENT_TEST(DeserializeFromSecondSerializationAndRunScript2,
353 SerializeTwice) {
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000354 if (!Snapshot::HaveASnapshotToStartFrom()) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000355 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000356 v8::HandleScope scope(isolate);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000357 Deserialize();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000358
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000359 v8::Local<v8::Context> env = v8::Context::New(isolate);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000360 env->Enter();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000361
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000362 const char* c_source = "\"1234\".length";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000363 v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, c_source);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000364 v8::Local<v8::Script> script = v8::Script::Compile(source);
365 CHECK_EQ(4, script->Run()->Int32Value());
366 }
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000367}
368
369
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000370TEST(PartialSerialization) {
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000371 if (!Snapshot::HaveASnapshotToStartFrom()) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000372 Isolate* isolate = CcTest::i_isolate();
machenbach@chromium.orgfb547e02014-05-23 00:04:50 +0000373 CcTest::i_isolate()->enable_serializer();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000374 v8::V8::Initialize();
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000375 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000376 Heap* heap = isolate->heap();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000377
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000378 v8::Persistent<v8::Context> env;
379 {
380 HandleScope scope(isolate);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000381 env.Reset(v8_isolate, v8::Context::New(v8_isolate));
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000382 }
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000383 ASSERT(!env.IsEmpty());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000384 {
385 v8::HandleScope handle_scope(v8_isolate);
386 v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
387 }
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000388 // Make sure all builtin scripts are cached.
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000389 { HandleScope scope(isolate);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000390 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000391 isolate->bootstrapper()->NativesSourceLookup(i);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000392 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000393 }
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000394 heap->CollectAllGarbage(Heap::kNoGCFlags);
395 heap->CollectAllGarbage(Heap::kNoGCFlags);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000396
397 Object* raw_foo;
398 {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000399 v8::HandleScope handle_scope(v8_isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000400 v8::Local<v8::String> foo = v8::String::NewFromUtf8(v8_isolate, "foo");
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000401 ASSERT(!foo.IsEmpty());
402 raw_foo = *(v8::Utils::OpenHandle(*foo));
403 }
404
405 int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
406 Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
bmeurer@chromium.org70ec1a22014-06-16 11:20:10 +0000407 SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000408
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000409 {
410 v8::HandleScope handle_scope(v8_isolate);
411 v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
412 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000413 env.Reset();
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000414
415 FileByteSink startup_sink(startup_name.start());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000416 StartupSerializer startup_serializer(isolate, &startup_sink);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000417 startup_serializer.SerializeStrongReferences();
418
419 FileByteSink partial_sink(FLAG_testing_serialization_file);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000420 PartialSerializer p_ser(isolate, &startup_serializer, &partial_sink);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000421 p_ser.Serialize(&raw_foo);
422 startup_serializer.SerializeWeakReferences();
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000423
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000424 partial_sink.WriteSpaceUsed(
425 p_ser.CurrentAllocationAddress(NEW_SPACE),
426 p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
427 p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
428 p_ser.CurrentAllocationAddress(CODE_SPACE),
429 p_ser.CurrentAllocationAddress(MAP_SPACE),
danno@chromium.org41728482013-06-12 22:31:22 +0000430 p_ser.CurrentAllocationAddress(CELL_SPACE),
431 p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000432
433 startup_sink.WriteSpaceUsed(
434 startup_serializer.CurrentAllocationAddress(NEW_SPACE),
435 startup_serializer.CurrentAllocationAddress(OLD_POINTER_SPACE),
436 startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE),
437 startup_serializer.CurrentAllocationAddress(CODE_SPACE),
438 startup_serializer.CurrentAllocationAddress(MAP_SPACE),
danno@chromium.org41728482013-06-12 22:31:22 +0000439 startup_serializer.CurrentAllocationAddress(CELL_SPACE),
440 startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000441 startup_name.Dispose();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000442 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000443}
444
445
machenbach@chromium.orge3a73ec2014-06-10 10:57:45 +0000446static void ReserveSpaceForSnapshot(Deserializer* deserializer,
447 const char* file_name) {
448 int file_name_length = StrLength(file_name) + 10;
449 Vector<char> name = Vector<char>::New(file_name_length + 1);
bmeurer@chromium.org70ec1a22014-06-16 11:20:10 +0000450 SNPrintF(name, "%s.size", file_name);
machenbach@chromium.orge3a73ec2014-06-10 10:57:45 +0000451 FILE* fp = OS::FOpen(name.start(), "r");
452 name.Dispose();
453 int new_size, pointer_size, data_size, code_size, map_size, cell_size,
454 property_cell_size;
455#ifdef _MSC_VER
456 // Avoid warning about unsafe fscanf from MSVC.
457 // Please note that this is only fine if %c and %s are not being used.
458#define fscanf fscanf_s
459#endif
460 CHECK_EQ(1, fscanf(fp, "new %d\n", &new_size));
461 CHECK_EQ(1, fscanf(fp, "pointer %d\n", &pointer_size));
462 CHECK_EQ(1, fscanf(fp, "data %d\n", &data_size));
463 CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size));
464 CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size));
465 CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size));
466 CHECK_EQ(1, fscanf(fp, "property cell %d\n", &property_cell_size));
467#ifdef _MSC_VER
468#undef fscanf
469#endif
470 fclose(fp);
471 deserializer->set_reservation(NEW_SPACE, new_size);
472 deserializer->set_reservation(OLD_POINTER_SPACE, pointer_size);
473 deserializer->set_reservation(OLD_DATA_SPACE, data_size);
474 deserializer->set_reservation(CODE_SPACE, code_size);
475 deserializer->set_reservation(MAP_SPACE, map_size);
476 deserializer->set_reservation(CELL_SPACE, cell_size);
477 deserializer->set_reservation(PROPERTY_CELL_SPACE, property_cell_size);
478}
479
480
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000481DEPENDENT_TEST(PartialDeserialization, PartialSerialization) {
machenbach@chromium.orge3a73ec2014-06-10 10:57:45 +0000482 if (!Snapshot::IsEnabled()) {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000483 int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
484 Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
bmeurer@chromium.org70ec1a22014-06-16 11:20:10 +0000485 SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000486
machenbach@chromium.orge3a73ec2014-06-10 10:57:45 +0000487 CHECK(Snapshot::Initialize(startup_name.start()));
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000488 startup_name.Dispose();
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000489
490 const char* file_name = FLAG_testing_serialization_file;
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000491
492 int snapshot_size = 0;
493 byte* snapshot = ReadBytes(file_name, &snapshot_size);
494
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000495 Isolate* isolate = CcTest::i_isolate();
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000496 Object* root;
497 {
498 SnapshotByteSource source(snapshot, snapshot_size);
499 Deserializer deserializer(&source);
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000500 ReserveSpaceForSnapshot(&deserializer, file_name);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000501 deserializer.DeserializePartial(isolate, &root);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000502 CHECK(root->IsString());
503 }
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000504 HandleScope handle_scope(isolate);
505 Handle<Object> root_handle(root, isolate);
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +0000506
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000507
508 Object* root2;
509 {
510 SnapshotByteSource source(snapshot, snapshot_size);
511 Deserializer deserializer(&source);
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000512 ReserveSpaceForSnapshot(&deserializer, file_name);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000513 deserializer.DeserializePartial(isolate, &root2);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000514 CHECK(root2->IsString());
515 CHECK(*root_handle == root2);
516 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000517 }
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000518}
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000519
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000520
521TEST(ContextSerialization) {
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000522 if (!Snapshot::HaveASnapshotToStartFrom()) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000523 Isolate* isolate = CcTest::i_isolate();
machenbach@chromium.orgfb547e02014-05-23 00:04:50 +0000524 CcTest::i_isolate()->enable_serializer();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000525 v8::V8::Initialize();
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000526 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000527 Heap* heap = isolate->heap();
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000528
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000529 v8::Persistent<v8::Context> env;
530 {
531 HandleScope scope(isolate);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000532 env.Reset(v8_isolate, v8::Context::New(v8_isolate));
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000533 }
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000534 ASSERT(!env.IsEmpty());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000535 {
536 v8::HandleScope handle_scope(v8_isolate);
537 v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
538 }
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000539 // Make sure all builtin scripts are cached.
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000540 { HandleScope scope(isolate);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000541 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000542 isolate->bootstrapper()->NativesSourceLookup(i);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000543 }
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000544 }
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000545 // If we don't do this then we end up with a stray root pointing at the
546 // context even after we have disposed of env.
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000547 heap->CollectAllGarbage(Heap::kNoGCFlags);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000548
549 int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
550 Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
bmeurer@chromium.org70ec1a22014-06-16 11:20:10 +0000551 SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000552
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000553 {
554 v8::HandleScope handle_scope(v8_isolate);
555 v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
556 }
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000557
danno@chromium.orgf95d4b92013-06-13 14:40:17 +0000558 i::Object* raw_context = *v8::Utils::OpenPersistent(env);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000559
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000560 env.Reset();
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000561
562 FileByteSink startup_sink(startup_name.start());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000563 StartupSerializer startup_serializer(isolate, &startup_sink);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000564 startup_serializer.SerializeStrongReferences();
565
566 FileByteSink partial_sink(FLAG_testing_serialization_file);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000567 PartialSerializer p_ser(isolate, &startup_serializer, &partial_sink);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000568 p_ser.Serialize(&raw_context);
569 startup_serializer.SerializeWeakReferences();
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000570
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000571 partial_sink.WriteSpaceUsed(
572 p_ser.CurrentAllocationAddress(NEW_SPACE),
573 p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
574 p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
575 p_ser.CurrentAllocationAddress(CODE_SPACE),
576 p_ser.CurrentAllocationAddress(MAP_SPACE),
danno@chromium.org41728482013-06-12 22:31:22 +0000577 p_ser.CurrentAllocationAddress(CELL_SPACE),
578 p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000579
580 startup_sink.WriteSpaceUsed(
581 startup_serializer.CurrentAllocationAddress(NEW_SPACE),
582 startup_serializer.CurrentAllocationAddress(OLD_POINTER_SPACE),
583 startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE),
584 startup_serializer.CurrentAllocationAddress(CODE_SPACE),
585 startup_serializer.CurrentAllocationAddress(MAP_SPACE),
danno@chromium.org41728482013-06-12 22:31:22 +0000586 startup_serializer.CurrentAllocationAddress(CELL_SPACE),
587 startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000588 startup_name.Dispose();
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000589 }
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000590}
591
592
593DEPENDENT_TEST(ContextDeserialization, ContextSerialization) {
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000594 if (!Snapshot::HaveASnapshotToStartFrom()) {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000595 int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
596 Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
bmeurer@chromium.org70ec1a22014-06-16 11:20:10 +0000597 SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000598
machenbach@chromium.orge3a73ec2014-06-10 10:57:45 +0000599 CHECK(Snapshot::Initialize(startup_name.start()));
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000600 startup_name.Dispose();
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000601
602 const char* file_name = FLAG_testing_serialization_file;
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000603
604 int snapshot_size = 0;
605 byte* snapshot = ReadBytes(file_name, &snapshot_size);
606
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000607 Isolate* isolate = CcTest::i_isolate();
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000608 Object* root;
609 {
610 SnapshotByteSource source(snapshot, snapshot_size);
611 Deserializer deserializer(&source);
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000612 ReserveSpaceForSnapshot(&deserializer, file_name);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000613 deserializer.DeserializePartial(isolate, &root);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000614 CHECK(root->IsContext());
615 }
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000616 HandleScope handle_scope(isolate);
617 Handle<Object> root_handle(root, isolate);
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +0000618
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000619
620 Object* root2;
621 {
622 SnapshotByteSource source(snapshot, snapshot_size);
623 Deserializer deserializer(&source);
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000624 ReserveSpaceForSnapshot(&deserializer, file_name);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000625 deserializer.DeserializePartial(isolate, &root2);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000626 CHECK(root2->IsContext());
627 CHECK(*root_handle != root2);
628 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000629 }
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000630}
631
632
ager@chromium.org3811b432009-10-28 14:53:37 +0000633TEST(TestThatAlwaysSucceeds) {
634}
635
636
637TEST(TestThatAlwaysFails) {
638 bool ArtificialFailure = false;
639 CHECK(ArtificialFailure);
640}
641
642
643DEPENDENT_TEST(DependentTestThatAlwaysFails, TestThatAlwaysSucceeds) {
644 bool ArtificialFailure2 = false;
645 CHECK(ArtificialFailure2);
646}