diff options
Diffstat (limited to 'src/qml/jit/qv4isel_masm.cpp')
-rw-r--r-- | src/qml/jit/qv4isel_masm.cpp | 178 |
1 files changed, 8 insertions, 170 deletions
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index c5d612ae65..279ccabf81 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -68,175 +68,6 @@ using namespace QV4; using namespace QV4::JIT; -namespace { -class QIODevicePrintStream: public FilePrintStream -{ - Q_DISABLE_COPY(QIODevicePrintStream) - -public: - explicit QIODevicePrintStream(QIODevice *dest) - : FilePrintStream(0) - , dest(dest) - , buf(4096, '0') - { - Q_ASSERT(dest); - } - - ~QIODevicePrintStream() - {} - - void vprintf(const char* format, va_list argList) WTF_ATTRIBUTE_PRINTF(2, 0) - { - const int written = qvsnprintf(buf.data(), buf.size(), format, argList); - if (written > 0) - dest->write(buf.constData(), written); - memset(buf.data(), 0, qMin(written, buf.size())); - } - - void flush() - {} - -private: - QIODevice *dest; - QByteArray buf; -}; -} // anonymous namespace - -static void printDisassembledOutputWithCalls(QByteArray processedOutput, const QHash<void*, const char*>& functions) -{ - for (QHash<void*, const char*>::ConstIterator it = functions.begin(), end = functions.end(); - it != end; ++it) { - const QByteArray ptrString = "0x" + QByteArray::number(quintptr(it.key()), 16); - int idx = processedOutput.indexOf(ptrString); - if (idx < 0) - continue; - idx = processedOutput.lastIndexOf('\n', idx); - if (idx < 0) - continue; - processedOutput = processedOutput.insert(idx, QByteArrayLiteral(" ; call ") + it.value()); - } - - qDebug("%s", processedOutput.constData()); -} - -#if defined(Q_OS_LINUX) -static FILE *pmap; - -static void qt_closePmap() -{ - if (pmap) { - fclose(pmap); - pmap = 0; - } -} - -#endif - -JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize) -{ - Label endOfCode = label(); - - { - for (size_t i = 0, ei = _patches.size(); i != ei; ++i) { - Label target = _addrs.at(i); - Q_ASSERT(target.isSet()); - for (Jump jump : qAsConst(_patches.at(i))) - jump.linkTo(target, this); - } - } - - JSC::JSGlobalData dummy(_executableAllocator); - JSC::LinkBuffer linkBuffer(dummy, this, 0); - - for (const DataLabelPatch &p : qAsConst(_dataLabelPatches)) - linkBuffer.patch(p.dataLabel, linkBuffer.locationOf(p.target)); - - // link exception handlers - for (Jump jump : qAsConst(exceptionPropagationJumps)) - linkBuffer.link(jump, linkBuffer.locationOf(exceptionReturnLabel)); - - { - for (size_t i = 0, ei = _labelPatches.size(); i != ei; ++i) { - Label target = _addrs.at(i); - Q_ASSERT(target.isSet()); - for (DataLabelPtr label : _labelPatches.at(i)) - linkBuffer.patch(label, linkBuffer.locationOf(target)); - } - } - - *codeSize = linkBuffer.offsetOf(endOfCode); - - QByteArray name; - - JSC::MacroAssemblerCodeRef codeRef; - - static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_ASM"); - if (showCode) { - QHash<void*, const char*> functions; -#ifndef QT_NO_DEBUG - for (CallInfo call : qAsConst(_callInfos)) - functions[linkBuffer.locationOf(call.label).dataLocation()] = call.functionName; -#endif - - QBuffer buf; - buf.open(QIODevice::WriteOnly); - WTF::setDataFile(new QIODevicePrintStream(&buf)); - - name = _function->name->toUtf8(); - if (name.isEmpty()) - name = "IR::Function(0x" + QByteArray::number(quintptr(_function), 16) + ')'; - codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.data()); - - WTF::setDataFile(stderr); - printDisassembledOutputWithCalls(buf.data(), functions); - } else { - codeRef = linkBuffer.finalizeCodeWithoutDisassembly(); - } - -#if defined(Q_OS_LINUX) - // This implements writing of JIT'd addresses so that perf can find the - // symbol names. - // - // Perf expects the mapping to be in a certain place and have certain - // content, for more information, see: - // https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt - static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP"); - static bool profileInitialized = false; - if (doProfile && !profileInitialized) { - profileInitialized = true; - - char pname[PATH_MAX]; - snprintf(pname, PATH_MAX - 1, "/tmp/perf-%lu.map", - (unsigned long)QCoreApplication::applicationPid()); - - pmap = fopen(pname, "w"); - if (!pmap) - qWarning("QV4: Can't write %s, call stacks will not contain JavaScript function names", pname); - - // make sure we clean up nicely - std::atexit(qt_closePmap); - } - - if (pmap) { - // this may have been pre-populated, if QV4_SHOW_ASM was on - if (name.isEmpty()) { - name = _function->name->toUtf8(); - if (name.isEmpty()) - name = "IR::Function(0x" + QByteArray::number(quintptr(_function), 16) + ')'; - } - - fprintf(pmap, "%llx %x %.*s\n", - (long long unsigned int)codeRef.code().executableAddress(), - *codeSize, - name.length(), - name.constData()); - fflush(pmap); - } -#endif - - return codeRef; -} - InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory) : EvalInstructionSelection(execAllocator, module, jsGenerator, iselFactory) , _block(0) @@ -278,7 +109,7 @@ void InstructionSelection::run(int functionIndex) qSwap(_removableJumps, removableJumps); Assembler* oldAssembler = _as; - _as = new Assembler(this, _function, executableAllocator); + _as = new Assembler(jsGenerator, _function, executableAllocator); _as->setStackLayout(6, // 6 == max argc for calls to built-ins with an argument array regularRegistersToSave.size(), fpRegistersToSave.size()); @@ -1881,6 +1712,13 @@ bool InstructionSelection::visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock // neither operands are statically typed as bool, so bail out. return false; } + if (otherSrc->type == IR::UnknownType) { + // Ok, we really need to call into the runtime. + // (This case doesn't happen when the optimizer ran, because everything will be typed (yes, + // possibly as "var" meaning anything), but it does happen for $0===true, which is generated + // for things where the optimizer didn't run (like functions with a try block).) + return false; + } Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal : Assembler::NotEqual; |