blob: 811a85df59afbaa2b7622a13125ed703d17c798d [file] [log] [blame]
[email protected]41fba0e2014-01-16 18:19:421// 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
danakj89f47082020-09-02 17:53:435#include "content/web_test/renderer/gc_controller.h"
[email protected]41fba0e2014-01-16 18:19:426
Sebastien Marchandf8cbfab2019-01-25 16:02:307#include "base/bind.h"
Peter Boström2e6be142021-11-13 01:28:258#include "base/ignore_result.h"
[email protected]41fba0e2014-01-16 18:19:429#include "gin/arguments.h"
10#include "gin/handle.h"
11#include "gin/object_template_builder.h"
Blink Reformata30d4232018-04-07 15:31:0612#include "third_party/blink/public/web/blink.h"
13#include "third_party/blink/public/web/web_local_frame.h"
[email protected]41fba0e2014-01-16 18:19:4214#include "v8/include/v8.h"
15
danakj741848a2020-04-07 22:48:0616namespace content {
[email protected]41fba0e2014-01-16 18:19:4217
18gin::WrapperInfo GCController::kWrapperInfo = {gin::kEmbedderNativeGin};
19
20// static
danakjc989ac72020-04-15 20:31:2321void GCController::Install(blink::WebLocalFrame* frame) {
Blink Reformat1c4d759e2017-04-09 16:34:5422 v8::Isolate* isolate = blink::MainThreadIsolate();
[email protected]41fba0e2014-01-16 18:19:4223 v8::HandleScope handle_scope(isolate);
Blink Reformat1c4d759e2017-04-09 16:34:5424 v8::Local<v8::Context> context = frame->MainWorldScriptContext();
[email protected]41fba0e2014-01-16 18:19:4225 if (context.IsEmpty())
26 return;
27
28 v8::Context::Scope context_scope(context);
29
30 gin::Handle<GCController> controller =
danakjc989ac72020-04-15 20:31:2331 gin::CreateHandle(isolate, new GCController(frame));
[email protected]ad4d2032014-04-28 13:50:5932 if (controller.IsEmpty())
33 return;
deepak.s750d68f2015-04-30 07:32:4134 v8::Local<v8::Object> global = context->Global();
Dan Elphicka83be512019-02-05 15:57:2335 global
36 ->Set(context, gin::StringToV8(isolate, "GCController"),
37 controller.ToV8())
38 .Check();
[email protected]41fba0e2014-01-16 18:19:4239}
40
danakjc989ac72020-04-15 20:31:2341GCController::GCController(blink::WebLocalFrame* frame) : frame_(frame) {}
[email protected]41fba0e2014-01-16 18:19:4242
Michael Lippautz5b64e892018-09-24 11:10:0043GCController::~GCController() = default;
[email protected]41fba0e2014-01-16 18:19:4244
45gin::ObjectTemplateBuilder GCController::GetObjectTemplateBuilder(
46 v8::Isolate* isolate) {
47 return gin::Wrappable<GCController>::GetObjectTemplateBuilder(isolate)
48 .SetMethod("collect", &GCController::Collect)
[email protected]c7d90042014-02-05 08:25:1549 .SetMethod("collectAll", &GCController::CollectAll)
Michael Lippautz5b64e892018-09-24 11:10:0050 .SetMethod("minorCollect", &GCController::MinorCollect)
51 .SetMethod("asyncCollectAll", &GCController::AsyncCollectAll);
[email protected]41fba0e2014-01-16 18:19:4252}
53
54void GCController::Collect(const gin::Arguments& args) {
55 args.isolate()->RequestGarbageCollectionForTesting(
56 v8::Isolate::kFullGarbageCollection);
57}
58
[email protected]c7d90042014-02-05 08:25:1559void GCController::CollectAll(const gin::Arguments& args) {
Michael Lippautz5b64e892018-09-24 11:10:0060 for (int i = 0; i < kNumberOfGCsForFullCollection; i++) {
[email protected]c7d90042014-02-05 08:25:1561 args.isolate()->RequestGarbageCollectionForTesting(
62 v8::Isolate::kFullGarbageCollection);
63 }
64}
65
Michael Lippautz5b64e892018-09-24 11:10:0066void GCController::AsyncCollectAll(const gin::Arguments& args) {
Michael Lippautz584c69a82018-09-25 15:22:5167 v8::HandleScope scope(args.isolate());
68
69 if (args.PeekNext().IsEmpty() || !args.PeekNext()->IsFunction()) {
70 args.ThrowTypeError(
71 "asyncCollectAll should be called with a callback argument being a "
72 "v8::Function.");
73 return;
Michael Lippautz5b64e892018-09-24 11:10:0074 }
danakjc989ac72020-04-15 20:31:2375 v8::UniquePersistent<v8::Function> js_callback(
Michael Lippautz5b64e892018-09-24 11:10:0076 args.isolate(), v8::Local<v8::Function>::Cast(args.PeekNext()));
77
danakjc989ac72020-04-15 20:31:2378 // Bind the js callback into a OnceClosure that will be run asynchronously in
79 // a fresh call stack.
80 base::OnceClosure run_async =
Michael Lippautz5b64e892018-09-24 11:10:0081 base::BindOnce(&GCController::AsyncCollectAllWithEmptyStack,
danakjc989ac72020-04-15 20:31:2382 weak_ptr_factory_.GetWeakPtr(), std::move(js_callback));
83 frame_->GetTaskRunner(blink::TaskType::kInternalTest)
84 ->PostTask(FROM_HERE, std::move(run_async));
Michael Lippautz5b64e892018-09-24 11:10:0085}
86
87void GCController::AsyncCollectAllWithEmptyStack(
88 v8::UniquePersistent<v8::Function> callback) {
89 v8::Isolate* const isolate = blink::MainThreadIsolate();
90
91 for (int i = 0; i < kNumberOfGCsForFullCollection; i++) {
Omer Katzb65361a42021-11-22 21:46:4992 isolate->RequestGarbageCollectionForTesting(
93 v8::Isolate::kFullGarbageCollection,
Michael Lippautzac8bee72020-12-14 11:31:4294 v8::EmbedderHeapTracer::EmbedderStackState::kNoHeapPointers);
Michael Lippautz5b64e892018-09-24 11:10:0095 }
96
97 v8::HandleScope scope(isolate);
98 v8::Local<v8::Function> func = callback.Get(isolate);
99 v8::Local<v8::Context> context = func->CreationContext();
100 v8::Context::Scope context_scope(context);
Michael Lippautz54f67af22019-01-08 15:41:57101 v8::TryCatch try_catch(isolate);
Jochen Eisinger68f332862021-04-29 08:19:20102 v8::MicrotasksScope microtasks_scope(
103 isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
Michael Lippautz54f67af22019-01-08 15:41:57104 auto result = func->Call(context, context->Global(), 0, nullptr);
105 // Swallow potential exception.
106 ignore_result(result);
Michael Lippautz5b64e892018-09-24 11:10:00107}
108
[email protected]41fba0e2014-01-16 18:19:42109void GCController::MinorCollect(const gin::Arguments& args) {
110 args.isolate()->RequestGarbageCollectionForTesting(
111 v8::Isolate::kMinorGarbageCollection);
112}
113
danakj741848a2020-04-07 22:48:06114} // namespace content