Skip to content

Commit 76091c1

Browse files
alexmarkovcommit-bot@chromium.org
authored andcommitted
[vm/bytecode] Add PushNull, PushTrue, PushFalse and PushInt bytecodes
These bytecode instructions are added in order to shrink constant pools and reduce time spent for reading constant pool entries. Change-Id: I8522f73dc7a6236969ac0422c6cb89b945559b2d Reviewed-on: https://dart-review.googlesource.com/75125 Reviewed-by: Zach Anderson <zra@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
1 parent a80b13e commit 76091c1

22 files changed

+2695
-2950
lines changed

pkg/vm/lib/bytecode/assembler.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,22 @@ class BytecodeAssembler {
221221
emitWord(_encodeD(Opcode.kPushConstant, rd));
222222
}
223223

224+
void emitPushNull() {
225+
emitWord(_encode0(Opcode.kPushNull));
226+
}
227+
228+
void emitPushTrue() {
229+
emitWord(_encode0(Opcode.kPushTrue));
230+
}
231+
232+
void emitPushFalse() {
233+
emitWord(_encode0(Opcode.kPushFalse));
234+
}
235+
236+
void emitPushInt(int rx) {
237+
emitWord(_encodeX(Opcode.kPushInt, rx));
238+
}
239+
224240
void emitStoreLocal(int rx) {
225241
emitWord(_encodeX(Opcode.kStoreLocal, rx));
226242
}

pkg/vm/lib/bytecode/dbc.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ library vm.bytecode.dbc;
4343
// 12. JumpIfNotZeroTypeArgs instruction jumps if number of passed
4444
// function type arguments is not zero.
4545
//
46+
// 13. PushNull, PushTrue, PushFalse, PushInt instructions added.
47+
//
4648

4749
enum Opcode {
4850
kTrap,
@@ -65,6 +67,10 @@ enum Opcode {
6567
kLoadClassId,
6668
kLoadClassIdTOS,
6769
kPushConstant,
70+
kPushNull,
71+
kPushTrue,
72+
kPushFalse,
73+
kPushInt,
6874
kStoreLocal,
6975
kPopLocal,
7076
kIndirectStaticCall,
@@ -320,6 +326,14 @@ const Map<Opcode, Format> BytecodeFormats = const {
320326
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
321327
Opcode.kPushConstant: const Format(
322328
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
329+
Opcode.kPushNull: const Format(
330+
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
331+
Opcode.kPushTrue: const Format(
332+
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
333+
Opcode.kPushFalse: const Format(
334+
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
335+
Opcode.kPushInt: const Format(
336+
Encoding.kX, const [Operand.imm, Operand.none, Operand.none]),
323337
Opcode.kStoreLocal: const Format(
324338
Encoding.kX, const [Operand.xeg, Operand.none, Operand.none]),
325339
Opcode.kPopLocal: const Format(

pkg/vm/lib/bytecode/gen_bytecode.dart

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
150150
} else {
151151
node.function?.body?.accept(this);
152152
// TODO(alexmarkov): figure out when 'return null' should be generated.
153-
_genPushNull();
153+
asm.emitPushNull();
154154
}
155155
_genReturnTOS();
156156
end(node);
@@ -296,17 +296,27 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
296296
arguments.named.forEach((NamedExpression ne) => ne.value.accept(this));
297297
}
298298

299-
void _genPushNull() {
300-
final cpIndex = cp.add(const ConstantNull());
301-
asm.emitPushConstant(cpIndex);
299+
void _genPushBool(bool value) {
300+
if (value) {
301+
asm.emitPushTrue();
302+
} else {
303+
asm.emitPushFalse();
304+
}
302305
}
303306

304307
void _genPushInt(int value) {
305-
int cpIndex = cp.add(new ConstantInt(value));
306-
asm.emitPushConstant(cpIndex);
308+
if (value.bitLength + 1 <= 16) {
309+
asm.emitPushInt(value);
310+
} else {
311+
int cpIndex = cp.add(new ConstantInt(value));
312+
asm.emitPushConstant(cpIndex);
313+
}
307314
}
308315

309316
Constant _evaluateConstantExpression(Expression expr) {
317+
if (expr is ConstantExpression) {
318+
return expr.constant;
319+
}
310320
final constant = constantEvaluator.evaluate(expr);
311321
if (constant == null) {
312322
// Compile-time error is already reported. Proceed with compilation
@@ -319,7 +329,15 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
319329

320330
void _genPushConstExpr(Expression expr) {
321331
final constant = _evaluateConstantExpression(expr);
322-
asm.emitPushConstant(constant.accept(constantEmitter));
332+
if (constant is NullConstant) {
333+
asm.emitPushNull();
334+
} else if (constant is BoolConstant) {
335+
_genPushBool(constant.value);
336+
} else if (constant is IntConstant) {
337+
_genPushInt(constant.value);
338+
} else {
339+
asm.emitPushConstant(constant.accept(constantEmitter));
340+
}
323341
}
324342

325343
void _genReturnTOS() {
@@ -398,13 +416,13 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
398416
assert(instantiatorTypeArguments != null);
399417
_genPushInstantiatorTypeArguments();
400418
} else {
401-
_genPushNull();
419+
asm.emitPushNull();
402420
}
403421
if (functionTypeParameters != null &&
404422
types.any((t) => containsTypeVariable(t, functionTypeParameters))) {
405423
_genPushFunctionTypeArguments();
406424
} else {
407-
_genPushNull();
425+
asm.emitPushNull();
408426
}
409427
}
410428

@@ -421,7 +439,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
421439
asm.emitLoadTypeArgumentsField(cpIndex);
422440
}
423441
} else {
424-
_genPushNull();
442+
asm.emitPushNull();
425443
}
426444
}
427445

@@ -499,7 +517,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
499517
if (locals.hasFunctionTypeArgsVar) {
500518
asm.emitPush(locals.functionTypeArgsVarIndexInFrame);
501519
} else {
502-
_genPushNull();
520+
asm.emitPushNull();
503521
}
504522
}
505523

@@ -561,7 +579,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
561579
}
562580

563581
void _genJumpIfFalse(bool negated, Label dest) {
564-
asm.emitPushConstant(cp.add(new ConstantBool(true)));
582+
asm.emitPushTrue();
565583
if (negated) {
566584
asm.emitIfEqStrictTOS(); // if ((!condition) == true) ...
567585
} else {
@@ -595,7 +613,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
595613
void _genInstanceOf(DartType type) {
596614
if (typeEnvironment.isTop(type)) {
597615
asm.emitDrop1();
598-
asm.emitPushConstant(cp.add(new ConstantBool(true)));
616+
asm.emitPushTrue();
599617
return;
600618
}
601619

@@ -604,8 +622,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
604622
if (hasFreeTypeParameters([type])) {
605623
_genPushInstantiatorAndFunctionTypeArguments([type]);
606624
} else {
607-
_genPushNull(); // Instantiator type arguments.
608-
_genPushNull(); // Function type arguments.
625+
asm.emitPushNull(); // Instantiator type arguments.
626+
asm.emitPushNull(); // Function type arguments.
609627
}
610628
asm.emitPushConstant(cp.add(new ConstantType(type)));
611629
final argDescIndex = cp.add(new ConstantArgDesc(4));
@@ -686,11 +704,11 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
686704
Label done = new Label();
687705

688706
_genLoadVar(member.function.positionalParameters[0]);
689-
_genPushNull();
707+
asm.emitPushNull();
690708
asm.emitIfNeStrictTOS();
691709
asm.emitJump(done);
692710

693-
asm.emitPushConstant(cp.add(new ConstantBool(false)));
711+
asm.emitPushFalse();
694712
_genReturnTOS();
695713

696714
asm.bind(done);
@@ -1129,7 +1147,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
11291147
function.body.accept(this);
11301148

11311149
// TODO(alexmarkov): figure out when 'return null' should be generated.
1132-
_genPushNull();
1150+
asm.emitPushNull();
11331151
_genReturnTOS();
11341152

11351153
if (locals.isSyncYieldingFrame) {
@@ -1399,7 +1417,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
13991417
_createArgumentsArray(temp, typeArgs, args, storeLastArgumentToTemp);
14001418

14011419
// Argument 3 for _allocateInvocationMirror(): isSuperInvocation flag.
1402-
asm.emitPushConstant(cp.add(new ConstantBool(true)));
1420+
asm.emitPushTrue();
14031421

14041422
_genStaticCall(allocateInvocationMirror, new ConstantArgDesc(4), 4);
14051423

@@ -1435,14 +1453,12 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
14351453

14361454
@override
14371455
visitBoolLiteral(BoolLiteral node) {
1438-
final cpIndex = cp.add(new ConstantBool.fromLiteral(node));
1439-
asm.emitPushConstant(cpIndex);
1456+
_genPushBool(node.value);
14401457
}
14411458

14421459
@override
14431460
visitIntLiteral(IntLiteral node) {
1444-
final cpIndex = cp.add(new ConstantInt.fromLiteral(node));
1445-
asm.emitPushConstant(cpIndex);
1461+
_genPushInt(node.value);
14461462
}
14471463

14481464
@override
@@ -1653,7 +1669,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
16531669
final isOR = (node.operator == '||');
16541670

16551671
bool negated = _genCondition(node.left);
1656-
asm.emitPushConstant(cp.add(new ConstantBool(true)));
1672+
asm.emitPushTrue();
16571673
if (negated != isOR) {
16581674
// OR: if (condition == true)
16591675
// AND: if ((!condition) == true)
@@ -1673,7 +1689,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
16731689
asm.emitJump(done);
16741690

16751691
asm.bind(shortCircuit);
1676-
asm.emitPushConstant(cp.add(new ConstantBool(isOR)));
1692+
_genPushBool(isOR);
16771693
asm.emitPopLocal(temp);
16781694

16791695
asm.bind(done);
@@ -1847,8 +1863,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
18471863

18481864
@override
18491865
visitNullLiteral(NullLiteral node) {
1850-
final cpIndex = cp.add(const ConstantNull());
1851-
asm.emitPushConstant(cpIndex);
1866+
asm.emitPushNull();
18521867
}
18531868

18541869
@override
@@ -1920,7 +1935,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
19201935
assert(args.types.isEmpty);
19211936
// VM needs type arguments for every invocation of a factory
19221937
// constructor. TODO(alexmarkov): Clean this up.
1923-
_genPushNull();
1938+
asm.emitPushNull();
19241939
}
19251940
args =
19261941
new Arguments(node.arguments.positional, named: node.arguments.named);
@@ -1955,7 +1970,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
19551970
node.expressions.single.accept(this);
19561971
_genStaticCall(interpolateSingle, new ConstantArgDesc(1), 1);
19571972
} else {
1958-
_genPushNull();
1973+
asm.emitPushNull();
19591974
_genPushInt(node.expressions.length);
19601975
asm.emitCreateArrayTOS();
19611976

@@ -2050,7 +2065,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
20502065
}
20512066

20522067
void _genFutureNull() {
2053-
_genPushNull();
2068+
asm.emitPushNull();
20542069
_genStaticCall(futureValue, new ConstantArgDesc(1), 1);
20552070
}
20562071

@@ -2078,7 +2093,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
20782093
if (node.message != null) {
20792094
node.message.accept(this);
20802095
} else {
2081-
_genPushNull();
2096+
asm.emitPushNull();
20822097
}
20832098

20842099
_genStaticCall(throwNewAssertionError, new ConstantArgDesc(3), 3);
@@ -2602,7 +2617,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
26022617
if (node.initializer != null) {
26032618
node.initializer.accept(this);
26042619
} else {
2605-
_genPushNull();
2620+
asm.emitPushNull();
26062621
}
26072622
if (isCaptured) {
26082623
asm.emitStoreContextVar(locals.getVarIndexInContext(node));
@@ -2722,8 +2737,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
27222737

27232738
@override
27242739
visitConstantExpression(ConstantExpression node) {
2725-
int cpIndex = node.constant.accept(constantEmitter);
2726-
asm.emitPushConstant(cpIndex);
2740+
_genPushConstExpr(node);
27272741
}
27282742
}
27292743

pkg/vm/testcases/bytecode/asserts.dart.expect

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,22 @@ Bytecode {
99
JumpIfNoAsserts L1
1010
Push FP[-5]
1111
AssertBoolean 0
12-
PushConstant CP#0
12+
PushTrue
1313
IfEqStrictTOS
1414
Jump L1
15+
PushInt 0
16+
PushInt 0
17+
PushNull
1518
PushConstant CP#1
16-
PushConstant CP#1
17-
PushConstant CP#2
18-
PushConstant CP#4
19-
IndirectStaticCall 3, CP#3
19+
IndirectStaticCall 3, CP#0
2020
Drop1
2121
L1:
22-
PushConstant CP#2
22+
PushNull
2323
ReturnTOS
2424
}
2525
ConstantPool {
26-
[0] = Bool true
27-
[1] = Int 0
28-
[2] = Null
29-
[3] = ArgDesc num-args 3, num-type-args 0, names []
30-
[4] = StaticICData target 'dart.core::_AssertionError::_throwNew', arg-desc CP#3
26+
[0] = ArgDesc num-args 3, num-type-args 0, names []
27+
[1] = StaticICData target 'dart.core::_AssertionError::_throwNew', arg-desc CP#0
3128
}
3229
]static method test1(core::bool condition) → void {
3330
assert(condition);
@@ -40,29 +37,26 @@ Bytecode {
4037
Push FP[-6]
4138
InstanceCall 1, CP#1
4239
AssertBoolean 0
43-
PushConstant CP#2
40+
PushTrue
4441
IfEqStrictTOS
4542
Jump L1
46-
PushConstant CP#3
47-
PushConstant CP#3
43+
PushInt 0
44+
PushInt 0
4845
Push FP[-5]
49-
InstanceCall 1, CP#4
50-
PushConstant CP#6
51-
IndirectStaticCall 3, CP#5
46+
InstanceCall 1, CP#2
47+
PushConstant CP#4
48+
IndirectStaticCall 3, CP#3
5249
Drop1
5350
L1:
54-
PushConstant CP#7
51+
PushNull
5552
ReturnTOS
5653
}
5754
ConstantPool {
5855
[0] = ArgDesc num-args 1, num-type-args 0, names []
5956
[1] = ICData dynamic target-name 'call', arg-desc CP#0
60-
[2] = Bool true
61-
[3] = Int 0
62-
[4] = ICData dynamic target-name 'call', arg-desc CP#0
63-
[5] = ArgDesc num-args 3, num-type-args 0, names []
64-
[6] = StaticICData target 'dart.core::_AssertionError::_throwNew', arg-desc CP#5
65-
[7] = Null
57+
[2] = ICData dynamic target-name 'call', arg-desc CP#0
58+
[3] = ArgDesc num-args 3, num-type-args 0, names []
59+
[4] = StaticICData target 'dart.core::_AssertionError::_throwNew', arg-desc CP#3
6660
}
6761
]static method test2(() → core::bool condition, () → core::String message) → void {
6862
assert([@vm.call-site-attributes.metadata=receiverType:() → dart.core::bool] condition.call(), [@vm.call-site-attributes.metadata=receiverType:() → dart.core::String] message.call());
@@ -71,10 +65,9 @@ ConstantPool {
7165
Bytecode {
7266
Entry 0
7367
CheckStack
74-
PushConstant CP#0
68+
PushNull
7569
ReturnTOS
7670
}
7771
ConstantPool {
78-
[0] = Null
7972
}
8073
]static method main() → dynamic {}

0 commit comments

Comments
 (0)