📄 qscriptcontext_p.cpp
字号:
# define I(opc) qscript_execute_##opc# define Next() goto *iPtr->code# define Done() goto Ldone# define HandleException() goto Lhandle_exception static void *jump_table [] = {# define Q_SCRIPT_DEFINE_OPERATOR(op) &&I(op),# include "instruction.table"# undef Q_SCRIPT_DEFINE_OPERATOR }; // jump_table if (!code->optimized) { for (QScriptInstruction *current = code->firstInstruction; current != code->lastInstruction; ++current) { current->code = jump_table[current->op]; } code->optimized = true; }#endifLtop:#ifndef Q_SCRIPT_DIRECT_CODE switch (iPtr->op) {#else goto *iPtr->code;#endif I(Nop): { ++iPtr; } Next(); I(LoadUndefined): { CHECK_TEMPSTACK(1); eng->newUndefined(++stackPtr); ++iPtr; } Next(); I(LoadTrue): { CHECK_TEMPSTACK(1); eng->newBoolean(++stackPtr, true); ++iPtr; } Next(); I(LoadFalse): { CHECK_TEMPSTACK(1); eng->newBoolean(++stackPtr, false); ++iPtr; } Next(); I(LoadThis): { CHECK_TEMPSTACK(1); Q_ASSERT(m_thisObject.isObject()); *++stackPtr = m_thisObject; ++iPtr; } Next(); I(LoadNull): { CHECK_TEMPSTACK(1); eng->newNull(++stackPtr); ++iPtr; } Next(); I(LoadNumber): { CHECK_TEMPSTACK(1); *++stackPtr = iPtr->operand[0]; ++iPtr; } Next(); I(LoadString): { CHECK_TEMPSTACK(1); *++stackPtr = iPtr->operand[0]; ++iPtr; } Next(); I(NewString): { CHECK_TEMPSTACK(1); eng->newNameId(++stackPtr, iPtr->operand[0].m_string_value); ++iPtr; } Next(); I(Duplicate): { CHECK_TEMPSTACK(1); ++stackPtr; *stackPtr = stackPtr[-1]; ++iPtr; } Next(); I(Receive): { int n = iPtr->operand[0].m_int_value; if (n >= argc) { throwError(QLatin1String("invalid argument")); HandleException(); } CHECK_TEMPSTACK(1); *++stackPtr = argument(n); ++iPtr; } Next(); I(Fetch): { CHECK_TEMPSTACK(1); QScriptNameIdImpl *memberName = iPtr->operand[0].m_string_value; QScriptValueImpl base; QScript::Member member; QScriptObject *instance = m_scopeChain.m_object_value; if (instance->findMember(memberName, &member)) { instance->get(member, ++stackPtr); } else { if (m_scopeChain.resolve_helper(memberName, &member, &base, QScriptValue::ResolveFull)) { base.get(member, ++stackPtr); if (hasUncaughtException()) { stackPtr -= 1; HandleException(); } } else { throwNotDefined(memberName); HandleException(); } } if (member.isGetterOrSetter()) { // call the getter function QScriptValueImpl getter; if (member.isGetter()) { getter = *stackPtr; } else { if (!base.m_object_value->findGetter(&member)) { stackPtr -= 1; throwError(QLatin1String("No getter defined")); HandleException(); } base.get(member, &getter); } if (m_scopeChain.m_class == eng->m_class_with) *stackPtr = getter.call(m_scopeChain.prototype()); else *stackPtr = getter.call(m_scopeChain); if (hasUncaughtException()) { stackPtr -= 1; Done(); } } ++iPtr; } Next(); I(Resolve): { Q_ASSERT(iPtr->operand[0].isString()); CHECK_TEMPSTACK(2); *++stackPtr = m_scopeChain; *++stackPtr = iPtr->operand[0]; eng->newReference(++stackPtr, QScriptValue::ResolveScope); ++iPtr; } Next(); I(PutField): { Q_ASSERT(stackPtr[-1].isReference()); const QScriptValueImpl &object = stackPtr[-3]; QScriptNameIdImpl *memberName = stackPtr[-2].m_string_value; const QScriptValueImpl &value = stackPtr[0]; QScript::Member member; QScriptValueImpl base; if (! object.resolve(memberName, &member, &base, QScriptValue::ResolveLocal)) { base = object; CREATE_MEMBER(base, memberName, &member, /*flags=*/0); } base.put(member, value); stackPtr -= 4; if (hasUncaughtException()) HandleException(); ++iPtr; } Next(); I(Call): { int argc = iPtr->operand[0].m_int_value; QScriptValueImpl *argp = stackPtr - argc; QScriptValueImpl base; QScriptValueImpl callee; bool isReference = argp[0].isReference(); if (! isReference) { // we have a value base = eng->m_globalObject; callee = argp[0]; } else if (resolveField(eng, &argp[-1], &callee)) { if (hasUncaughtException()) { stackPtr = argp - 3; HandleException(); } base = argp[-2]; } else { QScriptValueImpl member = argp[-1]; stackPtr = argp - 1; Q_ASSERT(isReference); stackPtr -= 2; if (member.isString()) throwNotDefined(member.toString()); else throwNotDefined(QLatin1String("function")); HandleException(); } Q_ASSERT(base.isValid()); Q_ASSERT(callee.isValid()); QScriptFunction *function = eng->convertToNativeFunction(callee); if (! function) { QScriptValueImpl member = argp[-1]; QString message; if (member.isString()) { message = QString::fromLatin1("%0 is not a function") .arg(member.toString()); } else { message = QLatin1String("not a function"); } throwTypeError(message); HandleException(); } if (++eng->m_callDepth == eng->m_maxCallDepth) { throwError(QLatin1String("call stack overflow")); HandleException(); } QScriptContext *nested = eng->pushContext(); QScriptContextPrivate *nested_data = nested->d_func(); nested_data->m_thisObject = base; nested_data->m_callee = callee; // create the activation eng->newActivation(&nested_data->m_activation); QScriptObject *activation_data = nested_data->m_activation.m_object_value; int formalCount = function->formals.count(); int mx = qMax(formalCount, argc); activation_data->m_members.resize(mx); activation_data->m_objects.resize(mx); for (int i = 0; i < mx; ++i) { QScriptNameIdImpl *nameId = 0; if (i < formalCount) nameId = function->formals.at(i); activation_data->m_members[i].object(nameId, i, QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); activation_data->m_objects[i] = (i < argc) ? argp[i + 1] : undefined; } nested_data->argc = argc; if (callee.m_object_value->m_scope.isValid()) activation_data->m_scope = callee.m_object_value->m_scope; else activation_data->m_scope = eng->m_globalObject; nested_data->tempStack = stackPtr; nested_data->args = &argp[1]; function->execute(nested_data); --eng->m_callDepth; stackPtr = argp - 1; if (isReference) stackPtr -= 2; if (nested_data->m_state == QScriptContext::ExceptionState) { eng->popContext(); Done(); } CHECK_TEMPSTACK(1); *++stackPtr = nested_data->m_result; eng->popContext(); ++iPtr; } Next(); I(NewArray): { CHECK_TEMPSTACK(1); eng->arrayConstructor->newArray(++stackPtr); ++iPtr; } Next(); I(NewRegExp): { CHECK_TEMPSTACK(1); QString pattern = eng->toString(iPtr->operand[0].m_string_value);#ifndef QT_NO_REGEXP QString literal = pattern;#endif QString flags; if (iPtr->operand[1].isValid()) { flags = eng->toString(iPtr->operand[1].m_string_value);#ifndef QT_NO_REGEXP literal += QLatin1String("/"); literal += flags;#endif }#ifndef QT_NO_REGEXP QRegExp rx; // lazy compilation of regexp literals QHash<QString, QRegExp>::const_iterator it; it = eng->m_regExpLiterals.constFind(literal); if (it == eng->m_regExpLiterals.constEnd()) { bool ignoreCase = flags.contains(QLatin1Char('i')); rx = QRegExp(pattern, (ignoreCase ? Qt::CaseInsensitive: Qt::CaseSensitive), QRegExp::RegExp2); eng->m_regExpLiterals.insert(literal, rx); } else { rx = *it; } eng->regexpConstructor->newRegExp(++stackPtr, rx, flags);#else eng->regexpConstructor->newRegExp(++stackPtr, pattern, flags);#endif ++iPtr; } Next(); I(NewObject): { CHECK_TEMPSTACK(1); eng->objectConstructor->newObject(++stackPtr); ++iPtr; } Next(); I(New): { int argc = iPtr->operand[0].m_int_value; QScriptValueImpl *argp = stackPtr - argc; // QScriptValueImpl base; QScriptValueImpl callee; bool isReference = argp[0].isReference(); if (! isReference) { // we have a value // base = eng->globalObject; callee = argp[0]; } else if (resolveField(eng, &argp[-1], &callee)) { // base = argp[-2]; if (hasUncaughtException()) { stackPtr = argp - 3; HandleException(); } } else { QScriptValueImpl member = argp[-1]; stackPtr = argp - 1; Q_ASSERT(isReference); stackPtr -= 2; if (member.isString()) throwNotDefined(member.toString()); else throwNotDefined(QLatin1String("constructor")); HandleException(); } // Q_ASSERT(base.isValid()); Q_ASSERT(callee.isValid()); QScriptFunction *function = eng->convertToNativeFunction(callee); if (! function) { QScriptValueImpl member = argp[-1]; QString message; if (member.isString()) { message = QString::fromLatin1("%0 is not a constructor") .arg(member.toString()); } else { message = QLatin1String("not a constructor"); } throwTypeError(message); HandleException(); } if (++eng->m_callDepth == eng->m_maxCallDepth) { throwError(QLatin1String("call stack overflow")); HandleException(); } QScriptContext *nested = eng->pushContext(); QScriptContextPrivate *nested_data = nested->d_func(); nested_data->m_callee = callee; nested_data->m_calledAsConstructor = true; // create the activation eng->newActivation(&nested_data->m_activation); QScriptObject *activation_data = nested_data->m_activation.m_object_value; int formalCount = function->formals.count(); int mx = qMax(formalCount, argc); activation_data->m_members.resize(mx); activation_data->m_objects.resize(mx); for (int i = 0; i < mx; ++i) { QScriptNameIdImpl *nameId = 0; if (i < formalCount) nameId = function->formals.at(i); activation_data->m_members[i].object(nameId, i, QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); activation_data->m_objects[i] = (i < argc) ? argp[i + 1] : undefined; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -