2011-03-10  Greg Simon  <gregsimon@chromium.org>

        Reviewed by Pavel Feldman.

        Web Inspector: Need new graphic icon for garbage collect button.
        https://bugs.webkit.org/show_bug.cgi?id=55794

        No new tests: gc tests are flaky due to non-determinisic
        behavior of collection APIs (more notes in bug)

        * English.lproj/localizedStrings.js:
        * WebCore.gypi:
        * bindings/js/ScriptProfiler.cpp:
        (WebCore::ScriptProfiler::collectGarbage):
        * bindings/js/ScriptProfiler.h:
        * bindings/v8/ScriptProfiler.cpp:
        (WebCore::ScriptProfiler::collectGarbage):
        * bindings/v8/ScriptProfiler.h:
        * inspector/Inspector.idl:
        * inspector/InspectorProfilerAgent.cpp:
        (WebCore::InspectorProfilerAgent::collectGarbage):
        * inspector/InspectorProfilerAgent.h:
        * inspector/front-end/Images/garbageCollectButtonGlyph.png: Added.
        * inspector/front-end/TimelinePanel.js:
        (WebInspector.TimelinePanel.prototype.get statusBarItems):
        (WebInspector.TimelinePanel.prototype._createStatusbarButtons):
        (WebInspector.TimelinePanel.prototype._garbageCollectButtonClicked):
        * inspector/front-end/inspector.css:
        (.garbage-collect-status-bar-item .glyph):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@80723 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 46bb3b3..47cbce2 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,33 @@
+2011-03-10  Greg Simon  <gregsimon@chromium.org>
+
+        Reviewed by Pavel Feldman.
+
+        Web Inspector: Need new graphic icon for garbage collect button.
+        https://bugs.webkit.org/show_bug.cgi?id=55794
+
+        No new tests: gc tests are flaky due to non-determinisic
+        behavior of collection APIs (more notes in bug)
+
+        * English.lproj/localizedStrings.js:
+        * WebCore.gypi:
+        * bindings/js/ScriptProfiler.cpp:
+        (WebCore::ScriptProfiler::collectGarbage):
+        * bindings/js/ScriptProfiler.h:
+        * bindings/v8/ScriptProfiler.cpp:
+        (WebCore::ScriptProfiler::collectGarbage):
+        * bindings/v8/ScriptProfiler.h:
+        * inspector/Inspector.idl:
+        * inspector/InspectorProfilerAgent.cpp:
+        (WebCore::InspectorProfilerAgent::collectGarbage):
+        * inspector/InspectorProfilerAgent.h:
+        * inspector/front-end/Images/garbageCollectButtonGlyph.png: Added.
+        * inspector/front-end/TimelinePanel.js:
+        (WebInspector.TimelinePanel.prototype.get statusBarItems):
+        (WebInspector.TimelinePanel.prototype._createStatusbarButtons):
+        (WebInspector.TimelinePanel.prototype._garbageCollectButtonClicked):
+        * inspector/front-end/inspector.css:
+        (.garbage-collect-status-bar-item .glyph):
+
 2011-03-10  Andrey Kosyakov  <caseq@chromium.org>
 
         Web Inspector: better names for HAR export commands
diff --git a/Source/WebCore/English.lproj/localizedStrings.js b/Source/WebCore/English.lproj/localizedStrings.js
index d3e5c8e..40c8206 100644
--- a/Source/WebCore/English.lproj/localizedStrings.js
+++ b/Source/WebCore/English.lproj/localizedStrings.js
Binary files differ
diff --git a/Source/WebCore/WebCore.gypi b/Source/WebCore/WebCore.gypi
index 875d95e..c8313b9 100644
--- a/Source/WebCore/WebCore.gypi
+++ b/Source/WebCore/WebCore.gypi
@@ -5337,6 +5337,7 @@
             'inspector/front-end/Images/graphLabelCalloutRight.png',
             'inspector/front-end/Images/helpButtonGlyph.png',
             'inspector/front-end/Images/largerResourcesButtonGlyph.png',
+            'inspector/front-end/Images/garbageCollectButtonGlyph.png',
             'inspector/front-end/Images/localStorage.png',
             'inspector/front-end/Images/networkIcon.png',
             'inspector/front-end/Images/nodeSearchButtonGlyph.png',
diff --git a/Source/WebCore/bindings/js/ScriptProfiler.cpp b/Source/WebCore/bindings/js/ScriptProfiler.cpp
index f372c3c..3468ae3 100644
--- a/Source/WebCore/bindings/js/ScriptProfiler.cpp
+++ b/Source/WebCore/bindings/js/ScriptProfiler.cpp
@@ -30,11 +30,17 @@
 
 #include "ScriptProfiler.h"
 
+#include "GCController.h"
 #include "JSDOMBinding.h"
 #include <profiler/Profiler.h>
 
 namespace WebCore {
 
+void ScriptProfiler::collectGarbage()
+{
+    gcController().garbageCollectNow();
+}
+
 void ScriptProfiler::start(ScriptState* state, const String& title)
 {
     JSC::Profiler::profiler()->startProfiling(state, stringToUString(title));
diff --git a/Source/WebCore/bindings/js/ScriptProfiler.h b/Source/WebCore/bindings/js/ScriptProfiler.h
index d8ad482..05d5e92 100644
--- a/Source/WebCore/bindings/js/ScriptProfiler.h
+++ b/Source/WebCore/bindings/js/ScriptProfiler.h
@@ -47,6 +47,7 @@
         virtual bool isCanceled() = 0;
     };
 
+    static void collectGarbage();
     static void start(ScriptState* state, const String& title);
     static PassRefPtr<ScriptProfile> stop(ScriptState* state, const String& title);
     static PassRefPtr<ScriptHeapSnapshot> takeHeapSnapshot(const String&, HeapSnapshotProgress*) { return 0; }
diff --git a/Source/WebCore/bindings/v8/ScriptProfiler.cpp b/Source/WebCore/bindings/v8/ScriptProfiler.cpp
index 615dcfc..c210a5d 100644
--- a/Source/WebCore/bindings/v8/ScriptProfiler.cpp
+++ b/Source/WebCore/bindings/v8/ScriptProfiler.cpp
@@ -53,6 +53,14 @@
     return profile ? ScriptProfile::create(profile) : 0;
 }
 
+void ScriptProfiler::collectGarbage()
+{
+    // NOTE : There is currently no direct way to collect memory from the v8 C++ API
+    // but notifying low-memory forces a mark-compact, which is exactly what we want
+    // in this case.
+    v8::V8::LowMemoryNotification();
+}
+
 namespace {
 
 class ActivityControlAdapter : public v8::ActivityControl {
diff --git a/Source/WebCore/bindings/v8/ScriptProfiler.h b/Source/WebCore/bindings/v8/ScriptProfiler.h
index 9016668..9103f0c 100644
--- a/Source/WebCore/bindings/v8/ScriptProfiler.h
+++ b/Source/WebCore/bindings/v8/ScriptProfiler.h
@@ -53,6 +53,7 @@
         virtual bool isCanceled() = 0;
     };
 
+    static void collectGarbage();
     static void start(ScriptState* state, const String& title);
     static PassRefPtr<ScriptProfile> stop(ScriptState* state, const String& title);
     static PassRefPtr<ScriptHeapSnapshot> takeHeapSnapshot(const String& title, HeapSnapshotProgress*);
diff --git a/Source/WebCore/inspector/Inspector.idl b/Source/WebCore/inspector/Inspector.idl
index 3b4cfbd..9a2b7e1 100644
--- a/Source/WebCore/inspector/Inspector.idl
+++ b/Source/WebCore/inspector/Inspector.idl
@@ -271,6 +271,7 @@
         // FIXME: split into Profiler and HeapProfiler.
         void takeHeapSnapshot(in boolean detailed);
         void getExactHeapSnapshotNodeRetainedSize(in unsigned long uid, in unsigned long nodeId, out long size);
+        void collectGarbage();
         [event] void addProfileHeader(out Object header);
         [event] void addHeapSnapshotChunk(out unsigned long uid, out String chunk);
         [event] void finishHeapSnapshot(out unsigned long uid);
diff --git a/Source/WebCore/inspector/InspectorProfilerAgent.cpp b/Source/WebCore/inspector/InspectorProfilerAgent.cpp
index 8867023..d304c2c 100644
--- a/Source/WebCore/inspector/InspectorProfilerAgent.cpp
+++ b/Source/WebCore/inspector/InspectorProfilerAgent.cpp
@@ -40,6 +40,7 @@
 #include "InstrumentingAgents.h"
 #include "KURL.h"
 #include "Page.h"
+#include "ScriptController.h"
 #include "ScriptDebugServer.h"
 #include "ScriptHeapSnapshot.h"
 #include "ScriptProfile.h"
@@ -108,6 +109,11 @@
     m_consoleAgent->addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
 }
 
+void InspectorProfilerAgent::collectGarbage(WebCore::ErrorString*)
+{
+    ScriptProfiler::collectGarbage();
+}
+
 PassRefPtr<InspectorObject> InspectorProfilerAgent::createProfileHeader(const ScriptProfile& profile)
 {
     RefPtr<InspectorObject> header = InspectorObject::create();
diff --git a/Source/WebCore/inspector/InspectorProfilerAgent.h b/Source/WebCore/inspector/InspectorProfilerAgent.h
index 839d801..76ecc79 100644
--- a/Source/WebCore/inspector/InspectorProfilerAgent.h
+++ b/Source/WebCore/inspector/InspectorProfilerAgent.h
@@ -61,6 +61,7 @@
     void addProfile(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL);
     void addProfileFinishedMessageToConsole(PassRefPtr<ScriptProfile>, unsigned lineNumber, const String& sourceURL);
     void addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL);
+    void collectGarbage(ErrorString*);
     void clearProfiles(ErrorString*) { resetState(); }
     void disable();
     void enable(bool skipRecompile);
diff --git a/Source/WebCore/inspector/front-end/Images/garbageCollectButtonGlyph.png b/Source/WebCore/inspector/front-end/Images/garbageCollectButtonGlyph.png
new file mode 100644
index 0000000..ffa9e66
--- /dev/null
+++ b/Source/WebCore/inspector/front-end/Images/garbageCollectButtonGlyph.png
Binary files differ
diff --git a/Source/WebCore/inspector/front-end/TimelinePanel.js b/Source/WebCore/inspector/front-end/TimelinePanel.js
index 62c5de0..dd8963a 100644
--- a/Source/WebCore/inspector/front-end/TimelinePanel.js
+++ b/Source/WebCore/inspector/front-end/TimelinePanel.js
@@ -147,7 +147,7 @@
 
     get statusBarItems()
     {
-        return [this.toggleFilterButton.element, this.toggleTimelineButton.element, this.clearButton.element, this._overviewPane.statusBarFilters];
+        return [this.toggleFilterButton.element, this.toggleTimelineButton.element, this.garbageCollectButton.element, this.clearButton.element, this._overviewPane.statusBarFilters];
     },
 
     get categories()
@@ -209,6 +209,9 @@
         this.toggleFilterButton = new WebInspector.StatusBarButton(this._hideShortRecordsTitleText, "timeline-filter-status-bar-item");
         this.toggleFilterButton.addEventListener("click", this._toggleFilterButtonClicked.bind(this), false);
 
+        this.garbageCollectButton = new WebInspector.StatusBarButton(WebInspector.UIString("Collect Garbage"), "garbage-collect-status-bar-item");
+        this.garbageCollectButton.addEventListener("click", this._garbageCollectButtonClicked.bind(this), false);
+
         this.recordsCounter = document.createElement("span");
         this.recordsCounter.className = "timeline-records-counter";
     },
@@ -284,6 +287,11 @@
         this.toggleFilterButton.element.title = this._calculator._showShortEvents ? this._hideShortRecordsTitleText : this._showShortRecordsTitleText;
         this._scheduleRefresh(true);
     },
+    
+    _garbageCollectButtonClicked: function()
+    {
+        ProfilerAgent.collectGarbage();
+    },
 
     _timelineProfilerWasStarted: function()
     {
diff --git a/Source/WebCore/inspector/front-end/WebKit.qrc b/Source/WebCore/inspector/front-end/WebKit.qrc
index 91d72d8..3a5ea51 100644
--- a/Source/WebCore/inspector/front-end/WebKit.qrc
+++ b/Source/WebCore/inspector/front-end/WebKit.qrc
@@ -174,6 +174,7 @@
     <file>Images/focusButtonGlyph.png</file>
     <file>Images/forward.png</file>
     <file>Images/frame.png</file>
+    <file>Images/garbageCollectButtonGlyph.png</file>
     <file>Images/gearButtonGlyph.png</file>
     <file>Images/glossyHeader.png</file>
     <file>Images/glossyHeaderPressed.png</file>
diff --git a/Source/WebCore/inspector/front-end/inspector.css b/Source/WebCore/inspector/front-end/inspector.css
index c1b7503..a24ab82 100644
--- a/Source/WebCore/inspector/front-end/inspector.css
+++ b/Source/WebCore/inspector/front-end/inspector.css
@@ -3935,6 +3935,10 @@
     background-color: rgb(66, 129, 235) !important;
 }
 
+.garbage-collect-status-bar-item .glyph {
+    -webkit-mask-image: url(Images/garbageCollectButtonGlyph.png);
+}
+
 .timeline-records-counter, .storage-application-cache-status, .storage-application-cache-connectivity {
     font-size: 11px;
     text-shadow: white 0 1px 0;