📄 interpreter.cpp
字号:
ASSERT(m_opcodeIDTable.size() == numOpcodeIDs); #endif // HAVE(COMPUTED_GOTO) return noValue(); }#if ENABLE(JIT) // Currently with CTI enabled we never interpret functions ASSERT_NOT_REACHED();#endif JSGlobalData* globalData = &callFrame->globalData(); JSValuePtr exceptionValue = noValue(); HandlerInfo* handler = 0; Instruction* vPC = callFrame->codeBlock()->instructions().begin(); Profiler** enabledProfilerReference = Profiler::enabledProfilerReference(); unsigned tickCount = globalData->timeoutChecker.ticksUntilNextCheck();#define CHECK_FOR_EXCEPTION() \ do { \ if (UNLIKELY(globalData->exception != noValue())) { \ exceptionValue = globalData->exception; \ goto vm_throw; \ } \ } while (0)#if ENABLE(OPCODE_STATS) OpcodeStats::resetLastInstruction();#endif#define CHECK_FOR_TIMEOUT() \ if (!--tickCount) { \ if (globalData->timeoutChecker.didTimeOut(callFrame)) { \ exceptionValue = jsNull(); \ goto vm_throw; \ } \ tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); \ } #if ENABLE(OPCODE_SAMPLING) #define SAMPLE(codeBlock, vPC) m_sampler->sample(codeBlock, vPC)#else #define SAMPLE(codeBlock, vPC)#endif#if HAVE(COMPUTED_GOTO) #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto *vPC->u.opcode#if ENABLE(OPCODE_STATS) #define DEFINE_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);#else #define DEFINE_OPCODE(opcode) opcode:#endif NEXT_INSTRUCTION();#else #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto interpreterLoopStart#if ENABLE(OPCODE_STATS) #define DEFINE_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);#else #define DEFINE_OPCODE(opcode) case opcode:#endif while (1) { // iterator loop begins interpreterLoopStart:; switch (vPC->u.opcode)#endif { DEFINE_OPCODE(op_new_object) { /* new_object dst(r) Constructs a new empty Object instance using the original constructor, and puts the result in register dst. */ int dst = (++vPC)->u.operand; callFrame[dst] = JSValuePtr(constructEmptyObject(callFrame)); ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_new_array) { /* new_array dst(r) firstArg(r) argCount(n) Constructs a new Array instance using the original constructor, and puts the result in register dst. The array will contain argCount elements with values taken from registers starting at register firstArg. */ int dst = (++vPC)->u.operand; int firstArg = (++vPC)->u.operand; int argCount = (++vPC)->u.operand; ArgList args(callFrame->registers() + firstArg, argCount); callFrame[dst] = JSValuePtr(constructArray(callFrame, args)); ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_new_regexp) { /* new_regexp dst(r) regExp(re) Constructs a new RegExp instance using the original constructor from regexp regExp, and puts the result in register dst. */ int dst = (++vPC)->u.operand; int regExp = (++vPC)->u.operand; callFrame[dst] = JSValuePtr(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexp(regExp))); ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_mov) { /* mov dst(r) src(r) Copies register src to register dst. */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; callFrame[dst] = callFrame[src]; ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_eq) { /* eq dst(r) src1(r) src2(r) Checks whether register src1 and register src2 are equal, as with the ECMAScript '==' operator, and puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) callFrame[dst] = JSFastMath::equal(src1, src2); else { JSValuePtr result = jsBoolean(JSValuePtr::equalSlowCase(callFrame, src1, src2)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_eq_null) { /* eq_null dst(r) src(r) Checks whether register src is null, as with the ECMAScript '!=' operator, and puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame); if (src.isUndefinedOrNull()) { callFrame[dst] = jsBoolean(true); ++vPC; NEXT_INSTRUCTION(); } callFrame[dst] = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined()); ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_neq) { /* neq dst(r) src1(r) src2(r) Checks whether register src1 and register src2 are not equal, as with the ECMAScript '!=' operator, and puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) callFrame[dst] = JSFastMath::notEqual(src1, src2); else { JSValuePtr result = jsBoolean(!JSValuePtr::equalSlowCase(callFrame, src1, src2)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_neq_null) { /* neq_null dst(r) src(r) Checks whether register src is not null, as with the ECMAScript '!=' operator, and puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame); if (src.isUndefinedOrNull()) { callFrame[dst] = jsBoolean(false); ++vPC; NEXT_INSTRUCTION(); } callFrame[dst] = jsBoolean(!src.isCell() || !asCell(src)->structure()->typeInfo().masqueradesAsUndefined()); ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_stricteq) { /* stricteq dst(r) src1(r) src2(r) Checks whether register src1 and register src2 are strictly equal, as with the ECMAScript '===' operator, and puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); callFrame[dst] = jsBoolean(JSValuePtr::strictEqual(src1, src2)); ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_nstricteq) { /* nstricteq dst(r) src1(r) src2(r) Checks whether register src1 and register src2 are not strictly equal, as with the ECMAScript '!==' operator, and puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); callFrame[dst] = jsBoolean(!JSValuePtr::strictEqual(src1, src2)); ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_less) { /* less dst(r) src1(r) src2(r) Checks whether register src1 is less than register src2, as with the ECMAScript '<' operator, and puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); JSValuePtr result = jsBoolean(jsLess(callFrame, src1, src2)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_lesseq) { /* lesseq dst(r) src1(r) src2(r) Checks whether register src1 is less than or equal to register src2, as with the ECMAScript '<=' operator, and puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); JSValuePtr result = jsBoolean(jsLessEq(callFrame, src1, src2)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_pre_inc) { /* pre_inc srcDst(r) Converts register srcDst to number, adds one, and puts the result back in register srcDst. */ int srcDst = (++vPC)->u.operand; JSValuePtr v = callFrame[srcDst].jsValue(callFrame); if (JSFastMath::canDoFastAdditiveOperations(v)) callFrame[srcDst] = JSValuePtr(JSFastMath::incImmediateNumber(v)); else { JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) + 1); CHECK_FOR_EXCEPTION(); callFrame[srcDst] = result; } ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_pre_dec) { /* pre_dec srcDst(r) Converts register srcDst to number, subtracts one, and puts the result back in register srcDst. */ int srcDst = (++vPC)->u.operand; JSValuePtr v = callFrame[srcDst].jsValue(callFrame); if (JSFastMath::canDoFastAdditiveOperations(v)) callFrame[srcDst] = JSValuePtr(JSFastMath::decImmediateNumber(v)); else { JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) - 1); CHECK_FOR_EXCEPTION(); callFrame[srcDst] = result; } ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_post_inc) { /* post_inc dst(r) srcDst(r) Converts register srcDst to number. The number itself is written to register dst, and the number plus one is written back to register srcDst. */ int dst = (++vPC)->u.operand; int srcDst = (++vPC)->u.operand; JSValuePtr v = callFrame[srcDst].jsValue(callFrame); if (JSFastMath::canDoFastAdditiveOperations(v)) { callFrame[dst] = v; callFrame[srcDst] = JSValuePtr(JSFastMath::incImmediateNumber(v)); } else { JSValuePtr number = callFrame[srcDst].jsValue(callFrame).toJSNumber(callFrame); CHECK_FOR_EXCEPTION(); callFrame[dst] = number; callFrame[srcDst] = JSValuePtr(jsNumber(callFrame, number.uncheckedGetNumber() + 1)); } ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_post_dec) { /* post_dec dst(r) srcDst(r) Converts register srcDst to number. The number itself is written to register dst, and the number minus one is written back to register srcDst. */ int dst = (++vPC)->u.operand; int srcDst = (++vPC)->u.operand; JSValuePtr v = callFrame[srcDst].jsValue(callFrame); if (JSFastMath::canDoFastAdditiveOperations(v)) { callFrame[dst] = v; callFrame[srcDst] = JSValuePtr(JSFastMath::decImmediateNumber(v));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -