📄 bytecodegenerator.cpp
字号:
ASSERT(!m_scopeContextStack.last().isFinallyBlock); emitOpcode(op_pop_scope); m_scopeContextStack.removeLast(); m_dynamicScopeDepth--;}void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine){ if (!m_shouldEmitDebugHooks) return; emitOpcode(op_debug); instructions().append(debugHookID); instructions().append(firstLine); instructions().append(lastLine);}void BytecodeGenerator::pushFinallyContext(Label* target, RegisterID* retAddrDst){ ControlFlowContext scope; scope.isFinallyBlock = true; FinallyContext context = { target, retAddrDst }; scope.finallyContext = context; m_scopeContextStack.append(scope); m_finallyDepth++;}void BytecodeGenerator::popFinallyContext(){ ASSERT(m_scopeContextStack.size()); ASSERT(m_scopeContextStack.last().isFinallyBlock); ASSERT(m_finallyDepth > 0); m_scopeContextStack.removeLast(); m_finallyDepth--;}LabelScope* BytecodeGenerator::breakTarget(const Identifier& name){ // Reclaim free label scopes. while (m_labelScopes.size() && !m_labelScopes.last().refCount()) m_labelScopes.removeLast(); if (!m_labelScopes.size()) return 0; // We special-case the following, which is a syntax error in Firefox: // label: // break; if (name.isEmpty()) { for (int i = m_labelScopes.size() - 1; i >= 0; --i) { LabelScope* scope = &m_labelScopes[i]; if (scope->type() != LabelScope::NamedLabel) { ASSERT(scope->breakTarget()); return scope; } } return 0; } for (int i = m_labelScopes.size() - 1; i >= 0; --i) { LabelScope* scope = &m_labelScopes[i]; if (scope->name() && *scope->name() == name) { ASSERT(scope->breakTarget()); return scope; } } return 0;}LabelScope* BytecodeGenerator::continueTarget(const Identifier& name){ // Reclaim free label scopes. while (m_labelScopes.size() && !m_labelScopes.last().refCount()) m_labelScopes.removeLast(); if (!m_labelScopes.size()) return 0; if (name.isEmpty()) { for (int i = m_labelScopes.size() - 1; i >= 0; --i) { LabelScope* scope = &m_labelScopes[i]; if (scope->type() == LabelScope::Loop) { ASSERT(scope->continueTarget()); return scope; } } return 0; } // Continue to the loop nested nearest to the label scope that matches // 'name'. LabelScope* result = 0; for (int i = m_labelScopes.size() - 1; i >= 0; --i) { LabelScope* scope = &m_labelScopes[i]; if (scope->type() == LabelScope::Loop) { ASSERT(scope->continueTarget()); result = scope; } if (scope->name() && *scope->name() == name) return result; // may be 0 } return 0;}PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope){ while (topScope > bottomScope) { // First we count the number of dynamic scopes we need to remove to get // to a finally block. int nNormalScopes = 0; while (topScope > bottomScope) { if (topScope->isFinallyBlock) break; ++nNormalScopes; --topScope; } if (nNormalScopes) { // We need to remove a number of dynamic scopes to get to the next // finally block emitOpcode(op_jmp_scopes); instructions().append(nNormalScopes); // If topScope == bottomScope then there isn't actually a finally block // left to emit, so make the jmp_scopes jump directly to the target label if (topScope == bottomScope) { instructions().append(target->offsetFrom(instructions().size())); return target; } // Otherwise we just use jmp_scopes to pop a group of scopes and go // to the next instruction RefPtr<Label> nextInsn = newLabel(); instructions().append(nextInsn->offsetFrom(instructions().size())); emitLabel(nextInsn.get()); } // To get here there must be at least one finally block present do { ASSERT(topScope->isFinallyBlock); emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr); --topScope; if (!topScope->isFinallyBlock) break; } while (topScope > bottomScope); } return emitJump(target);}PassRefPtr<Label> BytecodeGenerator::emitJumpScopes(Label* target, int targetScopeDepth){ ASSERT(scopeDepth() - targetScopeDepth >= 0); ASSERT(target->isForward()); size_t scopeDelta = scopeDepth() - targetScopeDepth; ASSERT(scopeDelta <= m_scopeContextStack.size()); if (!scopeDelta) return emitJump(target); if (m_finallyDepth) return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta); emitOpcode(op_jmp_scopes); instructions().append(scopeDelta); instructions().append(target->offsetFrom(instructions().size())); return target;}RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target){ emitOpcode(op_next_pname); instructions().append(dst->index()); instructions().append(iter->index()); instructions().append(target->offsetFrom(instructions().size())); return dst;}RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end){#if ENABLE(JIT) HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, MacroAssembler::CodeLocationLabel() };#else HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };#endif m_codeBlock->addExceptionHandler(info); emitOpcode(op_catch); instructions().append(targetRegister->index()); return targetRegister;}RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValuePtr message){ emitOpcode(op_new_error); instructions().append(dst->index()); instructions().append(static_cast<int>(type)); instructions().append(addUnexpectedConstant(message)); return dst;}PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally){ emitOpcode(op_jsr); instructions().append(retAddrDst->index()); instructions().append(finally->offsetFrom(instructions().size())); return finally;}void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc){ emitOpcode(op_sret); instructions().append(retAddrSrc->index());}void BytecodeGenerator::emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value){ ControlFlowContext context; context.isFinallyBlock = false; m_scopeContextStack.append(context); m_dynamicScopeDepth++; emitOpcode(op_push_new_scope); instructions().append(dst->index()); instructions().append(addConstant(property)); instructions().append(value->index());}void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type){ SwitchInfo info = { instructions().size(), type }; switch (type) { case SwitchInfo::SwitchImmediate: emitOpcode(op_switch_imm); break; case SwitchInfo::SwitchCharacter: emitOpcode(op_switch_char); break; case SwitchInfo::SwitchString: emitOpcode(op_switch_string); break; default: ASSERT_NOT_REACHED(); } instructions().append(0); // place holder for table index instructions().append(0); // place holder for default target instructions().append(scrutineeRegister->index()); m_switchContextStack.append(info);}static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t max){ UNUSED_PARAM(max); ASSERT(node->isNumber()); double value = static_cast<NumberNode*>(node)->value(); int32_t key = static_cast<int32_t>(value); ASSERT(JSValuePtr::makeInt32Fast(key) && (JSValuePtr::makeInt32Fast(key).getInt32Fast() == value)); ASSERT(key == value); ASSERT(key >= min); ASSERT(key <= max); return key - min;}static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max){ jumpTable.min = min; jumpTable.branchOffsets.resize(max - min + 1); jumpTable.branchOffsets.fill(0); for (uint32_t i = 0; i < clauseCount; ++i) { // We're emitting this after the clause labels should have been fixed, so // the labels should not be "forward" references ASSERT(!labels[i]->isForward()); jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); }}static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t max){ UNUSED_PARAM(max); ASSERT(node->isString()); UString::Rep* clause = static_cast<StringNode*>(node)->value().ustring().rep(); ASSERT(clause->size() == 1); int32_t key = clause->data()[0]; ASSERT(key >= min); ASSERT(key <= max); return key - min;}static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max){ jumpTable.min = min; jumpTable.branchOffsets.resize(max - min + 1); jumpTable.branchOffsets.fill(0); for (uint32_t i = 0; i < clauseCount; ++i) { // We're emitting this after the clause labels should have been fixed, so // the labels should not be "forward" references ASSERT(!labels[i]->isForward()); jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); }}static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes){ for (uint32_t i = 0; i < clauseCount; ++i) { // We're emitting this after the clause labels should have been fixed, so // the labels should not be "forward" references ASSERT(!labels[i]->isForward()); ASSERT(nodes[i]->isString()); UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep(); OffsetLocation location; location.branchOffset = labels[i]->offsetFrom(switchAddress); jumpTable.offsetTable.add(clause, location); }}void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, Label* defaultLabel, int32_t min, int32_t max){ SwitchInfo switchInfo = m_switchContextStack.last(); m_switchContextStack.removeLast(); if (switchInfo.switchType == SwitchInfo::SwitchImmediate) { instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfImmediateSwitchJumpTables(); instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3); SimpleJumpTable& jumpTable = m_codeBlock->addImmediateSwitchJumpTable(); prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max); } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) { instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfCharacterSwitchJumpTables(); instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3); SimpleJumpTable& jumpTable = m_codeBlock->addCharacterSwitchJumpTable(); prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max); } else { ASSERT(switchInfo.switchType == SwitchInfo::SwitchString); instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables(); instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3); StringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable(); prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes); }}RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException(){ // It would be nice to do an even better job of identifying exactly where the expression is. // And we could make the caller pass the node pointer in, if there was some way of getting // that from an arbitrary node. However, calling emitExpressionInfo without any useful data // is still good enough to get us an accurate line number. emitExpressionInfo(0, 0, 0); RegisterID* exception = emitNewError(newTemporary(), SyntaxError, jsString(globalData(), "Expression too deep")); emitThrow(exception); return exception;}} // namespace JSC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -