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 const QString message =
674 QStringLiteral(
"Cannot read property '%1' of %2")
675 .arg(engine->currentStackFrame->v4Function->compilationUnit
676 ->runtimeStrings[l->nameIndex]
678 accumulator.toQStringNoThrow());
679 acc = engine->throwTypeError(message);
683 acc = l->getter(engine, accumulator);
691 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
693 if (accumulator.isNullOrUndefined()) {
696 acc = l->getter(engine, accumulator);
704 Runtime::StoreProperty::call(engine,
STACK_VALUE(base), name, accumulator);
711 QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
712 if (!l->setter(engine,
STACK_VALUE(base), accumulator) && function->isStrict())
713 engine->throwTypeError();
719 acc = Runtime::LoadSuperProperty::call(engine,
STACK_VALUE(property));
726 Runtime::StoreSuperProperty::call(engine,
STACK_VALUE(property), accumulator);
731 frame->setYield(code);
732 frame->setYieldIsIterator(
false);
737 frame->setYield(code);
738 frame->setYieldIsIterator(
true);
744 if (engine->hasException) {
746 if (engine->exceptionValue->asReturnedValue() != Value::emptyValue().asReturnedValue())
748 engine->hasException =
false;
749 *engine->exceptionValue = Value::undefinedValue();
757 acc = Runtime::IteratorNextForYieldStar::call(engine, accumulator,
STACK_VALUE(iterator), &
STACK_VALUE(object));
765 if (Q_UNLIKELY(!func.isFunctionObject())) {
766 acc = engine->throwTypeError(QStringLiteral(
"%1 is not a function").arg(func.toQStringNoThrow()));
769 Value undef = Value::undefinedValue();
770 acc =
static_cast<
const FunctionObject &>(func).call(&undef, stack + argv, argc);
777 if (Q_UNLIKELY(!func.isFunctionObject())) {
778 acc = engine->throwTypeError(QStringLiteral(
"%1 is not a function").arg(func.toQStringNoThrow()));
781 acc =
static_cast<
const FunctionObject &>(func).call(stack + thisObject, stack + argv, argc);
787 acc = Runtime::CallProperty::call(engine,
STACK_VALUE(base), name, stack + argv, argc);
793 Lookup *l = function->executableCompilationUnit()->runtimeLookups + lookupIndex;
796 const QString message =
797 QStringLiteral(
"Cannot call method '%1' of %2")
798 .arg(engine->currentStackFrame->v4Function->compilationUnit
799 ->runtimeStrings[l->nameIndex]
802 acc = engine->throwTypeError(message);
807 Value f = Value::fromReturnedValue(l->getter(engine,
STACK_VALUE(base)));
809 if (Q_LIKELY(f.isFunctionObject())) {
810 acc =
static_cast<FunctionObject &>(f).call(stack + base, stack + argv, argc);
811 }
else if (QmlSignalHandler *handler = f.as<QmlSignalHandler>()) {
812 acc = handler->call(stack + base, stack + argv, argc);
814 const QString message =
815 QStringLiteral(
"Property '%1' of object %2 is not a function")
816 .arg(engine->currentStackFrame->v4Function->compilationUnit
817 ->runtimeStrings[l->nameIndex]
820 acc = engine->throwTypeError(message);
829 acc = Runtime::CallName::call(engine, name, stack + argv, argc);
835 acc = Runtime::CallPossiblyDirectEval::call(engine, stack + argv, argc);
841 acc = Runtime::CallGlobalLookup::call(engine, index, stack + argv, argc);
847 acc = Runtime::CallQmlContextPropertyLookup::call(engine, index, stack + argv, argc);
853 acc = Runtime::CallWithSpread::call(engine,
STACK_VALUE(func),
STACK_VALUE(thisObject), stack + argv, argc);
859 *engine->jsAlloca(1) = Primitive::fromInt32(argc);
860 *engine->jsAlloca(1) = Primitive::fromInt32(argv);
863 return Runtime::TailCall::call(frame, engine);
870 acc = Runtime::Construct::call(engine,
STACK_VALUE(func),
ACC, stack + argv, argc);
877 acc = Runtime::ConstructWithSpread::call(engine,
STACK_VALUE(func),
ACC, stack + argv, argc);
882 frame->unwindHandler = offset ? code + offset :
nullptr;
887 if (frame->unwindLevel) {
888 --frame->unwindLevel;
889 if (frame->unwindLevel)
891 code = frame->unwindLabel;
896 frame->unwindLevel = level;
897 frame->unwindLabel = code + offset;
904 Runtime::ThrowReferenceError::call(engine, name);
912 Runtime::ThrowException::call(engine, accumulator);
917 acc = engine->hasException ? engine->exceptionValue->asReturnedValue()
918 : Value::emptyValue().asReturnedValue();
919 engine->hasException =
false;
923 if (acc != Value::emptyValue().asReturnedValue()) {
924 *engine->exceptionValue = acc;
925 engine->hasException =
true;
930 Runtime::PushCatchContext::call(engine, index, name);
934 Runtime::PushCallContext::call(frame);
940 acc = Runtime::PushWithContext::call(engine,
STACK_VALUE(CallData::Accumulator));
946 Runtime::PushBlockContext::call(engine, index);
951 Runtime::CloneBlockContext::call(engine);
955 Runtime::PushScriptContext::call(engine, index);
959 Runtime::PopScriptContext::call(engine);
963 ExecutionContext *c =
static_cast<ExecutionContext *>(stack + CallData::Context);
970 acc = Runtime::GetIterator::call(engine, accumulator, iterator);
977 acc = Runtime::IteratorNext::call(engine, accumulator, &
STACK_VALUE(value));
985 acc = Runtime::IteratorClose::call(engine, accumulator);
991 acc = Runtime::DestructureRestElement::call(engine,
ACC);
1001 acc = Runtime::DeleteName::call(engine, function, name);
1006 acc = Runtime::TypeofName::call(engine, name);
1011 acc = Runtime::TypeofValue::call(engine, accumulator);
1015 Runtime::DeclareVar::call(engine, isDeletable, varName);
1019 QV4::Value *arguments = stack + args;
1020 acc = Runtime::ArrayLiteral::call(engine, arguments, argc);
1024 QV4::Value *arguments = stack + args;
1025 acc = Runtime::ObjectLiteral::call(engine, internalClassId, arguments, argc);
1029 acc = Runtime::CreateClass::call(engine, classIndex,
STACK_VALUE(heritage), stack + computedNames);
1033 acc = Runtime::CreateMappedArgumentsObject::call(engine);
1037 acc = Runtime::CreateUnmappedArgumentsObject::call(engine);
1041 acc = Runtime::CreateRestParameter::call(engine, argIndex);
1046 stack[CallData::This] = Runtime::ConvertThisToObject::call(
1052 acc = Runtime::LoadSuperConstructor::call(engine,
STACK_VALUE(CallData::Function));
1058 acc =
ACC.toObject(engine)->asReturnedValue();
1068 if (Q_LIKELY(
ACC.integerCompatible()))
1069 takeJump =
ACC.int_32();
1071 takeJump =
ACC.toBoolean();
1078 if (Q_LIKELY(
ACC.integerCompatible()))
1079 takeJump = !
ACC.int_32();
1081 takeJump = !
ACC.toBoolean();
1087 if (!engine->hasException)
1092 if (Q_LIKELY(acc != QV4::Encode::undefined()))
1101 acc = Encode(
ACC.isNullOrUndefined());
1105 acc = Encode(!
ACC.isNullOrUndefined());
1109 if (
ACC.isIntOrBool()) {
1110 acc = Encode(
ACC.int_32() == lhs);
1113 acc = Encode(compareEqualInt(accumulator,
ACC, lhs));
1119 if (
ACC.isIntOrBool()) {
1120 acc = Encode(
bool(
ACC.int_32() != lhs));
1123 acc = Encode(!compareEqualInt(accumulator,
ACC, lhs));
1130 if (Q_LIKELY(left.asReturnedValue() ==
ACC.asReturnedValue())) {
1131 acc = Encode(!
ACC.isNaN());
1132 }
else if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1133 acc = Encode(left.int_32() ==
ACC.int_32());
1136 acc = Encode(
bool(Runtime::CompareEqual::call(left, accumulator)));
1143 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1144 acc = Encode(
bool(left.int_32() !=
ACC.int_32()));
1147 acc = Encode(
bool(!Runtime::CompareEqual::call(left, accumulator)));
1154 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1155 acc = Encode(left.int_32() >
ACC.int_32());
1156 }
else if (left.isNumber() &&
ACC.isNumber()) {
1157 acc = Encode(left.asDouble() >
ACC.asDouble());
1160 acc = Encode(
bool(Runtime::CompareGreaterThan::call(left, accumulator)));
1167 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1168 acc = Encode(left.int_32() >=
ACC.int_32());
1169 }
else if (left.isNumber() &&
ACC.isNumber()) {
1170 acc = Encode(left.asDouble() >=
ACC.asDouble());
1173 acc = Encode(
bool(Runtime::CompareGreaterEqual::call(left, accumulator)));
1180 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1181 acc = Encode(left.int_32() <
ACC.int_32());
1182 }
else if (left.isNumber() &&
ACC.isNumber()) {
1183 acc = Encode(left.asDouble() <
ACC.asDouble());
1186 acc = Encode(
bool(Runtime::CompareLessThan::call(left, accumulator)));
1193 if (Q_LIKELY(left.isInteger() &&
ACC.isInteger())) {
1194 acc = Encode(left.int_32() <=
ACC.int_32());
1195 }
else if (left.isNumber() &&
ACC.isNumber()) {
1196 acc = Encode(left.asDouble() <=
ACC.asDouble());
1199 acc = Encode(
bool(Runtime::CompareLessEqual::call(left, accumulator)));
1209 acc = Runtime::StrictEqual::call(
STACK_VALUE(lhs), accumulator);
1217 acc = Runtime::StrictNotEqual::call(
STACK_VALUE(lhs), accumulator);
1220 acc = Encode(
false);
1227 acc = Runtime::In::call(engine,
STACK_VALUE(lhs), accumulator);
1238 if (
ACC.integerCompatible()) {
1239 acc = Encode(!
static_cast<
bool>(
ACC.int_32()));
1241 acc = Encode(!Value::toBooleanImpl(
ACC));
1246 if (Q_UNLIKELY(!
ACC.isNumber())) {
1247 acc = Encode(
ACC.toNumberImpl());
1253 if (Q_LIKELY(
ACC.integerCompatible())) {
1254 int a =
ACC.int_32();
1255 if (a == 0 || a == std::numeric_limits<
int>::min()) {
1256 acc = Encode(-
static_cast<
double>(a));
1258 acc = sub_int32(0,
ACC.int_32());
1260 }
else if (
ACC.isDouble()) {
1261 acc ^= (1ull << 63);
1263 acc = Encode(-
ACC.toNumberImpl());
1274 if (Q_LIKELY(
ACC.integerCompatible())) {
1275 acc = add_int32(
ACC.int_32(), 1);
1276 }
else if (
ACC.isDouble()) {
1277 acc = QV4::Encode(
ACC.doubleValue() + 1.);
1279 acc = Encode(
ACC.toNumberImpl() + 1.);
1285 if (Q_LIKELY(
ACC.integerCompatible())) {
1286 acc = sub_int32(
ACC.int_32(), 1);
1287 }
else if (
ACC.isDouble()) {
1288 acc = QV4::Encode(
ACC.doubleValue() - 1.);
1290 acc = Encode(
ACC.toNumberImpl() - 1.);
1297 if (Q_LIKELY(Value::integerCompatible(left,
ACC))) {
1298 acc = add_int32(left.int_32(),
ACC.int_32());
1299 }
else if (left.isNumber() &&
ACC.isNumber()) {
1300 acc = Encode(left.asDouble() +
ACC.asDouble());
1303 acc = Runtime::Add::call(engine, left, accumulator);
1310 if (Q_LIKELY(Value::integerCompatible(left,
ACC))) {
1311 acc = sub_int32(left.int_32(),
ACC.int_32());
1312 }
else if (left.isNumber() &&
ACC.isNumber()) {
1313 acc = Encode(left.asDouble() -
ACC.asDouble());
1316 acc = Runtime::Sub::call(left, accumulator);
1324 acc = Runtime::As::call(engine, left, accumulator);
1329 double base = left.toNumber();
1330 double exp =
ACC.toNumber();
1331 acc = Encode(QQmlPrivate::jsExponentiate(base, exp));
1336 if (Q_LIKELY(Value::integerCompatible(left,
ACC))) {
1337 acc = mul_int32(left.int_32(),
ACC.int_32());
1338 }
else if (left.isNumber() &&
ACC.isNumber()) {
1339 acc = Encode(left.asDouble() *
ACC.asDouble());
1342 acc = Runtime::Mul::call(left, accumulator);
1349 acc = Runtime::Div::call(
STACK_VALUE(lhs), accumulator);
1355 acc = Runtime::Mod::call(
STACK_VALUE(lhs), accumulator);
1362 acc = Encode(l & a);
1368 acc = Encode(l | a);
1374 acc = Encode(l ^ a);
1380 acc = Encode(
static_cast<uint>(l) >> uint(a & 0x1f));
1386 acc = Encode(l >> (a & 0x1f));
1392 acc = Encode(l << (a & 0x1f));
1397 acc = Encode(a & rhs);
1403 acc = Encode(a | rhs);
1408 acc = Encode(a ^ rhs);
1412 acc = Encode(
ACC.toUInt32() >> uint(rhs));
1417 acc = Encode(a >> rhs);
1422 acc = Encode(a << rhs);
1430 acc = Encode(Value::emptyValue());
1431 for (
int i = firstReg, end = firstReg + count; i < end; ++i)
1436 if (Value::fromReturnedValue(acc).isNullOrUndefined()) {
1437 engine->throwTypeError();
1443 acc = Runtime::GetTemplateObject::call(function, index);
1447#if QT_CONFIG(qml_debug)
1449 debug_slowPath(engine);
1457 Q_ASSERT(engine->hasException || engine->isInterrupted.loadRelaxed() || frame->unwindLevel);
1458 if (!frame->unwindHandler) {
1459 acc = Encode::undefined();
1462 code = frame->unwindHandler;