| [email protected] | 41fba0e | 2014-01-16 18:19:42 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| Scott Violet | fdda96d | 2018-07-27 20:17:23 | [diff] [blame] | 5 | #include "content/shell/test_runner/gc_controller.h" |
| [email protected] | 41fba0e | 2014-01-16 18:19:42 | [diff] [blame] | 6 | |
| Sebastien Marchand | f8cbfab | 2019-01-25 16:02:30 | [diff] [blame] | 7 | #include "base/bind.h" |
| Michael Lippautz | 5b64e89 | 2018-09-24 11:10:00 | [diff] [blame] | 8 | #include "content/shell/test_runner/test_interfaces.h" |
| 9 | #include "content/shell/test_runner/web_test_delegate.h" |
| [email protected] | 41fba0e | 2014-01-16 18:19:42 | [diff] [blame] | 10 | #include "gin/arguments.h" |
| 11 | #include "gin/handle.h" |
| 12 | #include "gin/object_template_builder.h" |
| Blink Reformat | a30d423 | 2018-04-07 15:31:06 | [diff] [blame] | 13 | #include "third_party/blink/public/web/blink.h" |
| 14 | #include "third_party/blink/public/web/web_local_frame.h" |
| [email protected] | 41fba0e | 2014-01-16 18:19:42 | [diff] [blame] | 15 | #include "v8/include/v8.h" |
| 16 | |
| danakj | 741848a | 2020-04-07 22:48:06 | [diff] [blame^] | 17 | namespace content { |
| [email protected] | 41fba0e | 2014-01-16 18:19:42 | [diff] [blame] | 18 | |
| 19 | gin::WrapperInfo GCController::kWrapperInfo = {gin::kEmbedderNativeGin}; |
| 20 | |
| 21 | // static |
| Michael Lippautz | 5b64e89 | 2018-09-24 11:10:00 | [diff] [blame] | 22 | void GCController::Install(TestInterfaces* interfaces, |
| 23 | blink::WebLocalFrame* frame) { |
| Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 24 | v8::Isolate* isolate = blink::MainThreadIsolate(); |
| [email protected] | 41fba0e | 2014-01-16 18:19:42 | [diff] [blame] | 25 | v8::HandleScope handle_scope(isolate); |
| Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 26 | v8::Local<v8::Context> context = frame->MainWorldScriptContext(); |
| [email protected] | 41fba0e | 2014-01-16 18:19:42 | [diff] [blame] | 27 | if (context.IsEmpty()) |
| 28 | return; |
| 29 | |
| 30 | v8::Context::Scope context_scope(context); |
| 31 | |
| 32 | gin::Handle<GCController> controller = |
| Michael Lippautz | 5b64e89 | 2018-09-24 11:10:00 | [diff] [blame] | 33 | gin::CreateHandle(isolate, new GCController(interfaces)); |
| [email protected] | ad4d203 | 2014-04-28 13:50:59 | [diff] [blame] | 34 | if (controller.IsEmpty()) |
| 35 | return; |
| deepak.s | 750d68f | 2015-04-30 07:32:41 | [diff] [blame] | 36 | v8::Local<v8::Object> global = context->Global(); |
| Dan Elphick | a83be51 | 2019-02-05 15:57:23 | [diff] [blame] | 37 | global |
| 38 | ->Set(context, gin::StringToV8(isolate, "GCController"), |
| 39 | controller.ToV8()) |
| 40 | .Check(); |
| [email protected] | 41fba0e | 2014-01-16 18:19:42 | [diff] [blame] | 41 | } |
| 42 | |
| Michael Lippautz | 5b64e89 | 2018-09-24 11:10:00 | [diff] [blame] | 43 | GCController::GCController(TestInterfaces* interfaces) |
| 44 | : interfaces_(interfaces) {} |
| [email protected] | 41fba0e | 2014-01-16 18:19:42 | [diff] [blame] | 45 | |
| Michael Lippautz | 5b64e89 | 2018-09-24 11:10:00 | [diff] [blame] | 46 | GCController::~GCController() = default; |
| [email protected] | 41fba0e | 2014-01-16 18:19:42 | [diff] [blame] | 47 | |
| 48 | gin::ObjectTemplateBuilder GCController::GetObjectTemplateBuilder( |
| 49 | v8::Isolate* isolate) { |
| 50 | return gin::Wrappable<GCController>::GetObjectTemplateBuilder(isolate) |
| 51 | .SetMethod("collect", &GCController::Collect) |
| [email protected] | c7d9004 | 2014-02-05 08:25:15 | [diff] [blame] | 52 | .SetMethod("collectAll", &GCController::CollectAll) |
| Michael Lippautz | 5b64e89 | 2018-09-24 11:10:00 | [diff] [blame] | 53 | .SetMethod("minorCollect", &GCController::MinorCollect) |
| 54 | .SetMethod("asyncCollectAll", &GCController::AsyncCollectAll); |
| [email protected] | 41fba0e | 2014-01-16 18:19:42 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | void GCController::Collect(const gin::Arguments& args) { |
| 58 | args.isolate()->RequestGarbageCollectionForTesting( |
| 59 | v8::Isolate::kFullGarbageCollection); |
| 60 | } |
| 61 | |
| [email protected] | c7d9004 | 2014-02-05 08:25:15 | [diff] [blame] | 62 | void GCController::CollectAll(const gin::Arguments& args) { |
| Michael Lippautz | 5b64e89 | 2018-09-24 11:10:00 | [diff] [blame] | 63 | for (int i = 0; i < kNumberOfGCsForFullCollection; i++) { |
| [email protected] | c7d9004 | 2014-02-05 08:25:15 | [diff] [blame] | 64 | args.isolate()->RequestGarbageCollectionForTesting( |
| 65 | v8::Isolate::kFullGarbageCollection); |
| 66 | } |
| 67 | } |
| 68 | |
| Michael Lippautz | 5b64e89 | 2018-09-24 11:10:00 | [diff] [blame] | 69 | void GCController::AsyncCollectAll(const gin::Arguments& args) { |
| Michael Lippautz | 584c69a8 | 2018-09-25 15:22:51 | [diff] [blame] | 70 | v8::HandleScope scope(args.isolate()); |
| 71 | |
| 72 | if (args.PeekNext().IsEmpty() || !args.PeekNext()->IsFunction()) { |
| 73 | args.ThrowTypeError( |
| 74 | "asyncCollectAll should be called with a callback argument being a " |
| 75 | "v8::Function."); |
| 76 | return; |
| Michael Lippautz | 5b64e89 | 2018-09-24 11:10:00 | [diff] [blame] | 77 | } |
| 78 | |
| Michael Lippautz | 5b64e89 | 2018-09-24 11:10:00 | [diff] [blame] | 79 | v8::UniquePersistent<v8::Function> func( |
| 80 | args.isolate(), v8::Local<v8::Function>::Cast(args.PeekNext())); |
| 81 | |
| 82 | CHECK(interfaces_->GetDelegate()); |
| 83 | CHECK(!func.IsEmpty()); |
| 84 | interfaces_->GetDelegate()->PostTask( |
| 85 | base::BindOnce(&GCController::AsyncCollectAllWithEmptyStack, |
| 86 | base::Unretained(this), std::move(func))); |
| 87 | } |
| 88 | |
| 89 | void GCController::AsyncCollectAllWithEmptyStack( |
| 90 | v8::UniquePersistent<v8::Function> callback) { |
| 91 | v8::Isolate* const isolate = blink::MainThreadIsolate(); |
| 92 | |
| 93 | for (int i = 0; i < kNumberOfGCsForFullCollection; i++) { |
| 94 | isolate->GetEmbedderHeapTracer()->GarbageCollectionForTesting( |
| 95 | v8::EmbedderHeapTracer::kEmpty); |
| 96 | } |
| 97 | |
| 98 | v8::HandleScope scope(isolate); |
| 99 | v8::Local<v8::Function> func = callback.Get(isolate); |
| 100 | v8::Local<v8::Context> context = func->CreationContext(); |
| 101 | v8::Context::Scope context_scope(context); |
| Michael Lippautz | 54f67af2 | 2019-01-08 15:41:57 | [diff] [blame] | 102 | v8::TryCatch try_catch(isolate); |
| 103 | auto result = func->Call(context, context->Global(), 0, nullptr); |
| 104 | // Swallow potential exception. |
| 105 | ignore_result(result); |
| Michael Lippautz | 5b64e89 | 2018-09-24 11:10:00 | [diff] [blame] | 106 | } |
| 107 | |
| [email protected] | 41fba0e | 2014-01-16 18:19:42 | [diff] [blame] | 108 | void GCController::MinorCollect(const gin::Arguments& args) { |
| 109 | args.isolate()->RequestGarbageCollectionForTesting( |
| 110 | v8::Isolate::kMinorGarbageCollection); |
| 111 | } |
| 112 | |
| danakj | 741848a | 2020-04-07 22:48:06 | [diff] [blame^] | 113 | } // namespace content |