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>
, exception(Value::nullValue())
{
MemoryManager::GCBlocker gcBlocker(memoryManager);
- unwindHelper = UnwindHelper::create();
memoryManager->setExecutionEngine(this);
delete globalObject.asObject();
rootContext->destroy();
delete rootContext;
- if (unwindHelper)
- unwindHelper->deregisterFunctions(functions);
- delete unwindHelper;
+ UnwindHelper::deregisterFunctions(functions);
qDeleteAll(functions);
delete memoryManager;
}
struct Q_V4_EXPORT ExecutionEngine
{
MemoryManager *memoryManager;
- UnwindHelper *unwindHelper;
EvalISelFactory *iselFactory;
ExecutionContext *current;
ExecutionContext *rootContext;
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;
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);
}
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)
_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);
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);
#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
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
#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())
+ 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)
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