509QV4::ReturnedValue
VME::interpret(JSTypesStackFrame *frame, ExecutionEngine *engine,
const char *code)
511 QV4::Function *function = frame->v4Function;
512 QV4::Value &accumulator = frame->jsFrame->accumulator.asValue<Value>();
513 QV4::ReturnedValue acc = accumulator.asReturnedValue();
514 Value *stack =
reinterpret_cast<Value *>(frame->jsFrame);
523 acc = constant(function, index).asReturnedValue();
527 acc = Encode::null();
531 acc = Encode(
static_cast<
int>(0));
543 acc = Encode::undefined();
551 STACK_VALUE(destTemp) = constant(function, constIndex);
567 acc = function->compilationUnit->imports[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 acc = cc->locals[index].asReturnedValue();
578 auto cc =
static_cast<Heap::CallContext *>(
STACK_VALUE(CallData::Context).m());
579 Q_ASSERT(cc->type != QV4::Heap::CallContext::Type_GlobalContext);
580 QV4::WriteBarrier::write(engine, cc, cc->locals.values[index].data_ptr(), acc);
584 auto cc = getScope(stack, scope);
585 acc = cc->locals[index].asReturnedValue();
590 auto cc = getScope(stack, scope);
591 QV4::WriteBarrier::write(engine, cc, cc->locals.values[index].data_ptr(), acc);
595 acc = function->compilationUnit->runtimeStrings[stringId]->asReturnedValue();
599 STACK_VALUE(destReg) = Runtime::RegexpLiteral::call(engine, regExpId);
603 acc = Runtime::Closure::call(engine, value);
608 acc = Runtime::LoadName::call(engine, name);
614 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
615 acc = l->globalGetter(engine);
621 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
622 acc = l->contextGetter(engine,
nullptr);
629 Runtime::StoreNameStrict::call(engine, name, accumulator);
636 Runtime::StoreNameSloppy::call(engine, name, accumulator);
643 acc = Runtime::LoadElement::call(engine,
STACK_VALUE(base), accumulator);
657 acc = Runtime::LoadProperty::call(engine, accumulator, name);
664 if (accumulator.isNullOrUndefined()) {
665 acc = Encode::undefined();
668 acc = Runtime::LoadProperty::call(engine, accumulator, name);
677 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
679 if (accumulator.isNullOrUndefined()) {
680 const QString message =
681 QStringLiteral(
"Cannot read property '%1' of %2")
682 .arg(engine->currentStackFrame->v4Function->compilationUnit
683 ->runtimeStrings[l->nameIndex]
685 accumulator.toQStringNoThrow());
686 acc = engine->throwTypeError(message);
690 acc = l->getter(engine, accumulator);
698 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
700 if (accumulator.isNullOrUndefined()) {
703 acc = l->getter(engine, accumulator);
711 Runtime::StoreProperty::call(engine,
STACK_VALUE(base), name, accumulator);
718 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
719 if (!l->setter(engine,
STACK_VALUE(base), accumulator) && function->isStrict())
720 engine->throwTypeError();
726 acc = Runtime::LoadSuperProperty::call(engine,
STACK_VALUE(property));
733 Runtime::StoreSuperProperty::call(engine,
STACK_VALUE(property), accumulator);
738 frame->setYield(code);
739 frame->setYieldIsIterator(
false);
744 frame->setYield(code);
745 frame->setYieldIsIterator(
true);
751 if (engine->hasException) {
753 if (engine->exceptionValue->asReturnedValue() != Value::emptyValue().asReturnedValue())
755 engine->hasException =
false;
756 *engine->exceptionValue = Value::undefinedValue();
764 acc = Runtime::IteratorNextForYieldStar::call(engine, accumulator,
STACK_VALUE(iterator), &
STACK_VALUE(object));
772 if (Q_UNLIKELY(!func.isFunctionObject())) {
773 acc = engine->throwTypeError(QStringLiteral(
"%1 is not a function").arg(func.toQStringNoThrow()));
776 Value undef = Value::undefinedValue();
777 acc =
static_cast<
const FunctionObject &>(func).call(&undef, stack + argv, argc);
784 if (Q_UNLIKELY(!func.isFunctionObject())) {
785 acc = engine->throwTypeError(QStringLiteral(
"%1 is not a function").arg(func.toQStringNoThrow()));
788 acc =
static_cast<
const FunctionObject &>(func).call(stack + thisObject, stack + argv, argc);
794 acc = Runtime::CallProperty::call(engine,
STACK_VALUE(base), name, stack + argv, argc);
800 Lookup *l = function->executableCompilationUnit()->runtimeLookups + lookupIndex;
803 const QString message =
804 QStringLiteral(
"Cannot call method '%1' of %2")
805 .arg(engine->currentStackFrame->v4Function->compilationUnit
806 ->runtimeStrings[l->nameIndex]
809 acc = engine->throwTypeError(message);
814 Value f = Value::fromReturnedValue(l->getter(engine,
STACK_VALUE(base)));
816 if (Q_LIKELY(f.isFunctionObject())) {
817 acc =
static_cast<FunctionObject &>(f).call(stack + base, stack + argv, argc);
818 }
else if (QmlSignalHandler *handler = f.as<QmlSignalHandler>()) {
819 acc = handler->call(stack + base, stack + argv, argc);
821 const QString message =
822 QStringLiteral(
"Property '%1' of object %2 is not a function")
823 .arg(engine->currentStackFrame->v4Function->compilationUnit
824 ->runtimeStrings[l->nameIndex]
827 acc = engine->throwTypeError(message);
836 acc = Runtime::CallName::call(engine, name, stack + argv, argc);
842 acc = Runtime::CallPossiblyDirectEval::call(engine, stack + argv, argc);
848 acc = Runtime::CallGlobalLookup::call(engine, index, stack + argv, argc);
854 acc = Runtime::CallQmlContextPropertyLookup::call(engine, index, stack + argv, argc);
860 acc = Runtime::CallWithSpread::call(engine,
STACK_VALUE(func),
STACK_VALUE(thisObject), stack + argv, argc);
866 *engine->jsAlloca(1) = Primitive::fromInt32(argc);
867 *engine->jsAlloca(1) = Primitive::fromInt32(argv);
870 return Runtime::TailCall::call(frame, engine);
877 acc = Runtime::Construct::call(engine,
STACK_VALUE(func),
ACC, stack + argv, argc);
884 acc = Runtime::ConstructWithSpread::call(engine,
STACK_VALUE(func),
ACC, stack + argv, argc);
889 frame->unwindHandler = offset ? code + offset :
nullptr;
894 if (frame->unwindLevel) {
895 --frame->unwindLevel;
896 if (frame->unwindLevel)
898 code = frame->unwindLabel;
903 frame->unwindLevel = level;
904 frame->unwindLabel = code + offset;
911 Runtime::ThrowReferenceError::call(engine, name);
919 Runtime::ThrowException::call(engine, accumulator);
924 acc = engine->hasException ? engine->exceptionValue->asReturnedValue()
925 : Value::emptyValue().asReturnedValue();
926 engine->hasException =
false;
930 if (acc != Value::emptyValue().asReturnedValue()) {
931 *engine->exceptionValue = acc;
932 engine->hasException =
true;
937 Runtime::PushCatchContext::call(engine, index, name);
941 Runtime::PushCallContext::call(frame);
947 acc = Runtime::PushWithContext::call(engine,
STACK_VALUE(CallData::Accumulator));
953 Runtime::PushBlockContext::call(engine, index);
958 Runtime::CloneBlockContext::call(engine);
962 Runtime::PushScriptContext::call(engine, index);
966 Runtime::PopScriptContext::call(engine);
970 ExecutionContext *c =
static_cast<ExecutionContext *>(stack + CallData::Context);
977 acc = Runtime::GetIterator::call(engine, accumulator, iterator);
984 acc = Runtime::IteratorNext::call(engine, accumulator, &
STACK_VALUE(value));
992 acc = Runtime::IteratorClose::call(engine, accumulator);
998 acc = Runtime::DestructureRestElement::call(engine,
ACC);
1008 acc = Runtime::DeleteName::call(engine, function, name);
1013 acc = Runtime::TypeofName::call(engine, name);
1018 acc = Runtime::TypeofValue::call(engine, accumulator);
1022 Runtime::DeclareVar::call(engine, isDeletable, varName);
1026 QV4::Value *arguments = stack + args;
1027 acc = Runtime::ArrayLiteral::call(engine, arguments, argc);
1031 QV4::Value *arguments = stack + args;
1032 acc = Runtime::ObjectLiteral::call(engine, internalClassId, arguments, argc);
1036 acc = Runtime::CreateClass::call(engine, classIndex,
STACK_VALUE(heritage), stack + computedNames);
1040 acc = Runtime::CreateMappedArgumentsObject::call(engine);
1044 acc = Runtime::CreateUnmappedArgumentsObject::call(engine);
1048 acc = Runtime::CreateRestParameter::call(engine, argIndex);
1053 stack[CallData::This] = Runtime::ConvertThisToObject::call(
1059 acc = Runtime::LoadSuperConstructor::call(engine,
STACK_VALUE(CallData::Function));
1065 acc =
ACC.toObject(engine)->asReturnedValue();
1075 if (Q_LIKELY(
ACC.integerCompatible()))
1076 takeJump =
ACC.int_32();
1078 takeJump =
ACC.toBoolean();
1085 if (Q_LIKELY(
ACC.integerCompatible()))
1086 takeJump = !
ACC.int_32();
1088 takeJump = !
ACC.toBoolean();
1094 if (!engine->hasException)
1099 if (Q_LIKELY(acc != QV4::Encode::undefined()))
1108 acc = Encode(
ACC.isNullOrUndefined());
1112 acc = Encode(!
ACC.isNullOrUndefined());
1116 if (
ACC.isIntOrBool()) {
1117 acc = Encode(
ACC.int_32() == lhs);
1120 acc = Encode(compareEqualInt(accumulator,
ACC, lhs));
1126 if (
ACC.isIntOrBool()) {
1127 acc = Encode(
bool(
ACC.int_32() != lhs));
1130 acc = Encode(!compareEqualInt(accumulator,
ACC, lhs));
1137 if (Q_LIKELY(left.asReturnedValue() ==
ACC.asReturnedValue())) {
1138 acc = Encode(!
ACC.isNaN());
1139 }
else if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1140 acc = Encode(left.int_32() ==
ACC.int_32());
1143 acc = Encode(
bool(Runtime::CompareEqual::call(left, accumulator)));
1150 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1151 acc = Encode(
bool(left.int_32() !=
ACC.int_32()));
1154 acc = Encode(
bool(!Runtime::CompareEqual::call(left, accumulator)));
1161 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1162 acc = Encode(left.int_32() >
ACC.int_32());
1163 }
else if (left.isNumber() &&
ACC.isNumber()) {
1164 acc = Encode(left.asDouble() >
ACC.asDouble());
1167 acc = Encode(
bool(Runtime::CompareGreaterThan::call(left, accumulator)));
1174 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1175 acc = Encode(left.int_32() >=
ACC.int_32());
1176 }
else if (left.isNumber() &&
ACC.isNumber()) {
1177 acc = Encode(left.asDouble() >=
ACC.asDouble());
1180 acc = Encode(
bool(Runtime::CompareGreaterEqual::call(left, accumulator)));
1187 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1188 acc = Encode(left.int_32() <
ACC.int_32());
1189 }
else if (left.isNumber() &&
ACC.isNumber()) {
1190 acc = Encode(left.asDouble() <
ACC.asDouble());
1193 acc = Encode(
bool(Runtime::CompareLessThan::call(left, accumulator)));
1200 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1201 acc = Encode(left.int_32() <=
ACC.int_32());
1202 }
else if (left.isNumber() &&
ACC.isNumber()) {
1203 acc = Encode(left.asDouble() <=
ACC.asDouble());
1206 acc = Encode(
bool(Runtime::CompareLessEqual::call(left, accumulator)));
1216 acc = Runtime::StrictEqual::call(
STACK_VALUE(lhs), accumulator);
1224 acc = Runtime::StrictNotEqual::call(
STACK_VALUE(lhs), accumulator);
1227 acc = Encode(
false);
1234 acc = Runtime::In::call(engine,
STACK_VALUE(lhs), accumulator);
1245 if (
ACC.integerCompatible()) {
1246 acc = Encode(!
static_cast<
bool>(
ACC.int_32()));
1248 acc = Encode(!Value::toBooleanImpl(
ACC));
1253 if (Q_UNLIKELY(!
ACC.isNumber())) {
1254 acc = Encode(
ACC.toNumberImpl());
1260 if (Q_LIKELY(
ACC.integerCompatible())) {
1261 int a =
ACC.int_32();
1262 if (a == 0 || a == std::numeric_limits<
int>::min()) {
1263 acc = Encode(-
static_cast<
double>(a));
1265 acc = sub_int32(0,
ACC.int_32());
1267 }
else if (
ACC.isDouble()) {
1268 acc ^= (1ull << 63);
1270 acc = Encode(-
ACC.toNumberImpl());
1281 if (Q_LIKELY(
ACC.integerCompatible())) {
1282 acc = add_int32(
ACC.int_32(), 1);
1283 }
else if (
ACC.isDouble()) {
1284 acc = QV4::Encode(
ACC.doubleValue() + 1.);
1286 acc = Encode(
ACC.toNumberImpl() + 1.);
1292 if (Q_LIKELY(
ACC.integerCompatible())) {
1293 acc = sub_int32(
ACC.int_32(), 1);
1294 }
else if (
ACC.isDouble()) {
1295 acc = QV4::Encode(
ACC.doubleValue() - 1.);
1297 acc = Encode(
ACC.toNumberImpl() - 1.);
1304 if (Q_LIKELY(Value::integerCompatible(left,
ACC))) {
1305 acc = add_int32(left.int_32(),
ACC.int_32());
1306 }
else if (left.isNumber() &&
ACC.isNumber()) {
1307 acc = Encode(left.asDouble() +
ACC.asDouble());
1310 acc = Runtime::Add::call(engine, left, accumulator);
1317 if (Q_LIKELY(Value::integerCompatible(left,
ACC))) {
1318 acc = sub_int32(left.int_32(),
ACC.int_32());
1319 }
else if (left.isNumber() &&
ACC.isNumber()) {
1320 acc = Encode(left.asDouble() -
ACC.asDouble());
1323 acc = Runtime::Sub::call(left, accumulator);
1331 acc = Runtime::As::call(engine, left, accumulator);
1336 double base = left.toNumber();
1337 double exp =
ACC.toNumber();
1338 acc = Encode(QQmlPrivate::jsExponentiate(base, exp));
1343 if (Q_LIKELY(Value::integerCompatible(left,
ACC))) {
1344 acc = mul_int32(left.int_32(),
ACC.int_32());
1345 }
else if (left.isNumber() &&
ACC.isNumber()) {
1346 acc = Encode(left.asDouble() *
ACC.asDouble());
1349 acc = Runtime::Mul::call(left, accumulator);
1356 acc = Runtime::Div::call(
STACK_VALUE(lhs), accumulator);
1362 acc = Runtime::Mod::call(
STACK_VALUE(lhs), accumulator);
1369 acc = Encode(l & a);
1375 acc = Encode(l | a);
1381 acc = Encode(l ^ a);
1387 acc = Encode(
static_cast<uint>(l) >> uint(a & 0x1f));
1393 acc = Encode(l >> (a & 0x1f));
1399 acc = Encode(l << (a & 0x1f));
1404 acc = Encode(a & rhs);
1410 acc = Encode(a | rhs);
1415 acc = Encode(a ^ rhs);
1419 acc = Encode(
ACC.toUInt32() >> uint(rhs));
1424 acc = Encode(a >> rhs);
1429 acc = Encode(a << rhs);
1437 acc = Encode(Value::emptyValue());
1438 for (
int i = firstReg, end = firstReg + count; i < end; ++i)
1443 if (Value::fromReturnedValue(acc).isNullOrUndefined()) {
1444 engine->throwTypeError();
1450 acc = Runtime::GetTemplateObject::call(function, index);
1454#if QT_CONFIG(qml_debug)
1456 debug_slowPath(engine);
1464 Q_ASSERT(engine->hasException || engine->isInterrupted.loadRelaxed() || frame->unwindLevel);
1465 if (!frame->unwindHandler) {
1466 acc = Encode::undefined();
1469 code = frame->unwindHandler;