[vm/bytecode] Remove unreachable bytecode
Change-Id: I29393604547038cf359b8e19ea48078dd0eea3b1
Reviewed-on: https://dart-review.googlesource.com/c/81201
Reviewed-by: Zach Anderson <zra@google.com>
Reviewed-by: RĂ©gis Crelier <regis@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Auto-Submit: Alexander Markov <alexmarkov@google.com>
diff --git a/pkg/vm/lib/bytecode/assembler.dart b/pkg/vm/lib/bytecode/assembler.dart
index dce3410..b45b4c1 100644
--- a/pkg/vm/lib/bytecode/assembler.dart
+++ b/pkg/vm/lib/bytecode/assembler.dart
@@ -10,15 +10,19 @@
import 'exceptions.dart' show ExceptionsTable;
class Label {
+ final bool allowsBackwardJumps;
List<int> _jumps = <int>[];
int offset = -1;
- Label();
+ Label({this.allowsBackwardJumps: false});
bool get isBound => offset >= 0;
int jumpOperand(int jumpOffset) {
if (isBound) {
+ if (offset <= jumpOffset && !allowsBackwardJumps) {
+ throw 'Backward jump to this label is not allowed';
+ }
// Jump instruction takes an offset in DBC words.
return (offset - jumpOffset) >> BytecodeAssembler.kLog2BytesPerBytecode;
}
@@ -44,6 +48,7 @@
final Uint32List _encodeBufferIn;
final Uint8List _encodeBufferOut;
final ExceptionsTable exceptionsTable = new ExceptionsTable();
+ bool isUnreachable = false;
BytecodeAssembler._(this._encodeBufferIn, this._encodeBufferOut);
@@ -60,9 +65,15 @@
for (int jumpOffset in jumps) {
patchJump(jumpOffset, label.jumpOperand(jumpOffset));
}
+ if (jumps.isNotEmpty || label.allowsBackwardJumps) {
+ isUnreachable = false;
+ }
}
void emitWord(int word) {
+ if (isUnreachable) {
+ return;
+ }
_encodeBufferIn[0] = word; // TODO(alexmarkov): Which endianness to use?
bytecode.addAll(_encodeBufferOut);
}
@@ -145,8 +156,17 @@
emitWord(_encode0(opcode));
}
+ void _emitJumpBytecode(Opcode opcode, Label label) {
+ assert(isJump(opcode));
+ if (!isUnreachable) {
+ // Do not use label if not generating instruction.
+ emitWord(_encodeT(opcode, label.jumpOperand(offset)));
+ }
+ }
+
void emitTrap() {
emitWord(_encode0(Opcode.kTrap));
+ isUnreachable = true;
}
void emitDrop1() {
@@ -154,40 +174,40 @@
}
void emitJump(Label label) {
- emitWord(_encodeT(Opcode.kJump, label.jumpOperand(offset)));
+ _emitJumpBytecode(Opcode.kJump, label);
+ isUnreachable = true;
}
void emitJumpIfNoAsserts(Label label) {
- emitWord(_encodeT(Opcode.kJumpIfNoAsserts, label.jumpOperand(offset)));
+ _emitJumpBytecode(Opcode.kJumpIfNoAsserts, label);
}
void emitJumpIfNotZeroTypeArgs(Label label) {
- emitWord(
- _encodeT(Opcode.kJumpIfNotZeroTypeArgs, label.jumpOperand(offset)));
+ _emitJumpBytecode(Opcode.kJumpIfNotZeroTypeArgs, label);
}
void emitJumpIfEqStrict(Label label) {
- emitWord(_encodeT(Opcode.kJumpIfEqStrict, label.jumpOperand(offset)));
+ _emitJumpBytecode(Opcode.kJumpIfEqStrict, label);
}
void emitJumpIfNeStrict(Label label) {
- emitWord(_encodeT(Opcode.kJumpIfNeStrict, label.jumpOperand(offset)));
+ _emitJumpBytecode(Opcode.kJumpIfNeStrict, label);
}
void emitJumpIfTrue(Label label) {
- emitWord(_encodeT(Opcode.kJumpIfTrue, label.jumpOperand(offset)));
+ _emitJumpBytecode(Opcode.kJumpIfTrue, label);
}
void emitJumpIfFalse(Label label) {
- emitWord(_encodeT(Opcode.kJumpIfFalse, label.jumpOperand(offset)));
+ _emitJumpBytecode(Opcode.kJumpIfFalse, label);
}
void emitJumpIfNull(Label label) {
- emitWord(_encodeT(Opcode.kJumpIfNull, label.jumpOperand(offset)));
+ _emitJumpBytecode(Opcode.kJumpIfNull, label);
}
void emitJumpIfNotNull(Label label) {
- emitWord(_encodeT(Opcode.kJumpIfNotNull, label.jumpOperand(offset)));
+ _emitJumpBytecode(Opcode.kJumpIfNotNull, label);
}
void patchJump(int pos, int rt) {
@@ -198,6 +218,7 @@
void emitReturnTOS() {
emitWord(_encode0(Opcode.kReturnTOS));
+ isUnreachable = true;
}
void emitPush(int rx) {
@@ -306,6 +327,7 @@
void emitThrow(int ra) {
emitWord(_encodeA(Opcode.kThrow, ra));
+ isUnreachable = true;
}
void emitEntry(int rd) {
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index ad72107..1a95682 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -166,7 +166,7 @@
_genNativeCall(nativeName);
} else {
node.function?.body?.accept(this);
- // TODO(alexmarkov): figure out when 'return null' should be generated.
+ // BytecodeAssembler eliminates this bytecode if it is unreachable.
asm.emitPushNull();
}
_genReturnTOS();
@@ -624,6 +624,48 @@
_genJumpIfFalse(!negated, dest);
}
+ /// Returns value of the given expression if it is a bool constant.
+ /// Otherwise, returns `null`.
+ bool _constantConditionValue(Expression condition) {
+ // TODO(dartbug.com/34585): use constant evaluator to evaluate
+ // expressions in a non-constant context.
+ if (condition is Not) {
+ final operand = _constantConditionValue(condition.operand);
+ return (operand != null) ? !operand : null;
+ }
+ if (condition is BoolLiteral) {
+ return condition.value;
+ }
+ Constant constant;
+ if (condition is ConstantExpression) {
+ constant = condition.constant;
+ } else if ((condition is StaticGet && condition.target.isConst) ||
+ (condition is StaticInvocation && condition.isConst) ||
+ (condition is VariableGet && condition.variable.isConst)) {
+ constant = _evaluateConstantExpression(condition);
+ }
+ if (constant is BoolConstant) {
+ return constant.value;
+ }
+ return null;
+ }
+
+ void _genConditionAndJumpIf(Expression condition, bool value, Label dest) {
+ final bool constantValue = _constantConditionValue(condition);
+ if (constantValue != null) {
+ if (constantValue == value) {
+ asm.emitJump(dest);
+ }
+ return;
+ }
+ bool negated = _genCondition(condition);
+ if (value) {
+ _genJumpIfTrue(negated, dest);
+ } else {
+ _genJumpIfFalse(negated, dest);
+ }
+ }
+
int _getDefaultParamConstIndex(VariableDeclaration param) {
if (param.initializer == null) {
return cp.add(const ConstantNull());
@@ -1195,7 +1237,7 @@
function.body.accept(this);
- // TODO(alexmarkov): figure out when 'return null' should be generated.
+ // BytecodeAssembler eliminates this bytecode if it is unreachable.
asm.emitPushNull();
_genReturnTOS();
@@ -1513,8 +1555,7 @@
final Label done = new Label();
final int temp = locals.tempIndexInFrame(node);
- final bool negated = _genCondition(node.condition);
- _genJumpIfFalse(negated, otherwisePart);
+ _genConditionAndJumpIf(node.condition, false, otherwisePart);
node.then.accept(this);
asm.emitPopLocal(temp);
@@ -1708,18 +1749,9 @@
final int temp = locals.tempIndexInFrame(node);
final isOR = (node.operator == '||');
- bool negated = _genCondition(node.left);
- if (negated != isOR) {
- // OR: if (condition == true)
- // AND: if ((!condition) == true)
- asm.emitJumpIfTrue(shortCircuit);
- } else {
- // OR: if ((!condition) != true)
- // AND: if (condition != true)
- asm.emitJumpIfFalse(shortCircuit);
- }
+ _genConditionAndJumpIf(node.left, isOR, shortCircuit);
- negated = _genCondition(node.right);
+ bool negated = _genCondition(node.right);
if (negated) {
asm.emitBooleanNegateTOS();
}
@@ -2171,8 +2203,7 @@
final Label done = new Label();
asm.emitJumpIfNoAsserts(done);
- final bool negated = _genCondition(node.condition);
- _genJumpIfTrue(negated, done);
+ _genConditionAndJumpIf(node.condition, true, done);
_genPushInt(omitSourcePositions ? 0 : node.conditionStartOffset);
_genPushInt(omitSourcePositions ? 0 : node.conditionEndOffset);
@@ -2234,16 +2265,20 @@
@override
visitDoStatement(DoStatement node) {
- final Label join = new Label();
+ if (asm.isUnreachable) {
+ // Bail out before binding a label which allows backward jumps,
+ // as it is not handled by local unreachable code elimination.
+ return;
+ }
+
+ final Label join = new Label(allowsBackwardJumps: true);
asm.bind(join);
asm.emitCheckStack();
node.body.accept(this);
- // TODO(alexmarkov): do we need to break this critical edge in CFG?
- bool negated = _genCondition(node.condition);
- _genJumpIfTrue(negated, join);
+ _genConditionAndJumpIf(node.condition, true, join);
}
@override
@@ -2283,8 +2318,14 @@
_genStoreVar(capturedIteratorVar);
}
+ if (asm.isUnreachable) {
+ // Bail out before binding a label which allows backward jumps,
+ // as it is not handled by local unreachable code elimination.
+ return;
+ }
+
final Label done = new Label();
- final Label join = new Label();
+ final Label join = new Label(allowsBackwardJumps: true);
asm.bind(join);
asm.emitCheckStack();
@@ -2325,37 +2366,44 @@
@override
visitForStatement(ForStatement node) {
_enterScope(node);
+ try {
+ visitList(node.variables, this);
- visitList(node.variables, this);
+ if (asm.isUnreachable) {
+ // Bail out before binding a label which allows backward jumps,
+ // as it is not handled by local unreachable code elimination.
+ return;
+ }
- final Label done = new Label();
- final Label join = new Label();
- asm.bind(join);
+ final Label done = new Label();
+ final Label join = new Label(allowsBackwardJumps: true);
+ asm.bind(join);
- asm.emitCheckStack();
+ asm.emitCheckStack();
- if (node.condition != null) {
- bool negated = _genCondition(node.condition);
- _genJumpIfFalse(negated, done);
+ if (node.condition != null) {
+ _genConditionAndJumpIf(node.condition, false, done);
+ }
+
+ node.body.accept(this);
+
+ if (locals.currentContextSize > 0) {
+ asm.emitPush(locals.contextVarIndexInFrame);
+ asm.emitCloneContext();
+ asm.emitPopLocal(locals.contextVarIndexInFrame);
+ }
+
+ for (var update in node.updates) {
+ update.accept(this);
+ asm.emitDrop1();
+ }
+
+ asm.emitJump(join);
+
+ asm.bind(done);
+ } finally {
+ _leaveScope();
}
-
- node.body.accept(this);
-
- if (locals.currentContextSize > 0) {
- asm.emitPush(locals.contextVarIndexInFrame);
- asm.emitCloneContext();
- asm.emitPopLocal(locals.contextVarIndexInFrame);
- }
-
- for (var update in node.updates) {
- update.accept(this);
- asm.emitDrop1();
- }
-
- asm.emitJump(join);
-
- asm.bind(done);
- _leaveScope();
}
@override
@@ -2369,8 +2417,7 @@
visitIfStatement(IfStatement node) {
final Label otherwisePart = new Label();
- final bool negated = _genCondition(node.condition);
- _genJumpIfFalse(negated, otherwisePart);
+ _genConditionAndJumpIf(node.condition, false, otherwisePart);
node.then.accept(this);
@@ -2431,12 +2478,18 @@
node.expression.accept(this);
+ if (asm.isUnreachable) {
+ // Bail out before binding labels which allow backward jumps,
+ // as they are not handled by local unreachable code elimination.
+ return;
+ }
+
final int temp = locals.tempIndexInFrame(node);
asm.emitPopLocal(temp);
final Label done = new Label();
- final List<Label> caseLabels =
- new List<Label>.generate(node.cases.length, (_) => new Label());
+ final List<Label> caseLabels = new List<Label>.generate(
+ node.cases.length, (_) => new Label(allowsBackwardJumps: true));
final equalsArgDesc = cp.add(new ConstantArgDesc(2));
Label defaultLabel = done;
@@ -2550,6 +2603,9 @@
tryBlock.endPC = asm.offsetInWords;
tryBlock.handlerPC = asm.offsetInWords;
+ // Exception handlers are reachable although there are no labels or jumps.
+ asm.isUnreachable = false;
+
asm.emitSetFrame(locals.frameSize);
_restoreContextForTryBlock(node);
@@ -2594,6 +2650,10 @@
@override
visitTryCatch(TryCatch node) {
+ if (asm.isUnreachable) {
+ return;
+ }
+
final Label done = new Label();
final TryBlock tryBlock = _startTryBlock(node);
@@ -2660,17 +2720,22 @@
@override
visitTryFinally(TryFinally node) {
+ if (asm.isUnreachable) {
+ return;
+ }
+
final TryBlock tryBlock = _startTryBlock(node);
finallyBlocks[node] = <FinallyBlock>[];
node.body.accept(this);
- // TODO(alexmarkov): Do not generate normal continuation if control
- // does not return from body.
- final normalContinuation =
- new FinallyBlock(() {/* do nothing (fall through) */});
- finallyBlocks[node].add(normalContinuation);
- asm.emitJump(normalContinuation.entry);
+ if (!asm.isUnreachable) {
+ final normalContinuation = new FinallyBlock(() {
+ /* do nothing (fall through) */
+ });
+ finallyBlocks[node].add(normalContinuation);
+ asm.emitJump(normalContinuation.entry);
+ }
_endTryBlock(node, tryBlock);
@@ -2716,14 +2781,19 @@
@override
visitWhileStatement(WhileStatement node) {
+ if (asm.isUnreachable) {
+ // Bail out before binding a label which allows backward jumps,
+ // as it is not handled by local unreachable code elimination.
+ return;
+ }
+
final Label done = new Label();
- final Label join = new Label();
+ final Label join = new Label(allowsBackwardJumps: true);
asm.bind(join);
asm.emitCheckStack();
- bool negated = _genCondition(node.condition);
- _genJumpIfFalse(negated, done);
+ _genConditionAndJumpIf(node.condition, false, done);
node.body.accept(this);
@@ -2738,9 +2808,13 @@
throw 'YieldStatement must be desugared: $node';
}
+ if (asm.isUnreachable) {
+ return;
+ }
+
// 0 is reserved for normal entry, yield points are counted from 1.
final int yieldIndex = yieldPoints.length + 1;
- final Label continuationLabel = new Label();
+ final Label continuationLabel = new Label(allowsBackwardJumps: true);
yieldPoints.add(continuationLabel);
// :await_jump_var = #index
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index 5a5cd62..7b37aaa 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -120,7 +120,6 @@
Drop1
PushNull
ReturnTOS
- Jump L3
Try #0 end:
Try #0 handler:
SetFrame 10
@@ -243,8 +242,6 @@
LoadContextVar 1
InstanceCall 1, CP#34
ReturnTOS
- PushNull
- ReturnTOS
}
]static field (asy::Future<core::int>) → asy::Future<core::Null> asyncInFieldInitializer = (asy::Future<core::int> x) → asy::Future<core::Null> /* originally async */ {
@@ -340,11 +337,6 @@
LoadContextVar 0
InstanceCall 1, CP#28
ReturnTOS
- Push r0
- LoadContextParent
- PopLocal r0
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgumentsForInstanceAllocation dart.async::Completer [dart.core::int]
@@ -409,7 +401,6 @@
Drop1
PushNull
ReturnTOS
- Jump L3
Try #0 end:
Try #0 handler:
SetFrame 10
@@ -548,8 +539,6 @@
LoadContextVar 2
InstanceCall 1, CP#32
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgumentsForInstanceAllocation dart.async::Completer [dart.core::int]
@@ -677,7 +666,6 @@
Drop1
PushNull
ReturnTOS
- Jump L5
Try #0 end:
Try #0 handler:
SetFrame 10
@@ -831,8 +819,6 @@
LoadContextVar 1
InstanceCall 1, CP#37
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgumentsForInstanceAllocation dart.async::Completer [dart.core::int]
@@ -1076,9 +1062,6 @@
LoadContextParent
PopLocal r4
Jump L9
- Push r4
- LoadContextParent
- PopLocal r4
L9:
Push r4
LoadContextVar 1
@@ -1089,7 +1072,6 @@
Drop1
PushNull
ReturnTOS
- Jump L10
Try #0 end:
Try #0 handler:
SetFrame 11
@@ -1265,8 +1247,6 @@
LoadContextVar 3
InstanceCall 1, CP#45
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgumentsForInstanceAllocation dart.async::Completer [dart.core::int]
@@ -1484,8 +1464,6 @@
LoadContextParent
LoadContextVar 13
Throw 1
- Drop1
- Jump L3
L3:
Jump L7
Try #1 end:
@@ -1564,13 +1542,6 @@
LoadContextParent
PopLocal r4
Jump L9
- Push r4
- LoadContextParent
- LoadContextVar 12
- Push r4
- LoadContextParent
- LoadContextVar 13
- Throw 1
L5:
Push r0
LoadFieldTOS CP#5
@@ -1635,10 +1606,6 @@
LoadContextParent
PopLocal r4
Jump L9
- Push r4
- LoadContextParent
- PopLocal r4
- Jump L9
L7:
Push r0
LoadFieldTOS CP#5
@@ -1703,9 +1670,6 @@
LoadContextParent
PopLocal r4
Jump L9
- Push r4
- LoadContextParent
- PopLocal r4
L9:
Push r4
LoadContextVar 3
@@ -1716,7 +1680,6 @@
Drop1
PushNull
ReturnTOS
- Jump L12
Try #0 end:
Try #0 handler:
SetFrame 14
@@ -1829,28 +1792,26 @@
Push r0
PushInt 3
StoreContextVar 1
- Allocate CP#20
+ Allocate CP#19
StoreLocal r3
Push r3
PushNull
- StoreFieldTOS CP#21
+ StoreFieldTOS CP#20
Push r3
PushNull
- StoreFieldTOS CP#23
+ StoreFieldTOS CP#22
Push r3
- PushConstant CP#25
- StoreFieldTOS CP#26
+ PushConstant CP#24
+ StoreFieldTOS CP#25
Push r3
PushConstant CP#0
- StoreFieldTOS CP#28
+ StoreFieldTOS CP#27
Push r3
Push r0
StoreFieldTOS CP#1
PopLocal r2
Push r2
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ClosureFunction nested () → dart.async::Future<dart.core::int> /* originally async */ ;
@@ -1867,29 +1828,28 @@
[11] = String 'fin'
[12] = StaticICData target 'dart.core::print', arg-desc CP#4
[13] = StaticICData target 'dart.core::print', arg-desc CP#4
- [14] = StaticICData target 'dart.core::print', arg-desc CP#4
- [15] = ArgDesc num-args 2, num-type-args 0, names []
- [16] = StaticICData target 'dart.async::_completeOnAsyncReturn', arg-desc CP#15
- [17] = ArgDesc num-args 3, num-type-args 0, names []
- [18] = ICData target-name 'completeError', arg-desc CP#17
- [19] = EndClosureFunctionScope
- [20] = Class dart.core::_Closure
- [21] = InstanceField dart.core::_Closure::_instantiator_type_arguments
- [22] = Reserved
- [23] = InstanceField dart.core::_Closure::_function_type_arguments
- [24] = Reserved
- [25] = EmptyTypeArguments
- [26] = InstanceField dart.core::_Closure::_delayed_type_arguments
- [27] = Reserved
- [28] = InstanceField dart.core::_Closure::_function
- [29] = Reserved
- [30] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#4
- [31] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#4
- [32] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#4
- [33] = TypeArgumentsForInstanceAllocation dart.async::Future [dynamic]
- [34] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#15
- [35] = ICData get target-name 'future', arg-desc CP#4
- [36] = EndClosureFunctionScope
+ [14] = ArgDesc num-args 2, num-type-args 0, names []
+ [15] = StaticICData target 'dart.async::_completeOnAsyncReturn', arg-desc CP#14
+ [16] = ArgDesc num-args 3, num-type-args 0, names []
+ [17] = ICData target-name 'completeError', arg-desc CP#16
+ [18] = EndClosureFunctionScope
+ [19] = Class dart.core::_Closure
+ [20] = InstanceField dart.core::_Closure::_instantiator_type_arguments
+ [21] = Reserved
+ [22] = InstanceField dart.core::_Closure::_function_type_arguments
+ [23] = Reserved
+ [24] = EmptyTypeArguments
+ [25] = InstanceField dart.core::_Closure::_delayed_type_arguments
+ [26] = Reserved
+ [27] = InstanceField dart.core::_Closure::_function
+ [28] = Reserved
+ [29] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#4
+ [30] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#4
+ [31] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#4
+ [32] = TypeArgumentsForInstanceAllocation dart.async::Future [dynamic]
+ [33] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#14
+ [34] = ICData get target-name 'future', arg-desc CP#4
+ [35] = EndClosureFunctionScope
}
Closure CP#6 {
EntryOptional 1, 3, 0
@@ -1955,7 +1915,7 @@
PopLocal r11
PushNull
ReturnTOS
-L7:
+L6:
Push r2
JumpIfNull L2
Push r2
@@ -1976,7 +1936,6 @@
AddInt
StoreContextVar 1
Jump L3
- Jump L4
Try #1 end:
Try #1 handler:
SetFrame 12
@@ -2009,32 +1968,17 @@
Push r4
LoadContextParent
PopLocal r4
- Jump L5
+ Jump L4
L4:
- Push r0
- LoadFieldTOS CP#1
- PopLocal r4
- Push r4
- LoadContextVar 7
- PopLocal r4
- PushConstant CP#11
- PushConstant CP#14
- IndirectStaticCall 1, CP#4
- Drop1
- Push r4
- LoadContextParent
- PopLocal r4
-L5:
Push r4
LoadContextVar 0
Push r4
LoadContextVar 1
- PushConstant CP#16
- IndirectStaticCall 2, CP#15
+ PushConstant CP#15
+ IndirectStaticCall 2, CP#14
Drop1
PushNull
ReturnTOS
- Jump L6
Try #0 end:
Try #0 handler:
SetFrame 12
@@ -2054,17 +1998,17 @@
LoadContextVar 0
Push r8
Push r9
- InstanceCall 3, CP#18
+ InstanceCall 3, CP#17
Drop1
- Jump L6
-L6:
+ Jump L5
+L5:
PushNull
ReturnTOS
L1:
Push r4
LoadContextVar 5
PopLocal r4
- Jump L7
+ Jump L6
}
@@ -2109,55 +2053,50 @@
PushNull
StoreContextVar 7
Push r0
- Allocate CP#20
+ Allocate CP#19
StoreLocal r3
Push r3
PushNull
- StoreFieldTOS CP#21
+ StoreFieldTOS CP#20
Push r3
PushNull
- StoreFieldTOS CP#23
+ StoreFieldTOS CP#22
Push r3
- PushConstant CP#25
- StoreFieldTOS CP#26
+ PushConstant CP#24
+ StoreFieldTOS CP#25
Push r3
PushConstant CP#6
- StoreFieldTOS CP#28
+ StoreFieldTOS CP#27
Push r3
Push r0
StoreFieldTOS CP#1
StoreContextVar 8
Push r0
LoadContextVar 8
- PushConstant CP#30
+ PushConstant CP#29
IndirectStaticCall 1, CP#4
PopLocal r2
Push r0
Push r0
LoadContextVar 8
- PushConstant CP#31
+ PushConstant CP#30
IndirectStaticCall 1, CP#4
StoreContextVar 2
Push r0
Push r0
LoadContextVar 8
- PushConstant CP#32
+ PushConstant CP#31
IndirectStaticCall 1, CP#4
StoreContextVar 3
- PushConstant CP#33
+ PushConstant CP#32
Push r0
LoadContextVar 8
- PushConstant CP#34
- IndirectStaticCall 2, CP#15
+ PushConstant CP#33
+ IndirectStaticCall 2, CP#14
Drop1
Push r0
LoadContextVar 0
- InstanceCall 1, CP#35
- ReturnTOS
- Push r0
- LoadContextParent
- PopLocal r0
- PushNull
+ InstanceCall 1, CP#34
ReturnTOS
}
@@ -2283,8 +2222,6 @@
LoadContextVar 1
InstanceCall 1, CP#32
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgumentsForInstanceAllocation dart.async::Completer [dart.core::int]
@@ -2394,7 +2331,6 @@
Drop1
PushNull
ReturnTOS
- Jump L5
Try #0 end:
Try #0 handler:
SetFrame 10
diff --git a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
index 5711186..c47aadf 100644
--- a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
+++ b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
@@ -136,8 +136,6 @@
PushConstant CP#0
PushStatic CP#0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = StaticField #lib::_NamespaceImpl::_cachedNamespace
@@ -164,8 +162,6 @@
PushConstant CP#3
IndirectStaticCall 1, CP#2
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 0, num-type-args 0, names []
@@ -220,8 +216,6 @@
PushConstant CP#1
IndirectStaticCall 0, CP#0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 0, num-type-args 0, names []
@@ -236,8 +230,6 @@
PushConstant CP#1
IndirectStaticCall 0, CP#0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 0, num-type-args 0, names []
@@ -326,8 +318,6 @@
PushConstant CP#0
PushStatic CP#0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = StaticField #lib::VMLibraryHooks::_cachedScript
@@ -385,8 +375,6 @@
CheckStack
PushConstant CP#0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TearOff #lib::_print
@@ -474,7 +462,6 @@
PushConstant CP#9
IndirectStaticCall 1, CP#8
ReturnTOS
- Jump L6
L5:
PushConstant CP#11
IndirectStaticCall 0, CP#10
@@ -485,9 +472,6 @@
IndirectStaticCall 2, CP#2
InstanceCall 2, CP#13
ReturnTOS
-L6:
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = StaticField #lib::_rawScript
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index e7acb3d..d73647e 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -936,8 +936,6 @@
LoadContextVar 0
AddInt
ReturnTOS
- PushNull
- ReturnTOS
}
@@ -1131,8 +1129,6 @@
Push r0
StoreFieldTOS CP#5
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = Type #lib::D::T
@@ -1163,8 +1159,6 @@
Push r0
LoadContextVar 0
ReturnTOS
- PushNull
- ReturnTOS
}
] method foo(generic-covariant-impl self::D::T t) → dynamic {
@@ -1205,11 +1199,6 @@
Push r0
LoadContextVar 0
ReturnTOS
- Push r0
- LoadContextParent
- PopLocal r0
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ClosureFunction <anonymous closure> (dart.core::int y) → dart.core::Null;
@@ -1461,8 +1450,6 @@
PopLocal r4
Push r4
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ClosureFunction foo <T extends dart.core::Object = dynamic>(T t) → void;
diff --git a/pkg/vm/testcases/bytecode/deferred_lib.dart.expect b/pkg/vm/testcases/bytecode/deferred_lib.dart.expect
index d0261e3..67139cb 100644
--- a/pkg/vm/testcases/bytecode/deferred_lib.dart.expect
+++ b/pkg/vm/testcases/bytecode/deferred_lib.dart.expect
@@ -13,8 +13,6 @@
PushConstant CP#3
IndirectStaticCall 0, CP#2
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 1, num-type-args 0, names []
@@ -32,8 +30,6 @@
PushConstant CP#1
IndirectStaticCall 1, CP#0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 1, num-type-args 0, names []
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
index 1f0cfa2..1cd0231 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
@@ -200,8 +200,6 @@
PushConstant CP#2
IndirectStaticCall 1, CP#1
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgumentsField #lib::E
@@ -239,8 +237,6 @@
PushConstant CP#2
IndirectStaticCall 1, CP#1
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgumentsField #lib::F
@@ -284,8 +280,6 @@
IndirectStaticCall 1, CP#2
Drop1
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = Class #lib::H
@@ -350,8 +344,6 @@
IndirectStaticCall 2, CP#3
Drop1
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = String 'param'
@@ -392,8 +384,6 @@
IndirectStaticCall 1, CP#1
Drop1
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = Class #lib::TestTypeArgReuse
@@ -435,8 +425,6 @@
IndirectStaticCall 2, CP#2
Drop1
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = Class #lib::C
@@ -569,8 +557,6 @@
PushConstant CP#2
IndirectStaticCall 2, CP#1
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgumentsForInstanceAllocation dart.core::_GrowableList [dart.core::String]
@@ -588,8 +574,6 @@
PushConstant CP#2
IndirectStaticCall 2, CP#1
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgumentsForInstanceAllocation dart.core::_List [dart.core::int]
diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect
index 0954a1f..e5ace82 100644
--- a/pkg/vm/testcases/bytecode/literals.dart.expect
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -122,8 +122,6 @@
PushConstant CP#1
IndirectStaticCall 1, CP#0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 1, num-type-args 0, names []
@@ -693,8 +691,6 @@
CheckStack
PushConstant CP#1
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgumentsForInstanceAllocation #lib::F [dart.core::int, dart.core::String]
@@ -708,8 +704,6 @@
CheckStack
PushConstant CP#0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = Type <X extends dart.core::Object = dynamic>(X) → X
@@ -723,8 +717,6 @@
PushConstant CP#0
PushStatic CP#0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = StaticField #lib::fieldWithDoubleLiteralInitializer
diff --git a/pkg/vm/testcases/bytecode/loops.dart.expect b/pkg/vm/testcases/bytecode/loops.dart.expect
index 913c397..3c0804e 100644
--- a/pkg/vm/testcases/bytecode/loops.dart.expect
+++ b/pkg/vm/testcases/bytecode/loops.dart.expect
@@ -33,8 +33,6 @@
L1:
Push r0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 1, num-type-args 0, names []
@@ -87,8 +85,6 @@
L1:
Push r0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 1, num-type-args 0, names []
@@ -147,8 +143,6 @@
L1:
Push r0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 1, num-type-args 0, names []
@@ -201,8 +195,6 @@
L1:
Push r0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 1, num-type-args 0, names []
@@ -246,8 +238,6 @@
JumpIfTrue L1
Push r0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 2, num-type-args 0, names []
@@ -290,8 +280,6 @@
L1:
Push r0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 1, num-type-args 0, names []
@@ -335,8 +323,6 @@
L1:
Push r0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 1, num-type-args 0, names []
diff --git a/pkg/vm/testcases/bytecode/super_calls.dart.expect b/pkg/vm/testcases/bytecode/super_calls.dart.expect
index 7c6b17e..f466a6d 100644
--- a/pkg/vm/testcases/bytecode/super_calls.dart.expect
+++ b/pkg/vm/testcases/bytecode/super_calls.dart.expect
@@ -38,8 +38,6 @@
CheckStack
PushInt 42
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
}
@@ -86,8 +84,6 @@
PushConstant CP#3
IndirectStaticCall 4, CP#2
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgs [dart.core::String]
@@ -105,8 +101,6 @@
PushConstant CP#1
IndirectStaticCall 1, CP#0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 1, num-type-args 0, names []
@@ -122,8 +116,6 @@
PushConstant CP#1
IndirectStaticCall 1, CP#0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 1, num-type-args 0, names []
@@ -142,8 +134,6 @@
PushConstant CP#3
InstanceCall 3, CP#5
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgs [dart.core::int]
@@ -254,8 +244,6 @@
PushConstant CP#9
IndirectStaticCall 2, CP#8
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = String 'foo'
@@ -292,8 +280,6 @@
PushConstant CP#6
IndirectStaticCall 2, CP#5
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = String 'foo'
@@ -327,8 +313,6 @@
PushConstant CP#6
IndirectStaticCall 2, CP#5
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = String 'bar'
@@ -365,8 +349,6 @@
PushConstant CP#8
InstanceCall 3, CP#10
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgs [dart.core::int]
diff --git a/pkg/vm/testcases/bytecode/switch.dart.expect b/pkg/vm/testcases/bytecode/switch.dart.expect
index 6fd01d5..bb4fbbb 100644
--- a/pkg/vm/testcases/bytecode/switch.dart.expect
+++ b/pkg/vm/testcases/bytecode/switch.dart.expect
@@ -38,8 +38,6 @@
L4:
Push r0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 2, num-type-args 0, names []
@@ -119,8 +117,6 @@
L4:
Push r0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 2, num-type-args 0, names []
@@ -206,8 +202,6 @@
PopLocal r0
Push r0
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = ArgDesc num-args 2, num-type-args 0, names []
diff --git a/pkg/vm/testcases/bytecode/try_blocks.dart.expect b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
index ac93137..e513f1e 100644
--- a/pkg/vm/testcases/bytecode/try_blocks.dart.expect
+++ b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
@@ -325,7 +325,6 @@
PopLocal r6
Push r6
ReturnTOS
- Jump L1
L1:
Push r0
LoadContextParent
@@ -533,7 +532,6 @@
Push r2
Push r3
Throw 1
- Drop1
L2:
Jump L3
Try #2 end:
@@ -575,9 +573,9 @@
ReturnTOS
}
ExceptionsTable {
- try-index 0, outer -1, start 2, end 36, handler 36, needs-stack-trace, types [CP#3]
+ try-index 0, outer -1, start 2, end 35, handler 35, needs-stack-trace, types [CP#3]
try-index 1, outer 0, start 2, end 7, handler 7, needs-stack-trace, types [CP#3]
- try-index 2, outer 0, start 12, end 24, handler 24, types [CP#3]
+ try-index 2, outer 0, start 12, end 23, handler 23, types [CP#3]
}
ConstantPool {
[0] = String 'try 1 > try 2'
@@ -753,7 +751,6 @@
InstanceCall 1, CP#24
Drop1
Jump L4
- Jump L5
Try #1 end:
Try #1 handler:
SetFrame 9
@@ -775,19 +772,7 @@
PushConstant CP#28
IndirectStaticCall 1, CP#4
Drop1
- Jump L6
-L5:
- Push r5
- PopLocal r0
- PushConstant CP#26
- PushConstant CP#29
- IndirectStaticCall 1, CP#4
- Drop1
- PushConstant CP#30
- PushConstant CP#31
- IndirectStaticCall 1, CP#4
- Drop1
- Jump L7
+ Jump L5
Try #0 end:
Try #0 handler:
SetFrame 9
@@ -795,32 +780,24 @@
PopLocal r0
MoveSpecial r3, exception
MoveSpecial r4, stackTrace
+ PushConstant CP#31
PushConstant CP#32
- PushConstant CP#33
IndirectStaticCall 1, CP#4
Drop1
Push r3
Push r4
Throw 1
-L6:
+L5:
Push r3
PopLocal r0
- PushConstant CP#32
- PushConstant CP#34
+ PushConstant CP#31
+ PushConstant CP#33
IndirectStaticCall 1, CP#4
Drop1
Jump L2
-L7:
- Push r3
- PopLocal r0
- PushConstant CP#32
- PushConstant CP#35
- IndirectStaticCall 1, CP#4
- Drop1
- Jump L3
L2:
- PushConstant CP#36
- PushConstant CP#37
+ PushConstant CP#34
+ PushConstant CP#35
IndirectStaticCall 1, CP#4
Drop1
Jump L3
@@ -829,8 +806,8 @@
ReturnTOS
}
ExceptionsTable {
- try-index 0, outer -1, start 21, end 87, handler 87, needs-stack-trace, types [CP#25]
- try-index 1, outer 0, start 30, end 57, handler 57, needs-stack-trace, types [CP#25]
+ try-index 0, outer -1, start 21, end 75, handler 75, needs-stack-trace, types [CP#25]
+ try-index 1, outer 0, start 30, end 56, handler 56, needs-stack-trace, types [CP#25]
}
ConstantPool {
[0] = ArgDesc num-args 2, num-type-args 0, names []
@@ -862,15 +839,13 @@
[26] = String 'finally 1'
[27] = StaticICData target 'dart.core::print', arg-desc CP#4
[28] = StaticICData target 'dart.core::print', arg-desc CP#4
- [29] = StaticICData target 'dart.core::print', arg-desc CP#4
- [30] = String 'after try 1'
- [31] = StaticICData target 'dart.core::print', arg-desc CP#4
- [32] = String 'finally 2'
+ [29] = String 'after try 1'
+ [30] = StaticICData target 'dart.core::print', arg-desc CP#4
+ [31] = String 'finally 2'
+ [32] = StaticICData target 'dart.core::print', arg-desc CP#4
[33] = StaticICData target 'dart.core::print', arg-desc CP#4
- [34] = StaticICData target 'dart.core::print', arg-desc CP#4
+ [34] = String 'case 2'
[35] = StaticICData target 'dart.core::print', arg-desc CP#4
- [36] = String 'case 2'
- [37] = StaticICData target 'dart.core::print', arg-desc CP#4
}
Closure CP#8 {
EntryFixed 1, 2
@@ -942,20 +917,20 @@
Push r0
PopLocal r3
Try #0 start:
- Allocate CP#22
+ Allocate CP#16
StoreLocal r5
Push r5
PushNull
- StoreFieldTOS CP#23
+ StoreFieldTOS CP#17
Push r5
PushNull
- StoreFieldTOS CP#25
+ StoreFieldTOS CP#19
Push r5
- PushConstant CP#27
- StoreFieldTOS CP#28
+ PushConstant CP#21
+ StoreFieldTOS CP#22
Push r5
PushConstant CP#0
- StoreFieldTOS CP#30
+ StoreFieldTOS CP#24
Push r5
Push r0
StoreFieldTOS CP#1
@@ -970,11 +945,11 @@
MoveSpecial r4, stackTrace
Push r0
LoadContextVar 0
- PushConstant CP#32
+ PushConstant CP#26
IndirectStaticCall 1, CP#3
Drop1
Push r2
- InstanceCall 1, CP#33
+ InstanceCall 1, CP#27
Drop1
Push r3
Push r4
@@ -984,11 +959,11 @@
PopLocal r0
Push r0
LoadContextVar 0
- PushConstant CP#34
+ PushConstant CP#28
IndirectStaticCall 1, CP#3
Drop1
Push r2
- InstanceCall 1, CP#35
+ InstanceCall 1, CP#29
Drop1
Push r0
LoadContextParent
@@ -1015,27 +990,21 @@
[12] = StaticICData target 'dart.core::print', arg-desc CP#3
[13] = StaticICData target 'dart.core::print', arg-desc CP#3
[14] = StaticICData target 'dart.core::print', arg-desc CP#3
- [15] = StaticICData target 'dart.core::print', arg-desc CP#3
- [16] = StaticICData target 'dart.core::print', arg-desc CP#3
- [17] = StaticICData target 'dart.core::print', arg-desc CP#3
- [18] = StaticICData target 'dart.core::print', arg-desc CP#3
- [19] = StaticICData target 'dart.core::print', arg-desc CP#3
- [20] = StaticICData target 'dart.core::print', arg-desc CP#3
- [21] = EndClosureFunctionScope
- [22] = Class dart.core::_Closure
- [23] = InstanceField dart.core::_Closure::_instantiator_type_arguments
- [24] = Reserved
- [25] = InstanceField dart.core::_Closure::_function_type_arguments
- [26] = Reserved
- [27] = EmptyTypeArguments
- [28] = InstanceField dart.core::_Closure::_delayed_type_arguments
- [29] = Reserved
- [30] = InstanceField dart.core::_Closure::_function
- [31] = Reserved
- [32] = StaticICData target 'dart.core::print', arg-desc CP#3
- [33] = ICData dynamic target-name 'call', arg-desc CP#3
- [34] = StaticICData target 'dart.core::print', arg-desc CP#3
- [35] = ICData dynamic target-name 'call', arg-desc CP#3
+ [15] = EndClosureFunctionScope
+ [16] = Class dart.core::_Closure
+ [17] = InstanceField dart.core::_Closure::_instantiator_type_arguments
+ [18] = Reserved
+ [19] = InstanceField dart.core::_Closure::_function_type_arguments
+ [20] = Reserved
+ [21] = EmptyTypeArguments
+ [22] = InstanceField dart.core::_Closure::_delayed_type_arguments
+ [23] = Reserved
+ [24] = InstanceField dart.core::_Closure::_function
+ [25] = Reserved
+ [26] = StaticICData target 'dart.core::print', arg-desc CP#3
+ [27] = ICData dynamic target-name 'call', arg-desc CP#3
+ [28] = StaticICData target 'dart.core::print', arg-desc CP#3
+ [29] = ICData dynamic target-name 'call', arg-desc CP#3
}
Closure CP#0 {
EntryFixed 1, 6
@@ -1056,7 +1025,6 @@
IndirectStaticCall 1, CP#3
Drop1
Jump L1
- Jump L2
Try #0 end:
Try #0 handler:
SetFrame 6
@@ -1071,8 +1039,7 @@
PushConstant CP#9
IndirectStaticCall 1, CP#3
Drop1
- Jump L3
- Jump L4
+ Jump L2
Try #1 end:
Try #1 handler:
SetFrame 6
@@ -1088,7 +1055,7 @@
Push r4
Push r5
Throw 1
-L3:
+L2:
Push r4
PopLocal r0
Push r0
@@ -1098,17 +1065,6 @@
Drop1
PushInt 43
ReturnTOS
-L4:
- Push r4
- PopLocal r0
- Push r0
- LoadContextVar 0
- PushConstant CP#12
- IndirectStaticCall 1, CP#3
- Drop1
- Push r2
- Push r3
- Throw 1
L1:
Push r2
PopLocal r0
@@ -1116,11 +1072,10 @@
PopLocal r4
Try #2 start:
PushConstant CP#8
- PushConstant CP#13
+ PushConstant CP#12
IndirectStaticCall 1, CP#3
Drop1
- Jump L5
- Jump L6
+ Jump L3
Try #2 end:
Try #2 handler:
SetFrame 6
@@ -1130,79 +1085,22 @@
MoveSpecial r5, stackTrace
Push r0
LoadContextVar 0
+ PushConstant CP#13
+ IndirectStaticCall 1, CP#3
+ Drop1
+ Push r4
+ Push r5
+ Throw 1
+L3:
+ Push r4
+ PopLocal r0
+ Push r0
+ LoadContextVar 0
PushConstant CP#14
IndirectStaticCall 1, CP#3
Drop1
- Push r4
- Push r5
- Throw 1
-L5:
- Push r4
- PopLocal r0
- Push r0
- LoadContextVar 0
- PushConstant CP#15
- IndirectStaticCall 1, CP#3
- Drop1
PushInt 43
ReturnTOS
-L6:
- Push r4
- PopLocal r0
- Push r0
- LoadContextVar 0
- PushConstant CP#16
- IndirectStaticCall 1, CP#3
- Drop1
- PushInt 42
- ReturnTOS
-L2:
- Push r2
- PopLocal r0
- Push r0
- PopLocal r4
-Try #3 start:
- PushConstant CP#8
- PushConstant CP#17
- IndirectStaticCall 1, CP#3
- Drop1
- Jump L7
- Jump L8
-Try #3 end:
-Try #3 handler:
- SetFrame 6
- Push r4
- PopLocal r0
- MoveSpecial r4, exception
- MoveSpecial r5, stackTrace
- Push r0
- LoadContextVar 0
- PushConstant CP#18
- IndirectStaticCall 1, CP#3
- Drop1
- Push r4
- Push r5
- Throw 1
-L7:
- Push r4
- PopLocal r0
- Push r0
- LoadContextVar 0
- PushConstant CP#19
- IndirectStaticCall 1, CP#3
- Drop1
- PushInt 43
- ReturnTOS
-L8:
- Push r4
- PopLocal r0
- Push r0
- LoadContextVar 0
- PushConstant CP#20
- IndirectStaticCall 1, CP#3
- Drop1
- PushNull
- ReturnTOS
}
]static method testTryFinally3() → dynamic {
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index c718bdb..ef13709 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -206,8 +206,6 @@
AssertAssignable 0, CP#13
InstanceCall 1, CP#14
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = Type #lib::A<#lib::D::foo3::T1>
@@ -269,8 +267,6 @@
PushConstant CP#3
AssertAssignable 0, CP#7
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = TypeArgumentsField #lib::D
@@ -294,8 +290,6 @@
CheckStack
PushNull
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
}
@@ -366,8 +360,6 @@
PushConstant CP#12
AssertAssignable 0, CP#13
ReturnTOS
- PushNull
- ReturnTOS
}
ConstantPool {
[0] = Type #lib::B
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index d5ac9d0..6d48c90 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -1011,8 +1011,17 @@
}
void BytecodeFlowGraphBuilder::BuildJumpIfNoAsserts() {
+ ASSERT(B->stack_ == nullptr);
if (!isolate()->asserts()) {
BuildJump();
+ // Skip all instructions up to the target PC, as they are all unreachable.
+ // If not skipped, some of the assert code may be considered reachable
+ // (if it contains jumps) and generated. The problem is that generated
+ // code may expect values left on the stack from unreachable
+ // (and not generated) code which immediately follows this Jump.
+ const intptr_t target_pc = pc_ + DecodeOperandT().value();
+ ASSERT(target_pc > pc_);
+ pc_ = target_pc - 1;
}
}
@@ -1107,6 +1116,7 @@
LoadStackSlots(1);
ASSERT(code_.is_open());
code_ += B->Return(position_);
+ ASSERT(B->stack_ == nullptr);
}
void BytecodeFlowGraphBuilder::BuildTrap() {
@@ -1419,6 +1429,9 @@
handler_info.handler_pc_offset, /* is_return_address = */ false);
JoinEntryInstr* join = EnsureControlFlowJoin(descriptors, handler_pc);
+ // Make sure exception handler starts with SetFrame bytecode instruction.
+ InstructionAt(handler_pc, KernelBytecode::kSetFrame);
+
const Array& handler_types =
Array::ZoneHandle(Z, handlers.GetHandledTypes(try_index));
@@ -1476,9 +1489,9 @@
}
code_ = Fragment(join);
B->SetCurrentTryIndex(join->try_index());
- } else if (code_.is_closed()) {
- // Skip unreachable bytecode instructions.
- continue;
+ } else {
+ // Unreachable bytecode is not allowed.
+ ASSERT(!code_.is_closed());
}
BuildInstruction(KernelBytecode::DecodeOpcode(bytecode_instr_));