blob: de36877dfa6f3dc82267d8bc0fa140a98a732ae6 [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 Murdoch61f157c2016-09-16 13:49:30 +010039#include "src/macro-assembler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040#include "src/objects.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041#include "src/parsing/parser.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040042#include "src/runtime/runtime.h"
Ben Murdochda12d292016-06-02 14:46:10 +010043#include "src/snapshot/code-serializer.h"
44#include "src/snapshot/deserializer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045#include "src/snapshot/natives.h"
Ben Murdochda12d292016-06-02 14:46:10 +010046#include "src/snapshot/partial-serializer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047#include "src/snapshot/snapshot.h"
Ben Murdochda12d292016-06-02 14:46:10 +010048#include "src/snapshot/startup-serializer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049#include "test/cctest/cctest.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010050#include "test/cctest/heap/heap-utils.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000051
52using namespace v8::internal;
53
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054void DisableTurbofan() {
55 const char* flag = "--turbo-filter=\"\"";
56 FlagList::SetFlagsFromString(flag, StrLength(flag));
Steve Blocka7e24c12009-10-30 11:49:00 +000057}
58
59
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060// TestIsolate is used for testing isolate serialization.
61class TestIsolate : public Isolate {
62 public:
63 static v8::Isolate* NewInitialized(bool enable_serializer) {
64 i::Isolate* isolate = new TestIsolate(enable_serializer);
65 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
66 v8::Isolate::Scope isolate_scope(v8_isolate);
67 isolate->Init(NULL);
68 return v8_isolate;
69 }
70 explicit TestIsolate(bool enable_serializer) : Isolate(enable_serializer) {
71 set_array_buffer_allocator(CcTest::array_buffer_allocator());
72 }
73};
Steve Blocka7e24c12009-10-30 11:49:00 +000074
Ben Murdochda12d292016-06-02 14:46:10 +010075static Vector<const byte> WritePayload(const Vector<const byte>& payload) {
76 int length = payload.length();
77 byte* blob = NewArray<byte>(length);
78 memcpy(blob, payload.begin(), length);
79 return Vector<const byte>(const_cast<const byte*>(blob), length);
Leon Clarked91b9f72010-01-27 17:25:45 +000080}
81
Ben Murdochda12d292016-06-02 14:46:10 +010082static Vector<const byte> Serialize(v8::Isolate* isolate) {
Steve Blockd0582a62009-12-15 09:54:21 +000083 // We have to create one context. One reason for this is so that the builtins
84 // can be loaded from v8natives.js and their addresses can be processed. This
85 // will clear the pending fixups array, which would otherwise contain GC roots
86 // that would confuse the serialization/deserialization process.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087 v8::Isolate::Scope isolate_scope(isolate);
88 {
89 v8::HandleScope scope(isolate);
90 v8::Context::New(isolate);
91 }
92
93 Isolate* internal_isolate = reinterpret_cast<Isolate*>(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040094 internal_isolate->heap()->CollectAllAvailableGarbage("serialize");
Ben Murdoch61f157c2016-09-16 13:49:30 +010095 StartupSerializer ser(internal_isolate,
96 v8::SnapshotCreator::FunctionCodeHandling::kClear);
Ben Murdochda12d292016-06-02 14:46:10 +010097 ser.SerializeStrongReferences();
98 ser.SerializeWeakReferencesAndDeferred();
Ben Murdoch61f157c2016-09-16 13:49:30 +010099 SnapshotData snapshot_data(&ser);
Ben Murdochda12d292016-06-02 14:46:10 +0100100 return WritePayload(snapshot_data.RawData());
Steve Blocka7e24c12009-10-30 11:49:00 +0000101}
102
103
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104Vector<const uint8_t> ConstructSource(Vector<const uint8_t> head,
105 Vector<const uint8_t> body,
106 Vector<const uint8_t> tail, int repeats) {
107 int source_length = head.length() + body.length() * repeats + tail.length();
108 uint8_t* source = NewArray<uint8_t>(static_cast<size_t>(source_length));
109 CopyChars(source, head.start(), head.length());
110 for (int i = 0; i < repeats; i++) {
111 CopyChars(source + head.length() + i * body.length(), body.start(),
112 body.length());
113 }
114 CopyChars(source + head.length() + repeats * body.length(), tail.start(),
115 tail.length());
116 return Vector<const uint8_t>(const_cast<const uint8_t*>(source),
117 source_length);
118}
119
Ben Murdochda12d292016-06-02 14:46:10 +0100120v8::Isolate* InitializeFromBlob(Vector<const byte> blob) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121 v8::Isolate* v8_isolate = NULL;
122 {
Ben Murdochda12d292016-06-02 14:46:10 +0100123 SnapshotData snapshot_data(blob);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400124 Deserializer deserializer(&snapshot_data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 Isolate* isolate = new TestIsolate(false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000126 v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
127 v8::Isolate::Scope isolate_scope(v8_isolate);
128 isolate->Init(&deserializer);
129 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000130 return v8_isolate;
131}
132
Ben Murdochda12d292016-06-02 14:46:10 +0100133static v8::Isolate* Deserialize(Vector<const byte> blob) {
134 v8::Isolate* isolate = InitializeFromBlob(blob);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000135 CHECK(isolate);
136 return isolate;
137}
138
139
140static void SanityCheck(v8::Isolate* v8_isolate) {
141 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
142 v8::HandleScope scope(v8_isolate);
143#ifdef VERIFY_HEAP
144 isolate->heap()->Verify();
145#endif
146 CHECK(isolate->global_object()->IsJSObject());
147 CHECK(isolate->native_context()->IsContext());
148 CHECK(isolate->heap()->string_table()->IsStringTable());
149 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("Empty"));
150}
151
Ben Murdochda12d292016-06-02 14:46:10 +0100152UNINITIALIZED_TEST(StartupSerializerOnce) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153 // The serialize-deserialize tests only work if the VM is built without
154 // serialization. That doesn't matter. We don't need to be able to
155 // serialize a snapshot in a VM that is booted from a snapshot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100157 v8::Isolate* isolate = TestIsolate::NewInitialized(true);
158 Vector<const byte> blob = Serialize(isolate);
159 isolate = Deserialize(blob);
160 blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161 {
162 v8::HandleScope handle_scope(isolate);
163 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165 v8::Local<v8::Context> env = v8::Context::New(isolate);
166 env->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168 SanityCheck(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 isolate->Dispose();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171}
172
Ben Murdochda12d292016-06-02 14:46:10 +0100173UNINITIALIZED_TEST(StartupSerializerTwice) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100175 v8::Isolate* isolate = TestIsolate::NewInitialized(true);
176 Vector<const byte> blob1 = Serialize(isolate);
177 Vector<const byte> blob2 = Serialize(isolate);
178 blob1.Dispose();
179 isolate = Deserialize(blob2);
180 blob2.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181 {
182 v8::Isolate::Scope isolate_scope(isolate);
183 v8::HandleScope handle_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000185 v8::Local<v8::Context> env = v8::Context::New(isolate);
186 env->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000187
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188 SanityCheck(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000190 isolate->Dispose();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191}
192
Ben Murdochda12d292016-06-02 14:46:10 +0100193UNINITIALIZED_TEST(StartupSerializerOnceRunScript) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100195 v8::Isolate* isolate = TestIsolate::NewInitialized(true);
196 Vector<const byte> blob = Serialize(isolate);
197 isolate = Deserialize(blob);
198 blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199 {
200 v8::Isolate::Scope isolate_scope(isolate);
201 v8::HandleScope handle_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202
203
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 v8::Local<v8::Context> env = v8::Context::New(isolate);
205 env->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 const char* c_source = "\"1234\".length";
208 v8::Local<v8::Script> script = v8_compile(c_source);
209 v8::Maybe<int32_t> result = script->Run(isolate->GetCurrentContext())
210 .ToLocalChecked()
211 ->Int32Value(isolate->GetCurrentContext());
212 CHECK_EQ(4, result.FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000213 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214 isolate->Dispose();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000215}
216
Ben Murdochda12d292016-06-02 14:46:10 +0100217UNINITIALIZED_TEST(StartupSerializerTwiceRunScript) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100219 v8::Isolate* isolate = TestIsolate::NewInitialized(true);
220 Vector<const byte> blob1 = Serialize(isolate);
221 Vector<const byte> blob2 = Serialize(isolate);
222 blob1.Dispose();
223 isolate = Deserialize(blob2);
224 blob2.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225 {
226 v8::Isolate::Scope isolate_scope(isolate);
227 v8::HandleScope handle_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229 v8::Local<v8::Context> env = v8::Context::New(isolate);
230 env->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 const char* c_source = "\"1234\".length";
233 v8::Local<v8::Script> script = v8_compile(c_source);
234 v8::Maybe<int32_t> result = script->Run(isolate->GetCurrentContext())
235 .ToLocalChecked()
236 ->Int32Value(isolate->GetCurrentContext());
237 CHECK_EQ(4, result.FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 isolate->Dispose();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000240}
241
Ben Murdochda12d292016-06-02 14:46:10 +0100242static void PartiallySerializeObject(Vector<const byte>* startup_blob_out,
243 Vector<const byte>* partial_blob_out) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
245 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
246 v8_isolate->Enter();
247 {
248 Heap* heap = isolate->heap();
249
250 v8::Persistent<v8::Context> env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000251 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000252 HandleScope scope(isolate);
253 env.Reset(v8_isolate, v8::Context::New(v8_isolate));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000255 CHECK(!env.IsEmpty());
256 {
257 v8::HandleScope handle_scope(v8_isolate);
258 v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
259 }
260 // Make sure all builtin scripts are cached.
261 {
262 HandleScope scope(isolate);
263 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
264 isolate->bootstrapper()->SourceLookup<Natives>(i);
265 }
266 }
267 heap->CollectAllGarbage();
268 heap->CollectAllGarbage();
269
270 Object* raw_foo;
271 {
272 v8::HandleScope handle_scope(v8_isolate);
273 v8::Local<v8::String> foo = v8_str("foo");
274 CHECK(!foo.IsEmpty());
275 raw_foo = *(v8::Utils::OpenHandle(*foo));
276 }
277
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 {
279 v8::HandleScope handle_scope(v8_isolate);
280 v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
281 }
282 env.Reset();
283
Ben Murdoch61f157c2016-09-16 13:49:30 +0100284 StartupSerializer startup_serializer(
285 isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000286 startup_serializer.SerializeStrongReferences();
287
Ben Murdoch61f157c2016-09-16 13:49:30 +0100288 PartialSerializer partial_serializer(isolate, &startup_serializer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000289 partial_serializer.Serialize(&raw_foo);
290
291 startup_serializer.SerializeWeakReferencesAndDeferred();
292
Ben Murdoch61f157c2016-09-16 13:49:30 +0100293 SnapshotData startup_snapshot(&startup_serializer);
294 SnapshotData partial_snapshot(&partial_serializer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295
Ben Murdochda12d292016-06-02 14:46:10 +0100296 *partial_blob_out = WritePayload(partial_snapshot.RawData());
297 *startup_blob_out = WritePayload(startup_snapshot.RawData());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000299 v8_isolate->Exit();
300 v8_isolate->Dispose();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000301}
302
Ben Murdochda12d292016-06-02 14:46:10 +0100303UNINITIALIZED_TEST(PartialSerializerObject) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100305 Vector<const byte> startup_blob;
306 Vector<const byte> partial_blob;
307 PartiallySerializeObject(&startup_blob, &partial_blob);
Andrei Popescu31002712010-02-23 13:46:05 +0000308
Ben Murdochda12d292016-06-02 14:46:10 +0100309 v8::Isolate* v8_isolate = InitializeFromBlob(startup_blob);
310 startup_blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000311 CHECK(v8_isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000312 {
313 v8::Isolate::Scope isolate_scope(v8_isolate);
314
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000315 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
316 HandleScope handle_scope(isolate);
317 Handle<Object> root;
318 // Intentionally empty handle. The deserializer should not come across
319 // any references to the global proxy in this test.
320 Handle<JSGlobalProxy> global_proxy = Handle<JSGlobalProxy>::null();
Andrei Popescu31002712010-02-23 13:46:05 +0000321 {
Ben Murdochda12d292016-06-02 14:46:10 +0100322 SnapshotData snapshot_data(partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000323 Deserializer deserializer(&snapshot_data);
324 root = deserializer.DeserializePartial(isolate, global_proxy)
325 .ToHandleChecked();
326 CHECK(root->IsString());
Andrei Popescu31002712010-02-23 13:46:05 +0000327 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000328
329 Handle<Object> root2;
330 {
Ben Murdochda12d292016-06-02 14:46:10 +0100331 SnapshotData snapshot_data(partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000332 Deserializer deserializer(&snapshot_data);
333 root2 = deserializer.DeserializePartial(isolate, global_proxy)
334 .ToHandleChecked();
335 CHECK(root2->IsString());
336 CHECK(root.is_identical_to(root2));
337 }
Ben Murdochda12d292016-06-02 14:46:10 +0100338 partial_blob.Dispose();
Leon Clarked91b9f72010-01-27 17:25:45 +0000339 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 v8_isolate->Dispose();
Andrei Popescu31002712010-02-23 13:46:05 +0000341}
Leon Clarked91b9f72010-01-27 17:25:45 +0000342
Ben Murdochda12d292016-06-02 14:46:10 +0100343static void PartiallySerializeContext(Vector<const byte>* startup_blob_out,
344 Vector<const byte>* partial_blob_out) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000345 v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
346 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
347 Heap* heap = isolate->heap();
348 {
349 v8::Isolate::Scope isolate_scope(v8_isolate);
350
351 v8::Persistent<v8::Context> env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353 HandleScope scope(isolate);
354 env.Reset(v8_isolate, v8::Context::New(v8_isolate));
Andrei Popescu31002712010-02-23 13:46:05 +0000355 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000356 CHECK(!env.IsEmpty());
357 {
358 v8::HandleScope handle_scope(v8_isolate);
359 v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
360 }
361 // Make sure all builtin scripts are cached.
362 {
363 HandleScope scope(isolate);
364 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
365 isolate->bootstrapper()->SourceLookup<Natives>(i);
366 }
367 }
368 // If we don't do this then we end up with a stray root pointing at the
369 // context even after we have disposed of env.
370 heap->CollectAllGarbage();
Andrei Popescu31002712010-02-23 13:46:05 +0000371
Andrei Popescu31002712010-02-23 13:46:05 +0000372 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373 v8::HandleScope handle_scope(v8_isolate);
374 v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
375 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000376
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000377 i::Object* raw_context = *v8::Utils::OpenPersistent(env);
Andrei Popescu31002712010-02-23 13:46:05 +0000378
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000379 env.Reset();
Leon Clarkee46be812010-01-19 14:06:41 +0000380
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000381 SnapshotByteSink startup_sink;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100382 StartupSerializer startup_serializer(
383 isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000384 startup_serializer.SerializeStrongReferences();
385
386 SnapshotByteSink partial_sink;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100387 PartialSerializer partial_serializer(isolate, &startup_serializer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000388 partial_serializer.Serialize(&raw_context);
389 startup_serializer.SerializeWeakReferencesAndDeferred();
390
Ben Murdoch61f157c2016-09-16 13:49:30 +0100391 SnapshotData startup_snapshot(&startup_serializer);
392 SnapshotData partial_snapshot(&partial_serializer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000393
Ben Murdochda12d292016-06-02 14:46:10 +0100394 *partial_blob_out = WritePayload(partial_snapshot.RawData());
395 *startup_blob_out = WritePayload(startup_snapshot.RawData());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000396 }
397 v8_isolate->Dispose();
398}
Leon Clarkee46be812010-01-19 14:06:41 +0000399
Ben Murdochda12d292016-06-02 14:46:10 +0100400UNINITIALIZED_TEST(PartialSerializerContext) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000401 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100402 Vector<const byte> startup_blob;
403 Vector<const byte> partial_blob;
404 PartiallySerializeContext(&startup_blob, &partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000405
Ben Murdochda12d292016-06-02 14:46:10 +0100406 v8::Isolate* v8_isolate = InitializeFromBlob(startup_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000407 CHECK(v8_isolate);
Ben Murdochda12d292016-06-02 14:46:10 +0100408 startup_blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000409 {
410 v8::Isolate::Scope isolate_scope(v8_isolate);
411
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
413 HandleScope handle_scope(isolate);
414 Handle<Object> root;
415 Handle<JSGlobalProxy> global_proxy =
416 isolate->factory()->NewUninitializedJSGlobalProxy();
417 {
Ben Murdochda12d292016-06-02 14:46:10 +0100418 SnapshotData snapshot_data(partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419 Deserializer deserializer(&snapshot_data);
420 root = deserializer.DeserializePartial(isolate, global_proxy)
421 .ToHandleChecked();
422 CHECK(root->IsContext());
423 CHECK(Handle<Context>::cast(root)->global_proxy() == *global_proxy);
424 }
425
426 Handle<Object> root2;
427 {
Ben Murdochda12d292016-06-02 14:46:10 +0100428 SnapshotData snapshot_data(partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000429 Deserializer deserializer(&snapshot_data);
430 root2 = deserializer.DeserializePartial(isolate, global_proxy)
431 .ToHandleChecked();
432 CHECK(root2->IsContext());
433 CHECK(!root.is_identical_to(root2));
434 }
Ben Murdochda12d292016-06-02 14:46:10 +0100435 partial_blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000436 }
437 v8_isolate->Dispose();
438}
439
Ben Murdochda12d292016-06-02 14:46:10 +0100440static void PartiallySerializeCustomContext(
441 Vector<const byte>* startup_blob_out,
442 Vector<const byte>* partial_blob_out) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000443 v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
444 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
445 {
446 v8::Isolate::Scope isolate_scope(v8_isolate);
447
448 v8::Persistent<v8::Context> env;
449 {
450 HandleScope scope(isolate);
451 env.Reset(v8_isolate, v8::Context::New(v8_isolate));
452 }
453 CHECK(!env.IsEmpty());
454 {
455 v8::HandleScope handle_scope(v8_isolate);
456 v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
457 // After execution, e's function context refers to the global object.
458 CompileRun(
459 "var e;"
460 "(function() {"
461 " e = function(s) { return eval (s); }"
462 "})();"
463 "var o = this;"
Ben Murdochda12d292016-06-02 14:46:10 +0100464 "var r = Math.random();"
465 "var c = Math.sin(0) + Math.cos(0);"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466 "var f = (function(a, b) { return a + b; }).bind(1, 2, 3);"
467 "var s = parseInt('12345');");
468
469 Vector<const uint8_t> source = ConstructSource(
470 STATIC_CHAR_VECTOR("function g() { return [,"),
471 STATIC_CHAR_VECTOR("1,"),
472 STATIC_CHAR_VECTOR("];} a = g(); b = g(); b.push(1);"), 100000);
473 v8::MaybeLocal<v8::String> source_str = v8::String::NewFromOneByte(
474 v8_isolate, source.start(), v8::NewStringType::kNormal,
475 source.length());
476 CompileRun(source_str.ToLocalChecked());
477 source.Dispose();
478 }
479 // Make sure all builtin scripts are cached.
480 {
481 HandleScope scope(isolate);
482 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
483 isolate->bootstrapper()->SourceLookup<Natives>(i);
Leon Clarkee46be812010-01-19 14:06:41 +0000484 }
Leon Clarkee46be812010-01-19 14:06:41 +0000485 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000486 // If we don't do this then we end up with a stray root pointing at the
487 // context even after we have disposed of env.
488 isolate->heap()->CollectAllAvailableGarbage("snapshotting");
489
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490 {
491 v8::HandleScope handle_scope(v8_isolate);
492 v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
493 }
494
495 i::Object* raw_context = *v8::Utils::OpenPersistent(env);
496
497 env.Reset();
498
499 SnapshotByteSink startup_sink;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100500 StartupSerializer startup_serializer(
501 isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000502 startup_serializer.SerializeStrongReferences();
503
504 SnapshotByteSink partial_sink;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100505 PartialSerializer partial_serializer(isolate, &startup_serializer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000506 partial_serializer.Serialize(&raw_context);
507 startup_serializer.SerializeWeakReferencesAndDeferred();
508
Ben Murdoch61f157c2016-09-16 13:49:30 +0100509 SnapshotData startup_snapshot(&startup_serializer);
510 SnapshotData partial_snapshot(&partial_serializer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000511
Ben Murdochda12d292016-06-02 14:46:10 +0100512 *partial_blob_out = WritePayload(partial_snapshot.RawData());
513 *startup_blob_out = WritePayload(startup_snapshot.RawData());
Leon Clarkee46be812010-01-19 14:06:41 +0000514 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000515 v8_isolate->Dispose();
516}
517
Ben Murdochda12d292016-06-02 14:46:10 +0100518UNINITIALIZED_TEST(PartialSerializerCustomContext) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000519 DisableTurbofan();
Ben Murdochda12d292016-06-02 14:46:10 +0100520 Vector<const byte> startup_blob;
521 Vector<const byte> partial_blob;
522 PartiallySerializeCustomContext(&startup_blob, &partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000523
Ben Murdochda12d292016-06-02 14:46:10 +0100524 v8::Isolate* v8_isolate = InitializeFromBlob(startup_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000525 CHECK(v8_isolate);
Ben Murdochda12d292016-06-02 14:46:10 +0100526 startup_blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000527 {
528 v8::Isolate::Scope isolate_scope(v8_isolate);
529
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000530 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
531 HandleScope handle_scope(isolate);
532 Handle<Object> root;
533 Handle<JSGlobalProxy> global_proxy =
534 isolate->factory()->NewUninitializedJSGlobalProxy();
535 {
Ben Murdochda12d292016-06-02 14:46:10 +0100536 SnapshotData snapshot_data(partial_blob);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000537 Deserializer deserializer(&snapshot_data);
538 root = deserializer.DeserializePartial(isolate, global_proxy)
539 .ToHandleChecked();
540 CHECK(root->IsContext());
541 Handle<Context> context = Handle<Context>::cast(root);
Ben Murdochda12d292016-06-02 14:46:10 +0100542
543 // Add context to the weak native context list
544 context->set(Context::NEXT_CONTEXT_LINK,
545 isolate->heap()->native_contexts_list(),
546 UPDATE_WEAK_WRITE_BARRIER);
547 isolate->heap()->set_native_contexts_list(*context);
548
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 CHECK(context->global_proxy() == *global_proxy);
550 Handle<String> o = isolate->factory()->NewStringFromAsciiChecked("o");
551 Handle<JSObject> global_object(context->global_object(), isolate);
552 Handle<Object> property = JSReceiver::GetDataProperty(global_object, o);
553 CHECK(property.is_identical_to(global_proxy));
554
555 v8::Local<v8::Context> v8_context = v8::Utils::ToLocal(context);
556 v8::Context::Scope context_scope(v8_context);
557 double r = CompileRun("r")
558 ->ToNumber(v8_isolate->GetCurrentContext())
559 .ToLocalChecked()
560 ->Value();
Ben Murdochda12d292016-06-02 14:46:10 +0100561 CHECK(0.0 <= r && r < 1.0);
562 // Math.random still works.
563 double random = CompileRun("Math.random()")
564 ->ToNumber(v8_isolate->GetCurrentContext())
565 .ToLocalChecked()
566 ->Value();
567 CHECK(0.0 <= random && random < 1.0);
568 double c = CompileRun("c")
569 ->ToNumber(v8_isolate->GetCurrentContext())
570 .ToLocalChecked()
571 ->Value();
572 CHECK_EQ(1, c);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000573 int f = CompileRun("f()")
574 ->ToNumber(v8_isolate->GetCurrentContext())
575 .ToLocalChecked()
576 ->Int32Value(v8_isolate->GetCurrentContext())
577 .FromJust();
578 CHECK_EQ(5, f);
579 f = CompileRun("e('f()')")
580 ->ToNumber(v8_isolate->GetCurrentContext())
581 .ToLocalChecked()
582 ->Int32Value(v8_isolate->GetCurrentContext())
583 .FromJust();
584 CHECK_EQ(5, f);
585 v8::Local<v8::String> s = CompileRun("s")
586 ->ToString(v8_isolate->GetCurrentContext())
587 .ToLocalChecked();
588 CHECK(s->Equals(v8_isolate->GetCurrentContext(), v8_str("12345"))
589 .FromJust());
590 int a = CompileRun("a.length")
591 ->ToNumber(v8_isolate->GetCurrentContext())
592 .ToLocalChecked()
593 ->Int32Value(v8_isolate->GetCurrentContext())
594 .FromJust();
595 CHECK_EQ(100001, a);
596 int b = CompileRun("b.length")
597 ->ToNumber(v8_isolate->GetCurrentContext())
598 .ToLocalChecked()
599 ->Int32Value(v8_isolate->GetCurrentContext())
600 .FromJust();
601 CHECK_EQ(100002, b);
602 }
Ben Murdochda12d292016-06-02 14:46:10 +0100603 partial_blob.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000604 }
605 v8_isolate->Dispose();
606}
607
Ben Murdochda12d292016-06-02 14:46:10 +0100608TEST(CustomSnapshotDataBlob) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000609 DisableTurbofan();
610 const char* source1 = "function f() { return 42; }";
611 const char* source2 =
612 "function f() { return g() * 2; }"
613 "function g() { return 43; }"
614 "/./.test('a')";
615
616 v8::StartupData data1 = v8::V8::CreateSnapshotDataBlob(source1);
617 v8::StartupData data2 = v8::V8::CreateSnapshotDataBlob(source2);
618
619 v8::Isolate::CreateParams params1;
620 params1.snapshot_blob = &data1;
621 params1.array_buffer_allocator = CcTest::array_buffer_allocator();
622
623 v8::Isolate* isolate1 = v8::Isolate::New(params1);
624 {
625 v8::Isolate::Scope i_scope(isolate1);
626 v8::HandleScope h_scope(isolate1);
627 v8::Local<v8::Context> context = v8::Context::New(isolate1);
628 delete[] data1.data; // We can dispose of the snapshot blob now.
629 v8::Context::Scope c_scope(context);
630 v8::Maybe<int32_t> result =
631 CompileRun("f()")->Int32Value(isolate1->GetCurrentContext());
632 CHECK_EQ(42, result.FromJust());
633 CHECK(CompileRun("this.g")->IsUndefined());
634 }
635 isolate1->Dispose();
636
637 v8::Isolate::CreateParams params2;
638 params2.snapshot_blob = &data2;
639 params2.array_buffer_allocator = CcTest::array_buffer_allocator();
640 v8::Isolate* isolate2 = v8::Isolate::New(params2);
641 {
642 v8::Isolate::Scope i_scope(isolate2);
643 v8::HandleScope h_scope(isolate2);
644 v8::Local<v8::Context> context = v8::Context::New(isolate2);
645 delete[] data2.data; // We can dispose of the snapshot blob now.
646 v8::Context::Scope c_scope(context);
647 v8::Maybe<int32_t> result =
648 CompileRun("f()")->Int32Value(isolate2->GetCurrentContext());
649 CHECK_EQ(86, result.FromJust());
650 result = CompileRun("g()")->Int32Value(isolate2->GetCurrentContext());
651 CHECK_EQ(43, result.FromJust());
652 }
653 isolate2->Dispose();
654}
655
656
657static void SerializationFunctionTemplate(
658 const v8::FunctionCallbackInfo<v8::Value>& args) {
659 args.GetReturnValue().Set(args[0]);
660}
661
Ben Murdochda12d292016-06-02 14:46:10 +0100662TEST(CustomSnapshotDataBlobOutdatedContextWithOverflow) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000663 DisableTurbofan();
664
665 const char* source1 =
666 "var o = {};"
667 "(function() {"
668 " function f1(x) { return f2(x) instanceof Array; }"
669 " function f2(x) { return foo.bar(x); }"
670 " o.a = f2.bind(null);"
671 " o.b = 1;"
672 " o.c = 2;"
673 " o.d = 3;"
674 " o.e = 4;"
675 "})();\n";
676
677 const char* source2 = "o.a(42)";
678
679 v8::StartupData data = v8::V8::CreateSnapshotDataBlob(source1);
680
681 v8::Isolate::CreateParams params;
682 params.snapshot_blob = &data;
683 params.array_buffer_allocator = CcTest::array_buffer_allocator();
684
685 v8::Isolate* isolate = v8::Isolate::New(params);
686 {
687 v8::Isolate::Scope i_scope(isolate);
688 v8::HandleScope h_scope(isolate);
689
690 v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
691 v8::Local<v8::ObjectTemplate> property = v8::ObjectTemplate::New(isolate);
692 v8::Local<v8::FunctionTemplate> function =
693 v8::FunctionTemplate::New(isolate, SerializationFunctionTemplate);
694 property->Set(isolate, "bar", function);
695 global->Set(isolate, "foo", property);
696
697 v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
698 delete[] data.data; // We can dispose of the snapshot blob now.
699 v8::Context::Scope c_scope(context);
700 v8::Local<v8::Value> result = CompileRun(source2);
701 v8::Maybe<bool> compare = v8_str("42")->Equals(
702 v8::Isolate::GetCurrent()->GetCurrentContext(), result);
703 CHECK(compare.FromJust());
704 }
705 isolate->Dispose();
706}
707
Ben Murdochda12d292016-06-02 14:46:10 +0100708TEST(CustomSnapshotDataBlobWithLocker) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000709 DisableTurbofan();
710 v8::Isolate::CreateParams create_params;
711 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
712 v8::Isolate* isolate0 = v8::Isolate::New(create_params);
713 {
714 v8::Locker locker(isolate0);
715 v8::Isolate::Scope i_scope(isolate0);
716 v8::HandleScope h_scope(isolate0);
717 v8::Local<v8::Context> context = v8::Context::New(isolate0);
718 v8::Context::Scope c_scope(context);
719 v8::Maybe<int32_t> result =
720 CompileRun("Math.cos(0)")->Int32Value(isolate0->GetCurrentContext());
721 CHECK_EQ(1, result.FromJust());
722 }
723 isolate0->Dispose();
724
725 const char* source1 = "function f() { return 42; }";
726
727 v8::StartupData data1 = v8::V8::CreateSnapshotDataBlob(source1);
728
729 v8::Isolate::CreateParams params1;
730 params1.snapshot_blob = &data1;
731 params1.array_buffer_allocator = CcTest::array_buffer_allocator();
732 v8::Isolate* isolate1 = v8::Isolate::New(params1);
733 {
734 v8::Locker locker(isolate1);
735 v8::Isolate::Scope i_scope(isolate1);
736 v8::HandleScope h_scope(isolate1);
737 v8::Local<v8::Context> context = v8::Context::New(isolate1);
738 delete[] data1.data; // We can dispose of the snapshot blob now.
739 v8::Context::Scope c_scope(context);
740 v8::Maybe<int32_t> result = CompileRun("f()")->Int32Value(context);
741 CHECK_EQ(42, result.FromJust());
742 }
743 isolate1->Dispose();
744}
745
Ben Murdochda12d292016-06-02 14:46:10 +0100746TEST(CustomSnapshotDataBlobStackOverflow) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000747 DisableTurbofan();
748 const char* source =
749 "var a = [0];"
750 "var b = a;"
751 "for (var i = 0; i < 10000; i++) {"
752 " var c = [i];"
753 " b.push(c);"
754 " b.push(c);"
755 " b = c;"
756 "}";
757
758 v8::StartupData data = v8::V8::CreateSnapshotDataBlob(source);
759
760 v8::Isolate::CreateParams params;
761 params.snapshot_blob = &data;
762 params.array_buffer_allocator = CcTest::array_buffer_allocator();
763
764 v8::Isolate* isolate = v8::Isolate::New(params);
765 {
766 v8::Isolate::Scope i_scope(isolate);
767 v8::HandleScope h_scope(isolate);
768 v8::Local<v8::Context> context = v8::Context::New(isolate);
769 delete[] data.data; // We can dispose of the snapshot blob now.
770 v8::Context::Scope c_scope(context);
771 const char* test =
772 "var sum = 0;"
773 "while (a) {"
774 " sum += a[0];"
775 " a = a[1];"
776 "}"
777 "sum";
778 v8::Maybe<int32_t> result =
779 CompileRun(test)->Int32Value(isolate->GetCurrentContext());
780 CHECK_EQ(9999 * 5000, result.FromJust());
781 }
782 isolate->Dispose();
Leon Clarkee46be812010-01-19 14:06:41 +0000783}
784
Ben Murdochda12d292016-06-02 14:46:10 +0100785bool IsCompiled(const char* name) {
786 return i::Handle<i::JSFunction>::cast(
787 v8::Utils::OpenHandle(*CompileRun(name)))
788 ->shared()
789 ->is_compiled();
790}
791
792TEST(SnapshotDataBlobWithWarmup) {
793 DisableTurbofan();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100794 const char* warmup = "Math.tanh(1); Math.sinh = 1;";
Ben Murdochda12d292016-06-02 14:46:10 +0100795
796 v8::StartupData cold = v8::V8::CreateSnapshotDataBlob();
797 v8::StartupData warm = v8::V8::WarmUpSnapshotDataBlob(cold, warmup);
798 delete[] cold.data;
799
800 v8::Isolate::CreateParams params;
801 params.snapshot_blob = &warm;
802 params.array_buffer_allocator = CcTest::array_buffer_allocator();
803
804 v8::Isolate* isolate = v8::Isolate::New(params);
805 {
806 v8::Isolate::Scope i_scope(isolate);
807 v8::HandleScope h_scope(isolate);
808 v8::Local<v8::Context> context = v8::Context::New(isolate);
809 delete[] warm.data;
810 v8::Context::Scope c_scope(context);
811 // Running the warmup script has effect on whether functions are
812 // pre-compiled, but does not pollute the context.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100813 CHECK(IsCompiled("Math.tanh"));
814 CHECK(!IsCompiled("Math.cosh"));
815 CHECK(CompileRun("Math.sinh")->IsFunction());
Ben Murdochda12d292016-06-02 14:46:10 +0100816 }
817 isolate->Dispose();
818}
819
820TEST(CustomSnapshotDataBlobWithWarmup) {
821 DisableTurbofan();
822 const char* source =
Ben Murdoch61f157c2016-09-16 13:49:30 +0100823 "function f() { return Math.sinh(1); }\n"
824 "function g() { return Math.cosh(1); }\n"
825 "Math.tanh(1);"
Ben Murdochda12d292016-06-02 14:46:10 +0100826 "var a = 5";
827 const char* warmup = "a = f()";
828
829 v8::StartupData cold = v8::V8::CreateSnapshotDataBlob(source);
830 v8::StartupData warm = v8::V8::WarmUpSnapshotDataBlob(cold, warmup);
831 delete[] cold.data;
832
833 v8::Isolate::CreateParams params;
834 params.snapshot_blob = &warm;
835 params.array_buffer_allocator = CcTest::array_buffer_allocator();
836
837 v8::Isolate* isolate = v8::Isolate::New(params);
838 {
839 v8::Isolate::Scope i_scope(isolate);
840 v8::HandleScope h_scope(isolate);
841 v8::Local<v8::Context> context = v8::Context::New(isolate);
842 delete[] warm.data;
843 v8::Context::Scope c_scope(context);
844 // Running the warmup script has effect on whether functions are
845 // pre-compiled, but does not pollute the context.
846 CHECK(IsCompiled("f"));
Ben Murdoch61f157c2016-09-16 13:49:30 +0100847 CHECK(IsCompiled("Math.sinh"));
Ben Murdochda12d292016-06-02 14:46:10 +0100848 CHECK(!IsCompiled("g"));
Ben Murdoch61f157c2016-09-16 13:49:30 +0100849 CHECK(!IsCompiled("Math.cosh"));
850 CHECK(!IsCompiled("Math.tanh"));
Ben Murdochda12d292016-06-02 14:46:10 +0100851 CHECK_EQ(5, CompileRun("a")->Int32Value(context).FromJust());
852 }
853 isolate->Dispose();
854}
855
856TEST(CustomSnapshotDataBlobImmortalImmovableRoots) {
857 DisableTurbofan();
858 // Flood the startup snapshot with shared function infos. If they are
859 // serialized before the immortal immovable root, the root will no longer end
860 // up on the first page.
861 Vector<const uint8_t> source =
862 ConstructSource(STATIC_CHAR_VECTOR("var a = [];"),
863 STATIC_CHAR_VECTOR("a.push(function() {return 7});"),
864 STATIC_CHAR_VECTOR("\0"), 10000);
865
866 v8::StartupData data = v8::V8::CreateSnapshotDataBlob(
867 reinterpret_cast<const char*>(source.start()));
868
869 v8::Isolate::CreateParams params;
870 params.snapshot_blob = &data;
871 params.array_buffer_allocator = CcTest::array_buffer_allocator();
872
873 v8::Isolate* isolate = v8::Isolate::New(params);
874 {
875 v8::Isolate::Scope i_scope(isolate);
876 v8::HandleScope h_scope(isolate);
877 v8::Local<v8::Context> context = v8::Context::New(isolate);
878 delete[] data.data; // We can dispose of the snapshot blob now.
879 v8::Context::Scope c_scope(context);
880 CHECK_EQ(7, CompileRun("a[0]()")->Int32Value(context).FromJust());
881 }
882 isolate->Dispose();
883 source.Dispose();
884}
Leon Clarkee46be812010-01-19 14:06:41 +0000885
Steve Block3ce2e202009-11-05 08:53:23 +0000886TEST(TestThatAlwaysSucceeds) {
887}
888
889
890TEST(TestThatAlwaysFails) {
891 bool ArtificialFailure = false;
892 CHECK(ArtificialFailure);
893}
894
895
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000896int CountBuiltins() {
897 // Check that we have not deserialized any additional builtin.
898 HeapIterator iterator(CcTest::heap());
899 DisallowHeapAllocation no_allocation;
900 int counter = 0;
901 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
902 if (obj->IsCode() && Code::cast(obj)->kind() == Code::BUILTIN) counter++;
903 }
904 return counter;
905}
906
907
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000908static Handle<SharedFunctionInfo> CompileScript(
909 Isolate* isolate, Handle<String> source, Handle<String> name,
910 ScriptData** cached_data, v8::ScriptCompiler::CompileOptions options) {
Ben Murdochda12d292016-06-02 14:46:10 +0100911 return Compiler::GetSharedFunctionInfoForScript(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000912 source, name, 0, 0, v8::ScriptOriginOptions(), Handle<Object>(),
913 Handle<Context>(isolate->native_context()), NULL, cached_data, options,
914 NOT_NATIVES_CODE, false);
915}
916
Ben Murdochda12d292016-06-02 14:46:10 +0100917TEST(CodeSerializerOnePlusOne) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000918 FLAG_serialize_toplevel = true;
919 LocalContext context;
920 Isolate* isolate = CcTest::i_isolate();
921 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
922
923 v8::HandleScope scope(CcTest::isolate());
924
925 const char* source = "1 + 1";
926
927 Handle<String> orig_source = isolate->factory()
928 ->NewStringFromUtf8(CStrVector(source))
929 .ToHandleChecked();
930 Handle<String> copy_source = isolate->factory()
931 ->NewStringFromUtf8(CStrVector(source))
932 .ToHandleChecked();
933 CHECK(!orig_source.is_identical_to(copy_source));
934 CHECK(orig_source->Equals(*copy_source));
935
936 ScriptData* cache = NULL;
937
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000938 Handle<SharedFunctionInfo> orig =
939 CompileScript(isolate, orig_source, Handle<String>(), &cache,
940 v8::ScriptCompiler::kProduceCodeCache);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000941
942 int builtins_count = CountBuiltins();
943
944 Handle<SharedFunctionInfo> copy;
945 {
946 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000947 copy = CompileScript(isolate, copy_source, Handle<String>(), &cache,
948 v8::ScriptCompiler::kConsumeCodeCache);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000949 }
950
951 CHECK_NE(*orig, *copy);
952 CHECK(Script::cast(copy->script())->source() == *copy_source);
953
954 Handle<JSFunction> copy_fun =
955 isolate->factory()->NewFunctionFromSharedFunctionInfo(
956 copy, isolate->native_context());
957 Handle<JSObject> global(isolate->context()->global_object());
958 Handle<Object> copy_result =
959 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
960 CHECK_EQ(2, Handle<Smi>::cast(copy_result)->value());
961
962 CHECK_EQ(builtins_count, CountBuiltins());
963
964 delete cache;
965}
966
Ben Murdochda12d292016-06-02 14:46:10 +0100967TEST(CodeSerializerPromotedToCompilationCache) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 FLAG_serialize_toplevel = true;
969 LocalContext context;
970 Isolate* isolate = CcTest::i_isolate();
971
972 v8::HandleScope scope(CcTest::isolate());
973
974 const char* source = "1 + 1";
975
976 Handle<String> src = isolate->factory()
977 ->NewStringFromUtf8(CStrVector(source))
978 .ToHandleChecked();
979 ScriptData* cache = NULL;
980
981 CompileScript(isolate, src, src, &cache,
982 v8::ScriptCompiler::kProduceCodeCache);
983
984 DisallowCompilation no_compile_expected(isolate);
985 Handle<SharedFunctionInfo> copy = CompileScript(
986 isolate, src, src, &cache, v8::ScriptCompiler::kConsumeCodeCache);
987
988 CHECK(isolate->compilation_cache()
989 ->LookupScript(src, src, 0, 0, v8::ScriptOriginOptions(),
990 isolate->native_context(), SLOPPY)
991 .ToHandleChecked()
992 .is_identical_to(copy));
993
994 delete cache;
995}
996
Ben Murdochda12d292016-06-02 14:46:10 +0100997TEST(CodeSerializerInternalizedString) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998 FLAG_serialize_toplevel = true;
999 LocalContext context;
1000 Isolate* isolate = CcTest::i_isolate();
1001 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1002
1003 v8::HandleScope scope(CcTest::isolate());
1004
1005 const char* source = "'string1'";
1006
1007 Handle<String> orig_source = isolate->factory()
1008 ->NewStringFromUtf8(CStrVector(source))
1009 .ToHandleChecked();
1010 Handle<String> copy_source = isolate->factory()
1011 ->NewStringFromUtf8(CStrVector(source))
1012 .ToHandleChecked();
1013 CHECK(!orig_source.is_identical_to(copy_source));
1014 CHECK(orig_source->Equals(*copy_source));
1015
1016 Handle<JSObject> global(isolate->context()->global_object());
1017 ScriptData* cache = NULL;
1018
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001019 Handle<SharedFunctionInfo> orig =
1020 CompileScript(isolate, orig_source, Handle<String>(), &cache,
1021 v8::ScriptCompiler::kProduceCodeCache);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001022 Handle<JSFunction> orig_fun =
1023 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1024 orig, isolate->native_context());
1025 Handle<Object> orig_result =
1026 Execution::Call(isolate, orig_fun, global, 0, NULL).ToHandleChecked();
1027 CHECK(orig_result->IsInternalizedString());
1028
1029 int builtins_count = CountBuiltins();
1030
1031 Handle<SharedFunctionInfo> copy;
1032 {
1033 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001034 copy = CompileScript(isolate, copy_source, Handle<String>(), &cache,
1035 v8::ScriptCompiler::kConsumeCodeCache);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001036 }
1037 CHECK_NE(*orig, *copy);
1038 CHECK(Script::cast(copy->script())->source() == *copy_source);
1039
1040 Handle<JSFunction> copy_fun =
1041 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1042 copy, isolate->native_context());
1043 CHECK_NE(*orig_fun, *copy_fun);
1044 Handle<Object> copy_result =
1045 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
1046 CHECK(orig_result.is_identical_to(copy_result));
1047 Handle<String> expected =
1048 isolate->factory()->NewStringFromAsciiChecked("string1");
1049
1050 CHECK(Handle<String>::cast(copy_result)->Equals(*expected));
1051 CHECK_EQ(builtins_count, CountBuiltins());
1052
1053 delete cache;
1054}
1055
Ben Murdochda12d292016-06-02 14:46:10 +01001056TEST(CodeSerializerLargeCodeObject) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001057 FLAG_serialize_toplevel = true;
1058 LocalContext context;
1059 Isolate* isolate = CcTest::i_isolate();
1060 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1061
1062 v8::HandleScope scope(CcTest::isolate());
1063
1064 Vector<const uint8_t> source =
1065 ConstructSource(STATIC_CHAR_VECTOR("var j=1; try { if (j) throw 1;"),
1066 STATIC_CHAR_VECTOR("for(var i=0;i<1;i++)j++;"),
1067 STATIC_CHAR_VECTOR("} catch (e) { j=7; } j"), 10000);
1068 Handle<String> source_str =
1069 isolate->factory()->NewStringFromOneByte(source).ToHandleChecked();
1070
1071 Handle<JSObject> global(isolate->context()->global_object());
1072 ScriptData* cache = NULL;
1073
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001074 Handle<SharedFunctionInfo> orig =
1075 CompileScript(isolate, source_str, Handle<String>(), &cache,
1076 v8::ScriptCompiler::kProduceCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001077
1078 CHECK(isolate->heap()->InSpace(orig->code(), LO_SPACE));
1079
1080 Handle<SharedFunctionInfo> copy;
1081 {
1082 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001083 copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
1084 v8::ScriptCompiler::kConsumeCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001085 }
1086 CHECK_NE(*orig, *copy);
1087
1088 Handle<JSFunction> copy_fun =
1089 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1090 copy, isolate->native_context());
1091
1092 Handle<Object> copy_result =
1093 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
1094
1095 int result_int;
1096 CHECK(copy_result->ToInt32(&result_int));
1097 CHECK_EQ(7, result_int);
1098
1099 delete cache;
1100 source.Dispose();
1101}
1102
Ben Murdochda12d292016-06-02 14:46:10 +01001103TEST(CodeSerializerLargeStrings) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001104 FLAG_serialize_toplevel = true;
1105 LocalContext context;
1106 Isolate* isolate = CcTest::i_isolate();
1107 Factory* f = isolate->factory();
1108 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1109
1110 v8::HandleScope scope(CcTest::isolate());
1111
1112 Vector<const uint8_t> source_s = ConstructSource(
1113 STATIC_CHAR_VECTOR("var s = \""), STATIC_CHAR_VECTOR("abcdef"),
1114 STATIC_CHAR_VECTOR("\";"), 1000000);
1115 Vector<const uint8_t> source_t = ConstructSource(
1116 STATIC_CHAR_VECTOR("var t = \""), STATIC_CHAR_VECTOR("uvwxyz"),
1117 STATIC_CHAR_VECTOR("\"; s + t"), 999999);
1118 Handle<String> source_str =
1119 f->NewConsString(f->NewStringFromOneByte(source_s).ToHandleChecked(),
1120 f->NewStringFromOneByte(source_t).ToHandleChecked())
1121 .ToHandleChecked();
1122
1123 Handle<JSObject> global(isolate->context()->global_object());
1124 ScriptData* cache = NULL;
1125
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001126 Handle<SharedFunctionInfo> orig =
1127 CompileScript(isolate, source_str, Handle<String>(), &cache,
1128 v8::ScriptCompiler::kProduceCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001129
1130 Handle<SharedFunctionInfo> copy;
1131 {
1132 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001133 copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
1134 v8::ScriptCompiler::kConsumeCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001135 }
1136 CHECK_NE(*orig, *copy);
1137
1138 Handle<JSFunction> copy_fun =
1139 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1140 copy, isolate->native_context());
1141
1142 Handle<Object> copy_result =
1143 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
1144
1145 CHECK_EQ(6 * 1999999, Handle<String>::cast(copy_result)->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001146 Handle<Object> property = JSReceiver::GetDataProperty(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001147 isolate->global_object(), f->NewStringFromAsciiChecked("s"));
1148 CHECK(isolate->heap()->InSpace(HeapObject::cast(*property), LO_SPACE));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001149 property = JSReceiver::GetDataProperty(isolate->global_object(),
1150 f->NewStringFromAsciiChecked("t"));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001151 CHECK(isolate->heap()->InSpace(HeapObject::cast(*property), LO_SPACE));
1152 // Make sure we do not serialize too much, e.g. include the source string.
1153 CHECK_LT(cache->length(), 13000000);
1154
1155 delete cache;
1156 source_s.Dispose();
1157 source_t.Dispose();
1158}
1159
Ben Murdochda12d292016-06-02 14:46:10 +01001160TEST(CodeSerializerThreeBigStrings) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001161 FLAG_serialize_toplevel = true;
1162 LocalContext context;
1163 Isolate* isolate = CcTest::i_isolate();
1164 Factory* f = isolate->factory();
1165 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1166
1167 v8::HandleScope scope(CcTest::isolate());
1168
1169 Vector<const uint8_t> source_a =
1170 ConstructSource(STATIC_CHAR_VECTOR("var a = \""), STATIC_CHAR_VECTOR("a"),
1171 STATIC_CHAR_VECTOR("\";"), 700000);
1172 Handle<String> source_a_str =
1173 f->NewStringFromOneByte(source_a).ToHandleChecked();
1174
1175 Vector<const uint8_t> source_b =
1176 ConstructSource(STATIC_CHAR_VECTOR("var b = \""), STATIC_CHAR_VECTOR("b"),
1177 STATIC_CHAR_VECTOR("\";"), 600000);
1178 Handle<String> source_b_str =
1179 f->NewStringFromOneByte(source_b).ToHandleChecked();
1180
1181 Vector<const uint8_t> source_c =
1182 ConstructSource(STATIC_CHAR_VECTOR("var c = \""), STATIC_CHAR_VECTOR("c"),
1183 STATIC_CHAR_VECTOR("\";"), 500000);
1184 Handle<String> source_c_str =
1185 f->NewStringFromOneByte(source_c).ToHandleChecked();
1186
1187 Handle<String> source_str =
1188 f->NewConsString(
1189 f->NewConsString(source_a_str, source_b_str).ToHandleChecked(),
1190 source_c_str).ToHandleChecked();
1191
1192 Handle<JSObject> global(isolate->context()->global_object());
1193 ScriptData* cache = NULL;
1194
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001195 Handle<SharedFunctionInfo> orig =
1196 CompileScript(isolate, source_str, Handle<String>(), &cache,
1197 v8::ScriptCompiler::kProduceCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001198
1199 Handle<SharedFunctionInfo> copy;
1200 {
1201 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001202 copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
1203 v8::ScriptCompiler::kConsumeCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001204 }
1205 CHECK_NE(*orig, *copy);
1206
1207 Handle<JSFunction> copy_fun =
1208 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1209 copy, isolate->native_context());
1210
1211 USE(Execution::Call(isolate, copy_fun, global, 0, NULL));
1212
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213 v8::Maybe<int32_t> result =
1214 CompileRun("(a + b).length")
1215 ->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext());
1216 CHECK_EQ(600000 + 700000, result.FromJust());
1217 result = CompileRun("(b + c).length")
1218 ->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext());
1219 CHECK_EQ(500000 + 600000, result.FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001220 Heap* heap = isolate->heap();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001221 v8::Local<v8::String> result_str =
1222 CompileRun("a")
1223 ->ToString(CcTest::isolate()->GetCurrentContext())
1224 .ToLocalChecked();
1225 CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), LO_SPACE));
1226 result_str = CompileRun("b")
1227 ->ToString(CcTest::isolate()->GetCurrentContext())
1228 .ToLocalChecked();
1229 CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), OLD_SPACE));
1230 result_str = CompileRun("c")
1231 ->ToString(CcTest::isolate()->GetCurrentContext())
1232 .ToLocalChecked();
1233 CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), OLD_SPACE));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001234
1235 delete cache;
1236 source_a.Dispose();
1237 source_b.Dispose();
1238 source_c.Dispose();
1239}
1240
1241
1242class SerializerOneByteResource
1243 : public v8::String::ExternalOneByteStringResource {
1244 public:
1245 SerializerOneByteResource(const char* data, size_t length)
1246 : data_(data), length_(length) {}
1247 virtual const char* data() const { return data_; }
1248 virtual size_t length() const { return length_; }
1249
1250 private:
1251 const char* data_;
1252 size_t length_;
1253};
1254
1255
1256class SerializerTwoByteResource : public v8::String::ExternalStringResource {
1257 public:
1258 SerializerTwoByteResource(const char* data, size_t length)
1259 : data_(AsciiToTwoByteString(data)), length_(length) {}
1260 ~SerializerTwoByteResource() { DeleteArray<const uint16_t>(data_); }
1261
1262 virtual const uint16_t* data() const { return data_; }
1263 virtual size_t length() const { return length_; }
1264
1265 private:
1266 const uint16_t* data_;
1267 size_t length_;
1268};
1269
Ben Murdochda12d292016-06-02 14:46:10 +01001270TEST(CodeSerializerExternalString) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001271 FLAG_serialize_toplevel = true;
1272 LocalContext context;
1273 Isolate* isolate = CcTest::i_isolate();
1274 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1275
1276 v8::HandleScope scope(CcTest::isolate());
1277
1278 // Obtain external internalized one-byte string.
1279 SerializerOneByteResource one_byte_resource("one_byte", 8);
1280 Handle<String> one_byte_string =
1281 isolate->factory()->NewStringFromAsciiChecked("one_byte");
1282 one_byte_string = isolate->factory()->InternalizeString(one_byte_string);
1283 one_byte_string->MakeExternal(&one_byte_resource);
1284 CHECK(one_byte_string->IsExternalOneByteString());
1285 CHECK(one_byte_string->IsInternalizedString());
1286
1287 // Obtain external internalized two-byte string.
1288 SerializerTwoByteResource two_byte_resource("two_byte", 8);
1289 Handle<String> two_byte_string =
1290 isolate->factory()->NewStringFromAsciiChecked("two_byte");
1291 two_byte_string = isolate->factory()->InternalizeString(two_byte_string);
1292 two_byte_string->MakeExternal(&two_byte_resource);
1293 CHECK(two_byte_string->IsExternalTwoByteString());
1294 CHECK(two_byte_string->IsInternalizedString());
1295
1296 const char* source =
1297 "var o = {} \n"
1298 "o.one_byte = 7; \n"
1299 "o.two_byte = 8; \n"
1300 "o.one_byte + o.two_byte; \n";
1301 Handle<String> source_string = isolate->factory()
1302 ->NewStringFromUtf8(CStrVector(source))
1303 .ToHandleChecked();
1304
1305 Handle<JSObject> global(isolate->context()->global_object());
1306 ScriptData* cache = NULL;
1307
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001308 Handle<SharedFunctionInfo> orig =
1309 CompileScript(isolate, source_string, Handle<String>(), &cache,
1310 v8::ScriptCompiler::kProduceCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001311
1312 Handle<SharedFunctionInfo> copy;
1313 {
1314 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001315 copy = CompileScript(isolate, source_string, Handle<String>(), &cache,
1316 v8::ScriptCompiler::kConsumeCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001317 }
1318 CHECK_NE(*orig, *copy);
1319
1320 Handle<JSFunction> copy_fun =
1321 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1322 copy, isolate->native_context());
1323
1324 Handle<Object> copy_result =
1325 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
1326
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001327 CHECK_EQ(15.0, copy_result->Number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001328
1329 delete cache;
1330}
1331
Ben Murdochda12d292016-06-02 14:46:10 +01001332TEST(CodeSerializerLargeExternalString) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001333 FLAG_serialize_toplevel = true;
1334 LocalContext context;
1335 Isolate* isolate = CcTest::i_isolate();
1336 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1337
1338 Factory* f = isolate->factory();
1339
1340 v8::HandleScope scope(CcTest::isolate());
1341
1342 // Create a huge external internalized string to use as variable name.
1343 Vector<const uint8_t> string =
1344 ConstructSource(STATIC_CHAR_VECTOR(""), STATIC_CHAR_VECTOR("abcdef"),
1345 STATIC_CHAR_VECTOR(""), 999999);
1346 Handle<String> name = f->NewStringFromOneByte(string).ToHandleChecked();
1347 SerializerOneByteResource one_byte_resource(
1348 reinterpret_cast<const char*>(string.start()), string.length());
1349 name = f->InternalizeString(name);
1350 name->MakeExternal(&one_byte_resource);
1351 CHECK(name->IsExternalOneByteString());
1352 CHECK(name->IsInternalizedString());
1353 CHECK(isolate->heap()->InSpace(*name, LO_SPACE));
1354
1355 // Create the source, which is "var <literal> = 42; <literal>".
1356 Handle<String> source_str =
1357 f->NewConsString(
1358 f->NewConsString(f->NewStringFromAsciiChecked("var "), name)
1359 .ToHandleChecked(),
1360 f->NewConsString(f->NewStringFromAsciiChecked(" = 42; "), name)
1361 .ToHandleChecked()).ToHandleChecked();
1362
1363 Handle<JSObject> global(isolate->context()->global_object());
1364 ScriptData* cache = NULL;
1365
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001366 Handle<SharedFunctionInfo> orig =
1367 CompileScript(isolate, source_str, Handle<String>(), &cache,
1368 v8::ScriptCompiler::kProduceCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001369
1370 Handle<SharedFunctionInfo> copy;
1371 {
1372 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001373 copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
1374 v8::ScriptCompiler::kConsumeCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001375 }
1376 CHECK_NE(*orig, *copy);
1377
1378 Handle<JSFunction> copy_fun =
1379 f->NewFunctionFromSharedFunctionInfo(copy, isolate->native_context());
1380
1381 Handle<Object> copy_result =
1382 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
1383
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001384 CHECK_EQ(42.0, copy_result->Number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001385
1386 delete cache;
1387 string.Dispose();
1388}
1389
Ben Murdochda12d292016-06-02 14:46:10 +01001390TEST(CodeSerializerExternalScriptName) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001391 FLAG_serialize_toplevel = true;
1392 LocalContext context;
1393 Isolate* isolate = CcTest::i_isolate();
1394 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1395
1396 Factory* f = isolate->factory();
1397
1398 v8::HandleScope scope(CcTest::isolate());
1399
1400 const char* source =
1401 "var a = [1, 2, 3, 4];"
1402 "a.reduce(function(x, y) { return x + y }, 0)";
1403
1404 Handle<String> source_string =
1405 f->NewStringFromUtf8(CStrVector(source)).ToHandleChecked();
1406
1407 const SerializerOneByteResource one_byte_resource("one_byte", 8);
1408 Handle<String> name =
1409 f->NewExternalStringFromOneByte(&one_byte_resource).ToHandleChecked();
1410 CHECK(name->IsExternalOneByteString());
1411 CHECK(!name->IsInternalizedString());
1412
1413 Handle<JSObject> global(isolate->context()->global_object());
1414 ScriptData* cache = NULL;
1415
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001416 Handle<SharedFunctionInfo> orig =
1417 CompileScript(isolate, source_string, name, &cache,
1418 v8::ScriptCompiler::kProduceCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001419
1420 Handle<SharedFunctionInfo> copy;
1421 {
1422 DisallowCompilation no_compile_expected(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001423 copy = CompileScript(isolate, source_string, name, &cache,
1424 v8::ScriptCompiler::kConsumeCodeCache);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001425 }
1426 CHECK_NE(*orig, *copy);
1427
1428 Handle<JSFunction> copy_fun =
1429 f->NewFunctionFromSharedFunctionInfo(copy, isolate->native_context());
1430
1431 Handle<Object> copy_result =
1432 Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
1433
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001434 CHECK_EQ(10.0, copy_result->Number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001435
1436 delete cache;
1437}
1438
1439
1440static bool toplevel_test_code_event_found = false;
1441
1442
1443static void SerializerCodeEventListener(const v8::JitCodeEvent* event) {
1444 if (event->type == v8::JitCodeEvent::CODE_ADDED &&
1445 memcmp(event->name.str, "Script:~test", 12) == 0) {
1446 toplevel_test_code_event_found = true;
1447 }
1448}
1449
1450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001451v8::ScriptCompiler::CachedData* ProduceCache(const char* source) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001452 v8::ScriptCompiler::CachedData* cache;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001453 v8::Isolate::CreateParams create_params;
1454 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
1455 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001456 {
1457 v8::Isolate::Scope iscope(isolate1);
1458 v8::HandleScope scope(isolate1);
1459 v8::Local<v8::Context> context = v8::Context::New(isolate1);
1460 v8::Context::Scope context_scope(context);
1461
1462 v8::Local<v8::String> source_str = v8_str(source);
1463 v8::ScriptOrigin origin(v8_str("test"));
1464 v8::ScriptCompiler::Source source(source_str, origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001465 v8::Local<v8::UnboundScript> script =
1466 v8::ScriptCompiler::CompileUnboundScript(
1467 isolate1, &source, v8::ScriptCompiler::kProduceCodeCache)
1468 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001469 const v8::ScriptCompiler::CachedData* data = source.GetCachedData();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001470 CHECK(data);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001471 // Persist cached data.
1472 uint8_t* buffer = NewArray<uint8_t>(data->length);
1473 MemCopy(buffer, data->data, data->length);
1474 cache = new v8::ScriptCompiler::CachedData(
1475 buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned);
1476
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001477 v8::Local<v8::Value> result = script->BindToCurrentContext()
1478 ->Run(isolate1->GetCurrentContext())
1479 .ToLocalChecked();
1480 v8::Local<v8::String> result_string =
1481 result->ToString(isolate1->GetCurrentContext()).ToLocalChecked();
1482 CHECK(result_string->Equals(isolate1->GetCurrentContext(), v8_str("abcdef"))
1483 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001484 }
1485 isolate1->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001486 return cache;
1487}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001488
Ben Murdochda12d292016-06-02 14:46:10 +01001489TEST(CodeSerializerIsolates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001490 FLAG_serialize_toplevel = true;
1491
1492 const char* source = "function f() { return 'abc'; }; f() + 'def'";
1493 v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
1494
1495 v8::Isolate::CreateParams create_params;
1496 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
1497 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001498 isolate2->SetJitCodeEventHandler(v8::kJitCodeEventDefault,
1499 SerializerCodeEventListener);
1500 toplevel_test_code_event_found = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001501 {
1502 v8::Isolate::Scope iscope(isolate2);
1503 v8::HandleScope scope(isolate2);
1504 v8::Local<v8::Context> context = v8::Context::New(isolate2);
1505 v8::Context::Scope context_scope(context);
1506
1507 v8::Local<v8::String> source_str = v8_str(source);
1508 v8::ScriptOrigin origin(v8_str("test"));
1509 v8::ScriptCompiler::Source source(source_str, origin, cache);
1510 v8::Local<v8::UnboundScript> script;
1511 {
1512 DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001513 script = v8::ScriptCompiler::CompileUnboundScript(
1514 isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
1515 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001516 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001517 CHECK(!cache->rejected);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001518 v8::Local<v8::Value> result = script->BindToCurrentContext()
1519 ->Run(isolate2->GetCurrentContext())
1520 .ToLocalChecked();
1521 CHECK(result->ToString(isolate2->GetCurrentContext())
1522 .ToLocalChecked()
1523 ->Equals(isolate2->GetCurrentContext(), v8_str("abcdef"))
1524 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001525 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001526 CHECK(toplevel_test_code_event_found);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001527 isolate2->Dispose();
1528}
1529
Ben Murdochda12d292016-06-02 14:46:10 +01001530TEST(CodeSerializerFlagChange) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001531 FLAG_serialize_toplevel = true;
1532
1533 const char* source = "function f() { return 'abc'; }; f() + 'def'";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001534 v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001535
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001536 v8::Isolate::CreateParams create_params;
1537 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
1538 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001539
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001540 FLAG_allow_natives_syntax = true; // Flag change should trigger cache reject.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001541 FlagList::EnforceFlagImplications();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001542 {
1543 v8::Isolate::Scope iscope(isolate2);
1544 v8::HandleScope scope(isolate2);
1545 v8::Local<v8::Context> context = v8::Context::New(isolate2);
1546 v8::Context::Scope context_scope(context);
1547
1548 v8::Local<v8::String> source_str = v8_str(source);
1549 v8::ScriptOrigin origin(v8_str("test"));
1550 v8::ScriptCompiler::Source source(source_str, origin, cache);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001551 v8::ScriptCompiler::CompileUnboundScript(
1552 isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
1553 .ToLocalChecked();
1554 CHECK(cache->rejected);
1555 }
1556 isolate2->Dispose();
1557}
1558
Ben Murdochda12d292016-06-02 14:46:10 +01001559TEST(CodeSerializerBitFlip) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001560 FLAG_serialize_toplevel = true;
1561
1562 const char* source = "function f() { return 'abc'; }; f() + 'def'";
1563 v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
1564
1565 // Random bit flip.
1566 const_cast<uint8_t*>(cache->data)[337] ^= 0x40;
1567
1568 v8::Isolate::CreateParams create_params;
1569 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
1570 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
1571 {
1572 v8::Isolate::Scope iscope(isolate2);
1573 v8::HandleScope scope(isolate2);
1574 v8::Local<v8::Context> context = v8::Context::New(isolate2);
1575 v8::Context::Scope context_scope(context);
1576
1577 v8::Local<v8::String> source_str = v8_str(source);
1578 v8::ScriptOrigin origin(v8_str("test"));
1579 v8::ScriptCompiler::Source source(source_str, origin, cache);
1580 v8::ScriptCompiler::CompileUnboundScript(
1581 isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
1582 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001583 CHECK(cache->rejected);
1584 }
1585 isolate2->Dispose();
1586}
1587
Ben Murdochda12d292016-06-02 14:46:10 +01001588TEST(CodeSerializerWithHarmonyScoping) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001589 FLAG_serialize_toplevel = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001590
1591 const char* source1 = "'use strict'; let x = 'X'";
1592 const char* source2 = "'use strict'; let y = 'Y'";
1593 const char* source3 = "'use strict'; x + y";
1594
1595 v8::ScriptCompiler::CachedData* cache;
1596
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001597 v8::Isolate::CreateParams create_params;
1598 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
1599 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001600 {
1601 v8::Isolate::Scope iscope(isolate1);
1602 v8::HandleScope scope(isolate1);
1603 v8::Local<v8::Context> context = v8::Context::New(isolate1);
1604 v8::Context::Scope context_scope(context);
1605
1606 CompileRun(source1);
1607 CompileRun(source2);
1608
1609 v8::Local<v8::String> source_str = v8_str(source3);
1610 v8::ScriptOrigin origin(v8_str("test"));
1611 v8::ScriptCompiler::Source source(source_str, origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001612 v8::Local<v8::UnboundScript> script =
1613 v8::ScriptCompiler::CompileUnboundScript(
1614 isolate1, &source, v8::ScriptCompiler::kProduceCodeCache)
1615 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001616 const v8::ScriptCompiler::CachedData* data = source.GetCachedData();
1617 CHECK(data);
1618 // Persist cached data.
1619 uint8_t* buffer = NewArray<uint8_t>(data->length);
1620 MemCopy(buffer, data->data, data->length);
1621 cache = new v8::ScriptCompiler::CachedData(
1622 buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned);
1623
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001624 v8::Local<v8::Value> result = script->BindToCurrentContext()
1625 ->Run(isolate1->GetCurrentContext())
1626 .ToLocalChecked();
1627 v8::Local<v8::String> result_str =
1628 result->ToString(isolate1->GetCurrentContext()).ToLocalChecked();
1629 CHECK(result_str->Equals(isolate1->GetCurrentContext(), v8_str("XY"))
1630 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001631 }
1632 isolate1->Dispose();
1633
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001634 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001635 {
1636 v8::Isolate::Scope iscope(isolate2);
1637 v8::HandleScope scope(isolate2);
1638 v8::Local<v8::Context> context = v8::Context::New(isolate2);
1639 v8::Context::Scope context_scope(context);
1640
1641 // Reverse order of prior running scripts.
1642 CompileRun(source2);
1643 CompileRun(source1);
1644
1645 v8::Local<v8::String> source_str = v8_str(source3);
1646 v8::ScriptOrigin origin(v8_str("test"));
1647 v8::ScriptCompiler::Source source(source_str, origin, cache);
1648 v8::Local<v8::UnboundScript> script;
1649 {
1650 DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001651 script = v8::ScriptCompiler::CompileUnboundScript(
1652 isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
1653 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001654 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001655 v8::Local<v8::Value> result = script->BindToCurrentContext()
1656 ->Run(isolate2->GetCurrentContext())
1657 .ToLocalChecked();
1658 v8::Local<v8::String> result_str =
1659 result->ToString(isolate2->GetCurrentContext()).ToLocalChecked();
1660 CHECK(result_str->Equals(isolate2->GetCurrentContext(), v8_str("XY"))
1661 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001662 }
1663 isolate2->Dispose();
1664}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001665
Ben Murdochda12d292016-06-02 14:46:10 +01001666TEST(CodeSerializerInternalReference) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001667#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64
1668 return;
1669#endif
Ben Murdochda12d292016-06-02 14:46:10 +01001670 // In ignition there are only relative jumps, so the following code
1671 // would not have any internal references. This test is not relevant
1672 // for ignition.
1673 if (FLAG_ignition) {
1674 return;
1675 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001676 // Disable experimental natives that are loaded after deserialization.
1677 FLAG_function_context_specialization = false;
1678 FLAG_always_opt = true;
1679 const char* flag = "--turbo-filter=foo";
1680 FlagList::SetFlagsFromString(flag, StrLength(flag));
1681
1682 const char* source =
1683 "var foo = (function(stdlib, foreign, heap) {"
1684 " function foo(i) {"
1685 " i = i|0;"
1686 " var j = 0;"
1687 " switch (i) {"
1688 " case 0:"
1689 " case 1: j = 1; break;"
1690 " case 2:"
1691 " case 3: j = 2; break;"
1692 " case 4:"
1693 " case 5: j = foo(3) + 1; break;"
1694 " default: j = 0; break;"
1695 " }"
1696 " return j + 10;"
1697 " }"
1698 " return { foo: foo };"
1699 "})(this, {}, undefined).foo;"
1700 "foo(1);";
1701
1702 v8::StartupData data = v8::V8::CreateSnapshotDataBlob(source);
1703 CHECK(data.data);
1704
1705 v8::Isolate::CreateParams params;
1706 params.snapshot_blob = &data;
1707 params.array_buffer_allocator = CcTest::array_buffer_allocator();
1708 v8::Isolate* isolate = v8::Isolate::New(params);
1709 {
1710 v8::Isolate::Scope i_scope(isolate);
1711 v8::HandleScope h_scope(isolate);
1712 v8::Local<v8::Context> context = v8::Context::New(isolate);
1713 delete[] data.data; // We can dispose of the snapshot blob now.
1714 v8::Context::Scope c_scope(context);
1715 v8::Local<v8::Function> foo =
1716 v8::Local<v8::Function>::Cast(CompileRun("foo"));
1717
1718 // There are at least 6 internal references.
1719 int mask = RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
1720 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
1721 RelocIterator it(
1722 Handle<JSFunction>::cast(v8::Utils::OpenHandle(*foo))->code(), mask);
1723 for (int i = 0; i < 6; ++i) {
1724 CHECK(!it.done());
1725 it.next();
1726 }
1727
1728 CHECK(Handle<JSFunction>::cast(v8::Utils::OpenHandle(*foo))
1729 ->code()
1730 ->is_turbofanned());
1731 CHECK_EQ(11, CompileRun("foo(0)")
1732 ->Int32Value(isolate->GetCurrentContext())
1733 .FromJust());
1734 CHECK_EQ(11, CompileRun("foo(1)")
1735 ->Int32Value(isolate->GetCurrentContext())
1736 .FromJust());
1737 CHECK_EQ(12, CompileRun("foo(2)")
1738 ->Int32Value(isolate->GetCurrentContext())
1739 .FromJust());
1740 CHECK_EQ(12, CompileRun("foo(3)")
1741 ->Int32Value(isolate->GetCurrentContext())
1742 .FromJust());
1743 CHECK_EQ(23, CompileRun("foo(4)")
1744 ->Int32Value(isolate->GetCurrentContext())
1745 .FromJust());
1746 CHECK_EQ(23, CompileRun("foo(5)")
1747 ->Int32Value(isolate->GetCurrentContext())
1748 .FromJust());
1749 CHECK_EQ(10, CompileRun("foo(6)")
1750 ->Int32Value(isolate->GetCurrentContext())
1751 .FromJust());
1752 }
1753 isolate->Dispose();
1754}
1755
Ben Murdochda12d292016-06-02 14:46:10 +01001756TEST(CodeSerializerEagerCompilationAndPreAge) {
1757 if (FLAG_ignition) return;
1758
1759 FLAG_lazy = true;
1760 FLAG_serialize_toplevel = true;
1761 FLAG_serialize_age_code = true;
1762 FLAG_serialize_eager = true;
1763 FLAG_min_preparse_length = 1;
1764
1765 static const char* source =
1766 "function f() {"
1767 " function g() {"
1768 " return 1;"
1769 " }"
1770 " return g();"
1771 "}"
1772 "'abcdef';";
1773
1774 v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
1775
1776 v8::Isolate::CreateParams create_params;
1777 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
1778 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
1779 {
1780 v8::Isolate::Scope iscope(isolate2);
1781 v8::HandleScope scope(isolate2);
1782 v8::Local<v8::Context> context = v8::Context::New(isolate2);
1783 v8::Context::Scope context_scope(context);
1784
1785 v8::Local<v8::String> source_str = v8_str(source);
1786 v8::ScriptOrigin origin(v8_str("test"));
1787 v8::ScriptCompiler::Source source(source_str, origin, cache);
1788 v8::Local<v8::UnboundScript> unbound =
1789 v8::ScriptCompiler::CompileUnboundScript(
1790 isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
1791 .ToLocalChecked();
1792
1793 CHECK(!cache->rejected);
1794
1795 Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate2);
1796 HandleScope i_scope(i_isolate);
1797 Handle<SharedFunctionInfo> toplevel = v8::Utils::OpenHandle(*unbound);
1798 Handle<Script> script(Script::cast(toplevel->script()));
1799 WeakFixedArray::Iterator iterator(script->shared_function_infos());
1800 // Every function has been pre-compiled from the code cache.
1801 int count = 0;
1802 while (SharedFunctionInfo* shared = iterator.Next<SharedFunctionInfo>()) {
1803 CHECK(shared->is_compiled());
1804 CHECK_EQ(Code::kPreAgedCodeAge, shared->code()->GetAge());
1805 count++;
1806 }
1807 CHECK_EQ(3, count);
1808 }
1809 isolate2->Dispose();
1810}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001811
1812TEST(Regress503552) {
1813 // Test that the code serializer can deal with weak cells that form a linked
1814 // list during incremental marking.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001815 CcTest::InitializeVM();
1816 Isolate* isolate = CcTest::i_isolate();
1817
1818 HandleScope scope(isolate);
1819 Handle<String> source = isolate->factory()->NewStringFromAsciiChecked(
1820 "function f() {} function g() {}");
1821 ScriptData* script_data = NULL;
Ben Murdochda12d292016-06-02 14:46:10 +01001822 Handle<SharedFunctionInfo> shared = Compiler::GetSharedFunctionInfoForScript(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001823 source, Handle<String>(), 0, 0, v8::ScriptOriginOptions(),
1824 Handle<Object>(), Handle<Context>(isolate->native_context()), NULL,
1825 &script_data, v8::ScriptCompiler::kProduceCodeCache, NOT_NATIVES_CODE,
1826 false);
1827 delete script_data;
1828
Ben Murdoch61f157c2016-09-16 13:49:30 +01001829 heap::SimulateIncrementalMarking(isolate->heap());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001830
1831 script_data = CodeSerializer::Serialize(isolate, shared, source);
1832 delete script_data;
1833}
1834
Ben Murdoch61f157c2016-09-16 13:49:30 +01001835#if V8_TARGET_ARCH_X64
1836TEST(CodeSerializerCell) {
1837 FLAG_serialize_toplevel = true;
1838 LocalContext context;
1839 Isolate* isolate = CcTest::i_isolate();
1840 isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
1841
1842 v8::HandleScope scope(CcTest::isolate());
1843
1844 size_t actual_size;
1845 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1846 Assembler::kMinimalBufferSize, &actual_size, true));
1847 CHECK(buffer);
1848 HandleScope handles(isolate);
1849
1850 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
1851 v8::internal::CodeObjectRequired::kYes);
1852 assembler.enable_serializer();
1853 Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(0.3);
1854 CHECK(isolate->heap()->InNewSpace(*number));
1855 MacroAssembler* masm = &assembler;
1856 masm->MoveHeapObject(rax, number);
1857 masm->ret(0);
1858 CodeDesc desc;
1859 masm->GetCode(&desc);
1860 Handle<Code> code = isolate->factory()->NewCode(
1861 desc, Code::ComputeFlags(Code::FUNCTION), masm->CodeObject());
1862 code->set_has_reloc_info_for_serialization(true);
1863
1864 RelocIterator rit1(*code, 1 << RelocInfo::CELL);
1865 CHECK_EQ(*number, rit1.rinfo()->target_cell()->value());
1866
1867 Handle<String> source = isolate->factory()->empty_string();
1868 Handle<SharedFunctionInfo> sfi =
1869 isolate->factory()->NewSharedFunctionInfo(source, code, false);
1870 ScriptData* script_data = CodeSerializer::Serialize(isolate, sfi, source);
1871
1872 Handle<SharedFunctionInfo> copy =
1873 CodeSerializer::Deserialize(isolate, script_data, source)
1874 .ToHandleChecked();
1875 RelocIterator rit2(copy->code(), 1 << RelocInfo::CELL);
1876 CHECK(rit2.rinfo()->target_cell()->IsCell());
1877 Handle<Cell> cell(rit2.rinfo()->target_cell());
1878 CHECK(cell->value()->IsHeapNumber());
1879 CHECK_EQ(0.3, HeapNumber::cast(cell->value())->value());
1880
1881 delete script_data;
1882}
1883#endif // V8_TARGET_ARCH_X64
1884
1885TEST(SnapshotCreatorMultipleContexts) {
1886 DisableTurbofan();
1887 v8::StartupData blob;
1888 {
1889 v8::SnapshotCreator creator;
1890 v8::Isolate* isolate = creator.GetIsolate();
1891 {
1892 v8::HandleScope handle_scope(isolate);
1893 v8::Local<v8::Context> context = v8::Context::New(isolate);
1894 v8::Context::Scope context_scope(context);
1895 CompileRun("var f = function() { return 1; }");
1896 CHECK_EQ(0, creator.AddContext(context));
1897 }
1898 {
1899 v8::HandleScope handle_scope(isolate);
1900 v8::Local<v8::Context> context = v8::Context::New(isolate);
1901 v8::Context::Scope context_scope(context);
1902 CompileRun("var f = function() { return 2; }");
1903 CHECK_EQ(1, creator.AddContext(context));
1904 }
1905 {
1906 v8::HandleScope handle_scope(isolate);
1907 v8::Local<v8::Context> context = v8::Context::New(isolate);
1908 CHECK_EQ(2, creator.AddContext(context));
1909 }
1910 blob =
1911 creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
1912 }
1913
1914 v8::Isolate::CreateParams params;
1915 params.snapshot_blob = &blob;
1916 params.array_buffer_allocator = CcTest::array_buffer_allocator();
1917 v8::Isolate* isolate = v8::Isolate::New(params);
1918 {
1919 v8::Isolate::Scope isolate_scope(isolate);
1920 v8::ExtensionConfiguration* no_extension = nullptr;
1921 v8::Local<v8::ObjectTemplate> no_template = v8::Local<v8::ObjectTemplate>();
1922 v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
1923 {
1924 v8::HandleScope handle_scope(isolate);
1925 v8::Local<v8::Context> context =
1926 v8::Context::New(isolate, no_extension, no_template, no_object, 0);
1927 v8::Context::Scope context_scope(context);
1928 ExpectInt32("f()", 1);
1929 }
1930 {
1931 v8::HandleScope handle_scope(isolate);
1932 v8::Local<v8::Context> context =
1933 v8::Context::New(isolate, no_extension, no_template, no_object, 1);
1934 v8::Context::Scope context_scope(context);
1935 ExpectInt32("f()", 2);
1936 }
1937 {
1938 v8::HandleScope handle_scope(isolate);
1939 v8::Local<v8::Context> context =
1940 v8::Context::New(isolate, no_extension, no_template, no_object, 2);
1941 v8::Context::Scope context_scope(context);
1942 ExpectUndefined("this.f");
1943 }
1944 }
1945
1946 isolate->Dispose();
1947 delete[] blob.data;
1948}
1949
1950static void SerializedCallback(
1951 const v8::FunctionCallbackInfo<v8::Value>& args) {
1952 args.GetReturnValue().Set(v8_num(42));
1953}
1954
1955static void SerializedCallbackReplacement(
1956 const v8::FunctionCallbackInfo<v8::Value>& args) {
1957 args.GetReturnValue().Set(v8_num(1337));
1958}
1959
1960intptr_t original_external_references[] = {
1961 reinterpret_cast<intptr_t>(SerializedCallback), 0};
1962
1963intptr_t replaced_external_references[] = {
1964 reinterpret_cast<intptr_t>(SerializedCallbackReplacement), 0};
1965
1966TEST(SnapshotCreatorExternalReferences) {
1967 DisableTurbofan();
1968 v8::StartupData blob;
1969 {
1970 v8::SnapshotCreator creator(original_external_references);
1971 v8::Isolate* isolate = creator.GetIsolate();
1972 {
1973 v8::HandleScope handle_scope(isolate);
1974 v8::Local<v8::Context> context = v8::Context::New(isolate);
1975 v8::Context::Scope context_scope(context);
1976 v8::Local<v8::FunctionTemplate> callback =
1977 v8::FunctionTemplate::New(isolate, SerializedCallback);
1978 v8::Local<v8::Value> function =
1979 callback->GetFunction(context).ToLocalChecked();
1980 CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
1981 ExpectInt32("f()", 42);
1982 CHECK_EQ(0, creator.AddContext(context));
1983 }
1984 blob =
1985 creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
1986 }
1987
1988 // Deserialize with the original external reference.
1989 {
1990 v8::Isolate::CreateParams params;
1991 params.snapshot_blob = &blob;
1992 params.array_buffer_allocator = CcTest::array_buffer_allocator();
1993 params.external_references = original_external_references;
1994 v8::Isolate* isolate = v8::Isolate::New(params);
1995 {
1996 v8::Isolate::Scope isolate_scope(isolate);
1997 v8::HandleScope handle_scope(isolate);
1998 v8::ExtensionConfiguration* no_extension = nullptr;
1999 v8::Local<v8::ObjectTemplate> no_template =
2000 v8::Local<v8::ObjectTemplate>();
2001 v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
2002 v8::Local<v8::Context> context =
2003 v8::Context::New(isolate, no_extension, no_template, no_object, 0);
2004 v8::Context::Scope context_scope(context);
2005 ExpectInt32("f()", 42);
2006 }
2007 isolate->Dispose();
2008 }
2009
2010 // Deserialize with the some other external reference.
2011 {
2012 v8::Isolate::CreateParams params;
2013 params.snapshot_blob = &blob;
2014 params.array_buffer_allocator = CcTest::array_buffer_allocator();
2015 params.external_references = replaced_external_references;
2016 v8::Isolate* isolate = v8::Isolate::New(params);
2017 {
2018 v8::Isolate::Scope isolate_scope(isolate);
2019 v8::HandleScope handle_scope(isolate);
2020 v8::ExtensionConfiguration* no_extension = nullptr;
2021 v8::Local<v8::ObjectTemplate> no_template =
2022 v8::Local<v8::ObjectTemplate>();
2023 v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
2024 v8::Local<v8::Context> context =
2025 v8::Context::New(isolate, no_extension, no_template, no_object, 0);
2026 v8::Context::Scope context_scope(context);
2027 ExpectInt32("f()", 1337);
2028 }
2029 isolate->Dispose();
2030 }
2031 delete[] blob.data;
2032}
2033
2034TEST(SnapshotCreatorTemplates) {
2035 DisableTurbofan();
2036 v8::StartupData blob;
2037 {
2038 v8::SnapshotCreator creator(original_external_references);
2039 v8::Isolate* isolate = creator.GetIsolate();
2040 {
2041 v8::HandleScope handle_scope(isolate);
2042 v8::ExtensionConfiguration* no_extension = nullptr;
2043 v8::Local<v8::ObjectTemplate> global_template =
2044 v8::ObjectTemplate::New(isolate);
2045 v8::Local<v8::FunctionTemplate> callback =
2046 v8::FunctionTemplate::New(isolate, SerializedCallback);
2047 global_template->Set(v8_str("f"), callback);
2048 v8::Local<v8::Context> context =
2049 v8::Context::New(isolate, no_extension, global_template);
2050 v8::Context::Scope context_scope(context);
2051 ExpectInt32("f()", 42);
2052 CHECK_EQ(0, creator.AddContext(context));
2053 CHECK_EQ(0, creator.AddTemplate(callback));
2054 CHECK_EQ(1, creator.AddTemplate(global_template));
2055 }
2056 blob =
2057 creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
2058 }
2059
2060 {
2061 v8::Isolate::CreateParams params;
2062 params.snapshot_blob = &blob;
2063 params.array_buffer_allocator = CcTest::array_buffer_allocator();
2064 params.external_references = original_external_references;
2065 v8::Isolate* isolate = v8::Isolate::New(params);
2066 {
2067 v8::Isolate::Scope isolate_scope(isolate);
2068 {
2069 // Create a new context without a new object template.
2070 v8::HandleScope handle_scope(isolate);
2071 v8::ExtensionConfiguration* no_extension = nullptr;
2072 v8::Local<v8::ObjectTemplate> no_template =
2073 v8::Local<v8::ObjectTemplate>();
2074 v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
2075 v8::Local<v8::Context> context =
2076 v8::Context::New(isolate, no_extension, no_template, no_object, 0);
2077 v8::Context::Scope context_scope(context);
2078 ExpectInt32("f()", 42);
2079
2080 // Retrieve the snapshotted object template.
2081 v8::Local<v8::ObjectTemplate> obj_template =
2082 v8::ObjectTemplate::FromSnapshot(isolate, 1);
2083 CHECK(!obj_template.IsEmpty());
2084 v8::Local<v8::Object> object =
2085 obj_template->NewInstance(context).ToLocalChecked();
2086 CHECK(context->Global()->Set(context, v8_str("o"), object).FromJust());
2087 ExpectInt32("o.f()", 42);
2088 // Check that it instantiates to the same prototype.
2089 ExpectTrue("o.f.prototype === f.prototype");
2090
2091 // Retrieve the snapshotted function template.
2092 v8::Local<v8::FunctionTemplate> fun_template =
2093 v8::FunctionTemplate::FromSnapshot(isolate, 0);
2094 CHECK(!fun_template.IsEmpty());
2095 v8::Local<v8::Function> fun =
2096 fun_template->GetFunction(context).ToLocalChecked();
2097 CHECK(context->Global()->Set(context, v8_str("g"), fun).FromJust());
2098 ExpectInt32("g()", 42);
2099 // Check that it instantiates to the same prototype.
2100 ExpectTrue("g.prototype === f.prototype");
2101 }
2102
2103 {
2104 // Create a context with a new object template. It is merged into the
2105 // deserialized global object.
2106 v8::HandleScope handle_scope(isolate);
2107 v8::ExtensionConfiguration* no_extension = nullptr;
2108 v8::Local<v8::ObjectTemplate> global_template =
2109 v8::ObjectTemplate::New(isolate);
2110 global_template->Set(
2111 v8_str("g"),
2112 v8::FunctionTemplate::New(isolate, SerializedCallbackReplacement));
2113 v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
2114 v8::Local<v8::Context> context = v8::Context::New(
2115 isolate, no_extension, global_template, no_object, 0);
2116 v8::Context::Scope context_scope(context);
2117 ExpectInt32("g()", 1337);
2118 ExpectInt32("f()", 42);
2119 }
2120 }
2121 isolate->Dispose();
2122 }
2123 delete[] blob.data;
2124}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002125
2126TEST(SerializationMemoryStats) {
2127 FLAG_profile_deserialization = true;
2128 FLAG_always_opt = false;
2129 v8::StartupData blob = v8::V8::CreateSnapshotDataBlob();
2130 delete[] blob.data;
2131}