Bug 469739 - Add support for displaying Vista UAC shield icon; r=joe sr=vladimir
[wine-gecko.git] / js / src / nanojit / TraceTreeDrawer.cpp
blob033139929b9a21d87ff53abbe9419c7053993e36
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is [Open Source Virtual Machine].
16 * The Initial Developer of the Original Code is
17 * Adobe System Incorporated.
18 * Portions created by the Initial Developer are Copyright (C) 2004-2007
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Adobe AS3 Team
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include <stdio.h>
39 #include "nanojit.h"
41 #define verbose_draw_only(x)
43 namespace nanojit {
45 #ifdef AVMPLUS_VERBOSE
46 using namespace avmplus;
48 TraceTreeDrawer::TraceTreeDrawer(Fragmento *frago, AvmCore *core, char *fileName) {
49 this->_frago = frago;
50 this->_core = core;
51 this->_labels = frago->labels;
52 this->_fileName = fileName;
55 TraceTreeDrawer::~TraceTreeDrawer() {
58 void TraceTreeDrawer::addNode(Fragment *fragment, const char *color) {
59 fprintf(_fstream, "<node id=\"%d\">\n"
60 "<data key=\"nodeGraphicsID\">\n"
61 "<y:ShapeNode>\n"
62 "<y:Shape type=\"roundrectangle\"/>\n"
63 "<y:NodeLabel alignment=\"center\">%s"
64 " %s" //fragment->ip
65 "</y:NodeLabel>\n"
66 "<y:Fill color=\"#%s\" transparent=\"false\"/>\n"
67 "</y:ShapeNode>\n"
68 "</data>\n"
69 "</node>\n",
70 (int)fragment,
71 _labels->format(fragment),
72 _labels->format(fragment->ip), color);
75 void TraceTreeDrawer::addNode(Fragment *fragment) {
76 if (!fragment->isAnchor())
77 addNode(fragment, "FFCC99"); // standard color
78 else
79 addNode(fragment, "CCFFFF"); // Root node
82 void TraceTreeDrawer::addEdge(Fragment *from, Fragment *to) {
83 this->addNode(from);
84 this->addNode(to);
86 // Create the edge
87 fprintf(_fstream, "<edge directed=\"true\" source=\"%d\" target=\"%d\">\n", (int)from, (int)to);
88 drawDirectedEdge();
89 fprintf(_fstream, "</edge>\n");
92 void TraceTreeDrawer::recursiveDraw(Fragment *root) {
93 if (!isCompiled(root)) {
94 return;
97 addBackEdges(root);
99 Fragment *lastDrawnBranch = root;
100 for (Fragment *treeBranch = root->branches; treeBranch != 0; treeBranch = treeBranch->nextbranch) {
101 if (!isMergeFragment(treeBranch)) {
102 struct SideExit* exit = treeBranch->spawnedFrom->exit();
103 if (isValidSideExit(exit) && isCompiled(treeBranch)) {
104 verbose_draw_only(printf("Adding edge between %s and %s\n", _labels->format(lastDrawnBranch), _labels->format(treeBranch)));
106 this->addEdge(lastDrawnBranch, treeBranch);
107 lastDrawnBranch = treeBranch;
110 recursiveDraw(treeBranch);
112 else {
113 addMergeNode(treeBranch);
114 } // end ifelse
115 } // end for loop
118 void TraceTreeDrawer::addBackEdges(Fragment *root) {
119 // At the end of a tree, find out where it goes
120 if (isCrossFragment(root)) {
121 if (root->eot_target) {
122 verbose_draw_only(printf("Found a cross fragment %s TO %s \n", _labels->format(root), _labels->format(root->eot_target)));
123 this->addEdge(root, root->eot_target);
126 else if (isBackEdgeSideExit(root)) {
127 verbose_draw_only(printf("Adding anchor branch edge from %s TO %s\n", _labels->format(root), _labels->format(root->anchor)));
128 this->addEdge(root, root->anchor);
130 else if (isSingleTrace(root)) {
131 verbose_draw_only(printf("Found a single trace %s\n", _labels->format(root)));
132 this->addEdge(root, root);
134 else if (isSpawnedTrace(root)) {
135 struct SideExit *exit = root->spawnedFrom->exit();
136 if (isValidSideExit(exit) && isCompiled(root)) {
137 verbose_draw_only(printf("Found a spawned side exit from %s that is a spawn and compiled %s\n", _labels->format(root), _labels->format(exit->from)));
138 this->addEdge(root, root->parent);
141 else if (hasEndOfTraceFrag(root)) {
142 verbose_draw_only(printf("%s has an EOT to %s\n", _labels->format(root), _labels->format(root->eot_target)));
143 addEdge(root, root->eot_target);
147 void TraceTreeDrawer::addMergeNode(Fragment *mergeRoot) {
148 verbose_draw_only(printf("Found a merge fragment %s and anchor %s\n", _labels->format(mergeRoot), _labels->format(mergeRoot->anchor)));
150 if (hasCompiledBranch(mergeRoot)) {
151 verbose_draw_only(printf("Found a branch to %s\n", _labels->format(mergeRoot->branches)));
152 addEdge(mergeRoot, mergeRoot->branches);
153 recursiveDraw(mergeRoot->branches);
156 if (hasEndOfTraceFrag(mergeRoot)) {
157 verbose_draw_only(printf("Merge with an EOT to %s\n", _labels->format(mergeRoot->eot_target)));
158 addEdge(mergeRoot, mergeRoot->eot_target);
160 else {
161 verbose_draw_only(printf("Merge to anchor %s\n", _labels->format(mergeRoot->anchor)));
162 addEdge(mergeRoot, mergeRoot->anchor);
166 void TraceTreeDrawer::draw(Fragment *root) {
167 this->recursiveDraw(root);
169 verbose_draw_only(printf("\nFinished drawing, printing status\n"));
170 verbose_draw_only(this->printTreeStatus(root));
173 void TraceTreeDrawer::createGraphHeader() {
174 char outputFileName[128];
175 const char *graphMLExtension = ".graphml";
177 int fileNameLength = strlen(this->_fileName);
178 memset(outputFileName, 0, sizeof(outputFileName));
179 strncat(outputFileName, this->_fileName, 128);
180 strncat(outputFileName + fileNameLength - 1, graphMLExtension, 128); // -1 to overwrite the \0
182 verbose_draw_only(printf("output file name is %s\n", outputFileName));
183 this->_fstream = fopen(outputFileName, "w");
185 fprintf(_fstream, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
186 "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns/graphml\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:y=\"http://www.yworks.com/xml/graphml\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns/graphml http://www.yworks.com/xml/schema/graphml/1.0/ygraphml.xsd\">\n"
187 "<key for=\"node\" id=\"nodeGraphicsID\" yfiles.type=\"nodegraphics\"/>\n"
188 "<key attr.name=\"description\" attr.type=\"string\" for=\"node\" id=\"nodeDescID\"/>\n"
189 "<key for=\"edge\" id=\"edgeGraphicsID\" yfiles.type=\"edgegraphics\"/>\n"
190 "<key attr.name=\"description\" attr.type=\"string\" for=\"edge\" id=\"edgeDescID\"/>\n"
191 "<graph edgedefault=\"directed\" id=\"rootGraph\">\n");
195 void TraceTreeDrawer::createGraphFooter() {
196 fprintf(_fstream, " </graph></graphml>");
197 fclose(this->_fstream);
200 bool TraceTreeDrawer::isValidSideExit(struct SideExit *exit) {
201 return exit != 0;
204 bool TraceTreeDrawer::isCompiled(Fragment *f) {
205 return f->compileNbr != 0;
208 bool TraceTreeDrawer::isLoopFragment(Fragment *f) {
209 return f->kind == LoopTrace;
212 bool TraceTreeDrawer::isCrossFragment(Fragment *f) {
213 return f->kind == BranchTrace;
216 bool TraceTreeDrawer::isMergeFragment(Fragment *f) {
217 return f->kind == MergeTrace;
220 bool TraceTreeDrawer::isSingleTrace(Fragment *f) {
221 return f->isAnchor() && !hasCompiledBranch(f);
224 bool TraceTreeDrawer::hasCompiledBranch(Fragment *f) {
225 for (Fragment *current = f->branches; current != 0; current = current->nextbranch) {
226 if (isCompiled(current)) {
227 return true;
231 return false;
234 bool TraceTreeDrawer::isSpawnedTrace(Fragment *f) {
235 return f->spawnedFrom != 0;
238 bool TraceTreeDrawer::isBackEdgeSideExit(Fragment *f) {
239 return !f->branches && !f->isAnchor();
242 bool TraceTreeDrawer::hasEndOfTraceFrag(Fragment *f) {
243 return (f->eot_target) && (f != f->eot_target);
246 void TraceTreeDrawer::drawDirectedEdge() {
247 // Make it directed
248 fprintf(_fstream, "<data key=\"edgeGraphicsID\">\n"
249 "<y:PolyLineEdge>\n"
250 "<y:Arrows source=\"none\" target=\"standard\"/>\n"
251 "</y:PolyLineEdge>\n"
252 "</data>\n");
255 void TraceTreeDrawer::printTreeStatus(Fragment *root) {
256 if (!isCompiled(root)) {
257 return;
260 printf("\nRoot is %s\n", _labels->format(root));
261 if (root->spawnedFrom) {
262 if (root->compileNbr) {
263 printf("Found a root that is a spawn and compiled %s\n", _labels->format(root->parent));
267 for (Fragment *x = root->branches; x != 0; x = x->nextbranch) {
268 if (x->kind != MergeTrace) {
269 struct SideExit* exit = x->spawnedFrom->exit();
270 if (exit && x->compileNbr) {
271 printf("Found one with an SID and compiled %s\n", _labels->format(x));
274 printTreeStatus(x);
277 printf("\n");
279 #endif
283 void drawTraceTrees(nanojit::Fragmento *frago, nanojit::FragmentMap * _frags, avmplus::AvmCore *core, char *fileName) {
284 #ifdef AVMPLUS_VERBOSE
285 nanojit::TraceTreeDrawer *traceDrawer = new (core->gc) nanojit::TraceTreeDrawer(frago, core, fileName);
286 traceDrawer->createGraphHeader();
288 int32_t count = _frags->size();
289 for (int32_t i=0; i<count; i++)
291 Fragment *frag = _frags->at(i);
292 // Count only fragments which have something compiled. Needs the -Dverbose flag
293 if (frag->compileNbr) {
294 traceDrawer->draw(frag);
298 traceDrawer->createGraphFooter();
299 #else
300 (void)frago;
301 (void)_frags;
302 (void)core;
303 (void)fileName;
304 #endif