Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(695)

Unified Diff: runtime/observatory/lib/src/elements/script_inset.dart

Issue 1087833005: Add annotation for function declarations. Mark functions with performance problems in red. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | runtime/observatory/lib/src/elements/script_inset.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/observatory/lib/src/elements/script_inset.dart
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index 1f57b2abeb9a4eb4bba5658204d982d620e992f9..024d1602ab4b64b9753df9c3b9be8af78fa0db19 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -13,53 +13,59 @@ import 'package:polymer/polymer.dart';
const nbsp = "\u00A0";
-void addInfoBox(content, infoBox) {
- infoBox.style.position = 'absolute';
- infoBox.style.padding = '1em';
- infoBox.style.border = 'solid black 2px';
- infoBox.style.zIndex = '10';
- infoBox.style.backgroundColor = 'white';
- infoBox.style.cursor = 'auto';
- infoBox.style.display = 'none'; // Initially hidden.
-
+void addInfoBox(Element content, Function infoBoxGenerator) {
+ var infoBox;
var show = false;
+ var originalBackground = content.style.backgroundColor;
+ buildInfoBox() {
+ infoBox = infoBoxGenerator();
+ infoBox.style.position = 'absolute';
+ infoBox.style.padding = '1em';
+ infoBox.style.border = 'solid black 2px';
+ infoBox.style.zIndex = '10';
+ infoBox.style.backgroundColor = 'white';
+ infoBox.style.cursor = 'auto';
+ content.append(infoBox);
+ }
content.onClick.listen((event) {
show = !show;
+ if (infoBox == null) buildInfoBox(); // Created lazily on the first click.
infoBox.style.display = show ? 'block' : 'none';
- content.style.backgroundColor = show ? 'white' : '';
+ content.style.backgroundColor = show ? 'white' : originalBackground;
});
// Causes infoBox to be positioned relative to the bottom-left of content.
content.style.display = 'inline-block';
content.style.cursor = 'pointer';
- content.append(infoBox);
}
-abstract class Annotation {
+abstract class Annotation implements Comparable<Annotation> {
int line;
int columnStart;
int columnStop;
void applyStyleTo(element);
-}
-class CurrentExecutionAnnotation extends Annotation {
- void applyStyleTo(element) {
- if (element == null) {
- return; // TODO(rmacnak): Handling overlapping annotations.
+ int compareTo(Annotation other) {
+ if (line == other.line) {
+ return columnStart.compareTo(other.columnStart);
}
- element.classes.add("currentCol");
- element.title = "Current execution";
+ return line.compareTo(other.line);
}
-}
-class CallSiteAnnotation extends Annotation {
- CallSite callSite;
+ Element table() {
+ var e = new DivElement();
+ e.style.display = "table";
+ e.style.color = "#333";
+ e.style.font = "400 14px 'Montserrat', sans-serif";
+ return e;
+ }
Element row([content]) {
var e = new DivElement();
e.style.display = "table-row";
if (content is String) e.text = content;
+ if (content is Element) e.children.add(content);
return e;
}
@@ -77,32 +83,88 @@ class CallSiteAnnotation extends Annotation {
e.ref = object;
return e;
}
+}
- Element entriesTable() {
- var e = new DivElement();
- e.style.display = "table";
- e.style.color = "#333";
- e.style.font = "400 14px 'Montserrat', sans-serif";
+class CurrentExecutionAnnotation extends Annotation {
+ void applyStyleTo(element) {
+ if (element == null) {
+ return; // TODO(rmacnak): Handling overlapping annotations.
+ }
+ element.classes.add("currentCol");
+ element.title = "Current execution";
+ }
+}
- if (callSite.entries.isEmpty) {
- e.append(row('Did not execute'));
- } else {
- var r = row();
- r.append(cell("Container"));
- r.append(cell("Count"));
- r.append(cell("Target"));
- e.append(r);
+class CallSiteAnnotation extends Annotation {
+ CallSite callSite;
+
+ CallSiteAnnotation(this.callSite) {
+ line = callSite.line;
+ columnStart = callSite.column - 1; // Call site is 1-origin.
+ var tokenLength = callSite.name.length; // Approximate.
+ if (callSite.name.startsWith("get:") ||
+ callSite.name.startsWith("set:")) tokenLength -= 4;
+ columnStop = columnStart + tokenLength;
+ }
+
+ void applyStyleTo(element) {
+ if (element == null) {
+ return; // TODO(rmacnak): Handling overlapping annotations.
+ }
+ element.style.fontWeight = "bold";
+ element.title = "Call site: ${callSite.name}";
- for (var entry in callSite.entries) {
+ addInfoBox(element, () {
+ var details = table();
+ if (callSite.entries.isEmpty) {
+ details.append(row('Did not execute'));
+ } else {
var r = row();
- r.append(cell(serviceRef(entry.receiverContainer)));
- r.append(cell(entry.count.toString()));
- r.append(cell(serviceRef(entry.target)));
- e.append(r);
+ r.append(cell("Container"));
+ r.append(cell("Count"));
+ r.append(cell("Target"));
+ details.append(r);
+
+ for (var entry in callSite.entries) {
+ var r = row();
+ r.append(cell(serviceRef(entry.receiverContainer)));
+ r.append(cell(entry.count.toString()));
+ r.append(cell(serviceRef(entry.target)));
+ details.append(r);
+ }
}
- }
+ return details;
+ });
+ }
+}
- return e;
+
+class FunctionDeclarationAnnotation extends Annotation {
+ ServiceFunction function;
+
+ FunctionDeclarationAnnotation(this.function) {
+ assert(function.loaded);
+ var script = function.script;
+ line = script.tokenToLine(function.tokenPos);
+ columnStart = script.tokenToCol(function.tokenPos);
+ if ((line == null) || (columnStart == null)) {
+ line = 0;
+ columnStart = 0;
+ columnStop = 0;
+ } else {
+ columnStart--; // 1-origin -> 0-origin.
+
+ // The method's token position is at the beginning of the method
+ // declaration, which may be a return type annotation, metadata, static
+ // modifier, etc. Try to scan forward to position this annotation on the
+ // function's name instead.
+ var lineSource = script.getLine(line).text;
+ var betterStart = lineSource.indexOf(function.name, columnStart);
+ if (betterStart != -1) {
+ columnStart = betterStart;
+ }
+ columnStop = columnStart + function.name.length;
+ }
}
void applyStyleTo(element) {
@@ -110,9 +172,37 @@ class CallSiteAnnotation extends Annotation {
return; // TODO(rmacnak): Handling overlapping annotations.
}
element.style.fontWeight = "bold";
- element.title = "Call site: ${callSite.name}";
+ element.title = "Function declaration: ${function.name}";
+
+ if (function.isOptimizable == false ||
+ function.isInlinable == false ||
+ function.deoptimizations >0) {
+ element.style.backgroundColor = "red";
+ }
+
+ addInfoBox(element, () {
+ var details = table();
+ var r = row();
+ r.append(cell("Function"));
+ r.append(cell(serviceRef(function)));
+ details.append(r);
- addInfoBox(element, entriesTable());
+ r = row();
+ r.append(cell("Usage Count"));
+ r.append(cell("${function.usageCounter}"));
+ details.append(r);
+
+ if (function.isOptimizable == false) {
+ details.append(row(cell("Unoptimizable!")));
+ }
+ if (function.isInlinable == false) {
+ details.append(row(cell("Not inlinable!")));
+ }
+ if (function.deoptimizations > 0) {
+ details.append(row("Deoptimized ${function.deoptimizations} times!"));
+ }
+ return details;
+ });
}
}
@@ -226,6 +316,21 @@ class ScriptInsetElement extends ObservatoryElement {
container.children.add(table);
}
+ void loadFunctionsOf(Library lib) {
+ lib.load().then((lib) {
+ for (var func in lib.functions) {
+ func.load();
+ }
+ for (var cls in lib.classes) {
+ cls.load().then((cls) {
+ for (var func in cls.functions) {
+ func.load();
+ }
+ });
+ }
+ });
+ }
+
void computeAnnotations() {
startLine = (startPos != null
? script.tokenToLine(startPos)
@@ -249,22 +354,26 @@ class ScriptInsetElement extends ObservatoryElement {
annotations.add(a);
}
+ loadFunctionsOf(script.library);
+
+ for (var func in script.library.functions) {
+ if (func.script == script) {
+ annotations.add(new FunctionDeclarationAnnotation(func));
+ }
+ }
+ for (var cls in script.library.classes) {
+ for (var func in cls.functions) {
+ if (func.script == script) {
+ annotations.add(new FunctionDeclarationAnnotation(func));
+ }
+ }
+ }
+
for (var callSite in script.callSites) {
- var a = new CallSiteAnnotation();
- a.line = callSite.line;
- a.columnStart = callSite.column - 1; // Call site is 1-origin.
- var tokenLength = callSite.name.length; // Approximate.
- a.columnStop = a.columnStart + tokenLength;
- a.callSite = callSite;
- annotations.add(a);
+ annotations.add(new CallSiteAnnotation(callSite));
}
- annotations.sort((a, b) {
- if (a.line == b.line) {
- return a.columnStart.compareTo(b.columnStart);
- }
- return a.line.compareTo(b.line);
- });
+ annotations.sort();
}
Element linesTable() {
@@ -322,8 +431,59 @@ class ScriptInsetElement extends ObservatoryElement {
}
Element lineBreakpointElement(ScriptLine line) {
- BreakpointToggleElement e = new Element.tag("breakpoint-toggle");
- e.line = line;
+ var e = new DivElement();
+ var busy = false;
+ if (line == null || !line.possibleBpt) {
+ e.classes.add("emptyBreakpoint");
+ e.text = nbsp;
+ return e;
+ }
+ e.text = 'B';
+ update() {
+ if (busy) {
+ e.classes.clear();
+ e.classes.add("busyBreakpoint");
+ } else {
+ if (line.breakpoints != null) {
+ if (line.breakpointResolved) {
+ e.classes.clear();
+ e.classes.add("resolvedBreakpoint");
+ } else {
+ e.classes.clear();
+ e.classes.add("unresolvedBreakpoint");
+ }
+ } else {
+ e.classes.clear();
+ e.classes.add("possibleBreakpoint");
+ }
+ }
+ }
+ line.changes.listen((_) => update());
+ e.onClick.listen((event) {
+ if (busy) {
+ return;
+ }
+ busy = true;
+ if (line.breakpoints == null) {
+ // No breakpoint. Add it.
+ line.script.isolate.addBreakpoint(line.script, line.line).then((_) {
+ busy = false;
+ update();
+ });
+ } else {
+ // Existing breakpoint. Remove it.
+ List pending = [];
+ for (var bpt in line.breakpoints) {
+ pending.add(line.script.isolate.removeBreakpoint(bpt));
+ }
+ Future.wait(pending).then((_) {
+ busy = false;
+ update();
+ });
+ }
+ update();
+ });
+ update();
return e;
}
@@ -384,33 +544,3 @@ class ScriptInsetElement extends ObservatoryElement {
ScriptInsetElement.created() : super.created();
}
-
-@CustomTag('breakpoint-toggle')
-class BreakpointToggleElement extends ObservatoryElement {
- @published ScriptLine line;
- @observable bool busy = false;
-
- void toggleBreakpoint(var a, var b, var c) {
- if (busy) {
- return;
- }
- busy = true;
- if (line.breakpoints == null) {
- // No breakpoint. Add it.
- line.script.isolate.addBreakpoint(line.script, line.line).then((_) {
- busy = false;
- });
- } else {
- // Existing breakpoint. Remove it.
- List pending = [];
- for (var bpt in line.breakpoints) {
- pending.add(line.script.isolate.removeBreakpoint(bpt));
- }
- Future.wait(pending).then((_) {
- busy = false;
- });
- }
- }
-
- BreakpointToggleElement.created() : super.created();
-}
« no previous file with comments | « no previous file | runtime/observatory/lib/src/elements/script_inset.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698