JavaScript系列(65)--虚拟机实现详解

devtools/2025/2/10 17:48:21/

JavaScript虚拟机实现详解 🚀

今天,让我们深入探讨JavaScript虚拟机的实现。虚拟机是JavaScript引擎的核心组件,它负责执行字节码并管理运行时环境。

虚拟机基础概念 🌟

💡 小知识:JavaScript虚拟机是一个抽象的计算机,它提供了执行JavaScript代码所需的运行时环境。虚拟机负责管理内存、执行字节码、进行优化等核心任务。

基础虚拟机实现 📊

javascript">// 1. 词法分析器
class Lexer {constructor(source) {this.source = source;this.position = 0;this.tokens = [];}tokenize() {while (this.position < this.source.length) {const char = this.source[this.position];if (this.isWhitespace(char)) {this.position++;continue;}if (this.isNumber(char)) {this.tokens.push(this.readNumber());continue;}if (this.isIdentifierStart(char)) {this.tokens.push(this.readIdentifier());continue;}if (this.isOperator(char)) {this.tokens.push(this.readOperator());continue;}this.position++;}return this.tokens;}readNumber() {let value = '';while (this.position < this.source.length && this.isNumber(this.source[this.position])) {value += this.source[this.position++];}return { type: 'NUMBER', value: Number(value) };}readIdentifier() {let value = '';while (this.position < this.source.length && this.isIdentifierPart(this.source[this.position])) {value += this.source[this.position++];}return { type: 'IDENTIFIER', value };}readOperator() {const char = this.source[this.position++];return { type: 'OPERATOR', value: char };}isWhitespace(char) {return /\s/.test(char);}isNumber(char) {return /[0-9]/.test(char);}isIdentifierStart(char) {return /[a-zA-Z_$]/.test(char);}isIdentifierPart(char) {return /[a-zA-Z0-9_$]/.test(char);}isOperator(char) {return /[+\-*\/=<>!&|^%]/.test(char);}
}// 2. 语法分析器
class Parser {constructor(tokens) {this.tokens = tokens;this.position = 0;}parse() {const program = {type: 'Program',body: []};while (this.position < this.tokens.length) {program.body.push(this.parseStatement());}return program;}parseStatement() {const token = this.peek();switch (token.type) {case 'IDENTIFIER':if (token.value === 'let' || token.value === 'const' || token.value === 'var') {return this.parseVariableDeclaration();}return this.parseExpressionStatement();default:return this.parseExpressionStatement();}}parseVariableDeclaration() {const kind = this.consume().value;const declarations = [];do {const id = this.consume('IDENTIFIER');let init = null;if (this.peek().value === '=') {this.consume();init = this.parseExpression();}declarations.push({type: 'VariableDeclarator',id: { type: 'Identifier', name: id.value },init});} while (this.peek().value === ',' && this.consume());return {type: 'VariableDeclaration',kind,declarations};}parseExpression() {return this.parseBinaryExpression();}parseBinaryExpression(precedence = 0) {let left = this.parseUnaryExpression();while (true) {const operator = this.peek();const newPrecedence = this.getOperatorPrecedence(operator);if (newPrecedence <= precedence) {break;}this.consume();const right = this.parseBinaryExpression(newPrecedence);left = {type: 'BinaryExpression',operator: operator.value,left,right};}return left;}parseUnaryExpression() {if (this.isUnaryOperator(this.peek())) {const operator = this.consume();const argument = this.parseUnaryExpression();return {type: 'UnaryExpression',operator: operator.value,argument};}return this.parsePrimaryExpression();}parsePrimaryExpression() {const token = this.peek();switch (token.type) {case 'NUMBER':return {type: 'Literal',value: this.consume().value};case 'IDENTIFIER':return {type: 'Identifier',name: this.consume().value};default:throw new Error(`Unexpected token: ${token.type}`);}}peek() {return this.tokens[this.position];}consume(expectedType) {const token = this.tokens[this.position++];if (expectedType && token.type !== expectedType) {throw new Error(`Expected token type ${expectedType}, got ${token.type}`);}return token;}getOperatorPrecedence(token) {if (token.type !== 'OPERATOR') return 0;switch (token.value) {case '*':case '/':return 2;case '+':case '-':return 1;default:return 0;}}isUnaryOperator(token) {return token.type === 'OPERATOR' && (token.value === '-' || token.value === '!');}
}// 3. 字节码生成器
class BytecodeGenerator {constructor() {this.instructions = [];this.constants = new Map();}generate(ast) {this.visit(ast);return {instructions: this.instructions,constants: Array.from(this.constants.entries())};}visit(node) {const method = `visit${node.type}`;if (this[method]) {return this[method](node);}throw new Error(`Unknown node type: ${node.type}`);}visitProgram(node) {node.body.forEach(statement => this.visit(statement));}visitVariableDeclaration(node) {node.declarations.forEach(declarator => {if (declarator.init) {this.visit(declarator.init);this.emit('STORE_VAR', declarator.id.name);}});}visitBinaryExpression(node) {this.visit(node.left);this.visit(node.right);switch (node.operator) {case '+':this.emit('ADD');break;case '-':this.emit('SUBTRACT');break;case '*':this.emit('MULTIPLY');break;case '/':this.emit('DIVIDE');break;}}visitUnaryExpression(node) {this.visit(node.argument);switch (node.operator) {case '-':this.emit('NEGATE');break;case '!':this.emit('NOT');break;}}visitLiteral(node) {const constantIndex = this.addConstant(node.value);this.emit('LOAD_CONST', constantIndex);}visitIdentifier(node) {this.emit('LOAD_VAR', node.name);}emit(opcode, ...operands) {this.instructions.push({ opcode, operands });}addConstant(value) {const index = this.constants.size;this.constants.set(index, value);return index;}
}

虚拟机执行引擎 🚀

javascript">// 1. 虚拟机实现
class VirtualMachine {constructor() {this.stack = [];this.variables = new Map();this.callStack = [];}execute(bytecode) {const { instructions, constants } = bytecode;let ip = 0; // 指令指针while (ip < instructions.length) {const { opcode, operands } = instructions[ip];switch (opcode) {case 'LOAD_CONST':this.stack.push(constants[operands[0]][1]);break;case 'LOAD_VAR':const value = this.variables.get(operands[0]);if (value === undefined) {throw new Error(`Undefined variable: ${operands[0]}`);}this.stack.push(value);break;case 'STORE_VAR':this.variables.set(operands[0], this.stack.pop());break;case 'ADD':const b = this.stack.pop();const a = this.stack.pop();this.stack.push(a + b);break;case 'SUBTRACT':const right = this.stack.pop();const left = this.stack.pop();this.stack.push(left - right);break;case 'MULTIPLY':this.stack.push(this.stack.pop() * this.stack.pop());break;case 'DIVIDE':const divisor = this.stack.pop();const dividend = this.stack.pop();this.stack.push(dividend / divisor);break;case 'NEGATE':this.stack.push(-this.stack.pop());break;case 'NOT':this.stack.push(!this.stack.pop());break;default:throw new Error(`Unknown opcode: ${opcode}`);}ip++;}return this.stack.pop();}
}// 2. 内存管理器
class MemoryManager {constructor() {this.heap = new Map();this.nextAddress = 1;}allocate(size) {const address = this.nextAddress;this.heap.set(address, new Array(size));this.nextAddress += size;return address;}free(address) {this.heap.delete(address);}read(address, offset = 0) {const block = this.heap.get(address);if (!block) {throw new Error(`Invalid memory address: ${address}`);}return block[offset];}write(address, value, offset = 0) {const block = this.heap.get(address);if (!block) {throw new Error(`Invalid memory address: ${address}`);}block[offset] = value;}
}// 3. 垃圾回收器
class GarbageCollector {constructor(memoryManager) {this.memoryManager = memoryManager;this.roots = new Set();this.marked = new Set();}addRoot(address) {this.roots.add(address);}removeRoot(address) {this.roots.delete(address);}mark() {this.marked.clear();for (const root of this.roots) {this.markObject(root);}}markObject(address) {if (this.marked.has(address)) return;this.marked.add(address);const object = this.memoryManager.read(address);// 递归标记对象引用if (typeof object === 'object' && object !== null) {for (const value of Object.values(object)) {if (typeof value === 'number' && this.memoryManager.heap.has(value)) {this.markObject(value);}}}}sweep() {for (const address of this.memoryManager.heap.keys()) {if (!this.marked.has(address)) {this.memoryManager.free(address);}}}collect() {this.mark();this.sweep();}
}

优化技术实现 ⚡

javascript">// 1. JIT编译器
class JITCompiler {constructor() {this.cache = new Map();this.thresholds = new Map();}compile(bytecode) {const key = this.getBytecodeKey(bytecode);if (this.cache.has(key)) {return this.cache.get(key);}const compiledFunction = this.generateNativeCode(bytecode);this.cache.set(key, compiledFunction);return compiledFunction;}getBytecodeKey(bytecode) {return JSON.stringify(bytecode.instructions);}generateNativeCode(bytecode) {// 这里应该生成实际的机器码// 为了演示,我们返回一个优化的JavaScript函数return function optimizedExecute(vm) {const stack = [];const variables = vm.variables;for (const { opcode, operands } of bytecode.instructions) {switch (opcode) {case 'LOAD_CONST':stack.push(bytecode.constants[operands[0]][1]);break;case 'ADD':const b = stack.pop();const a = stack.pop();stack.push(a + b);break;// ... 其他操作码的优化实现}}return stack.pop();};}shouldCompile(bytecode) {const key = this.getBytecodeKey(bytecode);const count = (this.thresholds.get(key) || 0) + 1;this.thresholds.set(key, count);return count > 10; // 执行超过10次时进行编译}
}// 2. 优化器
class Optimizer {optimize(bytecode) {return this.applyOptimizations(bytecode, [this.constantFolding,this.deadCodeElimination,this.instructionCombining]);}applyOptimizations(bytecode, optimizations) {let optimized = bytecode;for (const optimization of optimizations) {optimized = optimization.call(this, optimized);}return optimized;}constantFolding(bytecode) {const newInstructions = [];const stack = [];for (const instruction of bytecode.instructions) {if (this.isConstantOperation(instruction)) {const result = this.evaluateConstantOperation(instruction,stack);newInstructions.push({opcode: 'LOAD_CONST',operands: [bytecode.constants.length]});bytecode.constants.push([bytecode.constants.length, result]);} else {newInstructions.push(instruction);}}return { ...bytecode, instructions: newInstructions };}deadCodeElimination(bytecode) {const newInstructions = [];const usedVariables = new Set();// 向后扫描找出使用的变量for (const { opcode, operands } of bytecode.instructions) {if (opcode === 'LOAD_VAR') {usedVariables.add(operands[0]);}}// 保留有用的指令for (const instruction of bytecode.instructions) {if (instruction.opcode !== 'STORE_VAR' || usedVariables.has(instruction.operands[0])) {newInstructions.push(instruction);}}return { ...bytecode, instructions: newInstructions };}instructionCombining(bytecode) {const newInstructions = [];for (let i = 0; i < bytecode.instructions.length; i++) {const current = bytecode.instructions[i];const next = bytecode.instructions[i + 1];if (this.canCombineInstructions(current, next)) {newInstructions.push(this.combineInstructions(current, next));i++; // 跳过下一条指令} else {newInstructions.push(current);}}return { ...bytecode, instructions: newInstructions };}isConstantOperation(instruction) {return ['ADD', 'SUBTRACT', 'MULTIPLY', 'DIVIDE'].includes(instruction.opcode);}evaluateConstantOperation(instruction, stack) {const b = stack.pop();const a = stack.pop();switch (instruction.opcode) {case 'ADD': return a + b;case 'SUBTRACT': return a - b;case 'MULTIPLY': return a * b;case 'DIVIDE': return a / b;default: throw new Error(`Unknown operation: ${instruction.opcode}`);}}canCombineInstructions(first, second) {// 检查是否可以合并的逻辑return false; // 简化示例}combineInstructions(first, second) {// 合并指令的逻辑return first; // 简化示例}
}

最佳实践建议 💡

  1. 性能优化策略
javascript">// 1. 指令缓存
class InstructionCache {constructor(size = 1000) {this.cache = new Map();this.maxSize = size;}get(key) {return this.cache.get(key);}set(key, value) {if (this.cache.size >= this.maxSize) {const firstKey = this.cache.keys().next().value;this.cache.delete(firstKey);}this.cache.set(key, value);}
}// 2. 热路径检测
class HotPathDetector {constructor() {this.executionCounts = new Map();this.hotPaths = new Set();}recordExecution(path) {const count = (this.executionCounts.get(path) || 0) + 1;this.executionCounts.set(path, count);if (count > 100 && !this.hotPaths.has(path)) {this.hotPaths.add(path);this.optimizePath(path);}}optimizePath(path) {// 实现热路径优化逻辑}
}// 3. 内存管理优化
class OptimizedMemoryManager {constructor() {this.smallObjectPool = new Map();this.largeObjectPool = new Map();}allocate(size) {if (size < 1024) {return this.allocateFromPool(this.smallObjectPool,size);}return this.allocateFromPool(this.largeObjectPool,size);}allocateFromPool(pool, size) {if (!pool.has(size)) {pool.set(size, []);}const objects = pool.get(size);return objects.length > 0 ? objects.pop() : new Array(size);}
}

结语 📝

JavaScript虚拟机是一个复杂但非常有趣的系统。通过本文,我们学习了:

  1. 虚拟机的基本概念和实现原理
  2. 词法分析、语法分析和字节码生成
  3. 虚拟机执行引擎的实现
  4. JIT编译和优化技术
  5. 内存管理和垃圾回收

💡 学习建议:在实现虚拟机时,要特别注意性能优化和内存管理。合理使用JIT编译、指令缓存等技术可以显著提升执行效率。同时,要注意处理边界情况和错误处理。


如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻


http://www.ppmy.cn/devtools/157303.html

相关文章

电脑开机提示按f1原因分析及终极解决方法来了

经常有网友问到一个问题&#xff0c;我电脑开机后提示按f1怎么解决&#xff1f;不管理是台式电脑&#xff0c;还是笔记本&#xff0c;都有可能会遇到开机需要按F1&#xff0c;才能进入系统的问题&#xff0c;引起这个问题的原因比较多&#xff0c;今天小编在这里给大家列举了比…

TLS 和 SSL区别

TLS 与 SSL 的区别 TLS&#xff08;传输层安全协议&#xff09;和 SSL&#xff08;安全套接字层&#xff09;都是用于加密网络通信的协议&#xff0c;特别是在 Web 流量&#xff08;如 HTTPS&#xff09;中保护数据传输的安全。虽然它们有相似的功能和目的&#xff0c;但在协议…

机试题——句子平均重量

题目描述 这是一个小岛上的传统活动&#xff0c;每年夏天居民们会举办一场盛大的比赛&#xff0c;以庆祝丰收和团结精神。比赛的主要环节是选手们轮流背诵他们准备好的一句话&#xff0c;而评判会根据每个句子的平均重量来评分。 今年&#xff0c;比赛的主题是环保&#xff0…

深入浅出:机器学习的全面解析

深入浅出&#xff1a;机器学习的全面解析 引言 机器学习&#xff08;Machine Learning, ML&#xff09;作为人工智能的一个重要分支&#xff0c;近年来取得了显著进展&#xff0c;并在多个领域中得到了广泛应用。本文将从基础概念、核心算法、应用场景以及未来发展趋势等方面…

golang使用sqlite3,开启wal模式,并发读写

因为sqlite是基于文件的&#xff0c;所以默认情况下&#xff0c;sqlite是不支持并发读写的&#xff0c;即写操作会阻塞其他操作&#xff0c;同时sqlite也很容易就产生死锁。 但是作为一个使用广泛的离线数据库&#xff0c;从sqlite3.7.0版本开始&#xff08;SQLite Release 3.…

Delphi语言的云计算

Delphi语言的云计算应用探索 引言 随着信息技术的迅猛发展&#xff0c;云计算已经成为现代计算机科学中一个不可或缺的重要组成部分。云计算不仅改变了企业的IT基础设施部署方式&#xff0c;还开启了新一轮的经济发展模式。开发者们也在积极寻找合适的编程语言&#xff0c;以…

Linux(CentOS)安装 Nginx

CentOS版本&#xff1a;CentOS 7 Nginx版本&#xff1a;1.24.0 两种安装方式&#xff1a; 一、通过 yum 安装&#xff0c;最简单&#xff0c;一键安装&#xff0c;全程无忧。 二、通过编译源码包安装&#xff0c;需具备配置相关操作。 最后附&#xff1a;设置 Nginx 服务开…

OpenSIPS-Dispatcher模块详解:优化SIP流量分发的利器

在 OpenSIPS 中&#xff0c;dispatcher 模块用于实现负载均衡和故障转移。通过 dispatcher 模块&#xff0c;你可以将 SIP 请求分发到一组后端服务器&#xff08;如媒体服务器、代理服务器等&#xff09;&#xff0c;并根据配置的算法和策略动态调整分发逻辑。 模块功能使用样…