f31522130f
Build system (5 gaps hardened): - COOKBOOK_OFFLINE defaults to true (fork-mode) - normalize_patch handles diff -ruN format - New 'repo validate-patches' command (25/25 relibc patches) - 14 patched Qt/Wayland/display recipes added to protected list - relibc archive regenerated with current patch chain Boot fixes (fixable): - Full ISO EFI partition: 16 MiB → 1 MiB (matches mini, BIOS hardcoded 2 MiB offset) - D-Bus system bus: absolute /usr/bin/dbus-daemon path (was skipped) - redbear-sessiond: absolute /usr/bin/redbear-sessiond path (was skipped) - daemon framework: silenced spurious INIT_NOTIFY warnings for oneshot_async services (P0-daemon-silence-init-notify.patch) - udev-shim: demoted INIT_NOTIFY warning to INFO (expected for oneshot_async) - relibc: comprehensive named semaphores (sem_open/close/unlink) replacing upstream todo!() stubs - greeterd: Wayland socket timeout 15s → 30s (compositor DRM wait) - greeter-ui: built and linked (header guard unification, sem_compat stubs removed) - mc: un-ignored in both configs, fixed glib/libiconv/pcre2 transitive deps - greeter config: removed stale keymapd dependency from display/greeter services - prefix toolchain: relibc headers synced, _RELIBC_STDLIB_H guard unified Unfixable (diagnosed, upstream): - i2c-hidd: abort on no-I2C-hardware (QEMU) — process::exit → relibc abort - kded6/greeter-ui: page fault 0x8 — Qt library null deref - Thread panics fd != -1 — Rust std library on Redox - DHCP timeout / eth0 MAC — QEMU user-mode networking - hwrngd/thermald — no hardware RNG/thermal in VM - live preload allocation — BIOS memory fragmentation, continues on demand
922 lines
27 KiB
C++
922 lines
27 KiB
C++
// Copyright (C) 2017 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
|
// Qt-Security score:critical reason:jit
|
|
|
|
#include "qv4baselinejit_p.h"
|
|
#include "qv4baselineassembler_p.h"
|
|
#include <private/qv4lookup_p.h>
|
|
#include <private/qv4generatorobject_p.h>
|
|
|
|
#if QT_CONFIG(qml_jit)
|
|
|
|
QT_USE_NAMESPACE
|
|
using namespace QV4;
|
|
using namespace QV4::JIT;
|
|
using namespace QV4::Moth;
|
|
|
|
BaselineJIT::BaselineJIT(Function *function)
|
|
: function(function)
|
|
, as(new BaselineAssembler(&(function->compilationUnit->constants->asValue<Value>())))
|
|
{}
|
|
|
|
BaselineJIT::~BaselineJIT()
|
|
{}
|
|
|
|
void BaselineJIT::generate()
|
|
{
|
|
// qDebug()<<"jitting" << function->name()->toQString();
|
|
const char *code = function->codeData;
|
|
uint len = function->compiledFunction->codeSize;
|
|
|
|
for (unsigned i = 0, ei = function->compiledFunction->nLabelInfos; i != ei; ++i)
|
|
labels.insert(int(function->compiledFunction->labelInfoTable()[i]));
|
|
|
|
as->generatePrologue();
|
|
// Make sure the ACC register is initialized and not clobbered by the caller.
|
|
as->loadAccumulatorFromFrame();
|
|
decode(code, len);
|
|
as->generateEpilogue();
|
|
|
|
as->link(function);
|
|
// qDebug()<<"done";
|
|
}
|
|
|
|
#define STORE_IP() as->storeInstructionPointer(nextInstructionOffset())
|
|
#define STORE_ACC() as->saveAccumulatorInFrame()
|
|
#define LOAD_ACC() as->loadAccumulatorFromFrame()
|
|
#define BASELINEJIT_GENERATE_RUNTIME_CALL(function, destination) { \
|
|
as->GENERATE_RUNTIME_CALL(function, destination); \
|
|
if (Runtime::function::throws) \
|
|
as->checkException(); \
|
|
else {} } // this else prevents else statements after the macro from attaching to the if above
|
|
|
|
void BaselineJIT::generate_Ret()
|
|
{
|
|
as->ret();
|
|
}
|
|
|
|
void BaselineJIT::generate_Debug() { Q_UNREACHABLE(); }
|
|
|
|
void BaselineJIT::generate_LoadConst(int index)
|
|
{
|
|
as->loadConst(index);
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadZero()
|
|
{
|
|
as->loadValue(Encode(int(0)));
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadTrue()
|
|
{
|
|
as->loadValue(Encode(true));
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadFalse()
|
|
{
|
|
as->loadValue(Encode(false));
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadNull()
|
|
{
|
|
as->loadValue(Encode::null());
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadUndefined()
|
|
{
|
|
as->loadValue(Encode::undefined());
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadInt(int value)
|
|
{
|
|
//###
|
|
as->loadValue(Encode(value));
|
|
}
|
|
|
|
void BaselineJIT::generate_MoveConst(int constIndex, int destTemp)
|
|
{
|
|
as->copyConst(constIndex, destTemp);
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadReg(int reg)
|
|
{
|
|
as->loadReg(reg);
|
|
}
|
|
|
|
void BaselineJIT::generate_StoreReg(int reg)
|
|
{
|
|
as->storeReg(reg);
|
|
}
|
|
|
|
void BaselineJIT::generate_MoveReg(int srcReg, int destReg)
|
|
{
|
|
// Don't clobber the accumulator.
|
|
as->moveReg(srcReg, destReg);
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadImport(int index)
|
|
{
|
|
as->loadImport(index);
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadLocal(int index)
|
|
{
|
|
as->loadLocal(index);
|
|
}
|
|
|
|
void BaselineJIT::generate_StoreLocal(int index)
|
|
{
|
|
as->checkException();
|
|
as->storeLocal(index);
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadScopedLocal(int scope, int index)
|
|
{
|
|
as->loadLocal(index, scope);
|
|
}
|
|
|
|
void BaselineJIT::generate_StoreScopedLocal(int scope, int index)
|
|
{
|
|
as->checkException();
|
|
as->storeLocal(index, scope);
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadRuntimeString(int stringId)
|
|
{
|
|
as->loadString(stringId);
|
|
}
|
|
|
|
void BaselineJIT::generate_MoveRegExp(int regExpId, int destReg)
|
|
{
|
|
as->prepareCallWithArgCount(2);
|
|
as->passInt32AsArg(regExpId, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(RegexpLiteral, CallResultDestination::InAccumulator);
|
|
as->storeReg(destReg);
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadClosure(int value)
|
|
{
|
|
as->prepareCallWithArgCount(2);
|
|
as->passInt32AsArg(value, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(Closure, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadName(int name)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passInt32AsArg(name, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(LoadName, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadGlobalLookup(int index)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passInt32AsArg(index, 2);
|
|
as->passFunctionAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(LoadGlobalLookup, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadQmlContextPropertyLookup(int index)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passInt32AsArg(index, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(LoadQmlContextPropertyLookup, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_StoreNameSloppy(int name)
|
|
{
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passAccumulatorAsArg(2);
|
|
as->passInt32AsArg(name, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(StoreNameSloppy, CallResultDestination::Ignore);
|
|
LOAD_ACC();
|
|
}
|
|
|
|
void BaselineJIT::generate_StoreNameStrict(int name)
|
|
{
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passAccumulatorAsArg(2);
|
|
as->passInt32AsArg(name, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(StoreNameStrict, CallResultDestination::Ignore);
|
|
LOAD_ACC();
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadElement(int base)
|
|
{
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passAccumulatorAsArg(2);
|
|
as->passJSSlotAsArg(base, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(LoadElement, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_StoreElement(int base, int index)
|
|
{
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(4);
|
|
as->passAccumulatorAsArg(3);
|
|
as->passJSSlotAsArg(index, 2);
|
|
as->passJSSlotAsArg(base, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(StoreElement, CallResultDestination::Ignore);
|
|
LOAD_ACC();
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadProperty(int name)
|
|
{
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passInt32AsArg(name, 2);
|
|
as->passAccumulatorAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(LoadProperty, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadOptionalProperty(int name, int offset)
|
|
{
|
|
labels.insert(as->jumpEqNull(absoluteOffset(offset)));
|
|
|
|
generate_LoadProperty(name);
|
|
}
|
|
|
|
void BaselineJIT::generate_GetLookup(int index)
|
|
{
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(4);
|
|
as->passInt32AsArg(index, 3);
|
|
as->passAccumulatorAsArg(2);
|
|
as->passFunctionAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(GetLookup, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_GetOptionalLookup(int index, int offset)
|
|
{
|
|
labels.insert(as->jumpEqNull(absoluteOffset(offset)));
|
|
|
|
generate_GetLookup(index);
|
|
}
|
|
|
|
void BaselineJIT::generate_StoreProperty(int name, int base)
|
|
{
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(4);
|
|
as->passAccumulatorAsArg(3);
|
|
as->passInt32AsArg(name, 2);
|
|
as->passJSSlotAsArg(base, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(StoreProperty, CallResultDestination::Ignore);
|
|
LOAD_ACC();
|
|
}
|
|
|
|
void BaselineJIT::generate_SetLookup(int index, int base)
|
|
{
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(4);
|
|
as->passAccumulatorAsArg(3);
|
|
as->passInt32AsArg(index, 2);
|
|
as->passJSSlotAsArg(base, 1);
|
|
as->passFunctionAsArg(0);
|
|
if (function->isStrict())
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(SetLookupStrict, CallResultDestination::InAccumulator)
|
|
else
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(SetLookupSloppy, CallResultDestination::InAccumulator)
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadSuperProperty(int property)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passJSSlotAsArg(property, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(LoadSuperProperty, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_StoreSuperProperty(int property)
|
|
{
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passAccumulatorAsArg(2);
|
|
as->passJSSlotAsArg(property, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(StoreSuperProperty, CallResultDestination::Ignore);
|
|
LOAD_ACC();
|
|
}
|
|
|
|
void BaselineJIT::generate_Yield()
|
|
{
|
|
// #####
|
|
Q_UNREACHABLE();
|
|
}
|
|
|
|
void BaselineJIT::generate_YieldStar()
|
|
{
|
|
// #####
|
|
Q_UNREACHABLE();
|
|
}
|
|
|
|
void BaselineJIT::generate_Resume(int)
|
|
{
|
|
// #####
|
|
Q_UNREACHABLE();
|
|
}
|
|
|
|
void BaselineJIT::generate_CallValue(int name, int argc, int argv)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(4);
|
|
as->passInt32AsArg(argc, 3);
|
|
as->passJSSlotAsArg(argv, 2);
|
|
as->passJSSlotAsArg(name, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CallValue, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_CallWithReceiver(int name, int thisObject, int argc, int argv)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(5);
|
|
as->passInt32AsArg(argc, 4);
|
|
as->passJSSlotAsArg(argv, 3);
|
|
as->passJSSlotAsArg(thisObject, 2);
|
|
as->passJSSlotAsArg(name, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CallWithReceiver, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_CallProperty(int name, int base, int argc, int argv)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(5);
|
|
as->passInt32AsArg(argc, 4);
|
|
as->passJSSlotAsArg(argv, 3);
|
|
as->passInt32AsArg(name, 2);
|
|
as->passJSSlotAsArg(base, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CallProperty, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_CallPropertyLookup(int lookupIndex, int base, int argc, int argv)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(5);
|
|
as->passInt32AsArg(argc, 4);
|
|
as->passJSSlotAsArg(argv, 3);
|
|
as->passInt32AsArg(lookupIndex, 2);
|
|
as->passJSSlotAsArg(base, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CallPropertyLookup, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_CallName(int name, int argc, int argv)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(4);
|
|
as->passInt32AsArg(argc, 3);
|
|
as->passJSSlotAsArg(argv, 2);
|
|
as->passInt32AsArg(name, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CallName, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_CallPossiblyDirectEval(int argc, int argv)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passInt32AsArg(argc, 2);
|
|
as->passJSSlotAsArg(argv, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CallPossiblyDirectEval, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_CallGlobalLookup(int index, int argc, int argv)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(4);
|
|
as->passInt32AsArg(argc, 3);
|
|
as->passJSSlotAsArg(argv, 2);
|
|
as->passInt32AsArg(index, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CallGlobalLookup, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_CallQmlContextPropertyLookup(int index, int argc, int argv)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(4);
|
|
as->passInt32AsArg(argc, 3);
|
|
as->passJSSlotAsArg(argv, 2);
|
|
as->passInt32AsArg(index, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CallQmlContextPropertyLookup, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_CallWithSpread(int func, int thisObject, int argc, int argv)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(5);
|
|
as->passInt32AsArg(argc, 4);
|
|
as->passJSSlotAsArg(argv, 3);
|
|
as->passJSSlotAsArg(thisObject, 2);
|
|
as->passJSSlotAsArg(func, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CallWithSpread, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_TailCall(int func, int thisObject, int argc, int argv)
|
|
{
|
|
STORE_IP();
|
|
as->jsTailCall(func, thisObject, argc, argv);
|
|
}
|
|
|
|
void BaselineJIT::generate_Construct(int func, int argc, int argv)
|
|
{
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(5);
|
|
as->passInt32AsArg(argc, 4);
|
|
as->passJSSlotAsArg(argv, 3);
|
|
as->passAccumulatorAsArg(2);
|
|
as->passJSSlotAsArg(func, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(Construct, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_ConstructWithSpread(int func, int argc, int argv)
|
|
{
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(5);
|
|
as->passInt32AsArg(argc, 4);
|
|
as->passJSSlotAsArg(argv, 3);
|
|
as->passAccumulatorAsArg(2);
|
|
as->passJSSlotAsArg(func, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(ConstructWithSpread, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_SetUnwindHandler(int offset)
|
|
{
|
|
if (offset)
|
|
labels.insert(as->setUnwindHandler(absoluteOffset(offset)));
|
|
else
|
|
as->clearUnwindHandler();
|
|
}
|
|
|
|
void BaselineJIT::generate_UnwindDispatch()
|
|
{
|
|
as->unwindDispatch();
|
|
}
|
|
|
|
void BaselineJIT::generate_UnwindToLabel(int level, int offset)
|
|
{
|
|
labels.insert(as->unwindToLabel(level, absoluteOffset(offset)));
|
|
}
|
|
|
|
void BaselineJIT::generate_DeadTemporalZoneCheck(int name)
|
|
{
|
|
as->deadTemporalZoneCheck(nextInstructionOffset(), name);
|
|
}
|
|
|
|
void BaselineJIT::generate_ThrowException()
|
|
{
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passAccumulatorAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(ThrowException, CallResultDestination::Ignore);
|
|
as->gotoCatchException();
|
|
|
|
// LOAD_ACC(); <- not needed here since it would be unreachable.
|
|
}
|
|
|
|
void BaselineJIT::generate_GetException() { as->getException(); }
|
|
void BaselineJIT::generate_SetException() { as->setException(); }
|
|
|
|
void BaselineJIT::generate_CreateCallContext()
|
|
{
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(1);
|
|
as->passCppFrameAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(PushCallContext, CallResultDestination::Ignore);
|
|
LOAD_ACC();
|
|
}
|
|
|
|
void BaselineJIT::generate_PushCatchContext(int index, int name) { as->pushCatchContext(index, name); }
|
|
|
|
void BaselineJIT::generate_PushWithContext()
|
|
{
|
|
STORE_IP();
|
|
as->saveAccumulatorInFrame();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passJSSlotAsArg(CallData::Accumulator, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(PushWithContext, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_PushBlockContext(int index)
|
|
{
|
|
as->saveAccumulatorInFrame();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passInt32AsArg(index, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(PushBlockContext, CallResultDestination::Ignore);
|
|
as->loadAccumulatorFromFrame();
|
|
}
|
|
|
|
void BaselineJIT::generate_CloneBlockContext()
|
|
{
|
|
as->saveAccumulatorInFrame();
|
|
as->prepareCallWithArgCount(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CloneBlockContext, CallResultDestination::Ignore);
|
|
as->loadAccumulatorFromFrame();
|
|
}
|
|
|
|
void BaselineJIT::generate_PushScriptContext(int index)
|
|
{
|
|
as->saveAccumulatorInFrame();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passInt32AsArg(index, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(PushScriptContext, CallResultDestination::Ignore);
|
|
as->loadAccumulatorFromFrame();
|
|
}
|
|
|
|
void BaselineJIT::generate_PopScriptContext()
|
|
{
|
|
as->saveAccumulatorInFrame();
|
|
as->prepareCallWithArgCount(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(PopScriptContext, CallResultDestination::Ignore);
|
|
as->loadAccumulatorFromFrame();
|
|
}
|
|
|
|
void BaselineJIT::generate_PopContext() { as->popContext(); }
|
|
|
|
void BaselineJIT::generate_GetIterator(int iterator)
|
|
{
|
|
as->saveAccumulatorInFrame();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passInt32AsArg(iterator, 2);
|
|
as->passAccumulatorAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(GetIterator, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_IteratorNext(int value, int offset)
|
|
{
|
|
as->saveAccumulatorInFrame();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passJSSlotAsArg(value, 2);
|
|
as->passAccumulatorAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(IteratorNext, CallResultDestination::InAccumulator);
|
|
labels.insert(as->jumpTrue(absoluteOffset(offset)));
|
|
}
|
|
|
|
void BaselineJIT::generate_IteratorNextForYieldStar(int iterator, int object, int offset)
|
|
{
|
|
as->saveAccumulatorInFrame();
|
|
as->prepareCallWithArgCount(4);
|
|
as->passJSSlotAsArg(object, 3);
|
|
as->passJSSlotAsArg(iterator, 2);
|
|
as->passAccumulatorAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(IteratorNextForYieldStar, CallResultDestination::InAccumulator);
|
|
labels.insert(as->jumpTrue(absoluteOffset(offset)));
|
|
}
|
|
|
|
void BaselineJIT::generate_IteratorClose()
|
|
{
|
|
as->saveAccumulatorInFrame();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passAccumulatorAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(IteratorClose, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_DestructureRestElement()
|
|
{
|
|
as->saveAccumulatorInFrame();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passAccumulatorAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(DestructureRestElement, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_DeleteProperty(int base, int index)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(4);
|
|
as->passJSSlotAsArg(index, 3);
|
|
as->passJSSlotAsArg(base, 2);
|
|
as->passFunctionAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(DeleteProperty, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_DeleteName(int name)
|
|
{
|
|
STORE_IP();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passInt32AsArg(name, 2);
|
|
as->passFunctionAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(DeleteName, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_TypeofName(int name)
|
|
{
|
|
as->prepareCallWithArgCount(2);
|
|
as->passInt32AsArg(name, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(TypeofName, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_TypeofValue()
|
|
{
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passAccumulatorAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(TypeofValue, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_DeclareVar(int varName, int isDeletable)
|
|
{
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passInt32AsArg(varName, 2);
|
|
as->passInt32AsArg(isDeletable, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(DeclareVar, CallResultDestination::Ignore);
|
|
LOAD_ACC();
|
|
}
|
|
|
|
void BaselineJIT::generate_DefineArray(int argc, int args)
|
|
{
|
|
as->prepareCallWithArgCount(3);
|
|
as->passInt32AsArg(argc, 2);
|
|
as->passJSSlotAsArg(args, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(ArrayLiteral, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_DefineObjectLiteral(int internalClassId, int argc, int args)
|
|
{
|
|
as->prepareCallWithArgCount(4);
|
|
as->passInt32AsArg(argc, 3);
|
|
as->passJSSlotAsArg(args, 2);
|
|
as->passInt32AsArg(internalClassId, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(ObjectLiteral, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_CreateClass(int classIndex, int heritage, int computedNames)
|
|
{
|
|
as->prepareCallWithArgCount(4);
|
|
as->passJSSlotAsArg(computedNames, 3);
|
|
as->passJSSlotAsArg(heritage, 2);
|
|
as->passInt32AsArg(classIndex, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CreateClass, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_CreateMappedArgumentsObject()
|
|
{
|
|
as->prepareCallWithArgCount(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CreateMappedArgumentsObject,
|
|
CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_CreateUnmappedArgumentsObject()
|
|
{
|
|
as->prepareCallWithArgCount(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CreateUnmappedArgumentsObject,
|
|
CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_CreateRestParameter(int argIndex)
|
|
{
|
|
as->prepareCallWithArgCount(2);
|
|
as->passInt32AsArg(argIndex, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(CreateRestParameter, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_ConvertThisToObject()
|
|
{
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passJSSlotAsArg(CallData::This, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(ConvertThisToObject, CallResultDestination::InAccumulator);
|
|
as->storeReg(CallData::This);
|
|
LOAD_ACC();
|
|
}
|
|
|
|
void BaselineJIT::generate_LoadSuperConstructor()
|
|
{
|
|
as->prepareCallWithArgCount(2);
|
|
as->passJSSlotAsArg(CallData::Function, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(LoadSuperConstructor, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_ToObject()
|
|
{
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passAccumulatorAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(ToObject, CallResultDestination::InAccumulator);
|
|
|
|
}
|
|
|
|
void BaselineJIT::generate_Jump(int offset)
|
|
{
|
|
labels.insert(as->jump(absoluteOffset(offset)));
|
|
}
|
|
|
|
void BaselineJIT::generate_JumpTrue(int offset)
|
|
{
|
|
labels.insert(as->jumpTrue(absoluteOffset(offset)));
|
|
}
|
|
|
|
void BaselineJIT::generate_JumpFalse(int offset)
|
|
{
|
|
labels.insert(as->jumpFalse(absoluteOffset(offset)));
|
|
}
|
|
|
|
void BaselineJIT::generate_JumpNoException(int offset)
|
|
{
|
|
labels.insert(as->jumpNoException(absoluteOffset(offset)));
|
|
}
|
|
|
|
void BaselineJIT::generate_JumpNotUndefined(int offset)
|
|
{
|
|
labels.insert(as->jumpNotUndefined(absoluteOffset(offset)));
|
|
}
|
|
|
|
void BaselineJIT::generate_CheckException()
|
|
{
|
|
as->checkException();
|
|
}
|
|
|
|
void BaselineJIT::generate_CmpEqNull() { as->cmpeqNull(); }
|
|
void BaselineJIT::generate_CmpNeNull() { as->cmpneNull(); }
|
|
void BaselineJIT::generate_CmpEqInt(int lhs) { as->cmpeqInt(lhs); }
|
|
void BaselineJIT::generate_CmpNeInt(int lhs) { as->cmpneInt(lhs); }
|
|
void BaselineJIT::generate_CmpEq(int lhs) { as->cmpeq(lhs); }
|
|
void BaselineJIT::generate_CmpNe(int lhs) { as->cmpne(lhs); }
|
|
void BaselineJIT::generate_CmpGt(int lhs) { as->cmpgt(lhs); }
|
|
void BaselineJIT::generate_CmpGe(int lhs) { as->cmpge(lhs); }
|
|
void BaselineJIT::generate_CmpLt(int lhs) { as->cmplt(lhs); }
|
|
void BaselineJIT::generate_CmpLe(int lhs) { as->cmple(lhs); }
|
|
void BaselineJIT::generate_CmpStrictEqual(int lhs) { as->cmpStrictEqual(lhs); }
|
|
void BaselineJIT::generate_CmpStrictNotEqual(int lhs) { as->cmpStrictNotEqual(lhs); }
|
|
|
|
void BaselineJIT::generate_CmpIn(int lhs)
|
|
{
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passAccumulatorAsArg(2);
|
|
as->passJSSlotAsArg(lhs, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(In, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_CmpInstanceOf(int lhs)
|
|
{
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passAccumulatorAsArg(2);
|
|
as->passJSSlotAsArg(lhs, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(Instanceof, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_As(int lhs)
|
|
{
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(3);
|
|
as->passAccumulatorAsArg(2);
|
|
as->passJSSlotAsArg(lhs, 1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(As, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
void BaselineJIT::generate_UNot() { as->unot(); }
|
|
void BaselineJIT::generate_UPlus() { as->toNumber(); }
|
|
void BaselineJIT::generate_UMinus() { as->uminus(); }
|
|
void BaselineJIT::generate_UCompl() { as->ucompl(); }
|
|
void BaselineJIT::generate_Increment() { as->inc(); }
|
|
void BaselineJIT::generate_Decrement() { as->dec(); }
|
|
void BaselineJIT::generate_Add(int lhs) { as->add(lhs); }
|
|
|
|
void BaselineJIT::generate_BitAnd(int lhs) { as->bitAnd(lhs); }
|
|
void BaselineJIT::generate_BitOr(int lhs) { as->bitOr(lhs); }
|
|
void BaselineJIT::generate_BitXor(int lhs) { as->bitXor(lhs); }
|
|
void BaselineJIT::generate_UShr(int lhs) { as->ushr(lhs); }
|
|
void BaselineJIT::generate_Shr(int lhs) { as->shr(lhs); }
|
|
void BaselineJIT::generate_Shl(int lhs) { as->shl(lhs); }
|
|
|
|
void BaselineJIT::generate_BitAndConst(int rhs) { as->bitAndConst(rhs); }
|
|
void BaselineJIT::generate_BitOrConst(int rhs) { as->bitOrConst(rhs); }
|
|
void BaselineJIT::generate_BitXorConst(int rhs) { as->bitXorConst(rhs); }
|
|
void BaselineJIT::generate_UShrConst(int rhs) { as->ushrConst(rhs); }
|
|
void BaselineJIT::generate_ShrConst(int rhs) { as->shrConst(rhs); }
|
|
void BaselineJIT::generate_ShlConst(int rhs) { as->shlConst(rhs); }
|
|
|
|
void BaselineJIT::generate_Exp(int lhs) {
|
|
STORE_IP();
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passAccumulatorAsArg(1);
|
|
as->passJSSlotAsArg(lhs, 0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(Exp, CallResultDestination::InAccumulator);
|
|
}
|
|
void BaselineJIT::generate_Mul(int lhs) { as->mul(lhs); }
|
|
void BaselineJIT::generate_Div(int lhs) { as->div(lhs); }
|
|
void BaselineJIT::generate_Mod(int lhs) { as->mod(lhs); }
|
|
void BaselineJIT::generate_Sub(int lhs) { as->sub(lhs); }
|
|
|
|
//void BaselineJIT::generate_BinopContext(int alu, int lhs)
|
|
//{
|
|
// auto engine = function->internalClass->engine;
|
|
// void *op = engine->runtime.runtimeMethods[alu];
|
|
// STORE_ACC();
|
|
// as->passAccumulatorAsArg(2);
|
|
// as->passRegAsArg(lhs, 1);
|
|
// as->passEngineAsArg(0);
|
|
// as->callRuntime("binopContext", op, CallResultDestination::InAccumulator);
|
|
// as->checkException();
|
|
//}
|
|
|
|
void BaselineJIT::generate_InitializeBlockDeadTemporalZone(int firstReg, int count)
|
|
{
|
|
as->loadValue(Value::emptyValue().rawValue());
|
|
for (int i = firstReg, end = firstReg + count; i < end; ++i)
|
|
as->storeReg(i);
|
|
}
|
|
|
|
void BaselineJIT::generate_ThrowOnNullOrUndefined()
|
|
{
|
|
STORE_ACC();
|
|
as->prepareCallWithArgCount(2);
|
|
as->passAccumulatorAsArg(1);
|
|
as->passEngineAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(ThrowOnNullOrUndefined, CallResultDestination::Ignore);
|
|
LOAD_ACC();
|
|
}
|
|
|
|
void BaselineJIT::generate_GetTemplateObject(int index)
|
|
{
|
|
as->prepareCallWithArgCount(2);
|
|
as->passInt32AsArg(index, 1);
|
|
as->passFunctionAsArg(0);
|
|
BASELINEJIT_GENERATE_RUNTIME_CALL(GetTemplateObject, CallResultDestination::InAccumulator);
|
|
}
|
|
|
|
ByteCodeHandler::Verdict BaselineJIT::startInstruction(Instr::Type /*instr*/)
|
|
{
|
|
if (labels.contains(currentInstructionOffset()))
|
|
as->addLabel(currentInstructionOffset());
|
|
return ProcessInstruction;
|
|
}
|
|
|
|
void BaselineJIT::endInstruction(Instr::Type instr)
|
|
{
|
|
Q_UNUSED(instr);
|
|
}
|
|
|
|
#endif // QT_CONFIG(qml_jit)
|
|
|