Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit69dddd4

Browse files
committed
LibJS: Start fleshing out a bytecode for the JavaScript engine :^)
This patch begins the work of implementing JavaScript execution in abytecode VM instead of an AST tree-walk interpreter.It's probably quite naive, but we have to start somewhere.The basic idea is that you call Bytecode::Generator::generate() on anAST node and it hands you back a Bytecode::Block filled withinstructions that can then be interpreted by a Bytecode::Interpreter.This first version only implements two instructions: Load and Add. :^)Each bytecode block has infinity registers, and the interpreter resizesits register file to fit the block being executed.Two new `js` options are added in this patch as well:`-d` will dump the generated bytecode`-b` will execute the generated bytecodeNote that unless `-d` and/or `-b` are specified, none of the bytecoderelated stuff in LibJS runs at all. This is implemented in parallelwith the existing AST interpreter. :^)
1 parentf9395ef commit69dddd4

File tree

16 files changed

+487
-24
lines changed

16 files changed

+487
-24
lines changed

‎Userland/Libraries/LibJS/AST.cpp‎

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
2+
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
33
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
44
*
55
* SPDX-License-Identifier: BSD-2-Clause
@@ -13,6 +13,9 @@
1313
#include<AK/TemporaryChange.h>
1414
#include<LibCrypto/BigInt/SignedBigInteger.h>
1515
#include<LibJS/AST.h>
16+
#include<LibJS/Bytecode/Generator.h>
17+
#include<LibJS/Bytecode/Op.h>
18+
#include<LibJS/Bytecode/Register.h>
1619
#include<LibJS/Interpreter.h>
1720
#include<LibJS/Runtime/Accessor.h>
1821
#include<LibJS/Runtime/Array.h>
@@ -2234,4 +2237,49 @@ void ScopeNode::add_functions(NonnullRefPtrVector<FunctionDeclaration> functions
22342237
m_functions.append(move(functions));
22352238
}
22362239

2240+
Optional<Bytecode::Register>ASTNode::generate_bytecode(Bytecode::Generator&)const
2241+
{
2242+
dbgln("Missing generate_bytecode()");
2243+
TODO();
2244+
}
2245+
2246+
Optional<Bytecode::Register>ScopeNode::generate_bytecode(Bytecode::Generator& generator)const
2247+
{
2248+
for (auto& child :children()) {
2249+
[[maybe_unused]]auto reg = child.generate_bytecode(generator);
2250+
}
2251+
return {};
2252+
}
2253+
2254+
Optional<Bytecode::Register>ExpressionStatement::generate_bytecode(Bytecode::Generator& generator)const
2255+
{
2256+
return m_expression->generate_bytecode(generator);
2257+
}
2258+
2259+
Optional<Bytecode::Register>BinaryExpression::generate_bytecode(Bytecode::Generator& generator)const
2260+
{
2261+
auto lhs_reg = m_lhs->generate_bytecode(generator);
2262+
auto rhs_reg = m_rhs->generate_bytecode(generator);
2263+
2264+
VERIFY(lhs_reg.has_value());
2265+
VERIFY(rhs_reg.has_value());
2266+
2267+
switch (m_op) {
2268+
case BinaryOp::Addition: {
2269+
auto dst_reg = generator.allocate_register();
2270+
generator.emit<Bytecode::Op::Add>(dst_reg, *lhs_reg, *rhs_reg);
2271+
return dst_reg;
2272+
}
2273+
default:
2274+
TODO();
2275+
}
2276+
}
2277+
2278+
Optional<Bytecode::Register>NumericLiteral::generate_bytecode(Bytecode::Generator& generator)const
2279+
{
2280+
auto dst = generator.allocate_register();
2281+
generator.emit<Bytecode::Op::Load>(dst, m_value);
2282+
return dst;
2283+
}
2284+
22372285
}

