Arquivos
hhvm/hphp/util/trace.cpp
T
bsimmers b8ebb48421 Profile vector instruction shapes
This adds a new profiling mode for vector instruction
shapes. I'm planning on using this to identify any common cases that
may be worth special casing, like we do for simple SetM, CGetM, and
IssetM instructions. Instead of adding Yet Another Hashtable Stats
Map, I created a generic version and changed TRACE=punt:1 to use it as
well.

I also changed emitInterpOneOrPunt to use a more specific name.
2013-04-01 13:47:50 -07:00

154 linhas
4.0 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string>
/*
* Forcibly define USE_TRACE, so we get the debug trace.h interface included
* here. This allows mixed compilation, where some units were compiled
* DEBUG and others compiled RELEASE, to successfully link.
*/
#ifndef USE_TRACE
# define USE_TRACE 1
#endif
#include "util/trace.h"
#include "util/ringbuffer.h"
namespace HPHP {
static const Trace::Module TRACEMOD = Trace::tprefix;
namespace Trace {
int levels[NumModules];
static FILE* out;
const char *tokNames[] = {
#define TM(x) #x,
TRACE_MODULES
#undef TM
};
/*
* Dummy class to get some code to run before main().
*/
class Init {
Module name2mod(const char *name) {
for (int i = 0; i < NumModules; i++) {
if (!strcmp(tokNames[i], name)) {
return (Module)i;
}
}
return (Module)-1;
}
public:
Init() {
/* Parse the environment for flags. */
const char *envName = "TRACE";
const char *env = getenv(envName);
const char *file = getenv("HPHP_TRACE_FILE");
if (!file) file = "/tmp/hphp.log";
if (env) {
out = fopen(file, "w");
if (!out) {
fprintf(stderr, "could not create log file (%s); using stderr\n", file);
out = stderr;
}
char *e = strdup(env);
char *tok;
for (tok = strtok(e, ","); tok; tok = strtok(nullptr, ",")) {
char *ctok;
char *moduleName = tok;
if (( ctok = strchr(moduleName, ':'))) {
*ctok++ = 0;
}
int level = ctok ? atoi(ctok) : 1;
int mod = name2mod(moduleName);
if (mod >= 0) {
levels[mod] = level;
}
if (mod == Trace::minstr || mod == Trace::punt) {
levels[Trace::statgroups] = std::max(levels[Trace::statgroups], 1);
}
}
free(e);
} else {
// If TRACE env var is not set, nothing should be traced...
// but if it does, use stderr.
out = stderr;
}
}
};
Init i;
const char* moduleName(Module mod) {
return tokNames[mod];
}
void flush() {
if (!moduleEnabledRelease(Trace::traceAsync)) {
fflush(out);
}
}
void vtrace(const char *fmt, va_list ap) {
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
if (moduleEnabledRelease(Trace::ringbuffer, 1)) {
vtraceRingbuffer(fmt, ap);
} else {
ONTRACE(1, pthread_mutex_lock(&mtx));
ONTRACE(1, fprintf(out, "t%#08x: ",
int((int64_t)pthread_self() & 0xFFFFFFFF)));
vfprintf(out, fmt, ap);
ONTRACE(1, pthread_mutex_unlock(&mtx));
flush();
}
}
void trace(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vtrace(fmt, ap);
va_end(ap);
}
void traceRelease(const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
vtrace(fmt, ap);
va_end(ap);
}
void trace(const std::string& s) {
trace("%s", s.c_str());
}
template<>
std::string prettyNode(const char* name, const std::string& s) {
using std::string;
return string("(") + string(name) + string(" ") +
s +
string(")");
}
} } // HPHP::Trace