naming 2/2 - use naming_db_path provider
[hiphop-php.git] / hphp / hhbbc / debug.cpp
blob043275c4170b535813627dced3f8dfcc6c5e35f4
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #include "hphp/hhbbc/debug.h"
18 #include <string>
19 #include <utility>
20 #include <cstdlib>
21 #include <iostream>
23 #include <boost/filesystem/path.hpp>
24 #include <boost/filesystem/operations.hpp>
25 #include <boost/filesystem/fstream.hpp>
26 #include <algorithm>
27 #include <memory>
28 #include <vector>
30 #include <folly/portability/Stdlib.h>
32 #include "hphp/hhbbc/class-util.h"
33 #include "hphp/hhbbc/context.h"
34 #include "hphp/hhbbc/misc.h"
35 #include "hphp/hhbbc/parallel.h"
37 namespace HPHP { namespace HHBBC {
39 namespace fs = boost::filesystem;
41 //////////////////////////////////////////////////////////////////////
43 namespace {
45 const StaticString s_invoke("__invoke");
47 template<class Operation>
48 void with_file(fs::path dir, const php::Unit* u, Operation op) {
49 auto const file = dir / fs::path(u->filename->data());
50 fs::create_directories(fs::path(file).remove_filename());
52 fs::ofstream out(file);
53 if (!out.is_open()) {
54 throw std::runtime_error(std::string("failed to open file ") +
55 file.string());
58 op(out);
60 if (out.bad()) {
61 throw std::runtime_error(std::string("couldn't write file ") +
62 file.string());
66 using NameTy = std::pair<SString,PropStateElem<>>;
67 std::vector<NameTy> sorted_prop_state(const PropState& ps) {
68 std::vector<NameTy> ret(begin(ps), end(ps));
69 std::sort(
70 begin(ret), end(ret),
71 [&] (NameTy a, NameTy b) { return a.first->compare(b.first) < 0; }
73 return ret;
76 void dump_class_state(std::ostream& out,
77 const Index& index,
78 const php::Class* c) {
79 auto const clsName = normalized_class_name(*c);
81 if (is_closure(*c)) {
82 auto const invoke = find_method(c, s_invoke.get());
83 auto const useVars = index.lookup_closure_use_vars(invoke);
84 for (auto i = size_t{0}; i < useVars.size(); ++i) {
85 out << clsName << "->" << c->properties[i].name->data() << " :: "
86 << show(useVars[i]) << '\n';
88 } else {
89 auto const pprops = sorted_prop_state(
90 index.lookup_private_props(c)
92 for (auto const& kv : pprops) {
93 out << clsName << "->" << kv.first->data() << " :: "
94 << show(kv.second.ty) << '\n';
97 auto const sprops = sorted_prop_state(
98 index.lookup_private_statics(c)
100 for (auto const& kv : sprops) {
101 out << clsName << "::$" << kv.first->data() << " :: "
102 << show(kv.second.ty) << '\n';
105 for (auto const& prop : c->properties) {
106 out << clsName << "::$" << prop.name->data() << " :: "
107 << show(index.lookup_public_static(Context{}, c, prop.name)) << '\n';
111 for (auto const& constant : c->constants) {
112 if (constant.val) {
113 auto const ty = from_cell(*constant.val);
114 out << clsName << "::" << constant.name->data() << " :: "
115 << (ty.subtypeOf(BUninit) ? "<dynamic>" : show(ty)) << '\n';
120 void dump_func_state(std::ostream& out,
121 const Index& index,
122 const php::Func* f) {
123 if (f->unit->pseudomain.get() == f) return;
125 auto const name = f->cls
126 ? folly::sformat(
127 "{}::{}()",
128 normalized_class_name(*f->cls), f->name->data()
130 : folly::sformat("{}()", f->name->toCppString());
132 auto const retTy = index.lookup_return_type_raw(f);
133 out << name << " :: " << show(retTy) << '\n';
138 //////////////////////////////////////////////////////////////////////
140 std::string debug_dump_to() {
141 if (!Trace::moduleEnabledRelease(Trace::hhbbc_dump, 1)) return "";
143 trace_time tracer("debug dump");
145 auto dir = [&]{
146 if (auto const dumpDir = getenv("HHBBC_DUMP_DIR")) {
147 return fs::path(dumpDir);
148 } else {
149 char dirBuf[] = "/tmp/hhbbcXXXXXX";
150 auto const dtmpRet = mkdtemp(dirBuf);
151 if (!dtmpRet) {
152 throw std::runtime_error(
153 std::string("Failed to create temporary directory") +
154 strerror(errno));
156 return fs::path(dtmpRet);
158 }();
159 fs::create_directory(dir);
161 Trace::ftraceRelease("debug dump going to {}\n", dir.string());
162 return dir.string();
165 void dump_representation(const std::string& dir, const php::Unit* unit) {
166 auto const rep_dir = fs::path{dir} / "representation";
167 with_file(rep_dir, unit, [&] (std::ostream& out) {
168 out << show(*unit, true);
173 void dump_index(const std::string& dir,
174 const Index& index,
175 const php::Unit* unit) {
176 if (!*unit->filename->data()) {
177 // The native systemlibs: for now just skip.
178 return;
181 auto ind_dir = fs::path{dir} / "index";
183 with_file(ind_dir, unit, [&] (std::ostream& out) {
184 for (auto& c : unit->classes) {
185 dump_class_state(out, index, c.get());
186 for (auto& m : c->methods) {
187 dump_func_state(out, index, m.get());
191 for (auto& f : unit->funcs) {
192 dump_func_state(out, index, f.get());
198 void debug_dump_program(const Index& index, const php::Program& program) {
199 auto const dir = debug_dump_to();
200 if (dir.empty()) return;
202 if (Trace::moduleEnabledRelease(Trace::hhbbc_dump, 2)) {
203 trace_time tracer2("debug dump: representation");
204 parallel::for_each(
205 program.units,
206 [&] (const std::unique_ptr<php::Unit>& u) {
207 dump_representation(dir, u.get());
213 trace_time tracer2("debug dump: index");
214 parallel::for_each(
215 program.units,
216 [&] (const std::unique_ptr<php::Unit>& u) {
217 dump_index(dir, index, u.get());
222 Trace::ftraceRelease("debug dump done\n");
225 //////////////////////////////////////////////////////////////////////