Cleanup unwind handler
authorSimon Hausmann <simon.hausmann@digia.com>
Mon, 4 Mar 2013 14:30:40 +0000 (15:30 +0100)
committerLars Knoll <lars.knoll@digia.com>
Tue, 5 Mar 2013 07:41:22 +0000 (08:41 +0100)
Store the platform specific unwind info (CIE/FDE on Linux/Mac x86/x86-64) directly
inside the VM::Function and therefore make all the functions of UnwindHelper static.

Also calculate the function size correctly.

Change-Id: If6a6b92a250044c6799218ef3506f34d630674c7
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/v4/qmljs_engine.cpp
src/v4/qmljs_engine.h
src/v4/qv4functionobject.h
src/v4/qv4isel_masm.cpp
src/v4/qv4unwindhelper.cpp
src/v4/qv4unwindhelper.h
src/v4/qv4unwindhelper_p-dw2.h

index 6df44ef..126162e 100644 (file)
@@ -71,7 +71,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
     , exception(Value::nullValue())
 {
     MemoryManager::GCBlocker gcBlocker(memoryManager);
-    unwindHelper = UnwindHelper::create();
 
     memoryManager->setExecutionEngine(this);
 
@@ -236,9 +235,7 @@ ExecutionEngine::~ExecutionEngine()
     delete globalObject.asObject();
     rootContext->destroy();
     delete rootContext;
-    if (unwindHelper)
-        unwindHelper->deregisterFunctions(functions);
-    delete unwindHelper;
+    UnwindHelper::deregisterFunctions(functions);
     qDeleteAll(functions);
     delete memoryManager;
 }
index 2289e73..0d8dd05 100644 (file)
@@ -102,7 +102,6 @@ class RegExp;
 struct Q_V4_EXPORT ExecutionEngine
 {
     MemoryManager *memoryManager;
-    UnwindHelper *unwindHelper;
     EvalISelFactory *iselFactory;
     ExecutionContext *current;
     ExecutionContext *rootContext;
index bbe6306..2cfb66f 100644 (file)
@@ -115,6 +115,7 @@ struct Function {
     VM::Value (*code)(VM::ExecutionContext *, const uchar *);
     const uchar *codeData;
     JSC::MacroAssemblerCodeRef codeRef;
+    QByteArray unwindInfo; // CIE+FDE on x86/x86-64
 
     QVector<String *> formals;
     QVector<String *> locals;
index 35bd638..fc39f4c 100644 (file)
@@ -422,6 +422,8 @@ void Assembler::link(VM::Function *vmFunc)
 
     JSC::JSGlobalData dummy;
     JSC::LinkBuffer linkBuffer(dummy, this, 0);
+    uint32_t codeSize = linkBuffer.offsetOf(label());
+
     QHash<void*, const char*> functions;
     foreach (CallToLink ctl, _callsToLink) {
         linkBuffer.link(ctl.call, ctl.externalFunction);
@@ -456,6 +458,7 @@ void Assembler::link(VM::Function *vmFunc)
     }
 
     vmFunc->code = (Value (*)(VM::ExecutionContext *, const uchar *)) vmFunc->codeRef.code().executableAddress();
+    vmFunc->unwindInfo = UnwindHelper::createUnwindInfo(vmFunc, codeSize);
 }
 
 InstructionSelection::InstructionSelection(VM::ExecutionEngine *engine, IR::Module *module)
@@ -517,7 +520,6 @@ void InstructionSelection::run(VM::Function *vmFunction, IR::Function *function)
     _as->poke(Assembler::ScratchRegister);
 #endif
     _as->ret();
-    // TODO: add a label and a nop, so we can determine the exact function length
 
     _as->link(_vmFunction);
 
@@ -526,8 +528,7 @@ void InstructionSelection::run(VM::Function *vmFunction, IR::Function *function)
         memcpy(_vmFunction->lookups, _lookups.constData(), _lookups.size()*sizeof(Lookup));
     }
 
-    if (engine()->unwindHelper)
-        engine()->unwindHelper->registerFunction(_vmFunction);
+    UnwindHelper::registerFunction(_vmFunction);
 
     qSwap(_vmFunction, vmFunction);
     qSwap(_function, function);
index 31d9d68..a376b33 100644 (file)
 
 #ifdef USE_NULL_HELPER
 using namespace QQmlJS::VM;
-UnwindHelper *UnwindHelper::create() { return 0; }
-UnwindHelper::UnwindHelper() {}
-UnwindHelper::~UnwindHelper() {}
 void UnwindHelper::registerFunction(Function *function) {Q_UNUSED(function);}
 void UnwindHelper::registerFunctions(QVector<Function *> functions) {Q_UNUSED(functions);}
 void UnwindHelper::deregisterFunction(Function *function) {Q_UNUSED(function);}
 void UnwindHelper::deregisterFunctions(QVector<Function *> functions) {Q_UNUSED(functions);}
+QByteArray UnwindHelper::createUnwindInfo(Function*, size_t) { return QByteArray(); }
 #endif // USE_NULL_HELPER
 
index bf70a01..19d33bb 100644 (file)
@@ -10,24 +10,13 @@ struct Function;
 
 class UnwindHelper
 {
-    Q_DISABLE_COPY(UnwindHelper)
-
-private:
-    UnwindHelper();
-
 public:
-    ~UnwindHelper();
-
-    static UnwindHelper *create();
-
-    void registerFunction(Function *function);
-    void registerFunctions(QVector<Function *> functions);
-    void deregisterFunction(Function *function);
-    void deregisterFunctions(QVector<Function *> functions);
+    static QByteArray createUnwindInfo(Function*f, size_t functionSize);
 
-private:
-    struct Private;
-    Private *p;
+    static void registerFunction(Function *function);
+    static void registerFunctions(QVector<Function *> functions);
+    static void deregisterFunction(Function *function);
+    static void deregisterFunctions(QVector<Function *> functions);
 };
 
 } // VM namespace
index 302e173..4d60812 100644 (file)
@@ -46,55 +46,6 @@ 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);
@@ -102,12 +53,9 @@ void UnwindHelper::registerFunctions(QVector<Function *> functions)
 
 void UnwindHelper::deregisterFunction(Function *function)
 {
-    QHash<Function *, EHInfo *>::iterator i = p->ehInfoForFunction.find(function);
-    if (i == p->ehInfoForFunction.end())
+    if (function->unwindInfo.isEmpty())
         return;
-
-    delete i.value();
-    p->ehInfoForFunction.erase(i);
+    __deregister_frame(function->unwindInfo.data() + fde_offset);
 }
 
 void UnwindHelper::deregisterFunctions(QVector<Function *> functions)
@@ -133,17 +81,25 @@ void writeIntPtrValue(unsigned char *addr, intptr_t val)
 
 void UnwindHelper::registerFunction(Function *function)
 {
-    unsigned char *cie_and_fde = new unsigned char[sizeof(cie_fde_data)];
+    if (function->unwindInfo.isEmpty())
+        return;
+    __register_frame(function->unwindInfo.data() + fde_offset);
+}
+
+QByteArray UnwindHelper::createUnwindInfo(Function *f, size_t functionSize)
+{
+    QByteArray info;
+    info.resize(sizeof(cie_fde_data));
+
+    unsigned char *cie_and_fde = reinterpret_cast<unsigned char *>(info.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);
+    intptr_t ptr = static_cast<char *>(f->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);
+    writeIntPtrValue(cie_and_fde + address_range_offset, functionSize);
 
-    p->ehInfoForFunction.insert(function, new EHInfo(cie_and_fde,
-                                                     cie_and_fde + fde_offset));
+    return info;
 }
 
 } // VM namespace