Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Side by Side Diff: src/api.cc

Issue 1805903002: [serializer] Add API to warm up startup snapshot with an additional script. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix comment Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/v8.h ('k') | src/globals.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/api.h" 5 #include "src/api.h"
6 6
7 #include <string.h> // For memcpy, strlen. 7 #include <string.h> // For memcpy, strlen.
8 #ifdef V8_USE_ADDRESS_SANITIZER 8 #ifdef V8_USE_ADDRESS_SANITIZER
9 #include <sanitizer/asan_interface.h> 9 #include <sanitizer/asan_interface.h>
10 #endif // V8_USE_ADDRESS_SANITIZER 10 #endif // V8_USE_ADDRESS_SANITIZER
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 334
335 void V8::SetNativesDataBlob(StartupData* natives_blob) { 335 void V8::SetNativesDataBlob(StartupData* natives_blob) {
336 i::V8::SetNativesBlob(natives_blob); 336 i::V8::SetNativesBlob(natives_blob);
337 } 337 }
338 338
339 339
340 void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) { 340 void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) {
341 i::V8::SetSnapshotBlob(snapshot_blob); 341 i::V8::SetSnapshotBlob(snapshot_blob);
342 } 342 }
343 343
344 namespace {
345
346 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
347 public:
348 virtual void* Allocate(size_t length) {
349 void* data = AllocateUninitialized(length);
350 return data == NULL ? data : memset(data, 0, length);
351 }
352 virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
353 virtual void Free(void* data, size_t) { free(data); }
354 };
344 355
345 bool RunExtraCode(Isolate* isolate, Local<Context> context, 356 bool RunExtraCode(Isolate* isolate, Local<Context> context,
346 const char* utf8_source) { 357 const char* utf8_source, const char* name) {
347 // Run custom script if provided.
348 base::ElapsedTimer timer; 358 base::ElapsedTimer timer;
349 timer.Start(); 359 timer.Start();
360 Context::Scope context_scope(context);
350 TryCatch try_catch(isolate); 361 TryCatch try_catch(isolate);
351 Local<String> source_string; 362 Local<String> source_string;
352 if (!String::NewFromUtf8(isolate, utf8_source, NewStringType::kNormal) 363 if (!String::NewFromUtf8(isolate, utf8_source, NewStringType::kNormal)
353 .ToLocal(&source_string)) { 364 .ToLocal(&source_string)) {
354 return false; 365 return false;
355 } 366 }
356 Local<String> resource_name = 367 Local<String> resource_name =
357 String::NewFromUtf8(isolate, "<embedded script>", NewStringType::kNormal) 368 String::NewFromUtf8(isolate, name, NewStringType::kNormal)
358 .ToLocalChecked(); 369 .ToLocalChecked();
359 ScriptOrigin origin(resource_name); 370 ScriptOrigin origin(resource_name);
360 ScriptCompiler::Source source(source_string, origin); 371 ScriptCompiler::Source source(source_string, origin);
361 Local<Script> script; 372 Local<Script> script;
362 if (!ScriptCompiler::Compile(context, &source).ToLocal(&script)) return false; 373 if (!ScriptCompiler::Compile(context, &source).ToLocal(&script)) return false;
363 if (script->Run(context).IsEmpty()) return false; 374 if (script->Run(context).IsEmpty()) return false;
364 if (i::FLAG_profile_deserialization) { 375 if (i::FLAG_profile_deserialization) {
365 i::PrintF("Executing custom snapshot script took %0.3f ms\n", 376 i::PrintF("Executing custom snapshot script %s took %0.3f ms\n", name,
366 timer.Elapsed().InMillisecondsF()); 377 timer.Elapsed().InMillisecondsF());
367 } 378 }
368 timer.Stop(); 379 timer.Stop();
369 CHECK(!try_catch.HasCaught()); 380 CHECK(!try_catch.HasCaught());
370 return true; 381 return true;
371 } 382 }
372 383
384 StartupData SerializeIsolateAndContext(
385 Isolate* isolate, Persistent<Context>* context,
386 i::Snapshot::Metadata metadata,
387 i::StartupSerializer::FunctionCodeHandling function_code_handling) {
388 if (context->IsEmpty()) return {NULL, 0};
373 389
374 namespace { 390 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
375 391
376 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { 392 // If we don't do this then we end up with a stray root pointing at the
377 public: 393 // context even after we have disposed of the context.
378 virtual void* Allocate(size_t length) { 394 internal_isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
379 void* data = AllocateUninitialized(length); 395
380 return data == NULL ? data : memset(data, 0, length); 396 // GC may have cleared weak cells, so compact any WeakFixedArrays
397 // found on the heap.
398 i::HeapIterator iterator(internal_isolate->heap(),
399 i::HeapIterator::kFilterUnreachable);
400 for (i::HeapObject* o = iterator.next(); o != NULL; o = iterator.next()) {
401 if (o->IsPrototypeInfo()) {
402 i::Object* prototype_users = i::PrototypeInfo::cast(o)->prototype_users();
403 if (prototype_users->IsWeakFixedArray()) {
404 i::WeakFixedArray* array = i::WeakFixedArray::cast(prototype_users);
405 array->Compact<i::JSObject::PrototypeRegistryCompactionCallback>();
406 }
407 } else if (o->IsScript()) {
408 i::Object* shared_list = i::Script::cast(o)->shared_function_infos();
409 if (shared_list->IsWeakFixedArray()) {
410 i::WeakFixedArray* array = i::WeakFixedArray::cast(shared_list);
411 array->Compact<i::WeakFixedArray::NullCallback>();
412 }
413 }
381 } 414 }
382 virtual void* AllocateUninitialized(size_t length) { return malloc(length); } 415
383 virtual void Free(void* data, size_t) { free(data); } 416 i::Object* raw_context = *v8::Utils::OpenPersistent(*context);
384 }; 417 context->Reset();
418
419 i::SnapshotByteSink snapshot_sink;
420 i::StartupSerializer ser(internal_isolate, &snapshot_sink,
421 function_code_handling);
422 ser.SerializeStrongReferences();
423
424 i::SnapshotByteSink context_sink;
425 i::PartialSerializer context_ser(internal_isolate, &ser, &context_sink);
426 context_ser.Serialize(&raw_context);
427 ser.SerializeWeakReferencesAndDeferred();
428
429 return i::Snapshot::CreateSnapshotBlob(ser, context_ser, metadata);
430 }
385 431
386 } // namespace 432 } // namespace
387 433
434 StartupData V8::CreateSnapshotDataBlob(const char* embedded_source) {
435 // Create a new isolate and a new context from scratch, optionally run
436 // a script to embed, and serialize to create a snapshot blob.
437 StartupData result = {NULL, 0};
388 438
389 StartupData V8::CreateSnapshotDataBlob(const char* custom_source) { 439 base::ElapsedTimer timer;
440 timer.Start();
441
442 ArrayBufferAllocator allocator;
390 i::Isolate* internal_isolate = new i::Isolate(true); 443 i::Isolate* internal_isolate = new i::Isolate(true);
391 ArrayBufferAllocator allocator;
392 internal_isolate->set_array_buffer_allocator(&allocator); 444 internal_isolate->set_array_buffer_allocator(&allocator);
393 Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate); 445 Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate);
394 StartupData result = {NULL, 0}; 446
395 { 447 {
396 base::ElapsedTimer timer;
397 timer.Start();
398 Isolate::Scope isolate_scope(isolate); 448 Isolate::Scope isolate_scope(isolate);
399 internal_isolate->Init(NULL); 449 internal_isolate->Init(NULL);
400 Persistent<Context> context; 450 Persistent<Context> context;
401 i::Snapshot::Metadata metadata;
402 { 451 {
403 HandleScope handle_scope(isolate); 452 HandleScope handle_scope(isolate);
404 Local<Context> new_context = Context::New(isolate); 453 Local<Context> new_context = Context::New(isolate);
405 context.Reset(isolate, new_context); 454 context.Reset(isolate, new_context);
406 if (custom_source != NULL) { 455 if (embedded_source != NULL &&
407 metadata.set_embeds_script(true); 456 !RunExtraCode(isolate, new_context, embedded_source, "<embedded>")) {
408 Context::Scope context_scope(new_context); 457 context.Reset();
409 if (!RunExtraCode(isolate, new_context, custom_source)) context.Reset();
410 } 458 }
411 } 459 }
412 if (!context.IsEmpty()) {
413 // If we don't do this then we end up with a stray root pointing at the
414 // context even after we have disposed of the context.
415 internal_isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
416 460
417 // GC may have cleared weak cells, so compact any WeakFixedArrays 461 i::Snapshot::Metadata metadata;
418 // found on the heap. 462 metadata.set_embeds_script(embedded_source != NULL);
419 i::HeapIterator iterator(internal_isolate->heap(),
420 i::HeapIterator::kFilterUnreachable);
421 for (i::HeapObject* o = iterator.next(); o != NULL; o = iterator.next()) {
422 if (o->IsPrototypeInfo()) {
423 i::Object* prototype_users =
424 i::PrototypeInfo::cast(o)->prototype_users();
425 if (prototype_users->IsWeakFixedArray()) {
426 i::WeakFixedArray* array = i::WeakFixedArray::cast(prototype_users);
427 array->Compact<i::JSObject::PrototypeRegistryCompactionCallback>();
428 }
429 } else if (o->IsScript()) {
430 i::Object* shared_list = i::Script::cast(o)->shared_function_infos();
431 if (shared_list->IsWeakFixedArray()) {
432 i::WeakFixedArray* array = i::WeakFixedArray::cast(shared_list);
433 array->Compact<i::WeakFixedArray::NullCallback>();
434 }
435 }
436 }
437 463
438 i::Object* raw_context = *v8::Utils::OpenPersistent(context); 464 result = SerializeIsolateAndContext(
439 context.Reset(); 465 isolate, &context, metadata, i::StartupSerializer::CLEAR_FUNCTION_CODE);
440 466 DCHECK(context.IsEmpty());
441 i::SnapshotByteSink snapshot_sink;
442 i::StartupSerializer ser(internal_isolate, &snapshot_sink);
443 ser.SerializeStrongReferences();
444
445 i::SnapshotByteSink context_sink;
446 i::PartialSerializer context_ser(internal_isolate, &ser, &context_sink);
447 context_ser.Serialize(&raw_context);
448 ser.SerializeWeakReferencesAndDeferred();
449
450 result = i::Snapshot::CreateSnapshotBlob(ser, context_ser, metadata);
451 }
452 if (i::FLAG_profile_deserialization) {
453 i::PrintF("Creating snapshot took %0.3f ms\n",
454 timer.Elapsed().InMillisecondsF());
455 }
456 timer.Stop();
457 } 467 }
458 isolate->Dispose(); 468 isolate->Dispose();
469
470 if (i::FLAG_profile_deserialization) {
471 i::PrintF("Creating snapshot took %0.3f ms\n",
472 timer.Elapsed().InMillisecondsF());
473 }
474 timer.Stop();
459 return result; 475 return result;
460 } 476 }
461 477
478 StartupData V8::WarmUpSnapshotDataBlob(StartupData cold_snapshot_blob,
479 const char* warmup_source) {
480 CHECK(cold_snapshot_blob.raw_size > 0 && cold_snapshot_blob.data != NULL);
481 CHECK(warmup_source != NULL);
482 // Use following steps to create a warmed up snapshot blob from a cold one:
483 // - Create a new isolate from the cold snapshot.
484 // - Create a new context to run the warmup script. This will trigger
485 // compilation of executed functions.
486 // - Create a new context. This context will be unpolluted.
487 // - Serialize the isolate and the second context into a new snapshot blob.
488 StartupData result = {NULL, 0};
489
490 base::ElapsedTimer timer;
491 timer.Start();
492
493 ArrayBufferAllocator allocator;
494 i::Isolate* internal_isolate = new i::Isolate(true);
495 internal_isolate->set_array_buffer_allocator(&allocator);
496 internal_isolate->set_snapshot_blob(&cold_snapshot_blob);
497 Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate);
498
499 {
500 Isolate::Scope isolate_scope(isolate);
501 i::Snapshot::Initialize(internal_isolate);
502 Persistent<Context> context;
503 {
504 HandleScope handle_scope(isolate);
505 Local<Context> warmup_context = Context::New(isolate);
506 if (RunExtraCode(isolate, warmup_context, warmup_source, "<warm-up>")) {
507 Local<Context> fresh_context = Context::New(isolate);
508 context.Reset(isolate, fresh_context);
509 }
510 }
511
512 i::Snapshot::Metadata metadata;
513 metadata.set_embeds_script(i::Snapshot::EmbedsScript(internal_isolate));
514
515 result = SerializeIsolateAndContext(
516 isolate, &context, metadata, i::StartupSerializer::KEEP_FUNCTION_CODE);
517 DCHECK(context.IsEmpty());
518 }
519 isolate->Dispose();
520
521 if (i::FLAG_profile_deserialization) {
522 i::PrintF("Warming up snapshot took %0.3f ms\n",
523 timer.Elapsed().InMillisecondsF());
524 }
525 timer.Stop();
526 return result;
527 }
528
462 529
463 void V8::SetFlagsFromString(const char* str, int length) { 530 void V8::SetFlagsFromString(const char* str, int length) {
464 i::FlagList::SetFlagsFromString(str, length); 531 i::FlagList::SetFlagsFromString(str, length);
465 } 532 }
466 533
467 534
468 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) { 535 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
469 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags); 536 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
470 } 537 }
471 538
(...skipping 8213 matching lines...) Expand 10 before | Expand all | Expand 10 after
8685 Address callback_address = 8752 Address callback_address =
8686 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback)); 8753 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback));
8687 VMState<EXTERNAL> state(isolate); 8754 VMState<EXTERNAL> state(isolate);
8688 ExternalCallbackScope call_scope(isolate, callback_address); 8755 ExternalCallbackScope call_scope(isolate, callback_address);
8689 callback(info); 8756 callback(info);
8690 } 8757 }
8691 8758
8692 8759
8693 } // namespace internal 8760 } // namespace internal
8694 } // namespace v8 8761 } // namespace v8
OLDNEW
« no previous file with comments | « include/v8.h ('k') | src/globals.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698