‎Userland/Libraries/LibJS/AST.h‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
2+
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
33
* Copyright (c) 2020, Linus Groh <linusg@serenityos.org>
44
*
55
* SPDX-License-Identifier: BSD-2-Clause
@@ -37,6 +37,7 @@ class ASTNode : public RefCounted<ASTNode> {
3737
public:
3838
virtual~ASTNode() { }
3939
virtual Valueexecute(Interpreter&, GlobalObject&)const = 0;
40+
virtual Optional<Bytecode::Register>generate_bytecode(Bytecode::Generator&)const;
4041
virtualvoiddump(int indent)const;
4142

4243
const SourceRange&source_range()const {return m_source_range; }
@@ -96,6 +97,7 @@ class ExpressionStatement final : public Statement {
9697

9798
virtual Valueexecute(Interpreter&, GlobalObject&)constoverride;
9899
virtualvoiddump(int indent)constoverride;
100+
virtual Optional<Bytecode::Register>generate_bytecode(Bytecode::Generator&)constoverride;
99101

100102
const Expression&expression()const {return m_expression; };
101103

@@ -120,6 +122,7 @@ class ScopeNode : public Statement {
120122
const NonnullRefPtrVector<Statement>&children()const {return m_children; }
121123
virtual Valueexecute(Interpreter&, GlobalObject&)constoverride;
122124
virtualvoiddump(int indent)constoverride;
125+
virtual Optional<Bytecode::Register>generate_bytecode(Bytecode::Generator&)constoverride;
123126

124127
voidadd_variables(NonnullRefPtrVector<VariableDeclaration>);
125128
voidadd_functions(NonnullRefPtrVector<FunctionDeclaration>);
@@ -522,6 +525,7 @@ class BinaryExpression final : public Expression {
522525

523526
virtual Valueexecute(Interpreter&, GlobalObject&)constoverride;
524527
virtualvoiddump(int indent)constoverride;
528+
virtual Optional<Bytecode::Register>generate_bytecode(Bytecode::Generator&)constoverride;
525529

526530
private:
527531
BinaryOp m_op;
@@ -630,6 +634,7 @@ class NumericLiteral final : public Literal {
630634

631635
virtual Valueexecute(Interpreter&, GlobalObject&)constoverride;
632636
virtualvoiddump(int indent)constoverride;
637+
virtual Optional<Bytecode::Register>generate_bytecode(Bytecode::Generator&)constoverride;
633638

634639
private:
635640
Value m_value;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#include<AK/String.h>
8+
#include<LibJS/Bytecode/Block.h>
9+
#include<LibJS/Bytecode/Instruction.h>
10+
11+
namespaceJS::Bytecode {
12+
13+
NonnullOwnPtr<Block>Block::create()
14+
{
15+
returnadopt_own(*new Block);
16+
}
17+
18+
Block::Block()
19+
{
20+
}
21+
22+
Block::~Block()
23+
{
24+
}
25+
26+
voidBlock::append(Badge<Bytecode::Generator>, NonnullOwnPtr<Instruction> instruction)
27+
{
28+
m_instructions.append(move(instruction));
29+
}
30+
31+
voidBlock::dump()const
32+
{
33+
for (size_t i =0; i < m_instructions.size(); ++i) {
34+
warnln("[{:3}] {}", i, m_instructions[i].to_string());
35+
}
36+
}
37+
38+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#pragma once
8+
9+
#include<AK/Badge.h>
10+
#include<AK/NonnullOwnPtrVector.h>
11+
#include<LibJS/Forward.h>
12+
13+
namespaceJS::Bytecode {
14+
15+
classBlock {
16+
public:
17+
static NonnullOwnPtr<Block>create();
18+
~Block();
19+
20+
NonnullOwnPtrVector<Instruction>const&instructions()const {return m_instructions; }
21+
voiddump()const;
22+
23+
size_tregister_count()const {return m_register_count; }
24+
25+
voidappend(Badge<Bytecode::Generator>, NonnullOwnPtr<Instruction>);
26+
voidset_register_count(Badge<Bytecode::Generator>,size_t count) { m_register_count = count; }
27+
28+
private:
29+
Block();
30+
31+
size_t m_register_count {0 };
32+
NonnullOwnPtrVector<Instruction> m_instructions;
33+
};
34+
35+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#include<AK/OwnPtr.h>
8+
#include<LibJS/AST.h>
9+
#include<LibJS/Bytecode/Block.h>
10+
#include<LibJS/Bytecode/Generator.h>
11+
#include<LibJS/Bytecode/Instruction.h>
12+
#include<LibJS/Bytecode/Register.h>
13+
#include<LibJS/Forward.h>
14+
15+
namespaceJS::Bytecode {
16+
17+
Generator::Generator()
18+
{
19+
m_block =Block::create();
20+
}
21+
22+
Generator::~Generator()
23+
{
24+
}
25+
26+
OwnPtr<Block>Generator::generate(ASTNodeconst& node)
27+
{
28+
Generator generator;
29+
[[maybe_unused]]auto dummy = node.generate_bytecode(generator);
30+
generator.m_block->set_register_count({}, generator.m_next_register);
31+
returnmove(generator.m_block);
32+
}
33+
34+
voidGenerator::append(NonnullOwnPtr<Instruction> instruction)
35+
{
36+
m_block->append({},move(instruction));
37+
}
38+
39+
RegisterGenerator::allocate_register()
40+
{
41+
VERIFY(m_next_register != NumericLimits<u32>::max());
42+
return Register { m_next_register++ };
43+
}
44+
45+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#pragma once
8+
9+
#include<AK/OwnPtr.h>
10+
#include<LibJS/Forward.h>
11+
12+
namespaceJS::Bytecode {
13+
14+
classGenerator {
15+
public:
16+
static OwnPtr<Block>generate(ASTNodeconst&);
17+
18+
Registerallocate_register();
19+
20+
template<typename OpType,typename... Args>
21+
voidemit(Args&&... args)
22+
{
23+
auto instruction = make<OpType>(forward<Args>(args)...);
24+
append(move(instruction));
25+
}
26+
27+
private:
28+
Generator();
29+
~Generator();
30+
31+
voidappend(NonnullOwnPtr<Instruction>);
32+
33+
OwnPtr<Block> m_block;
34+
u32 m_next_register {1 };
35+
};
36+
37+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#include<LibJS/Bytecode/Instruction.h>
8+
9+
namespaceJS::Bytecode {
10+
11+
Instruction::~Instruction()
12+
{
13+
}
14+
15+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#pragma once
8+
9+
#include<AK/Forward.h>
10+
#include<LibJS/Forward.h>
11+
12+
namespaceJS::Bytecode {
13+
14+
classInstruction {
15+
public:
16+
virtual~Instruction();
17+
18+
virtual Stringto_string()const = 0;
19+
virtualvoidexecute(Bytecode::Interpreter&)const = 0;
20+
};
21+
22+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#include<LibJS/Bytecode/Block.h>
8+
#include<LibJS/Bytecode/Instruction.h>
9+
#include<LibJS/Bytecode/Interpreter.h>
10+
11+
namespaceJS::Bytecode {
12+
13+
Interpreter::Interpreter(GlobalObject& global_object)
14+
: m_global_object(global_object)
15+
{
16+
}
17+
18+
Interpreter::~Interpreter()
19+
{
20+
}
21+
22+
voidInterpreter::run(Bytecode::Blockconst& block)
23+
{
24+
dbgln("Bytecode::Interpreter will run block {:p}", &block);
25+
26+
m_registers.resize(block.register_count());
27+
28+
for (auto& instruction : block.instructions())
29+
instruction.execute(*this);
30+
31+
dbgln("Bytecode::Interpreter did run block {:p}", &block);
32+
for (size_t i =0; i < m_registers.size(); ++i) {
33+
String value_string;
34+
if (m_registers[i].is_empty())
35+
value_string ="(empty)";
36+
else
37+
value_string = m_registers[i].to_string_without_side_effects();
38+
dbgln("[{:3}] {}", i, value_string);
39+
}
40+
}
41+
42+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#pragma once
8+
9+
#include<LibJS/Bytecode/Register.h>
10+
#include<LibJS/Forward.h>
11+
#include<LibJS/Heap/Cell.h>
12+
#include<LibJS/Runtime/Value.h>
13+
14+
namespaceJS::Bytecode {
15+
16+
classInterpreter {
17+
public:
18+
explicitInterpreter(GlobalObject&);
19+
~Interpreter();
20+
21+
GlobalObject&global_object() {return m_global_object; }
22+
23+
voidrun(Bytecode::Blockconst&);
24+
25+
Value&reg(Registerconst& r) {return m_registers[r.index()]; }
26+
27+
private:
28+
GlobalObject& m_global_object;
29+
Vector<Value> m_registers;
30+
};
31+
32+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp