- Revision
- 123556
- Author
- [email protected]
- Date
- 2012-07-24 17:37:11 -0700 (Tue, 24 Jul 2012)
Log Message
[chromium] Hint garbage collector to run if page uses Canvas contexts
https://bugs.webkit.org/show_bug.cgi?id=76225
Reviewed by Kentaro Hara.
Source/WebCore:
Upon creating a canvas context, set a hint in the current isolate
indicating that a full GC should be done upon the next page
navigation.
This improves Chrome's robustness on some WebGL stress tests which
simulate real-world behavior by repeatedly navigating among
several samples. More general measures are being investigated, but
this change makes V8 behave the same as JSC on these stress tests.
JSC doesn't currently use generational garbage collection, so it
has more opportunities to discover unreferenced canvas contexts.
Test: fast/canvas/webgl/context-creation-and-destruction.html
* bindings/v8/V8Binding.cpp:
(WebCore::V8BindingPerIsolateData::V8BindingPerIsolateData):
Initialize per-isolate low memory hint.
* bindings/v8/V8Binding.h:
(V8BindingPerIsolateData):
(WebCore::V8BindingPerIsolateData::setLowMemoryNotificationHint):
Set a per-isolate hint to signal a low memory condition upon the next page navigation.
(WebCore::V8BindingPerIsolateData::clearLowMemoryNotificationHint):
Clear the previously set hint.
(WebCore::V8BindingPerIsolateData::isLowMemoryNotificationHint):
Get the previously set hint.
* bindings/v8/V8Proxy.cpp:
(WebCore::V8Proxy::hintForGCIfNecessary):
If necessary, send V8 a hint that it should GC.
(WebCore):
(WebCore::V8Proxy::clearForClose):
(WebCore::V8Proxy::clearForNavigation):
Call hintForGCIfNecessary.
* bindings/v8/V8Proxy.h:
(V8Proxy):
* bindings/v8/custom/V8HTMLCanvasElementCustom.cpp:
(WebCore::V8HTMLCanvasElement::getContextCallback):
Set a hint that we should GC upon the next page navigation.
LayoutTests:
This test doesn't directly exercise this code path yet, but it
needs to work regardless and also needs to be expanded.
* fast/canvas/webgl/context-creation-and-destruction-expected.txt: Added.
* fast/canvas/webgl/context-creation-and-destruction.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (123555 => 123556)
--- trunk/LayoutTests/ChangeLog 2012-07-25 00:28:46 UTC (rev 123555)
+++ trunk/LayoutTests/ChangeLog 2012-07-25 00:37:11 UTC (rev 123556)
@@ -1,3 +1,16 @@
+2012-07-24 Kenneth Russell <[email protected]>
+
+ [chromium] Hint garbage collector to run if page uses Canvas contexts
+ https://bugs.webkit.org/show_bug.cgi?id=76225
+
+ Reviewed by Kentaro Hara.
+
+ This test doesn't directly exercise this code path yet, but it
+ needs to work regardless and also needs to be expanded.
+
+ * fast/canvas/webgl/context-creation-and-destruction-expected.txt: Added.
+ * fast/canvas/webgl/context-creation-and-destruction.html: Added.
+
2012-07-24 Alexis Menard <[email protected]>
[Qt] svg/as-background-image rebaseline after new test fonts
Added: trunk/LayoutTests/fast/canvas/webgl/context-creation-and-destruction-expected.txt (0 => 123556)
--- trunk/LayoutTests/fast/canvas/webgl/context-creation-and-destruction-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/context-creation-and-destruction-expected.txt 2012-07-25 00:37:11 UTC (rev 123556)
@@ -0,0 +1,25 @@
+Test that contexts are freed and garbage collected reasonably
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+test 1 of 8
+PASS getError was expected value: NO_ERROR : Should be no errors
+test 2 of 8
+PASS getError was expected value: NO_ERROR : Should be no errors
+test 3 of 8
+PASS getError was expected value: NO_ERROR : Should be no errors
+test 4 of 8
+PASS getError was expected value: NO_ERROR : Should be no errors
+test 5 of 8
+PASS getError was expected value: NO_ERROR : Should be no errors
+test 6 of 8
+PASS getError was expected value: NO_ERROR : Should be no errors
+test 7 of 8
+PASS getError was expected value: NO_ERROR : Should be no errors
+test 8 of 8
+PASS getError was expected value: NO_ERROR : Should be no errors
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/canvas/webgl/context-creation-and-destruction.html (0 => 123556)
--- trunk/LayoutTests/fast/canvas/webgl/context-creation-and-destruction.html (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/context-creation-and-destruction.html 2012-07-25 00:37:11 UTC (rev 123556)
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href=""
+<script src=""
+<script src="" </script>
+<script src="" </script>
+</head>
+<body>
+<script>
+var wtu = WebGLTestUtils;
+// Ideally we would make this test run far longer, but we need to keep
+// it within a reasonable per-test timeout.
+var target = 8;
+var count = 0;
+
+if (window.initNonKhronosFramework) {
+ window.initNonKhronosFramework(true);
+}
+
+description('Test that contexts are freed and garbage collected reasonably');
+doNextTest();
+
+// Creates a canvas and some textures then exits. There are
+// no references to either so all should be garbage collected.
+function test() {
+ var canvas = document.createElement("canvas");
+ // This is safe for any device. See drawingBufferWidth in spec.
+ canvas.width = 2048;
+ canvas.height = 2048;
+ var gl = wtu.create3DContext(canvas);
+ var maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
+ var size = Math.min(1024, maxTextureSize);
+ for (var jj = 0; jj < 5; ++jj) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array(size * size * 4));
+ }
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
+}
+
+function doNextTest() {
+ ++count;
+ debug("test " + count + " of " + target);
+ test();
+ if (count < target) {
+ setTimeout(doNextTest, 100);
+ } else {
+ finishTest();
+ }
+}
+</script>
+
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (123555 => 123556)
--- trunk/Source/WebCore/ChangeLog 2012-07-25 00:28:46 UTC (rev 123555)
+++ trunk/Source/WebCore/ChangeLog 2012-07-25 00:37:11 UTC (rev 123556)
@@ -1,3 +1,47 @@
+2012-07-24 Kenneth Russell <[email protected]>
+
+ [chromium] Hint garbage collector to run if page uses Canvas contexts
+ https://bugs.webkit.org/show_bug.cgi?id=76225
+
+ Reviewed by Kentaro Hara.
+
+ Upon creating a canvas context, set a hint in the current isolate
+ indicating that a full GC should be done upon the next page
+ navigation.
+
+ This improves Chrome's robustness on some WebGL stress tests which
+ simulate real-world behavior by repeatedly navigating among
+ several samples. More general measures are being investigated, but
+ this change makes V8 behave the same as JSC on these stress tests.
+ JSC doesn't currently use generational garbage collection, so it
+ has more opportunities to discover unreferenced canvas contexts.
+
+ Test: fast/canvas/webgl/context-creation-and-destruction.html
+
+ * bindings/v8/V8Binding.cpp:
+ (WebCore::V8BindingPerIsolateData::V8BindingPerIsolateData):
+ Initialize per-isolate low memory hint.
+ * bindings/v8/V8Binding.h:
+ (V8BindingPerIsolateData):
+ (WebCore::V8BindingPerIsolateData::setLowMemoryNotificationHint):
+ Set a per-isolate hint to signal a low memory condition upon the next page navigation.
+ (WebCore::V8BindingPerIsolateData::clearLowMemoryNotificationHint):
+ Clear the previously set hint.
+ (WebCore::V8BindingPerIsolateData::isLowMemoryNotificationHint):
+ Get the previously set hint.
+ * bindings/v8/V8Proxy.cpp:
+ (WebCore::V8Proxy::hintForGCIfNecessary):
+ If necessary, send V8 a hint that it should GC.
+ (WebCore):
+ (WebCore::V8Proxy::clearForClose):
+ (WebCore::V8Proxy::clearForNavigation):
+ Call hintForGCIfNecessary.
+ * bindings/v8/V8Proxy.h:
+ (V8Proxy):
+ * bindings/v8/custom/V8HTMLCanvasElementCustom.cpp:
+ (WebCore::V8HTMLCanvasElement::getContextCallback):
+ Set a hint that we should GC upon the next page navigation.
+
2012-07-24 Dave Tu <[email protected]>
[chromium] Add time spent painting to GPU benchmarking renderingStats() API.
Modified: trunk/Source/WebCore/bindings/v8/V8Binding.cpp (123555 => 123556)
--- trunk/Source/WebCore/bindings/v8/V8Binding.cpp 2012-07-25 00:28:46 UTC (rev 123555)
+++ trunk/Source/WebCore/bindings/v8/V8Binding.cpp 2012-07-25 00:37:11 UTC (rev 123556)
@@ -60,6 +60,7 @@
#ifndef NDEBUG
, m_internalScriptRecursionLevel(0)
#endif
+ , m_lowMemoryNotificationHint(false)
{
}
Modified: trunk/Source/WebCore/bindings/v8/V8Binding.h (123555 => 123556)
--- trunk/Source/WebCore/bindings/v8/V8Binding.h 2012-07-25 00:28:46 UTC (rev 123555)
+++ trunk/Source/WebCore/bindings/v8/V8Binding.h 2012-07-25 00:37:11 UTC (rev 123556)
@@ -220,6 +220,14 @@
void reportMemoryUsage(MemoryObjectInfo*) const;
+ // Gives the system a hint that we should send a low memory
+ // notification upon the next close or navigation event,
+ // because some expensive objects have been allocated that we
+ // want to take every opportunity to collect.
+ void setLowMemoryNotificationHint() { m_lowMemoryNotificationHint = true; }
+ void clearLowMemoryNotificationHint() { m_lowMemoryNotificationHint = false; }
+ bool isLowMemoryNotificationHint() const { return m_lowMemoryNotificationHint; }
+
private:
explicit V8BindingPerIsolateData(v8::Isolate*);
~V8BindingPerIsolateData();
@@ -248,6 +256,8 @@
int m_internalScriptRecursionLevel;
#endif
GCEventData m_gcEventData;
+
+ bool m_lowMemoryNotificationHint;
};
class ConstructorMode {
Modified: trunk/Source/WebCore/bindings/v8/V8Proxy.cpp (123555 => 123556)
--- trunk/Source/WebCore/bindings/v8/V8Proxy.cpp 2012-07-25 00:28:46 UTC (rev 123555)
+++ trunk/Source/WebCore/bindings/v8/V8Proxy.cpp 2012-07-25 00:37:11 UTC (rev 123556)
@@ -559,15 +559,26 @@
m_isolatedWorldSecurityOrigins.clear();
}
+void V8Proxy::hintForGCIfNecessary()
+{
+ V8BindingPerIsolateData* data = ""
+ if (data->isLowMemoryNotificationHint()) {
+ data->clearLowMemoryNotificationHint();
+ v8::V8::LowMemoryNotification();
+ }
+}
+
void V8Proxy::clearForClose()
{
resetIsolatedWorlds();
+ hintForGCIfNecessary();
windowShell()->clearForClose();
}
void V8Proxy::clearForNavigation()
{
resetIsolatedWorlds();
+ hintForGCIfNecessary();
windowShell()->clearForNavigation();
}
Modified: trunk/Source/WebCore/bindings/v8/V8Proxy.h (123555 => 123556)
--- trunk/Source/WebCore/bindings/v8/V8Proxy.h 2012-07-25 00:28:46 UTC (rev 123555)
+++ trunk/Source/WebCore/bindings/v8/V8Proxy.h 2012-07-25 00:37:11 UTC (rev 123556)
@@ -271,6 +271,8 @@
private:
void resetIsolatedWorlds();
+ void hintForGCIfNecessary();
+
PassOwnPtr<v8::ScriptData> precompileScript(v8::Handle<v8::String>, CachedScript*);
static const char* rangeExceptionName(int exceptionCode);
Modified: trunk/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp (123555 => 123556)
--- trunk/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp 2012-07-25 00:28:46 UTC (rev 123555)
+++ trunk/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp 2012-07-25 00:37:11 UTC (rev 123556)
@@ -86,6 +86,13 @@
CanvasRenderingContext* result = imp->getContext(contextId, attrs.get());
if (!result)
return v8::Null(args.GetIsolate());
+
+ // Both 2D and 3D canvas contexts can hold on to lots of GPU resources, and we
+ // want to take an opportunity to get rid of them as soon as possible when we
+ // navigate away from pages using them.
+ V8BindingPerIsolateData* perIsolateData = V8BindingPerIsolateData::current(args.GetIsolate());
+ perIsolateData->setLowMemoryNotificationHint();
+
if (result->is2d())
return toV8(static_cast<CanvasRenderingContext2D*>(result), args.GetIsolate());
#if ENABLE(WEBGL)