Commit 6b12172c authored by Yuzu Saijo's avatar Yuzu Saijo Committed by Commit Bot

Introduce kFrameIsDetachedAndV8MemoryIsPurged

When OomIntervention is performed on an iframe, its lifecycle becomes
kV8MemoryIsForciblyPurged. And then it is possible that the iframe gets
detached, and lifecycle moves to kFrameIsDetachedAndV8MemoryIsPurged.

This CL allows this transition to happen. Also it changes the name of
lifecycle from kForciblyPurgedV8Memory to kV8MemoryIsForciblyPurged.

Change-Id: Id1459ec99fdac840bcb3dc4b3355002af77c57ac
Reviewed-on: https://chromium-review.googlesource.com/c/1445341Reviewed-by: default avatarYuki Shiino <yukishiino@chromium.org>
Reviewed-by: default avatarKeishi Hattori <keishi@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Yuzu Saijo <yuzus@chromium.org>
Cr-Commit-Position: refs/heads/master@{#635869}
parent 6decccc5
......@@ -79,15 +79,20 @@ void LocalWindowProxy::Trace(blink::Visitor* visitor) {
void LocalWindowProxy::DisposeContext(Lifecycle next_status,
FrameReuseStatus frame_reuse_status) {
DCHECK(next_status == Lifecycle::kForciblyPurgeV8Memory ||
DCHECK(next_status == Lifecycle::kV8MemoryIsForciblyPurged ||
next_status == Lifecycle::kGlobalObjectIsDetached ||
next_status == Lifecycle::kFrameIsDetached);
// If the current lifecycle is kForciblyPurgeV8Memory, the next state should
// be kGlobalObjectIsDetached. The necessary operations are already done in
// kForciblyPurgeMemory and thus can return here.
if (lifecycle_ == Lifecycle::kForciblyPurgeV8Memory) {
DCHECK(next_status == Lifecycle::kGlobalObjectIsDetached);
next_status == Lifecycle::kFrameIsDetached ||
next_status == Lifecycle::kFrameIsDetachedAndV8MemoryIsPurged);
// If the current lifecycle is kV8MemoryIsForciblyPurged, next status should
// be either kFrameIsDetachedAndV8MemoryIsPurged, or kGlobalObjectIsDetached.
// If the former, |global_proxy_| should become weak, and if the latter, the
// necessary operations are already done so can return here.
if (lifecycle_ == Lifecycle::kV8MemoryIsForciblyPurged) {
DCHECK(next_status == Lifecycle::kGlobalObjectIsDetached ||
next_status == Lifecycle::kFrameIsDetachedAndV8MemoryIsPurged);
if (next_status == Lifecycle::kFrameIsDetachedAndV8MemoryIsPurged)
global_proxy_.SetPhantom();
lifecycle_ = next_status;
return;
}
......@@ -102,7 +107,7 @@ void LocalWindowProxy::DisposeContext(Lifecycle next_status,
// it returns.
GetFrame()->Client()->WillReleaseScriptContext(context, world_->GetWorldId());
MainThreadDebugger::Instance()->ContextWillBeDestroyed(script_state_);
if (next_status == Lifecycle::kForciblyPurgeV8Memory ||
if (next_status == Lifecycle::kV8MemoryIsForciblyPurged ||
next_status == Lifecycle::kGlobalObjectIsDetached) {
// Clean up state on the global proxy, which will be reused.
if (!global_proxy_.IsEmpty()) {
......
......@@ -51,15 +51,20 @@ RemoteWindowProxy::RemoteWindowProxy(v8::Isolate* isolate,
void RemoteWindowProxy::DisposeContext(Lifecycle next_status,
FrameReuseStatus) {
DCHECK(next_status == Lifecycle::kForciblyPurgeV8Memory ||
DCHECK(next_status == Lifecycle::kV8MemoryIsForciblyPurged ||
next_status == Lifecycle::kGlobalObjectIsDetached ||
next_status == Lifecycle::kFrameIsDetached);
// If the current lifecycle is kForciblyPurgeV8Memory, the next state should
// be kGlobalObjectIsDetached. The necessary operations are already done in
// kForciblyPurgeMemory and thus can return here.
if (lifecycle_ == Lifecycle::kForciblyPurgeV8Memory) {
DCHECK(next_status == Lifecycle::kGlobalObjectIsDetached);
next_status == Lifecycle::kFrameIsDetached ||
next_status == Lifecycle::kFrameIsDetachedAndV8MemoryIsPurged);
// If the current lifecycle is kV8MemoryIsForciblyPurged, next status should
// be either kFrameIsDetachedAndV8MemoryIsPurged, or kGlobalObjectIsDetached.
// If the former, |global_proxy_| should become weak, and if the latter, the
// necessary operations are already done so can return here.
if (lifecycle_ == Lifecycle::kV8MemoryIsForciblyPurged) {
DCHECK(next_status == Lifecycle::kGlobalObjectIsDetached ||
next_status == Lifecycle::kFrameIsDetachedAndV8MemoryIsPurged);
if (next_status == Lifecycle::kFrameIsDetachedAndV8MemoryIsPurged)
global_proxy_.SetPhantom();
lifecycle_ = next_status;
return;
}
......@@ -67,7 +72,7 @@ void RemoteWindowProxy::DisposeContext(Lifecycle next_status,
if (lifecycle_ != Lifecycle::kContextIsInitialized)
return;
if ((next_status == Lifecycle::kForciblyPurgeV8Memory ||
if ((next_status == Lifecycle::kV8MemoryIsForciblyPurged ||
next_status == Lifecycle::kGlobalObjectIsDetached) &&
!global_proxy_.IsEmpty()) {
global_proxy_.Get().SetWrapperClassId(0);
......
......@@ -62,7 +62,10 @@ WindowProxy::WindowProxy(v8::Isolate* isolate,
lifecycle_(Lifecycle::kContextIsUninitialized) {}
void WindowProxy::ClearForClose() {
DisposeContext(Lifecycle::kFrameIsDetached, kFrameWillNotBeReused);
DisposeContext(lifecycle_ == Lifecycle::kV8MemoryIsForciblyPurged
? Lifecycle::kFrameIsDetachedAndV8MemoryIsPurged
: Lifecycle::kFrameIsDetached,
kFrameWillNotBeReused);
}
void WindowProxy::ClearForNavigation() {
......@@ -74,7 +77,7 @@ void WindowProxy::ClearForSwap() {
}
void WindowProxy::ClearForV8MemoryPurge() {
DisposeContext(Lifecycle::kForciblyPurgeV8Memory, kFrameWillNotBeReused);
DisposeContext(Lifecycle::kV8MemoryIsForciblyPurged, kFrameWillNotBeReused);
}
v8::Local<v8::Object> WindowProxy::GlobalProxyIfNotDetached() {
......
......@@ -177,8 +177,8 @@ class WindowProxy : public GarbageCollectedFinalized<WindowProxy> {
// It's possible to detach the context's frame from the DOM or navigate to a
// new page without initializing the WindowProxy, however, there is no
// transition to |kFrameIsDetached| or |kGlobalObjectIsDetached| or
// |kForciblyPurgeV8Memory| because |DisposeContext| does not change the state
// if the state is |kContextIsUninitialized|. In either case of a) the
// |kV8MemoryIsForciblyPurged| because |DisposeContext| does not change the
// state if the state is |kContextIsUninitialized|. In either case of a) the
// browsing context container is detached from the DOM or b) the page is
// navigated away, there must be no way for author script to access the
// context of |kContextIsUninitialized| because |kContextIsUninitialized|
......@@ -188,16 +188,19 @@ class WindowProxy : public GarbageCollectedFinalized<WindowProxy> {
// * kContextIsInitialized
// The context is initialized and its frame is still attached to the DOM.
// - Possible next states: kFrameIsDetached, kGlobalObjectIsDetached,
// kForciblyPurgeV8Memory
// kV8MemoryIsForciblyPurged
//
// * kForciblyPurgeV8Memory
// * kV8MemoryIsForciblyPurged
// The context is initialized and its frame is still attached to the DOM, but
// the global object is detached from the global proxy in order to drop all
// references to v8, hopefully causing all JS objects to be collected for
// memory reduction.
// - Possible next states: kGlobalObjectIsDetached
// - Possible next states: kGlobalObjectIsDetached,
// kFrameIsDetachedAndV8MemoryIsPurged
// Navigation can occur after V8 memory purge, and the state will transition
// to kGlobalObjectIsDetached in that case.
// to kGlobalObjectIsDetached in that case. When frame is detached after V8
// memory purge, the global proxy will be a weak reference and will transition
// to kFrameIsDetachedAndV8MemoryIsPurged.
//
// * kGlobalObjectIsDetached
// The context is initialized and its frame is still attached to the DOM, but
......@@ -225,6 +228,12 @@ class WindowProxy : public GarbageCollectedFinalized<WindowProxy> {
// weak reference so that it's collectable when author script has no
// reference.
// - Possible next states: n/a
//
// * kFrameIsDetachedAndV8MemoryIsPurged
// V8 memory is purged for memory reduction and thus global object is detached
// from the global proxy, and also frame is detached from the DOM. Like
// kFrameIsDetached, |global_proxy_| becomes a weak reference.
// - Possible next states: n/a
enum class Lifecycle {
// v8::Context is not yet initialized.
kContextIsUninitialized,
......@@ -232,12 +241,15 @@ class WindowProxy : public GarbageCollectedFinalized<WindowProxy> {
kContextIsInitialized,
// The global object (inner global) is detached from the global proxy (outer
// global). Could transition to kGlobalObjectIsDetached.
kForciblyPurgeV8Memory,
kV8MemoryIsForciblyPurged,
// The global object (inner global) is detached from the global proxy (outer
// global).
kGlobalObjectIsDetached,
// The context's frame is detached from the DOM.
kFrameIsDetached,
// The context's frame is detached from the DOM, and global object is
// detached from the global proxy.
kFrameIsDetachedAndV8MemoryIsPurged,
};
WindowProxy(v8::Isolate*, Frame&, scoped_refptr<DOMWrapperWorld>);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment