blob: cd349f9d735160753e691473f4b50a4165de434e [file] [log] [blame]
Leon Clarkee46be812010-01-19 14:06:41 +00001// Copyright 2007-2010 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +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>
29
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030#include <sys/stat.h>
Steve Blocka7e24c12009-10-30 11:49:00 +000031
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032#include "src/v8.h"
33
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034#include "src/ast/scopeinfo.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035#include "src/bootstrapper.h"
36#include "src/compilation-cache.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037#include "src/debug/debug.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038#include "src/heap/spaces.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039#include "src/objects.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040#include "src/parsing/parser.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040041#include "src/runtime/runtime.h"
Ben Murdochda12d292016-06-02 14:46:10 +010042#include "src/snapshot/code-serializer.h"
43#include "src/snapshot/deserializer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044#include "src/snapshot/natives.h"
Ben Murdochda12d292016-06-02 14:46:10 +010045#include "src/snapshot/partial-serializer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000046#include "src/snapshot/snapshot.h"
Ben Murdochda12d292016-06-02 14:46:10 +010047#include "src/snapshot/startup-serializer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048#include "test/cctest/cctest.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049#include "test/cctest/heap/utils-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000050
51using namespace v8::internal;
52
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053void DisableTurbofan() {
54 const char* flag = "--turbo-filter=\"\"";
55 FlagList::SetFlagsFromString(flag, StrLength(flag));
Steve Blocka7e24c12009-10-30 11:49:00 +000056}
57
58
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059// TestIsolate is used for testing isolate serialization.
60class TestIsolate : public Isolate {
61 public:
62 static v8::Isolate* NewInitialized(bool enable_serializer) {
63 i::Isolate* isolate = new TestIsolate(enable_serializer);
64 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
65 v8::Isolate::Scope isolate_scope(v8_isolate);
66 isolate->Init(NULL);
67 return v8_isolate;
68 }
69 explicit TestIsolate(bool enable_serializer) : Isolate(enable_serializer) {
70 set_array_buffer_allocator(CcTest::array_buffer_allocator());
71 }
72};
Steve Blocka7e24c12009-10-30 11:49:00 +000073
Ben Murdochda12d292016-06-02 14:46:10 +010074static Vector<const byte> WritePayload(const Vector<const byte>& payload) {
75 int length = payload.length();
76 byte* blob = NewArray<byte>(length);
77 memcpy(blob, payload.begin(), length);
78 return Vector<const byte>(const_cast<const byte*>(blob), length);
Leon Clarked91b9f72010-01-27 17:25:45 +000079}
80
Ben Murdochda12d292016-06-02 14:46:10 +010081static Vector<const byte> Serialize(v8::Isolate* isolate) {
Steve Blockd0582a62009-12-15 09:54:21 +000082 // We have to create one context. One reason for this is so that the builtins
83 // can be loaded from v8natives.js and their addresses can be processed. This
84 // will clear the pending fixups array, which would otherwise contain GC roots
85 // that would confuse the serialization/deserialization process.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000086 v8::Isolate::Scope isolate_scope(isolate);
87 {
88 v8::HandleScope scope(isolate);
89 v8::Context::New(isolate);
90 }
91
92 Isolate* internal_isolate = reinterpret_cast<Isolate*>(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040093 internal_isolate->heap()->CollectAllAvailableGarbage("serialize");
Ben Murdochda12d292016-06-02 14:46:10 +010094 SnapshotByteSink sink;
95 StartupSerializer ser(internal_isolate, &sink);
96 ser.SerializeStrongReferences();
97 ser.SerializeWeakReferencesAndDeferred();
98 SnapshotData snapshot_data(ser);
99 return WritePayload(snapshot_data.RawData());
Steve Blocka7e24c12009-10-30 11:49:00 +0000100}
101
102
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000103Vector<const uint8_t> ConstructSource(Vector<const uint8_t> head,
104 Vector<const uint8_t> body,
105 Vector<const uint8_t> tail, int repeats) {
106 int source_length = head.length() + body.length() * repeats + tail.length();
107 uint8_t* source = NewArray<uint8_t>(static_cast<size_t>(source_length));
108 CopyChars(source, head.start(), head.length());
109 for (int i = 0; i < repeats; i++) {
110 CopyChars(source + head.length() + i * body.length(), body.start(),
111 body.length());
112 }
113 CopyChars(source + head.length() + repeats * body.length(), tail.start(),
114 tail.length());
115 return Vector<const uint8_t>(const_cast<const uint8_t*>(source),
116 source_length);
117}
118
Ben Murdochda12d292016-06-02 14:46:10 +0100119v8::Isolate* InitializeFromBlob(Vector<const byte> blob) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120 v8::Isolate* v8_isolate = NULL;
121 {
Ben Murdochda12d292016-06-02 14:46:10 +0100122 SnapshotData snapshot_data(blob);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123 Deserializer deserializer(&snapshot_data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124 Isolate* isolate = new TestIsolate(false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000125 v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
126 v8::Isolate::Scope isolate_scope(v8_isolate);
127 isolate->Init(&deserializer);
128 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000129 return v8_isolate;
130}
131
Ben Murdochda12d292016-06-02 14:46:10 +0100132static v8::Isolate* Deserialize(Vector<const byte> blob) {
133 v8::Isolate* isolate = InitializeFromBlob(blob);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000134 CHECK(isolate);
135 return isolate;
136}
137
138
139static void SanityCheck(v8::Isolate* v8_isolate) {
140 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
141 v8::HandleScope scope(v8_isolate);
142#ifdef VERIFY_HEAP
143 isolate->heap()->Verify();
144#endif
145 CHECK(isolate->global_object()->IsJSObject());
146 CHECK(isolate->native_context()->IsContext());
147 CHECK(isolate->heap()->string_table()->IsStringTable());
148 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("Empty"));
149}
150
Ben Murdochda12d292016-06-02 14:46:10 +0100151UNINITIALIZED_TEST(StartupSerializerOnce) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152 // The serialize-deserialize tests only work if the VM is built without
153 // serialization. That doesn't matter. We don't need to be able to
154 // serialize a snapshot in a VM that is booted from a snapshot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100156 v8::Isolate* isolate = TestIsolate::NewInitialized(true);
157 Vector<const byte> blob = Serialize(isolate);
158 isolate = Deserialize(blob);
159 blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000160 {
161 v8::HandleScope handle_scope(isolate);
162 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000163
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000164 v8::Local<v8::Context> env = v8::Context::New(isolate);
165 env->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000166
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167 SanityCheck(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 isolate->Dispose();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000170}
171
Ben Murdochda12d292016-06-02 14:46:10 +0100172UNINITIALIZED_TEST(StartupSerializerTwice) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100174 v8::Isolate* isolate = TestIsolate::NewInitialized(true);
175 Vector<const byte> blob1 = Serialize(isolate);
176 Vector<const byte> blob2 = Serialize(isolate);
177 blob1.Dispose();
178 isolate = Deserialize(blob2);
179 blob2.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000180 {
181 v8::Isolate::Scope isolate_scope(isolate);
182 v8::HandleScope handle_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 v8::Local<v8::Context> env = v8::Context::New(isolate);
185 env->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 SanityCheck(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189 isolate->Dispose();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190}
191
Ben Murdochda12d292016-06-02 14:46:10 +0100192UNINITIALIZED_TEST(StartupSerializerOnceRunScript) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100194 v8::Isolate* isolate = TestIsolate::NewInitialized(true);
195 Vector<const byte> blob = Serialize(isolate);
196 isolate = Deserialize(blob);
197 blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 {
199 v8::Isolate::Scope isolate_scope(isolate);
200 v8::HandleScope handle_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000201
202
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 v8::Local<v8::Context> env = v8::Context::New(isolate);
204 env->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 const char* c_source = "\"1234\".length";
207 v8::Local<v8::Script> script = v8_compile(c_source);
208 v8::Maybe<int32_t> result = script->Run(isolate->GetCurrentContext())
209 .ToLocalChecked()
210 ->Int32Value(isolate->GetCurrentContext());
211 CHECK_EQ(4, result.FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000213 isolate->Dispose();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214}
215
Ben Murdochda12d292016-06-02 14:46:10 +0100216UNINITIALIZED_TEST(StartupSerializerTwiceRunScript) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000217 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100218 v8::Isolate* isolate = TestIsolate::NewInitialized(true);
219 Vector<const byte> blob1 = Serialize(isolate);
220 Vector<const byte> blob2 = Serialize(isolate);
221 blob1.Dispose();
222 isolate = Deserialize(blob2);
223 blob2.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224 {
225 v8::Isolate::Scope isolate_scope(isolate);
226 v8::HandleScope handle_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000227
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 v8::Local<v8::Context> env = v8::Context::New(isolate);
229 env->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 const char* c_source = "\"1234\".length";
232 v8::Local<v8::Script> script = v8_compile(c_source);
233 v8::Maybe<int32_t> result = script->Run(isolate->GetCurrentContext())
234 .ToLocalChecked()
235 ->Int32Value(isolate->GetCurrentContext());
236 CHECK_EQ(4, result.FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 isolate->Dispose();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239}
240
Ben Murdochda12d292016-06-02 14:46:10 +0100241static void PartiallySerializeObject(Vector<const byte>* startup_blob_out,
242 Vector<const byte>* partial_blob_out) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000243 v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
244 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
245 v8_isolate->Enter();
246 {
247 Heap* heap = isolate->heap();
248
249 v8::Persistent<v8::Context> env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000250 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000251 HandleScope scope(isolate);
252 env.Reset(v8_isolate, v8::Context::New(v8_isolate));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000253 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000254 CHECK(!env.IsEmpty());
255 {
256 v8::HandleScope handle_scope(v8_isolate);
257 v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
258 }
259 // Make sure all builtin scripts are cached.
260 {
261 HandleScope scope(isolate);
262 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
263 isolate->bootstrapper()->SourceLookup<Natives>(i);
264 }
265 }
266 heap->CollectAllGarbage();
267 heap->CollectAllGarbage();
268
269 Object* raw_foo;
270 {
271 v8::HandleScope handle_scope(v8_isolate);
272 v8::Local<v8::String> foo = v8_str("foo");
273 CHECK(!foo.IsEmpty());
274 raw_foo = *(v8::Utils::OpenHandle(*foo));
275 }
276
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277 {
278 v8::HandleScope handle_scope(v8_isolate);
279 v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
280 }
281 env.Reset();
282
283 SnapshotByteSink startup_sink;
284 StartupSerializer startup_serializer(isolate, &startup_sink);
285 startup_serializer.SerializeStrongReferences();
286
287 SnapshotByteSink partial_sink;
288 PartialSerializer partial_serializer(isolate, &startup_serializer,
289 &partial_sink);
290 partial_serializer.Serialize(&raw_foo);
291
292 startup_serializer.SerializeWeakReferencesAndDeferred();
293
294 SnapshotData startup_snapshot(startup_serializer);
295 SnapshotData partial_snapshot(partial_serializer);
296
Ben Murdochda12d292016-06-02 14:46:10 +0100297 *partial_blob_out = WritePayload(partial_snapshot.RawData());
298 *startup_blob_out = WritePayload(startup_snapshot.RawData());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000299 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000300 v8_isolate->Exit();
301 v8_isolate->Dispose();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302}
303
Ben Murdochda12d292016-06-02 14:46:10 +0100304UNINITIALIZED_TEST(PartialSerializerObject) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000305 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100306 Vector<const byte> startup_blob;
307 Vector<const byte> partial_blob;
308 PartiallySerializeObject(&startup_blob, &partial_blob);
Andrei Popescu31002712010-02-23 13:46:05 +0000309
Ben Murdochda12d292016-06-02 14:46:10 +0100310 v8::Isolate* v8_isolate = InitializeFromBlob(startup_blob);
311 startup_blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000312 CHECK(v8_isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 {
314 v8::Isolate::Scope isolate_scope(v8_isolate);
315
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000316 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
317 HandleScope handle_scope(isolate);
318 Handle<Object> root;
319 // Intentionally empty handle. The deserializer should not come across
320 // any references to the global proxy in this test.
321 Handle<JSGlobalProxy> global_proxy = Handle<JSGlobalProxy>::null();
Andrei Popescu31002712010-02-23 13:46:05 +0000322 {
Ben Murdochda12d292016-06-02 14:46:10 +0100323 SnapshotData snapshot_data(partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324 Deserializer deserializer(&snapshot_data);
325 root = deserializer.DeserializePartial(isolate, global_proxy)
326 .ToHandleChecked();
327 CHECK(root->IsString());
Andrei Popescu31002712010-02-23 13:46:05 +0000328 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329
330 Handle<Object> root2;
331 {
Ben Murdochda12d292016-06-02 14:46:10 +0100332 SnapshotData snapshot_data(partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000333 Deserializer deserializer(&snapshot_data);
334 root2 = deserializer.DeserializePartial(isolate, global_proxy)
335 .ToHandleChecked();
336 CHECK(root2->IsString());
337 CHECK(root.is_identical_to(root2));
338 }
Ben Murdochda12d292016-06-02 14:46:10 +0100339 partial_blob.Dispose();
Leon Clarked91b9f72010-01-27 17:25:45 +0000340 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341 v8_isolate->Dispose();
Andrei Popescu31002712010-02-23 13:46:05 +0000342}
Leon Clarked91b9f72010-01-27 17:25:45 +0000343
Ben Murdochda12d292016-06-02 14:46:10 +0100344static void PartiallySerializeContext(Vector<const byte>* startup_blob_out,
345 Vector<const byte>* partial_blob_out) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000346 v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
347 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
348 Heap* heap = isolate->heap();
349 {
350 v8::Isolate::Scope isolate_scope(v8_isolate);
351
352 v8::Persistent<v8::Context> env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000353 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000354 HandleScope scope(isolate);
355 env.Reset(v8_isolate, v8::Context::New(v8_isolate));
Andrei Popescu31002712010-02-23 13:46:05 +0000356 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000357 CHECK(!env.IsEmpty());
358 {
359 v8::HandleScope handle_scope(v8_isolate);
360 v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
361 }
362 // Make sure all builtin scripts are cached.
363 {
364 HandleScope scope(isolate);
365 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
366 isolate->bootstrapper()->SourceLookup<Natives>(i);
367 }
368 }
369 // If we don't do this then we end up with a stray root pointing at the
370 // context even after we have disposed of env.
371 heap->CollectAllGarbage();
Andrei Popescu31002712010-02-23 13:46:05 +0000372
Andrei Popescu31002712010-02-23 13:46:05 +0000373 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000374 v8::HandleScope handle_scope(v8_isolate);
375 v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
376 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000377
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000378 i::Object* raw_context = *v8::Utils::OpenPersistent(env);
Andrei Popescu31002712010-02-23 13:46:05 +0000379
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000380 env.Reset();
Leon Clarkee46be812010-01-19 14:06:41 +0000381
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382 SnapshotByteSink startup_sink;
383 StartupSerializer startup_serializer(isolate, &startup_sink);
384 startup_serializer.SerializeStrongReferences();
385
386 SnapshotByteSink partial_sink;
387 PartialSerializer partial_serializer(isolate, &startup_serializer,
388 &partial_sink);
389 partial_serializer.Serialize(&raw_context);
390 startup_serializer.SerializeWeakReferencesAndDeferred();
391
392 SnapshotData startup_snapshot(startup_serializer);
393 SnapshotData partial_snapshot(partial_serializer);
394
Ben Murdochda12d292016-06-02 14:46:10 +0100395 *partial_blob_out = WritePayload(partial_snapshot.RawData());
396 *startup_blob_out = WritePayload(startup_snapshot.RawData());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000397 }
398 v8_isolate->Dispose();
399}
Leon Clarkee46be812010-01-19 14:06:41 +0000400
Ben Murdochda12d292016-06-02 14:46:10 +0100401UNINITIALIZED_TEST(PartialSerializerContext) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100403 Vector<const byte> startup_blob;
404 Vector<const byte> partial_blob;
405 PartiallySerializeContext(&startup_blob, &partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406
Ben Murdochda12d292016-06-02 14:46:10 +0100407 v8::Isolate* v8_isolate = InitializeFromBlob(startup_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000408 CHECK(v8_isolate);
Ben Murdochda12d292016-06-02 14:46:10 +0100409 startup_blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000410 {
411 v8::Isolate::Scope isolate_scope(v8_isolate);
412
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000413 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
414 HandleScope handle_scope(isolate);
415 Handle<Object> root;
416 Handle<JSGlobalProxy> global_proxy =
417 isolate->factory()->NewUninitializedJSGlobalProxy();
418 {
Ben Murdochda12d292016-06-02 14:46:10 +0100419 SnapshotData snapshot_data(partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000420 Deserializer deserializer(&snapshot_data);
421 root = deserializer.DeserializePartial(isolate, global_proxy)
422 .ToHandleChecked();
423 CHECK(root->IsContext());
424 CHECK(Handle<Context>::cast(root)->global_proxy() == *global_proxy);
425 }
426
427 Handle<Object> root2;
428 {
Ben Murdochda12d292016-06-02 14:46:10 +0100429 SnapshotData snapshot_data(partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430 Deserializer deserializer(&snapshot_data);
431 root2 = deserializer.DeserializePartial(isolate, global_proxy)
432 .ToHandleChecked();
433 CHECK(root2->IsContext());
434 CHECK(!root.is_identical_to(root2));
435 }
Ben Murdochda12d292016-06-02 14:46:10 +0100436 partial_blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000437 }
438 v8_isolate->Dispose();
439}
440
Ben Murdochda12d292016-06-02 14:46:10 +0100441static void PartiallySerializeCustomContext(
442 Vector<const byte>* startup_blob_out,
443 Vector<const byte>* partial_blob_out) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000444 v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
445 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
446 {
447 v8::Isolate::Scope isolate_scope(v8_isolate);
448
449 v8::Persistent<v8::Context> env;
450 {
451 HandleScope scope(isolate);
452 env.Reset(v8_isolate, v8::Context::New(v8_isolate));
453 }
454 CHECK(!env.IsEmpty());
455 {
456 v8::HandleScope handle_scope(v8_isolate);
457 v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
458 // After execution, e's function context refers to the global object.
459 CompileRun(
460 "var e;"
461 "(function() {"
462 " e = function(s) { return eval (s); }"
463 "})();"
464 "var o = this;"
Ben Murdochda12d292016-06-02 14:46:10 +0100465 "var r = Math.random();"
466 "var c = Math.sin(0) + Math.cos(0);"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000467 "var f = (function(a, b) { return a + b; }).bind(1, 2, 3);"
468 "var s = parseInt('12345');");
469
470 Vector<const uint8_t> source = ConstructSource(
471 STATIC_CHAR_VECTOR("function g() { return [,"),
472 STATIC_CHAR_VECTOR("1,"),
473 STATIC_CHAR_VECTOR("];} a = g(); b = g(); b.push(1);"), 100000);
474 v8::MaybeLocal<v8::String> source_str = v8::String::NewFromOneByte(
475 v8_isolate, source.start(), v8::NewStringType::kNormal,
476 source.length());
477 CompileRun(source_str.ToLocalChecked());
478 source.Dispose();
479 }
480 // Make sure all builtin scripts are cached.
481 {
482 HandleScope scope(isolate);
483 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
484 isolate->bootstrapper()->SourceLookup<Natives>(i);
Leon Clarkee46be812010-01-19 14:06:41 +0000485 }
Leon Clarkee46be812010-01-19 14:06:41 +0000486 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000487 // If we don't do this then we end up with a stray root pointing at the
488 // context even after we have disposed of env.
489 isolate->heap()->CollectAllAvailableGarbage("snapshotting");
490
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000491 {
492 v8::HandleScope handle_scope(v8_isolate);
493 v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
494 }
495
496 i::Object* raw_context = *v8::Utils::OpenPersistent(env);
497
498 env.Reset();
499
500 SnapshotByteSink startup_sink;
501 StartupSerializer startup_serializer(isolate, &startup_sink);
502 startup_serializer.SerializeStrongReferences();
503
504 SnapshotByteSink partial_sink;
505 PartialSerializer partial_serializer(isolate, &startup_serializer,
506 &partial_sink);
507 partial_serializer.Serialize(&raw_context);
508 startup_serializer.SerializeWeakReferencesAndDeferred();
509
510 SnapshotData startup_snapshot(startup_serializer);
511 SnapshotData partial_snapshot(partial_serializer);
512
Ben Murdochda12d292016-06-02 14:46:10 +0100513 *partial_blob_out = WritePayload(partial_snapshot.RawData());
514 *startup_blob_out = WritePayload(startup_snapshot.RawData());
Leon Clarkee46be812010-01-19 14:06:41 +0000515 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000516 v8_isolate->Dispose();
517}
518
Ben Murdochda12d292016-06-02 14:46:10 +0100519UNINITIALIZED_TEST(PartialSerializerCustomContext) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000520 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100521 Vector<const byte> startup_blob;
522 Vector<const byte> partial_blob;
523 PartiallySerializeCustomContext(&startup_blob, &partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000524
Ben Murdochda12d292016-06-02 14:46:10 +0100525 v8::Isolate* v8_isolate = InitializeFromBlob(startup_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000526 CHECK(v8_isolate);
Ben Murdochda12d292016-06-02 14:46:10 +0100527 startup_blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000528 {
529 v8::Isolate::Scope isolate_scope(v8_isolate);
530
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000531 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
532 HandleScope handle_scope(isolate);
533 Handle<Object> root;
534 Handle<JSGlobalProxy> global_proxy =
535 isolate->factory()->NewUninitializedJSGlobalProxy();
536 {
Ben Murdochda12d292016-06-02 14:46:10 +0100537 SnapshotData snapshot_data(partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000538 Deserializer deserializer(&snapshot_data);
539 root = deserializer.DeserializePartial(isolate, global_proxy)
540 .ToHandleChecked();
541 CHECK(root->IsContext());
542 Handle<Context> context = Handle<Context>::cast(root);
Ben Murdochda12d292016-06-02 14:46:10 +0100543
544 // Add context to the weak native context list
545 context->set(Context::NEXT_CONTEXT_LINK,
546 isolate->heap()->native_contexts_list(),
547 UPDATE_WEAK_WRITE_BARRIER);
548 isolate->heap()->set_native_contexts_list(*context);
549
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000550 CHECK(context->global_proxy() == *global_proxy);
551 Handle<String> o = isolate->factory()->NewStringFromAsciiChecked("o");
552 Handle<JSObject> global_object(context->global_object(), isolate);
553 Handle<Object> property = JSReceiver::GetDataProperty(global_object, o);
554 CHECK(property.is_identical_to(global_proxy));
555
556 v8::Local<v8::Context> v8_context = v8::Utils::ToLocal(context);
557 v8::Context::Scope context_scope(v8_context);
558 double r = CompileRun("r")
559 ->ToNumber(v8_isolate->GetCurrentContext())
560 .ToLocalChecked()
561 ->Value();
Ben Murdochda12d292016-06-02 14:46:10 +0100562 CHECK(0.0 <= r && r < 1.0);
563 // Math.random still works.
564 double random = CompileRun("Math.random()")
565 ->ToNumber(v8_isolate->GetCurrentContext())
566 .ToLocalChecked()
567 ->Value();
568 CHECK(0.0 <= random && random < 1.0);
569 double c = CompileRun("c")
570 ->ToNumber(v8_isolate->GetCurrentContext())
571 .ToLocalChecked()
572 ->Value();
573 CHECK_EQ(1, c);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000574 int f = CompileRun("f()")
575 ->ToNumber(v8_isolate->GetCurrentContext())
576 .ToLocalChecked()
577 ->Int32Value(v8_isolate->GetCurrentContext())
578 .FromJust();
579 CHECK_EQ(5, f);
580 f = CompileRun("e('f()')")
581 ->ToNumber(v8_isolate->GetCurrentContext())
582 .ToLocalChecked()
583 ->Int32Value(v8_isolate->GetCurrentContext())
584 .FromJust();
585 CHECK_EQ(5, f);
586 v8::Local<v8::String> s = CompileRun("s")
587 ->ToString(v8_isolate->GetCurrentContext())
588 .ToLocalChecked();
589 CHECK(s->Equals(v8_isolate->GetCurrentContext(), v8_str("12345"))
590 .FromJust());
591 int a = CompileRun("a.length")
592 ->ToNumber(v8_isolate->GetCurrentContext())
593 .ToLocalChecked()
594 ->Int32Value(v8_isolate->GetCurrentContext())
595 .FromJust();
596 CHECK_EQ(100001, a);
597 int b = CompileRun("b.length")
598 ->ToNumber(v8_isolate->GetCurrentContext())
599 .ToLocalChecked()
600 ->Int32Value(v8_isolate->GetCurrentContext())
601 .FromJust();
602 CHECK_EQ(100002, b);
603 }
Ben Murdochda12d292016-06-02 14:46:10 +0100604 partial_blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000605 }
606 v8_isolate->Dispose();
607}
608
Ben Murdochda12d292016-06-02 14:46:10 +0100609TEST(CustomSnapshotDataBlob) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610 DisableTurbofan();
611 const char* source1 = "function f() { return 42; }";
612 const char* source2 =
613 "function f() { return g() * 2; }"
614 "function g() { return 43; }"
615 "/./.test('a')";
616
617 v8::StartupData data1 = v8::V8::CreateSnapshotDataBlob(source1);
618 v8::StartupData data2 = v8::V8::CreateSnapshotDataBlob(source2);
619
620 v8::Isolate::CreateParams params1;
621 params1.snapshot_blob = &data1;
622 params1.array_buffer_allocator = CcTest::array_buffer_allocator();
623
624 v8::Isolate* isolate1 = v8::Isolate::New(params1);
625 {
626 v8::Isolate::Scope i_scope(isolate1);
627 v8::HandleScope h_scope(isolate1);
628 v8::Local<v8::Context> context = v8::Context::New(isolate1);
629 delete[] data1.data; // We can dispose of the snapshot blob now.
630 v8::Context::Scope c_scope(context);
631 v8::Maybe<int32_t> result =
632 CompileRun("f()")->Int32Value(isolate1->GetCurrentContext());
633 CHECK_EQ(42, result.FromJust());
634 CHECK(CompileRun("this.g")->IsUndefined());
635 }
636 isolate1->Dispose();
637
638 v8::Isolate::CreateParams params2;
639 params2.snapshot_blob = &data2;
640 params2.array_buffer_allocator = CcTest::array_buffer_allocator();
641 v8::Isolate* isolate2 = v8::Isolate::New(params2);
642 {
643 v8::Isolate::Scope i_scope(isolate2);
644 v8::HandleScope h_scope(isolate2);
645 v8::Local<v8::Context> context = v8::Context::New(isolate2);
646 delete[] data2.data; // We can dispose of the snapshot blob now.
647 v8::Context::Scope c_scope(context);
648 v8::Maybe<int32_t> result =
649 CompileRun("f()")->Int32Value(isolate2->GetCurrentContext());
650 CHECK_EQ(86, result.FromJust());
651 result = CompileRun("g()")->Int32Value(isolate2->GetCurrentContext());
652 CHECK_EQ(43, result.FromJust());
653 }
654 isolate2->Dispose();
655}
656
657
658static void SerializationFunctionTemplate(
659 const v8::FunctionCallbackInfo<v8::Value>& args) {
660 args.GetReturnValue().Set(args[0]);
661}
662
Ben Murdochda12d292016-06-02 14:46:10 +0100663TEST(CustomSnapshotDataBlobOutdatedContextWithOverflow) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000664 DisableTurbofan();
665
666 const char* source1 =
667 "var o = {};"
668 "(function() {"
669 " function f1(x) { return f2(x) instanceof Array; }"
670 " function f2(x) { return foo.bar(x); }"
671 " o.a = f2.bind(null);"
672 " o.b = 1;"
673 " o.c = 2;"
674 " o.d = 3;"
675 " o.e = 4;"
676 "})();\n";
677
678 const char* source2 = "o.a(42)";
679
680 v8::StartupData data = v8::V8::CreateSnapshotDataBlob(source1);
681
682 v8::Isolate::CreateParams params;
683 params.snapshot_blob = &data;
684 params.array_buffer_allocator = CcTest::array_buffer_allocator();
685
686 v8::Isolate* isolate = v8::Isolate::New(params);
687 {
688 v8::Isolate::Scope i_scope(isolate);
689 v8::HandleScope h_scope(isolate);
690
691 v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
692 v8::Local<v8::ObjectTemplate> property = v8::ObjectTemplate::New(isolate);
693 v8::Local<v8::FunctionTemplate> function =
694 v8::FunctionTemplate::New(isolate, SerializationFunctionTemplate);
695 property->Set(isolate, "bar", function);
696 global->Set(isolate, "foo", property);
697
698 v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
699 delete[] data.data; // We can dispose of the snapshot blob now.
700 v8::Context::Scope c_scope(context);
701 v8::Local<v8::Value> result = CompileRun(source2);
702 v8::Maybe<bool> compare = v8_str("42")->Equals(
703 v8::Isolate::GetCurrent()->GetCurrentContext(), result);
704 CHECK(compare.FromJust());
705 }
706 isolate->Dispose();
707}
708
Ben Murdochda12d292016-06-02 14:46:10 +0100709TEST(CustomSnapshotDataBlobWithLocker) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000710 DisableTurbofan();
711 v8::Isolate::CreateParams create_params;
712 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
713 v8::Isolate* isolate0 = v8::Isolate::New(create_params);
714 {
715 v8::Locker locker(isolate0);
716 v8::Isolate::Scope i_scope(isolate0);
717 v8::HandleScope h_scope(isolate0);
718 v8::Local<v8::Context> context = v8::Context::New(isolate0);
719 v8::Context::Scope c_scope(context);
720 v8::Maybe<int32_t> result =
721 CompileRun("Math.cos(0)")->Int32Value(isolate0->GetCurrentContext());
722 CHECK_EQ(1, result.FromJust());
723 }
724 isolate0->Dispose();
725
726 const char* source1 = "function f() { return 42; }";
727
728 v8::StartupData data1 = v8::V8::CreateSnapshotDataBlob(source1);
729
730 v8::Isolate::CreateParams params1;
731 params1.snapshot_blob = &data1;
732 params1.array_buffer_allocator = CcTest::array_buffer_allocator();
733 v8::Isolate* isolate1 = v8::Isolate::New(params1);
734 {
735 v8::Locker locker(isolate1);
736 v8::Isolate::Scope i_scope(isolate1);
737 v8::HandleScope h_scope(isolate1);
738 v8::Local<v8::Context> context = v8::Context::New(isolate1);
739 delete[] data1.data; // We can dispose of the snapshot blob now.
740 v8::Context::Scope c_scope(context);
741 v8::Maybe<int32_t> result = CompileRun("f()")->Int32Value(context);
742 CHECK_EQ(42, result.FromJust());
743 }
744 isolate1->Dispose();
745}
746
Ben Murdochda12d292016-06-02 14:46:10 +0100747TEST(CustomSnapshotDataBlobStackOverflow) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000748 DisableTurbofan();
749 const char* source =
750 "var a = [0];"
751 "var b = a;"
752 "for (var i = 0; i < 10000; i++) {"
753 " var c = [i];"
754 " b.push(c);"
755 " b.push(c);"
756 " b = c;"
757 "}";
758
759 v8::StartupData data = v8::V8::CreateSnapshotDataBlob(source);
760
761 v8::Isolate::CreateParams params;
762 params.snapshot_blob = &data;
763 params.array_buffer_allocator = CcTest::array_buffer_allocator();
764
765 v8::Isolate* isolate = v8::Isolate::New(params);
766 {
767 v8::Isolate::Scope i_scope(isolate);
768 v8::HandleScope h_scope(isolate);
769 v8::Local<v8::Context> context = v8::Context::New(isolate);
770 delete[] data.data; // We can dispose of the snapshot blob now.
771 v8::Context::Scope c_scope(context);
772 const char* test =
773 "var sum = 0;"
774 "while (a) {"
775 " sum += a[0];"
776 " a = a[1];"
777 "}"
778 "sum";
779 v8::Maybe<int32_t> result =
780 CompileRun(test)->Int32Value(isolate->GetCurrentContext());
781 CHECK_EQ(9999 * 5000, result.FromJust());
782 }
783 isolate->Dispose();
Leon Clarkee46be812010-01-19 14:06:41 +0000784}
785
Ben Murdochda12d292016-06-02 14:46:10 +0100786bool IsCompiled(const char* name) {
787 return i::Handle<i::JSFunction>::cast(
788 v8::Utils::OpenHandle(*CompileRun(name)))
789 ->shared()
790 ->is_compiled();
791}
792
793TEST(SnapshotDataBlobWithWarmup) {
794 DisableTurbofan();
795 const char* warmup = "Math.tan(1); Math.sin = 1;";
796
797 v8::StartupData cold = v8::V8::CreateSnapshotDataBlob();
798 v8::StartupData warm = v8::V8::WarmUpSnapshotDataBlob(cold, warmup);
799 delete[] cold.data;
800
801 v8::Isolate::CreateParams params;
802 params.snapshot_blob = &warm;
803 params.array_buffer_allocator = CcTest::array_buffer_allocator();
804
805 v8::Isolate* isolate = v8::Isolate::New(params);
806 {
807 v8::Isolate::Scope i_scope(isolate);
808 v8::HandleScope h_scope(isolate);
809 v8::Local<v8::Context> context = v8::Context::New(isolate);
810 delete[] warm.data;
811 v8::Context::Scope c_scope(context);
812 // Running the warmup script has effect on whether functions are
813 // pre-compiled, but does not pollute the context.
814 CHECK(IsCompiled("Math.tan"));
815 CHECK(!IsCompiled("Math.cos"));
816 CHECK(CompileRun("Math.sin")->IsFunction());
817 }
818 isolate->Dispose();
819}
820
821TEST(CustomSnapshotDataBlobWithWarmup) {
822 DisableTurbofan();
823 const char* source =
824 "function f() { return Math.sin(1); }\n"
825 "function g() { return Math.cos(1); }\n"
826 "Math.tan(1);"
827 "var a = 5";
828 const char* warmup = "a = f()";
829
830 v8::StartupData cold = v8::V8::CreateSnapshotDataBlob(source);
831 v8::StartupData warm = v8::V8::WarmUpSnapshotDataBlob(cold, warmup);
832 delete[] cold.data;
833
834 v8::Isolate::CreateParams params;
835 params.snapshot_blob = &warm;
836 params.array_buffer_allocator = CcTest::array_buffer_allocator();
837
838 v8::Isolate* isolate = v8::Isolate::New(params);
839 {
840 v8::Isolate::Scope i_scope(isolate);
841 v8::HandleScope h_scope(isolate);
842 v8::Local<v8::Context> context = v8::Context::New(isolate);
843 delete[] warm.data;
844 v8::Context::Scope c_scope(context);
845 // Running the warmup script has effect on whether functions are
846 // pre-compiled, but does not pollute the context.
847 CHECK(IsCompiled("f"));
848 CHECK(IsCompiled("Math.sin"));
849 CHECK(!IsCompiled("g"));
850 CHECK(!IsCompiled("Math.cos"));
851 CHECK(!IsCompiled("Math.tan"));
852 CHECK_EQ(5, CompileRun("a")->Int32Value(context).FromJust());
853 }
854 isolate->Dispose();
855}
856
857TEST(CustomSnapshotDataBlobImmortalImmovableRoots) {
858 DisableTurbofan();
859 // Flood the startup snapshot with shared function infos. If they are
860 // serialized before the immortal immovable root, the root will no longer end
861 // up on the first page.
862 Vector<const uint8_t> source =
863 ConstructSource(STATIC_CHAR_VECTOR("var a = [];"),
864 STATIC_CHAR_VECTOR("a.push(function() {return 7});"),
865 STATIC_CHAR_VECTOR("\0"), 10000);
866
867 v8::StartupData data = v8::V8::CreateSnapshotDataBlob(
868 reinterpret_cast<const char*>(source.start()));
869
870 v8::Isolate::CreateParams params;
871 params.snapshot_blob = &data;
872 params.array_buffer_allocator = CcTest::array_buffer_allocator();
873
874 v8::Isolate* isolate = v8::Isolate::New(params);
875 {
876 v8::Isolate::Scope i_scope(isolate);
877 v8::HandleScope h_scope(isolate);
878 v8::Local<v8::Context> context = v8::Context::New(isolate);
879 delete[] data.data; // We can dispose of the snapshot blob now.
880 v8::Context::Scope c_scope(context);
881 CHECK_EQ(7, CompileRun("a[0]()")->Int32Value(context).FromJust());
882 }
883 isolate->Dispose();
884 source.Dispose();
885}
Leon Clarkee46be812010-01-19 14:06:41 +0000886
Steve Block3ce2e202009-11-05 08:53:23 +0000887TEST(TestThatAlwaysSucceeds) {
888}
889
890
891TEST(TestThatAlwaysFails) {
892 bool ArtificialFailure = false;
893 CHECK(ArtificialFailure);
894}
895
896
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000897int CountBuiltins() {
898 // Check that we have not deserialized any additional builtin.
899 HeapIterator iterator(CcTest::heap());
900 DisallowHeapAllocation no_allocation;
901 int counter = 0;
902 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
903 if (obj->IsCode() && Code::cast(obj)->kind() == Code::BUILTIN) counter++;
904 }
905 return counter;
906}
907
908
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000909static Handle<SharedFunctionInfo> CompileScript(
910 Isolate* isolate, Handle<String> source, Handle<String> name,
911 ScriptData** cached_data, v8::ScriptCompiler::CompileOptions options) {
Ben Murdochda12d292016-06-02 14:46:10 +0100912 return Compiler::GetSharedFunctionInfoForScript(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000913 source, name, 0, 0, v8::ScriptOriginOptions(), Handle<Object>(),
914 Handle<Context>(isolate->native_context()), NULL, cached_data, options,
915 NOT_NATIVES_CODE, false);
916}
917
Ben Murdochda12d292016-06-02 14:46:10 +0100918TEST(CodeSerializerOnePlusOne) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000919 FLAG_serialize_toplevel = true;
920 LocalContext context;
921 Isolate* isolate = CcTest::i_isolate();
922 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
923
924 v8::HandleScope scope(CcTest::isolate());
925
926 const char* source = "1 + 1";
927
928 Handle<String> orig_source = isolate->factory()
929 ->NewStringFromUtf8(CStrVector(source))
930 .ToHandleChecked();
931 Handle<String> copy_source = isolate->factory()
932 ->NewStringFromUtf8(CStrVector(source))
933 .ToHandleChecked();
934 CHECK(!orig_source.is_identical_to(copy_source));
935 CHECK(orig_source->Equals(*copy_source));
936
937 ScriptData* cache = NULL;
938
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000939 Handle<SharedFunctionInfo> orig =
940 CompileScript(isolate, orig_source, Handle<String>(), &cache,
941 v8::ScriptCompiler::kProduceCodeCache);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000942
943 int builtins_count = CountBuiltins();
944
945 Handle<SharedFunctionInfo> copy;
946 {
947 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000948 copy = CompileScript(isolate, copy_source, Handle<String>(), &cache,
949 v8::ScriptCompiler::kConsumeCodeCache);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000950 }
951
952 CHECK_NE(*orig, *copy);
953 CHECK(Script::cast(copy->script())->source() == *copy_source);
954
955 Handle<JSFunction> copy_fun =
956 isolate->factory()->NewFunctionFromSharedFunctionInfo(
957 copy, isolate->native_context());
958 Handle<JSObject> global(isolate->context()->global_object());
959 Handle<Object> copy_result =
960 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
961 CHECK_EQ(2, Handle<Smi>::cast(copy_result)->value());
962
963 CHECK_EQ(builtins_count, CountBuiltins());
964
965 delete cache;
966}
967
Ben Murdochda12d292016-06-02 14:46:10 +0100968TEST(CodeSerializerPromotedToCompilationCache) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000969 FLAG_serialize_toplevel = true;
970 LocalContext context;
971 Isolate* isolate = CcTest::i_isolate();
972
973 v8::HandleScope scope(CcTest::isolate());
974
975 const char* source = "1 + 1";
976
977 Handle<String> src = isolate->factory()
978 ->NewStringFromUtf8(CStrVector(source))
979 .ToHandleChecked();
980 ScriptData* cache = NULL;
981
982 CompileScript(isolate, src, src, &cache,
983 v8::ScriptCompiler::kProduceCodeCache);
984
985 DisallowCompilation no_compile_expected(isolate);
986 Handle<SharedFunctionInfo> copy = CompileScript(
987 isolate, src, src, &cache, v8::ScriptCompiler::kConsumeCodeCache);
988
989 CHECK(isolate->compilation_cache()
990 ->LookupScript(src, src, 0, 0, v8::ScriptOriginOptions(),
991 isolate->native_context(), SLOPPY)
992 .ToHandleChecked()
993 .is_identical_to(copy));
994
995 delete cache;
996}
997
Ben Murdochda12d292016-06-02 14:46:10 +0100998TEST(CodeSerializerInternalizedString) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000999 FLAG_serialize_toplevel = true;
1000 LocalContext context;
1001 Isolate* isolate = CcTest::i_isolate();
1002 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1003
1004 v8::HandleScope scope(CcTest::isolate());
1005
1006 const char* source = "'string1'";
1007
1008 Handle<String> orig_source = isolate->factory()
1009 ->NewStringFromUtf8(CStrVector(source))
1010 .ToHandleChecked();
1011 Handle<String> copy_source = isolate->factory()
1012 ->NewStringFromUtf8(CStrVector(source))
1013 .ToHandleChecked();
1014 CHECK(!orig_source.is_identical_to(copy_source));
1015 CHECK(orig_source->Equals(*copy_source));
1016
1017 Handle<JSObject> global(isolate->context()->global_object());
1018 ScriptData* cache = NULL;
1019
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001020 Handle<SharedFunctionInfo> orig =
1021 CompileScript(isolate, orig_source, Handle<String>(), &cache,
1022 v8::ScriptCompiler::kProduceCodeCache);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001023 Handle<JSFunction> orig_fun =
1024 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1025 orig, isolate->native_context());
1026 Handle<Object> orig_result =
1027 Execution::Call(isolate, orig_fun, global, 0, NULL).ToHandleChecked();
1028 CHECK(orig_result->IsInternalizedString());
1029
1030 int builtins_count = CountBuiltins();
1031
1032 Handle<SharedFunctionInfo> copy;
1033 {
1034 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001035 copy = CompileScript(isolate, copy_source, Handle<String>(), &cache,
1036 v8::ScriptCompiler::kConsumeCodeCache);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001037 }
1038 CHECK_NE(*orig, *copy);
1039 CHECK(Script::cast(copy->script())->source() == *copy_source);
1040
1041 Handle<JSFunction> copy_fun =
1042 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1043 copy, isolate->native_context());
1044 CHECK_NE(*orig_fun, *copy_fun);
1045 Handle<Object> copy_result =
1046 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
1047 CHECK(orig_result.is_identical_to(copy_result));
1048 Handle<String> expected =
1049 isolate->factory()->NewStringFromAsciiChecked("string1");
1050
1051 CHECK(Handle<String>::cast(copy_result)->Equals(*expected));
1052 CHECK_EQ(builtins_count, CountBuiltins());
1053
1054 delete cache;
1055}
1056
Ben Murdochda12d292016-06-02 14:46:10 +01001057TEST(CodeSerializerLargeCodeObject) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001058 FLAG_serialize_toplevel = true;
1059 LocalContext context;
1060 Isolate* isolate = CcTest::i_isolate();
1061 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1062
1063 v8::HandleScope scope(CcTest::isolate());
1064
1065 Vector<const uint8_t> source =
1066 ConstructSource(STATIC_CHAR_VECTOR("var j=1; try { if (j) throw 1;"),
1067 STATIC_CHAR_VECTOR("for(var i=0;i<1;i++)j++;"),
1068 STATIC_CHAR_VECTOR("} catch (e) { j=7; } j"), 10000);
1069 Handle<String> source_str =
1070 isolate->factory()->NewStringFromOneByte(source).ToHandleChecked();
1071
1072 Handle<JSObject> global(isolate->context()->global_object());
1073 ScriptData* cache = NULL;
1074
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001075 Handle<SharedFunctionInfo> orig =
1076 CompileScript(isolate, source_str, Handle<String>(), &cache,
1077 v8::ScriptCompiler::kProduceCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001078
1079 CHECK(isolate->heap()->InSpace(orig->code(), LO_SPACE));
1080
1081 Handle<SharedFunctionInfo> copy;
1082 {
1083 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001084 copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
1085 v8::ScriptCompiler::kConsumeCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001086 }
1087 CHECK_NE(*orig, *copy);
1088
1089 Handle<JSFunction> copy_fun =
1090 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1091 copy, isolate->native_context());
1092
1093 Handle<Object> copy_result =
1094 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
1095
1096 int result_int;
1097 CHECK(copy_result->ToInt32(&result_int));
1098 CHECK_EQ(7, result_int);
1099
1100 delete cache;
1101 source.Dispose();
1102}
1103
Ben Murdochda12d292016-06-02 14:46:10 +01001104TEST(CodeSerializerLargeStrings) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001105 FLAG_serialize_toplevel = true;
1106 LocalContext context;
1107 Isolate* isolate = CcTest::i_isolate();
1108 Factory* f = isolate->factory();
1109 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1110
1111 v8::HandleScope scope(CcTest::isolate());
1112
1113 Vector<const uint8_t> source_s = ConstructSource(
1114 STATIC_CHAR_VECTOR("var s = \""), STATIC_CHAR_VECTOR("abcdef"),
1115 STATIC_CHAR_VECTOR("\";"), 1000000);
1116 Vector<const uint8_t> source_t = ConstructSource(
1117 STATIC_CHAR_VECTOR("var t = \""), STATIC_CHAR_VECTOR("uvwxyz"),
1118 STATIC_CHAR_VECTOR("\"; s + t"), 999999);
1119 Handle<String> source_str =
1120 f->NewConsString(f->NewStringFromOneByte(source_s).ToHandleChecked(),
1121 f->NewStringFromOneByte(source_t).ToHandleChecked())
1122 .ToHandleChecked();
1123
1124 Handle<JSObject> global(isolate->context()->global_object());
1125 ScriptData* cache = NULL;
1126
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001127 Handle<SharedFunctionInfo> orig =
1128 CompileScript(isolate, source_str, Handle<String>(), &cache,
1129 v8::ScriptCompiler::kProduceCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001130
1131 Handle<SharedFunctionInfo> copy;
1132 {
1133 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001134 copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
1135 v8::ScriptCompiler::kConsumeCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001136 }
1137 CHECK_NE(*orig, *copy);
1138
1139 Handle<JSFunction> copy_fun =
1140 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1141 copy, isolate->native_context());
1142
1143 Handle<Object> copy_result =
1144 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
1145
1146 CHECK_EQ(6 * 1999999, Handle<String>::cast(copy_result)->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001147 Handle<Object> property = JSReceiver::GetDataProperty(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001148 isolate->global_object(), f->NewStringFromAsciiChecked("s"));
1149 CHECK(isolate->heap()->InSpace(HeapObject::cast(*property), LO_SPACE));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001150 property = JSReceiver::GetDataProperty(isolate->global_object(),
1151 f->NewStringFromAsciiChecked("t"));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001152 CHECK(isolate->heap()->InSpace(HeapObject::cast(*property), LO_SPACE));
1153 // Make sure we do not serialize too much, e.g. include the source string.
1154 CHECK_LT(cache->length(), 13000000);
1155
1156 delete cache;
1157 source_s.Dispose();
1158 source_t.Dispose();
1159}
1160
Ben Murdochda12d292016-06-02 14:46:10 +01001161TEST(CodeSerializerThreeBigStrings) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001162 FLAG_serialize_toplevel = true;
1163 LocalContext context;
1164 Isolate* isolate = CcTest::i_isolate();
1165 Factory* f = isolate->factory();
1166 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1167
1168 v8::HandleScope scope(CcTest::isolate());
1169
1170 Vector<const uint8_t> source_a =
1171 ConstructSource(STATIC_CHAR_VECTOR("var a = \""), STATIC_CHAR_VECTOR("a"),
1172 STATIC_CHAR_VECTOR("\";"), 700000);
1173 Handle<String> source_a_str =
1174 f->NewStringFromOneByte(source_a).ToHandleChecked();
1175
1176 Vector<const uint8_t> source_b =
1177 ConstructSource(STATIC_CHAR_VECTOR("var b = \""), STATIC_CHAR_VECTOR("b"),
1178 STATIC_CHAR_VECTOR("\";"), 600000);
1179 Handle<String> source_b_str =
1180 f->NewStringFromOneByte(source_b).ToHandleChecked();
1181
1182 Vector<const uint8_t> source_c =
1183 ConstructSource(STATIC_CHAR_VECTOR("var c = \""), STATIC_CHAR_VECTOR("c"),
1184 STATIC_CHAR_VECTOR("\";"), 500000);
1185 Handle<String> source_c_str =
1186 f->NewStringFromOneByte(source_c).ToHandleChecked();
1187
1188 Handle<String> source_str =
1189 f->NewConsString(
1190 f->NewConsString(source_a_str, source_b_str).ToHandleChecked(),
1191 source_c_str).ToHandleChecked();
1192
1193 Handle<JSObject> global(isolate->context()->global_object());
1194 ScriptData* cache = NULL;
1195
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001196 Handle<SharedFunctionInfo> orig =
1197 CompileScript(isolate, source_str, Handle<String>(), &cache,
1198 v8::ScriptCompiler::kProduceCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001199
1200 Handle<SharedFunctionInfo> copy;
1201 {
1202 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001203 copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
1204 v8::ScriptCompiler::kConsumeCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001205 }
1206 CHECK_NE(*orig, *copy);
1207
1208 Handle<JSFunction> copy_fun =
1209 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1210 copy, isolate->native_context());
1211
1212 USE(Execution::Call(isolate, copy_fun, global, 0, NULL));
1213
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001214 v8::Maybe<int32_t> result =
1215 CompileRun("(a + b).length")
1216 ->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext());
1217 CHECK_EQ(600000 + 700000, result.FromJust());
1218 result = CompileRun("(b + c).length")
1219 ->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext());
1220 CHECK_EQ(500000 + 600000, result.FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001221 Heap* heap = isolate->heap();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001222 v8::Local<v8::String> result_str =
1223 CompileRun("a")
1224 ->ToString(CcTest::isolate()->GetCurrentContext())
1225 .ToLocalChecked();
1226 CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), LO_SPACE));
1227 result_str = CompileRun("b")
1228 ->ToString(CcTest::isolate()->GetCurrentContext())
1229 .ToLocalChecked();
1230 CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), OLD_SPACE));
1231 result_str = CompileRun("c")
1232 ->ToString(CcTest::isolate()->GetCurrentContext())
1233 .ToLocalChecked();
1234 CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), OLD_SPACE));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001235
1236 delete cache;
1237 source_a.Dispose();
1238 source_b.Dispose();
1239 source_c.Dispose();
1240}
1241
1242
1243class SerializerOneByteResource
1244 : public v8::String::ExternalOneByteStringResource {
1245 public:
1246 SerializerOneByteResource(const char* data, size_t length)
1247 : data_(data), length_(length) {}
1248 virtual const char* data() const { return data_; }
1249 virtual size_t length() const { return length_; }
1250
1251 private:
1252 const char* data_;
1253 size_t length_;
1254};
1255
1256
1257class SerializerTwoByteResource : public v8::String::ExternalStringResource {
1258 public:
1259 SerializerTwoByteResource(const char* data, size_t length)
1260 : data_(AsciiToTwoByteString(data)), length_(length) {}
1261 ~SerializerTwoByteResource() { DeleteArray<const uint16_t>(data_); }
1262
1263 virtual const uint16_t* data() const { return data_; }
1264 virtual size_t length() const { return length_; }
1265
1266 private:
1267 const uint16_t* data_;
1268 size_t length_;
1269};
1270
Ben Murdochda12d292016-06-02 14:46:10 +01001271TEST(CodeSerializerExternalString) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001272 FLAG_serialize_toplevel = true;
1273 LocalContext context;
1274 Isolate* isolate = CcTest::i_isolate();
1275 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1276
1277 v8::HandleScope scope(CcTest::isolate());
1278
1279 // Obtain external internalized one-byte string.
1280 SerializerOneByteResource one_byte_resource("one_byte", 8);
1281 Handle<String> one_byte_string =
1282 isolate->factory()->NewStringFromAsciiChecked("one_byte");
1283 one_byte_string = isolate->factory()->InternalizeString(one_byte_string);
1284 one_byte_string->MakeExternal(&one_byte_resource);
1285 CHECK(one_byte_string->IsExternalOneByteString());
1286 CHECK(one_byte_string->IsInternalizedString());
1287
1288 // Obtain external internalized two-byte string.
1289 SerializerTwoByteResource two_byte_resource("two_byte", 8);
1290 Handle<String> two_byte_string =
1291 isolate->factory()->NewStringFromAsciiChecked("two_byte");
1292 two_byte_string = isolate->factory()->InternalizeString(two_byte_string);
1293 two_byte_string->MakeExternal(&two_byte_resource);
1294 CHECK(two_byte_string->IsExternalTwoByteString());
1295 CHECK(two_byte_string->IsInternalizedString());
1296
1297 const char* source =
1298 "var o = {} \n"
1299 "o.one_byte = 7; \n"
1300 "o.two_byte = 8; \n"
1301 "o.one_byte + o.two_byte; \n";
1302 Handle<String> source_string = isolate->factory()
1303 ->NewStringFromUtf8(CStrVector(source))
1304 .ToHandleChecked();
1305
1306 Handle<JSObject> global(isolate->context()->global_object());
1307 ScriptData* cache = NULL;
1308
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001309 Handle<SharedFunctionInfo> orig =
1310 CompileScript(isolate, source_string, Handle<String>(), &cache,
1311 v8::ScriptCompiler::kProduceCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001312
1313 Handle<SharedFunctionInfo> copy;
1314 {
1315 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001316 copy = CompileScript(isolate, source_string, Handle<String>(), &cache,
1317 v8::ScriptCompiler::kConsumeCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001318 }
1319 CHECK_NE(*orig, *copy);
1320
1321 Handle<JSFunction> copy_fun =
1322 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1323 copy, isolate->native_context());
1324
1325 Handle<Object> copy_result =
1326 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
1327
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001328 CHECK_EQ(15.0, copy_result->Number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001329
1330 delete cache;
1331}
1332
Ben Murdochda12d292016-06-02 14:46:10 +01001333TEST(CodeSerializerLargeExternalString) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001334 FLAG_serialize_toplevel = true;
1335 LocalContext context;
1336 Isolate* isolate = CcTest::i_isolate();
1337 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1338
1339 Factory* f = isolate->factory();
1340
1341 v8::HandleScope scope(CcTest::isolate());
1342
1343 // Create a huge external internalized string to use as variable name.
1344 Vector<const uint8_t> string =
1345 ConstructSource(STATIC_CHAR_VECTOR(""), STATIC_CHAR_VECTOR("abcdef"),
1346 STATIC_CHAR_VECTOR(""), 999999);
1347 Handle<String> name = f->NewStringFromOneByte(string).ToHandleChecked();
1348 SerializerOneByteResource one_byte_resource(
1349 reinterpret_cast<const char*>(string.start()), string.length());
1350 name = f->InternalizeString(name);
1351 name->MakeExternal(&one_byte_resource);
1352 CHECK(name->IsExternalOneByteString());
1353 CHECK(name->IsInternalizedString());
1354 CHECK(isolate->heap()->InSpace(*name, LO_SPACE));
1355
1356 // Create the source, which is "var <literal> = 42; <literal>".
1357 Handle<String> source_str =
1358 f->NewConsString(
1359 f->NewConsString(f->NewStringFromAsciiChecked("var "), name)
1360 .ToHandleChecked(),
1361 f->NewConsString(f->NewStringFromAsciiChecked(" = 42; "), name)
1362 .ToHandleChecked()).ToHandleChecked();
1363
1364 Handle<JSObject> global(isolate->context()->global_object());
1365 ScriptData* cache = NULL;
1366
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001367 Handle<SharedFunctionInfo> orig =
1368 CompileScript(isolate, source_str, Handle<String>(), &cache,
1369 v8::ScriptCompiler::kProduceCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001370
1371 Handle<SharedFunctionInfo> copy;
1372 {
1373 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001374 copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
1375 v8::ScriptCompiler::kConsumeCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001376 }
1377 CHECK_NE(*orig, *copy);
1378
1379 Handle<JSFunction> copy_fun =
1380 f->NewFunctionFromSharedFunctionInfo(copy, isolate->native_context());
1381
1382 Handle<Object> copy_result =
1383 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
1384
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001385 CHECK_EQ(42.0, copy_result->Number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001386
1387 delete cache;
1388 string.Dispose();
1389}
1390
Ben Murdochda12d292016-06-02 14:46:10 +01001391TEST(CodeSerializerExternalScriptName) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001392 FLAG_serialize_toplevel = true;
1393 LocalContext context;
1394 Isolate* isolate = CcTest::i_isolate();
1395 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1396
1397 Factory* f = isolate->factory();
1398
1399 v8::HandleScope scope(CcTest::isolate());
1400
1401 const char* source =
1402 "var a = [1, 2, 3, 4];"
1403 "a.reduce(function(x, y) { return x + y }, 0)";
1404
1405 Handle<String> source_string =
1406 f->NewStringFromUtf8(CStrVector(source)).ToHandleChecked();
1407
1408 const SerializerOneByteResource one_byte_resource("one_byte", 8);
1409 Handle<String> name =
1410 f->NewExternalStringFromOneByte(&one_byte_resource).ToHandleChecked();
1411 CHECK(name->IsExternalOneByteString());
1412 CHECK(!name->IsInternalizedString());
1413
1414 Handle<JSObject> global(isolate->context()->global_object());
1415 ScriptData* cache = NULL;
1416
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001417 Handle<SharedFunctionInfo> orig =
1418 CompileScript(isolate, source_string, name, &cache,
1419 v8::ScriptCompiler::kProduceCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001420
1421 Handle<SharedFunctionInfo> copy;
1422 {
1423 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001424 copy = CompileScript(isolate, source_string, name, &cache,
1425 v8::ScriptCompiler::kConsumeCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001426 }
1427 CHECK_NE(*orig, *copy);
1428
1429 Handle<JSFunction> copy_fun =
1430 f->NewFunctionFromSharedFunctionInfo(copy, isolate->native_context());
1431
1432 Handle<Object> copy_result =
1433 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
1434
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001435 CHECK_EQ(10.0, copy_result->Number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001436
1437 delete cache;
1438}
1439
1440
1441static bool toplevel_test_code_event_found = false;
1442
1443
1444static void SerializerCodeEventListener(const v8::JitCodeEvent* event) {
1445 if (event->type == v8::JitCodeEvent::CODE_ADDED &&
1446 memcmp(event->name.str, "Script:~test", 12) == 0) {
1447 toplevel_test_code_event_found = true;
1448 }
1449}
1450
1451
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001452v8::ScriptCompiler::CachedData* ProduceCache(const char* source) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001453 v8::ScriptCompiler::CachedData* cache;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001454 v8::Isolate::CreateParams create_params;
1455 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
1456 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001457 {
1458 v8::Isolate::Scope iscope(isolate1);
1459 v8::HandleScope scope(isolate1);
1460 v8::Local<v8::Context> context = v8::Context::New(isolate1);
1461 v8::Context::Scope context_scope(context);
1462
1463 v8::Local<v8::String> source_str = v8_str(source);
1464 v8::ScriptOrigin origin(v8_str("test"));
1465 v8::ScriptCompiler::Source source(source_str, origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001466 v8::Local<v8::UnboundScript> script =
1467 v8::ScriptCompiler::CompileUnboundScript(
1468 isolate1, &source, v8::ScriptCompiler::kProduceCodeCache)
1469 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001470 const v8::ScriptCompiler::CachedData* data = source.GetCachedData();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001471 CHECK(data);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001472 // Persist cached data.
1473 uint8_t* buffer = NewArray<uint8_t>(data->length);
1474 MemCopy(buffer, data->data, data->length);
1475 cache = new v8::ScriptCompiler::CachedData(
1476 buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned);
1477
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001478 v8::Local<v8::Value> result = script->BindToCurrentContext()
1479 ->Run(isolate1->GetCurrentContext())
1480 .ToLocalChecked();
1481 v8::Local<v8::String> result_string =
1482 result->ToString(isolate1->GetCurrentContext()).ToLocalChecked();
1483 CHECK(result_string->Equals(isolate1->GetCurrentContext(), v8_str("abcdef"))
1484 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001485 }
1486 isolate1->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001487 return cache;
1488}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001489
Ben Murdochda12d292016-06-02 14:46:10 +01001490TEST(CodeSerializerIsolates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001491 FLAG_serialize_toplevel = true;
1492
1493 const char* source = "function f() { return 'abc'; }; f() + 'def'";
1494 v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
1495
1496 v8::Isolate::CreateParams create_params;
1497 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
1498 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001499 isolate2->SetJitCodeEventHandler(v8::kJitCodeEventDefault,
1500 SerializerCodeEventListener);
1501 toplevel_test_code_event_found = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001502 {
1503 v8::Isolate::Scope iscope(isolate2);
1504 v8::HandleScope scope(isolate2);
1505 v8::Local<v8::Context> context = v8::Context::New(isolate2);
1506 v8::Context::Scope context_scope(context);
1507
1508 v8::Local<v8::String> source_str = v8_str(source);
1509 v8::ScriptOrigin origin(v8_str("test"));
1510 v8::ScriptCompiler::Source source(source_str, origin, cache);
1511 v8::Local<v8::UnboundScript> script;
1512 {
1513 DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001514 script = v8::ScriptCompiler::CompileUnboundScript(
1515 isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
1516 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001517 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001518 CHECK(!cache->rejected);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001519 v8::Local<v8::Value> result = script->BindToCurrentContext()
1520 ->Run(isolate2->GetCurrentContext())
1521 .ToLocalChecked();
1522 CHECK(result->ToString(isolate2->GetCurrentContext())
1523 .ToLocalChecked()
1524 ->Equals(isolate2->GetCurrentContext(), v8_str("abcdef"))
1525 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001526 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001527 CHECK(toplevel_test_code_event_found);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001528 isolate2->Dispose();
1529}
1530
Ben Murdochda12d292016-06-02 14:46:10 +01001531TEST(CodeSerializerFlagChange) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001532 FLAG_serialize_toplevel = true;
1533
1534 const char* source = "function f() { return 'abc'; }; f() + 'def'";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001535 v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001536
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001537 v8::Isolate::CreateParams create_params;
1538 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
1539 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001540
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001541 FLAG_allow_natives_syntax = true; // Flag change should trigger cache reject.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001542 FlagList::EnforceFlagImplications();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001543 {
1544 v8::Isolate::Scope iscope(isolate2);
1545 v8::HandleScope scope(isolate2);
1546 v8::Local<v8::Context> context = v8::Context::New(isolate2);
1547 v8::Context::Scope context_scope(context);
1548
1549 v8::Local<v8::String> source_str = v8_str(source);
1550 v8::ScriptOrigin origin(v8_str("test"));
1551 v8::ScriptCompiler::Source source(source_str, origin, cache);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001552 v8::ScriptCompiler::CompileUnboundScript(
1553 isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
1554 .ToLocalChecked();
1555 CHECK(cache->rejected);
1556 }
1557 isolate2->Dispose();
1558}
1559
Ben Murdochda12d292016-06-02 14:46:10 +01001560TEST(CodeSerializerBitFlip) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001561 FLAG_serialize_toplevel = true;
1562
1563 const char* source = "function f() { return 'abc'; }; f() + 'def'";
1564 v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
1565
1566 // Random bit flip.
1567 const_cast<uint8_t*>(cache->data)[337] ^= 0x40;
1568
1569 v8::Isolate::CreateParams create_params;
1570 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
1571 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
1572 {
1573 v8::Isolate::Scope iscope(isolate2);
1574 v8::HandleScope scope(isolate2);
1575 v8::Local<v8::Context> context = v8::Context::New(isolate2);
1576 v8::Context::Scope context_scope(context);
1577
1578 v8::Local<v8::String> source_str = v8_str(source);
1579 v8::ScriptOrigin origin(v8_str("test"));
1580 v8::ScriptCompiler::Source source(source_str, origin, cache);
1581 v8::ScriptCompiler::CompileUnboundScript(
1582 isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
1583 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001584 CHECK(cache->rejected);
1585 }
1586 isolate2->Dispose();
1587}
1588
Ben Murdochda12d292016-06-02 14:46:10 +01001589TEST(CodeSerializerWithHarmonyScoping) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001590 FLAG_serialize_toplevel = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001591
1592 const char* source1 = "'use strict'; let x = 'X'";
1593 const char* source2 = "'use strict'; let y = 'Y'";
1594 const char* source3 = "'use strict'; x + y";
1595
1596 v8::ScriptCompiler::CachedData* cache;
1597
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001598 v8::Isolate::CreateParams create_params;
1599 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
1600 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001601 {
1602 v8::Isolate::Scope iscope(isolate1);
1603 v8::HandleScope scope(isolate1);
1604 v8::Local<v8::Context> context = v8::Context::New(isolate1);
1605 v8::Context::Scope context_scope(context);
1606
1607 CompileRun(source1);
1608 CompileRun(source2);
1609
1610 v8::Local<v8::String> source_str = v8_str(source3);
1611 v8::ScriptOrigin origin(v8_str("test"));
1612 v8::ScriptCompiler::Source source(source_str, origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001613 v8::Local<v8::UnboundScript> script =
1614 v8::ScriptCompiler::CompileUnboundScript(
1615 isolate1, &source, v8::ScriptCompiler::kProduceCodeCache)
1616 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001617 const v8::ScriptCompiler::CachedData* data = source.GetCachedData();
1618 CHECK(data);
1619 // Persist cached data.
1620 uint8_t* buffer = NewArray<uint8_t>(data->length);
1621 MemCopy(buffer, data->data, data->length);
1622 cache = new v8::ScriptCompiler::CachedData(
1623 buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned);
1624
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001625 v8::Local<v8::Value> result = script->BindToCurrentContext()
1626 ->Run(isolate1->GetCurrentContext())
1627 .ToLocalChecked();
1628 v8::Local<v8::String> result_str =
1629 result->ToString(isolate1->GetCurrentContext()).ToLocalChecked();
1630 CHECK(result_str->Equals(isolate1->GetCurrentContext(), v8_str("XY"))
1631 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001632 }
1633 isolate1->Dispose();
1634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001635 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001636 {
1637 v8::Isolate::Scope iscope(isolate2);
1638 v8::HandleScope scope(isolate2);
1639 v8::Local<v8::Context> context = v8::Context::New(isolate2);
1640 v8::Context::Scope context_scope(context);
1641
1642 // Reverse order of prior running scripts.
1643 CompileRun(source2);
1644 CompileRun(source1);
1645
1646 v8::Local<v8::String> source_str = v8_str(source3);
1647 v8::ScriptOrigin origin(v8_str("test"));
1648 v8::ScriptCompiler::Source source(source_str, origin, cache);
1649 v8::Local<v8::UnboundScript> script;
1650 {
1651 DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001652 script = v8::ScriptCompiler::CompileUnboundScript(
1653 isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
1654 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001655 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001656 v8::Local<v8::Value> result = script->BindToCurrentContext()
1657 ->Run(isolate2->GetCurrentContext())
1658 .ToLocalChecked();
1659 v8::Local<v8::String> result_str =
1660 result->ToString(isolate2->GetCurrentContext()).ToLocalChecked();
1661 CHECK(result_str->Equals(isolate2->GetCurrentContext(), v8_str("XY"))
1662 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001663 }
1664 isolate2->Dispose();
1665}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001666
Ben Murdochda12d292016-06-02 14:46:10 +01001667TEST(CodeSerializerInternalReference) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001668#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64
1669 return;
1670#endif
Ben Murdochda12d292016-06-02 14:46:10 +01001671 // In ignition there are only relative jumps, so the following code
1672 // would not have any internal references. This test is not relevant
1673 // for ignition.
1674 if (FLAG_ignition) {
1675 return;
1676 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001677 // Disable experimental natives that are loaded after deserialization.
1678 FLAG_function_context_specialization = false;
1679 FLAG_always_opt = true;
1680 const char* flag = "--turbo-filter=foo";
1681 FlagList::SetFlagsFromString(flag, StrLength(flag));
1682
1683 const char* source =
1684 "var foo = (function(stdlib, foreign, heap) {"
1685 " function foo(i) {"
1686 " i = i|0;"
1687 " var j = 0;"
1688 " switch (i) {"
1689 " case 0:"
1690 " case 1: j = 1; break;"
1691 " case 2:"
1692 " case 3: j = 2; break;"
1693 " case 4:"
1694 " case 5: j = foo(3) + 1; break;"
1695 " default: j = 0; break;"
1696 " }"
1697 " return j + 10;"
1698 " }"
1699 " return { foo: foo };"
1700 "})(this, {}, undefined).foo;"
1701 "foo(1);";
1702
1703 v8::StartupData data = v8::V8::CreateSnapshotDataBlob(source);
1704 CHECK(data.data);
1705
1706 v8::Isolate::CreateParams params;
1707 params.snapshot_blob = &data;
1708 params.array_buffer_allocator = CcTest::array_buffer_allocator();
1709 v8::Isolate* isolate = v8::Isolate::New(params);
1710 {
1711 v8::Isolate::Scope i_scope(isolate);
1712 v8::HandleScope h_scope(isolate);
1713 v8::Local<v8::Context> context = v8::Context::New(isolate);
1714 delete[] data.data; // We can dispose of the snapshot blob now.
1715 v8::Context::Scope c_scope(context);
1716 v8::Local<v8::Function> foo =
1717 v8::Local<v8::Function>::Cast(CompileRun("foo"));
1718
1719 // There are at least 6 internal references.
1720 int mask = RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
1721 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
1722 RelocIterator it(
1723 Handle<JSFunction>::cast(v8::Utils::OpenHandle(*foo))->code(), mask);
1724 for (int i = 0; i < 6; ++i) {
1725 CHECK(!it.done());
1726 it.next();
1727 }
1728
1729 CHECK(Handle<JSFunction>::cast(v8::Utils::OpenHandle(*foo))
1730 ->code()
1731 ->is_turbofanned());
1732 CHECK_EQ(11, CompileRun("foo(0)")
1733 ->Int32Value(isolate->GetCurrentContext())
1734 .FromJust());
1735 CHECK_EQ(11, CompileRun("foo(1)")
1736 ->Int32Value(isolate->GetCurrentContext())
1737 .FromJust());
1738 CHECK_EQ(12, CompileRun("foo(2)")
1739 ->Int32Value(isolate->GetCurrentContext())
1740 .FromJust());
1741 CHECK_EQ(12, CompileRun("foo(3)")
1742 ->Int32Value(isolate->GetCurrentContext())
1743 .FromJust());
1744 CHECK_EQ(23, CompileRun("foo(4)")
1745 ->Int32Value(isolate->GetCurrentContext())
1746 .FromJust());
1747 CHECK_EQ(23, CompileRun("foo(5)")
1748 ->Int32Value(isolate->GetCurrentContext())
1749 .FromJust());
1750 CHECK_EQ(10, CompileRun("foo(6)")
1751 ->Int32Value(isolate->GetCurrentContext())
1752 .FromJust());
1753 }
1754 isolate->Dispose();
1755}
1756
Ben Murdochda12d292016-06-02 14:46:10 +01001757TEST(CodeSerializerEagerCompilationAndPreAge) {
1758 if (FLAG_ignition) return;
1759
1760 FLAG_lazy = true;
1761 FLAG_serialize_toplevel = true;
1762 FLAG_serialize_age_code = true;
1763 FLAG_serialize_eager = true;
1764 FLAG_min_preparse_length = 1;
1765
1766 static const char* source =
1767 "function f() {"
1768 " function g() {"
1769 " return 1;"
1770 " }"
1771 " return g();"
1772 "}"
1773 "'abcdef';";
1774
1775 v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
1776
1777 v8::Isolate::CreateParams create_params;
1778 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
1779 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
1780 {
1781 v8::Isolate::Scope iscope(isolate2);
1782 v8::HandleScope scope(isolate2);
1783 v8::Local<v8::Context> context = v8::Context::New(isolate2);
1784 v8::Context::Scope context_scope(context);
1785
1786 v8::Local<v8::String> source_str = v8_str(source);
1787 v8::ScriptOrigin origin(v8_str("test"));
1788 v8::ScriptCompiler::Source source(source_str, origin, cache);
1789 v8::Local<v8::UnboundScript> unbound =
1790 v8::ScriptCompiler::CompileUnboundScript(
1791 isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
1792 .ToLocalChecked();
1793
1794 CHECK(!cache->rejected);
1795
1796 Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate2);
1797 HandleScope i_scope(i_isolate);
1798 Handle<SharedFunctionInfo> toplevel = v8::Utils::OpenHandle(*unbound);
1799 Handle<Script> script(Script::cast(toplevel->script()));
1800 WeakFixedArray::Iterator iterator(script->shared_function_infos());
1801 // Every function has been pre-compiled from the code cache.
1802 int count = 0;
1803 while (SharedFunctionInfo* shared = iterator.Next<SharedFunctionInfo>()) {
1804 CHECK(shared->is_compiled());
1805 CHECK_EQ(Code::kPreAgedCodeAge, shared->code()->GetAge());
1806 count++;
1807 }
1808 CHECK_EQ(3, count);
1809 }
1810 isolate2->Dispose();
1811}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001812
1813TEST(Regress503552) {
1814 // Test that the code serializer can deal with weak cells that form a linked
1815 // list during incremental marking.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001816 CcTest::InitializeVM();
1817 Isolate* isolate = CcTest::i_isolate();
1818
1819 HandleScope scope(isolate);
1820 Handle<String> source = isolate->factory()->NewStringFromAsciiChecked(
1821 "function f() {} function g() {}");
1822 ScriptData* script_data = NULL;
Ben Murdochda12d292016-06-02 14:46:10 +01001823 Handle<SharedFunctionInfo> shared = Compiler::GetSharedFunctionInfoForScript(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001824 source, Handle<String>(), 0, 0, v8::ScriptOriginOptions(),
1825 Handle<Object>(), Handle<Context>(isolate->native_context()), NULL,
1826 &script_data, v8::ScriptCompiler::kProduceCodeCache, NOT_NATIVES_CODE,
1827 false);
1828 delete script_data;
1829
1830 SimulateIncrementalMarking(isolate->heap());
1831
1832 script_data = CodeSerializer::Serialize(isolate, shared, source);
1833 delete script_data;
1834}
1835
1836
1837TEST(SerializationMemoryStats) {
1838 FLAG_profile_deserialization = true;
1839 FLAG_always_opt = false;
1840 v8::StartupData blob = v8::V8::CreateSnapshotDataBlob();
1841 delete[] blob.data;
1842}