Arquivos
hhvm/hphp/runtime/vm/debug/debug.h
T
bsimmers 8733cdc4f3 Run hhir exit traces during unwinding; don't spillstack before most helpers
Most of the SpillStacks we do are just to keep the in-memory VM stack
clean in case a helper call throws an exception. Many of these exceptions are
vanishingly rare, so let's stop making the fast path slower for them. This diff
adds support for catch traces, which are just like normal exit traces with one
major exception: they're never jumped to from translated code. If we're
unwinding a TC frame and discover that the current rip has a catch trace
registered, the unwinder will execute it before resuming unwinding.

The unwinder parts were fairly straightfoward, then I ran into a bunch of
issues with SetM. The SetElem instruction sometimes consumes a reference to one
of its inputs, which is bad news for our optimizations. To make everything work
again, I changed SetElem to throw an exception in cases where it would've
previously decreffed the value input. This is a special exception that the new
unwinding code recognizes. When one of these is caught, the catch trace
executed for that TC frame will finish up the vector instruction and push the
value provided by the exception on the stack. This allows us to optimize most
traces under the assumption that SetM's output is the same as its input,
letting the catch trace clean things up if the helper decides that's not the
case and throws.

There is one common case where SetM's output isn't the same as its input:
setting an offset in a string base returns a new String. Luckily, we can detect
most of these at compile time so SetElem returns a new StringData* when the
base is known to be a string. If the base might be a string, SetElem will
return nullptr if the base wasn't a string, and a StringData* if it was. We
test the output in these cases and side exit if the return value of SetElem is
non-null (I have yet to see this side exit happen outside of artificially
created test cases).

Once I got things working in the vector translator, I went through every other
call to spillStack and exceptionBarrier, replacing them with catch traces as
appropriate.
2013-05-30 17:39:25 -07:00

73 linhas
2.5 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. |
+----------------------------------------------------------------------+
*/
#ifndef TRANSLATOR_DEBUG_H_
#define TRANSLATOR_DEBUG_H_
#include "hphp/runtime/base/types.h"
#include "hphp/runtime/vm/translator/translator.h"
#include "hphp/runtime/vm/hhbc.h"
#include "hphp/runtime/vm/debug/dwarf.h"
namespace HPHP {
namespace Debug {
class DebugInfo {
public:
DebugInfo();
~DebugInfo();
void recordTracelet(TCRange range,
const Func* func,
const Opcode *instr, bool exit,
bool inPrologue);
void recordStub(TCRange range,
const char* name);
void recordPerfMap(TCRange range, const Func* func, bool exit,
bool inPrologue);
void recordBCInstr(TCRange range, uint32_t op);
void debugSync();
static DebugInfo* Get();
private:
/* maintain separate dwarf info for a and astubs, so that we
* don't emit dwarf info for the two in the same ELF file.
* gdb tends to get confused when it sees dwarf info for
* widely separated addresses ranges in the same ELF file.
*/
DwarfInfo m_aDwarfInfo;
DwarfInfo m_astubsDwarfInfo;
/*
* Stuff to output symbol names to /tmp/perf-%d.map files. This stuff
* can be read by perf top/record, etc.
*/
FILE* m_perfMap;
char m_perfMapName[64];
};
/*
* Gets the fake symbol name we want to use for a php function.
*/
std::string lookupFunction(const Func* func,
bool exit,
bool inPrologue,
bool pseudoWithFileName);
}
}
#endif