--- /dev/null
+#ifndef QV4UNWINDHELPER_PDW2_H
+#define QV4UNWINDHELPER_PDW2_H
+
+#include <qv4unwindhelper.h>
+#include <qv4functionobject.h>
+#include <wtf/Platform.h>
+
+#include <QtCore/QHash>
+
+extern "C" void __register_frame(void*);
+extern "C" void __deregister_frame(void*);
+
+namespace QQmlJS {
+namespace VM {
+
+namespace {
+#if CPU(X86_64)
+// Generated by fdegen
+static const unsigned char cie_fde_data[] = {
+ 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0x0, 0x8, 0x78, 0x10, 0xc, 0x7, 0x8,
+ 0x90, 0x1, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0,
+ 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x41, 0x13, 0x7e, 0x86,
+ 0x2, 0x43, 0xd, 0x6, 0x8c, 0x3, 0x8e, 0x4,
+ 0x0, 0x0, 0x0, 0x0
+};
+static const int fde_offset = 20;
+static const int initial_location_offset = 28;
+static const int address_range_offset = 36;
+#elif CPU(X86) && OS(LINUX)
+static const unsigned char cie_fde_data[] = {
+ 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0x0, 0x4, 0x7c, 0x8, 0xc, 0x4, 0x4,
+ 0x88, 0x1, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0,
+ 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x41, 0x13, 0x7e, 0x85,
+ 0x2, 0x43, 0xd, 0x5, 0x86, 0x3, 0x87, 0x4,
+ 0x0, 0x0, 0x0, 0x0,
+};
+static const int fde_offset = 20;
+static const int initial_location_offset = 28;
+static const int address_range_offset = 32;
+#endif
+} // anonymous namespace
+
+namespace {
+struct EHInfo {
+ unsigned char *cie_and_fde;
+ unsigned char *fde;
+
+ EHInfo(unsigned char *cie_and_fde, unsigned char *fde)
+ : cie_and_fde(cie_and_fde), fde(fde)
+ {
+ Q_ASSERT(cie_and_fde);
+ Q_ASSERT(fde);
+
+ __register_frame(fde);
+ }
+
+ ~EHInfo()
+ {
+ Q_ASSERT(cie_and_fde);
+ Q_ASSERT(fde);
+
+ __deregister_frame(fde);
+
+ delete[] cie_and_fde;
+ }
+};
+} // anonymous namespace
+
+struct Function;
+
+struct UnwindHelper::Private
+{
+ QHash<Function *, EHInfo *> ehInfoForFunction;
+};
+
+UnwindHelper *UnwindHelper::create()
+{
+ return new UnwindHelper;
+}
+
+UnwindHelper::UnwindHelper()
+ : p(new Private)
+{}
+
+UnwindHelper::~UnwindHelper()
+{
+ foreach (Function *f, p->ehInfoForFunction.keys())
+ deregisterFunction(f);
+ delete p;
+}
+
+void UnwindHelper::registerFunctions(QVector<Function *> functions)
+{
+ foreach (Function *f, functions) registerFunction(f);
+}
+
+void UnwindHelper::deregisterFunction(Function *function)
+{
+ QHash<Function *, EHInfo *>::iterator i = p->ehInfoForFunction.find(function);
+ if (i == p->ehInfoForFunction.end())
+ return;
+
+ delete i.value();
+ p->ehInfoForFunction.erase(i);
+}
+
+void UnwindHelper::deregisterFunctions(QVector<Function *> functions)
+{
+ foreach (Function *f, functions) deregisterFunction(f);
+}
+
+namespace {
+void writeIntPtrValue(unsigned char *addr, intptr_t val)
+{
+ addr[0] = (val >> 0) & 0xff;
+ addr[1] = (val >> 8) & 0xff;
+ addr[2] = (val >> 16) & 0xff;
+ addr[3] = (val >> 24) & 0xff;
+#if QT_POINTER_SIZE == 8
+ addr[4] = (val >> 32) & 0xff;
+ addr[5] = (val >> 40) & 0xff;
+ addr[6] = (val >> 48) & 0xff;
+ addr[7] = (val >> 56) & 0xff;
+#endif
+}
+} // anonymous namespace
+
+void UnwindHelper::registerFunction(Function *function)
+{
+ unsigned char *cie_and_fde = new unsigned char[sizeof(cie_fde_data)];
+ memcpy(cie_and_fde, cie_fde_data, sizeof(cie_fde_data));
+
+ intptr_t ptr = static_cast<char *>(function->codeRef.code().executableAddress()) - static_cast<char *>(0);
+ writeIntPtrValue(cie_and_fde + initial_location_offset, ptr);
+
+ size_t len = function->codeRef.size();
+ writeIntPtrValue(cie_and_fde + address_range_offset, len);
+
+ p->ehInfoForFunction.insert(function, new EHInfo(cie_and_fde,
+ cie_and_fde + fde_offset));
+}
+
+} // VM namespace
+} // QQmlJS namespace
+
+#endif // QV4UNWINDHELPER_PDW2_H