502QV4::ReturnedValue
VME::interpret(JSTypesStackFrame *frame, ExecutionEngine *engine,
const char *code)
504 QV4::Function *function = frame->v4Function;
505 QV4::Value &accumulator = frame->jsFrame->accumulator.asValue<Value>();
506 QV4::ReturnedValue acc = accumulator.asReturnedValue();
507 Value *stack =
reinterpret_cast<Value *>(frame->jsFrame);
516 acc = constant(function, index).asReturnedValue();
520 acc = Encode::null();
524 acc = Encode(
static_cast<
int>(0));
536 acc = Encode::undefined();
544 STACK_VALUE(destTemp) = constant(function, constIndex);
560 acc = function->compilationUnit->imports[index]->asReturnedValue();
564 auto cc =
static_cast<Heap::CallContext *>(
STACK_VALUE(CallData::Context).m());
565 Q_ASSERT(cc->type != QV4::Heap::CallContext::Type_GlobalContext);
566 acc = cc->locals[index].asReturnedValue();
571 auto cc =
static_cast<Heap::CallContext *>(
STACK_VALUE(CallData::Context).m());
572 Q_ASSERT(cc->type != QV4::Heap::CallContext::Type_GlobalContext);
573 QV4::WriteBarrier::write(engine, cc, cc->locals.values[index].data_ptr(), acc);
577 auto cc = getScope(stack, scope);
578 acc = cc->locals[index].asReturnedValue();
583 auto cc = getScope(stack, scope);
584 QV4::WriteBarrier::write(engine, cc, cc->locals.values[index].data_ptr(), acc);
588 acc = function->compilationUnit->runtimeStrings[stringId]->asReturnedValue();
592 STACK_VALUE(destReg) = Runtime::RegexpLiteral::call(engine, regExpId);
596 acc = Runtime::Closure::call(engine, value);
601 acc = Runtime::LoadName::call(engine, name);
607 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
608 acc = l->globalGetter(engine);
614 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
615 acc = l->contextGetter(engine,
nullptr);
622 Runtime::StoreNameStrict::call(engine, name, accumulator);
629 Runtime::StoreNameSloppy::call(engine, name, accumulator);
636 acc = Runtime::LoadElement::call(engine,
STACK_VALUE(base), accumulator);
650 acc = Runtime::LoadProperty::call(engine, accumulator, name);
657 if (accumulator.isNullOrUndefined()) {
658 acc = Encode::undefined();
661 acc = Runtime::LoadProperty::call(engine, accumulator, name);
670 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
672 if (accumulator.isNullOrUndefined()) {
673 QString message = QStringLiteral(
"Cannot read property '%1' of %2")
674 .arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString())
675 .arg(accumulator.toQStringNoThrow());
676 acc = engine->throwTypeError(message);
680 acc = l->getter(engine, accumulator);
688 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
690 if (accumulator.isNullOrUndefined()) {
693 acc = l->getter(engine, accumulator);
701 Runtime::StoreProperty::call(engine,
STACK_VALUE(base), name, accumulator);
708 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
709 if (!l->setter(engine,
STACK_VALUE(base), accumulator) && function->isStrict())
710 engine->throwTypeError();
716 acc = Runtime::LoadSuperProperty::call(engine,
STACK_VALUE(property));
723 Runtime::StoreSuperProperty::call(engine,
STACK_VALUE(property), accumulator);
728 frame->setYield(code);
729 frame->setYieldIsIterator(
false);
734 frame->setYield(code);
735 frame->setYieldIsIterator(
true);
741 if (engine->hasException) {
743 if (engine->exceptionValue->asReturnedValue() != Value::emptyValue().asReturnedValue())
745 engine->hasException =
false;
746 *engine->exceptionValue = Value::undefinedValue();
754 acc = Runtime::IteratorNextForYieldStar::call(engine, accumulator,
STACK_VALUE(iterator), &
STACK_VALUE(object));
762 if (Q_UNLIKELY(!func.isFunctionObject())) {
763 acc = engine->throwTypeError(QStringLiteral(
"%1 is not a function").arg(func.toQStringNoThrow()));
766 Value undef = Value::undefinedValue();
767 acc =
static_cast<
const FunctionObject &>(func).call(&undef, stack + argv, argc);
774 if (Q_UNLIKELY(!func.isFunctionObject())) {
775 acc = engine->throwTypeError(QStringLiteral(
"%1 is not a function").arg(func.toQStringNoThrow()));
778 acc =
static_cast<
const FunctionObject &>(func).call(stack + thisObject, stack + argv, argc);
784 acc = Runtime::CallProperty::call(engine,
STACK_VALUE(base), name, stack + argv, argc);
790 Lookup *l = function->executableCompilationUnit()->runtimeLookups + lookupIndex;
793 QString message = QStringLiteral(
"Cannot call method '%1' of %2")
794 .arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString())
796 acc = engine->throwTypeError(message);
801 Value f = Value::fromReturnedValue(l->getter(engine,
STACK_VALUE(base)));
803 if (Q_LIKELY(f.isFunctionObject())) {
804 acc =
static_cast<FunctionObject &>(f).call(stack + base, stack + argv, argc);
805 }
else if (QmlSignalHandler *handler = f.as<QmlSignalHandler>()) {
806 acc = handler->call(stack + base, stack + argv, argc);
808 const QString message = QStringLiteral(
"Property '%1' of object %2 is not a function")
809 .arg(engine->currentStackFrame->v4Function->compilationUnit
810 ->runtimeStrings[l->nameIndex]->toQString())
812 acc = engine->throwTypeError(message);
821 acc = Runtime::CallName::call(engine, name, stack + argv, argc);
827 acc = Runtime::CallPossiblyDirectEval::call(engine, stack + argv, argc);
833 acc = Runtime::CallGlobalLookup::call(engine, index, stack + argv, argc);
839 acc = Runtime::CallQmlContextPropertyLookup::call(engine, index, stack + argv, argc);
845 acc = Runtime::CallWithSpread::call(engine,
STACK_VALUE(func),
STACK_VALUE(thisObject), stack + argv, argc);
851 *engine->jsAlloca(1) = Primitive::fromInt32(argc);
852 *engine->jsAlloca(1) = Primitive::fromInt32(argv);
855 return Runtime::TailCall::call(frame, engine);
862 acc = Runtime::Construct::call(engine,
STACK_VALUE(func),
ACC, stack + argv, argc);
869 acc = Runtime::ConstructWithSpread::call(engine,
STACK_VALUE(func),
ACC, stack + argv, argc);
874 frame->unwindHandler = offset ? code + offset :
nullptr;
879 if (frame->unwindLevel) {
880 --frame->unwindLevel;
881 if (frame->unwindLevel)
883 code = frame->unwindLabel;
888 frame->unwindLevel = level;
889 frame->unwindLabel = code + offset;
896 Runtime::ThrowReferenceError::call(engine, name);
904 Runtime::ThrowException::call(engine, accumulator);
909 acc = engine->hasException ? engine->exceptionValue->asReturnedValue()
910 : Value::emptyValue().asReturnedValue();
911 engine->hasException =
false;
915 if (acc != Value::emptyValue().asReturnedValue()) {
916 *engine->exceptionValue = acc;
917 engine->hasException =
true;
922 Runtime::PushCatchContext::call(engine, index, name);
926 Runtime::PushCallContext::call(frame);
932 acc = Runtime::PushWithContext::call(engine,
STACK_VALUE(CallData::Accumulator));
938 Runtime::PushBlockContext::call(engine, index);
943 Runtime::CloneBlockContext::call(engine);
947 Runtime::PushScriptContext::call(engine, index);
951 Runtime::PopScriptContext::call(engine);
955 ExecutionContext *c =
static_cast<ExecutionContext *>(stack + CallData::Context);
962 acc = Runtime::GetIterator::call(engine, accumulator, iterator);
969 acc = Runtime::IteratorNext::call(engine, accumulator, &
STACK_VALUE(value));
977 acc = Runtime::IteratorClose::call(engine, accumulator);
983 acc = Runtime::DestructureRestElement::call(engine,
ACC);
993 acc = Runtime::DeleteName::call(engine, function, name);
998 acc = Runtime::TypeofName::call(engine, name);
1003 acc = Runtime::TypeofValue::call(engine, accumulator);
1007 Runtime::DeclareVar::call(engine, isDeletable, varName);
1011 QV4::Value *arguments = stack + args;
1012 acc = Runtime::ArrayLiteral::call(engine, arguments, argc);
1016 QV4::Value *arguments = stack + args;
1017 acc = Runtime::ObjectLiteral::call(engine, internalClassId, arguments, argc);
1021 acc = Runtime::CreateClass::call(engine, classIndex,
STACK_VALUE(heritage), stack + computedNames);
1025 acc = Runtime::CreateMappedArgumentsObject::call(engine);
1029 acc = Runtime::CreateUnmappedArgumentsObject::call(engine);
1033 acc = Runtime::CreateRestParameter::call(engine, argIndex);
1038 stack[CallData::This] = Runtime::ConvertThisToObject::call(
1044 acc = Runtime::LoadSuperConstructor::call(engine,
STACK_VALUE(CallData::Function));
1050 acc =
ACC.toObject(engine)->asReturnedValue();
1060 if (Q_LIKELY(
ACC.integerCompatible()))
1061 takeJump =
ACC.int_32();
1063 takeJump =
ACC.toBoolean();
1070 if (Q_LIKELY(
ACC.integerCompatible()))
1071 takeJump = !
ACC.int_32();
1073 takeJump = !
ACC.toBoolean();
1079 if (!engine->hasException)
1084 if (Q_LIKELY(acc != QV4::Encode::undefined()))
1093 acc = Encode(
ACC.isNullOrUndefined());
1097 acc = Encode(!
ACC.isNullOrUndefined());
1101 if (
ACC.isIntOrBool()) {
1102 acc = Encode(
ACC.int_32() == lhs);
1105 acc = Encode(compareEqualInt(accumulator,
ACC, lhs));
1111 if (
ACC.isIntOrBool()) {
1112 acc = Encode(
bool(
ACC.int_32() != lhs));
1115 acc = Encode(!compareEqualInt(accumulator,
ACC, lhs));
1122 if (Q_LIKELY(left.asReturnedValue() ==
ACC.asReturnedValue())) {
1123 acc = Encode(!
ACC.isNaN());
1124 }
else if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1125 acc = Encode(left.int_32() ==
ACC.int_32());
1128 acc = Encode(
bool(Runtime::CompareEqual::call(left, accumulator)));
1135 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1136 acc = Encode(
bool(left.int_32() !=
ACC.int_32()));
1139 acc = Encode(
bool(!Runtime::CompareEqual::call(left, accumulator)));
1146 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1147 acc = Encode(left.int_32() >
ACC.int_32());
1148 }
else if (left.isNumber() &&
ACC.isNumber()) {
1149 acc = Encode(left.asDouble() >
ACC.asDouble());
1152 acc = Encode(
bool(Runtime::CompareGreaterThan::call(left, accumulator)));
1159 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1160 acc = Encode(left.int_32() >=
ACC.int_32());
1161 }
else if (left.isNumber() &&
ACC.isNumber()) {
1162 acc = Encode(left.asDouble() >=
ACC.asDouble());
1165 acc = Encode(
bool(Runtime::CompareGreaterEqual::call(left, accumulator)));
1172 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1173 acc = Encode(left.int_32() <
ACC.int_32());
1174 }
else if (left.isNumber() &&
ACC.isNumber()) {
1175 acc = Encode(left.asDouble() <
ACC.asDouble());
1178 acc = Encode(
bool(Runtime::CompareLessThan::call(left, accumulator)));
1185 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1186 acc = Encode(left.int_32() <=
ACC.int_32());
1187 }
else if (left.isNumber() &&
ACC.isNumber()) {
1188 acc = Encode(left.asDouble() <=
ACC.asDouble());
1191 acc = Encode(
bool(Runtime::CompareLessEqual::call(left, accumulator)));
1201 acc = Runtime::StrictEqual::call(
STACK_VALUE(lhs), accumulator);
1209 acc = Runtime::StrictNotEqual::call(
STACK_VALUE(lhs), accumulator);
1212 acc = Encode(
false);
1219 acc = Runtime::In::call(engine,
STACK_VALUE(lhs), accumulator);
1230 if (
ACC.integerCompatible()) {
1231 acc = Encode(!
static_cast<
bool>(
ACC.int_32()));
1233 acc = Encode(!Value::toBooleanImpl(
ACC));
1238 if (Q_UNLIKELY(!
ACC.isNumber())) {
1239 acc = Encode(
ACC.toNumberImpl());
1245 if (Q_LIKELY(
ACC.integerCompatible())) {
1246 int a =
ACC.int_32();
1247 if (a == 0 || a == std::numeric_limits<
int>::min()) {
1248 acc = Encode(-
static_cast<
double>(a));
1250 acc = sub_int32(0,
ACC.int_32());
1252 }
else if (
ACC.isDouble()) {
1253 acc ^= (1ull << 63);
1255 acc = Encode(-
ACC.toNumberImpl());
1266 if (Q_LIKELY(
ACC.integerCompatible())) {
1267 acc = add_int32(
ACC.int_32(), 1);
1268 }
else if (
ACC.isDouble()) {
1269 acc = QV4::Encode(
ACC.doubleValue() + 1.);
1271 acc = Encode(
ACC.toNumberImpl() + 1.);
1277 if (Q_LIKELY(
ACC.integerCompatible())) {
1278 acc = sub_int32(
ACC.int_32(), 1);
1279 }
else if (
ACC.isDouble()) {
1280 acc = QV4::Encode(
ACC.doubleValue() - 1.);
1282 acc = Encode(
ACC.toNumberImpl() - 1.);
1289 if (Q_LIKELY(Value::integerCompatible(left,
ACC))) {
1290 acc = add_int32(left.int_32(),
ACC.int_32());
1291 }
else if (left.isNumber() &&
ACC.isNumber()) {
1292 acc = Encode(left.asDouble() +
ACC.asDouble());
1295 acc = Runtime::Add::call(engine, left, accumulator);
1302 if (Q_LIKELY(Value::integerCompatible(left,
ACC))) {
1303 acc = sub_int32(left.int_32(),
ACC.int_32());
1304 }
else if (left.isNumber() &&
ACC.isNumber()) {
1305 acc = Encode(left.asDouble() -
ACC.asDouble());
1308 acc = Runtime::Sub::call(left, accumulator);
1316 acc = Runtime::As::call(engine, left, accumulator);
1321 double base = left.toNumber();
1322 double exp =
ACC.toNumber();
1323 acc = Encode(QQmlPrivate::jsExponentiate(base, exp));
1328 if (Q_LIKELY(Value::integerCompatible(left,
ACC))) {
1329 acc = mul_int32(left.int_32(),
ACC.int_32());
1330 }
else if (left.isNumber() &&
ACC.isNumber()) {
1331 acc = Encode(left.asDouble() *
ACC.asDouble());
1334 acc = Runtime::Mul::call(left, accumulator);
1341 acc = Runtime::Div::call(
STACK_VALUE(lhs), accumulator);
1347 acc = Runtime::Mod::call(
STACK_VALUE(lhs), accumulator);
1354 acc = Encode(l & a);
1360 acc = Encode(l | a);
1366 acc = Encode(l ^ a);
1372 acc = Encode(
static_cast<uint>(l) >> uint(a & 0x1f));
1378 acc = Encode(l >> (a & 0x1f));
1384 acc = Encode(l << (a & 0x1f));
1389 acc = Encode(a & rhs);
1395 acc = Encode(a | rhs);
1400 acc = Encode(a ^ rhs);
1404 acc = Encode(
ACC.toUInt32() >> uint(rhs));
1409 acc = Encode(a >> rhs);
1414 acc = Encode(a << rhs);
1422 acc = Encode(Value::emptyValue());
1423 for (
int i = firstReg, end = firstReg + count; i < end; ++i)
1428 if (Value::fromReturnedValue(acc).isNullOrUndefined()) {
1429 engine->throwTypeError();
1435 acc = Runtime::GetTemplateObject::call(function, index);
1439#if QT_CONFIG(qml_debug)
1441 debug_slowPath(engine);
1449 Q_ASSERT(engine->hasException || engine->isInterrupted.loadRelaxed() || frame->unwindLevel);
1450 if (!frame->unwindHandler) {
1451 acc = Encode::undefined();
1454 code = frame->unwindHandler;