Skip to content

Commit 37a25d9

Browse files
alexmarkovcommit-bot@chromium.org
authored andcommitted
[vm/bytecode] Add a compile-time error if there are too many arguments.
Issue: #37305 Change-Id: I9dac7c1b7b49fca8531ca2bf83b1c309d8217969 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106984 Reviewed-by: Aart Bik <[email protected]> Reviewed-by: Dmitry Stefantsov <[email protected]> Commit-Queue: Alexander Markov <[email protected]>
1 parent 7142345 commit 37a25d9

6 files changed

Lines changed: 54 additions & 15 deletions

File tree

pkg/front_end/lib/src/api_unstable/vm.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ export '../fasta/compiler_context.dart' show CompilerContext;
3434
export '../fasta/fasta_codes.dart'
3535
show
3636
LocatedMessage,
37+
messageBytecodeLimitExceededTooManyArguments,
38+
noLength,
3739
templateFfiFieldAnnotation,
3840
templateFfiStructAnnotation,
3941
templateFfiNotStatic,

pkg/front_end/lib/src/fasta/fasta_codes_generated.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,15 @@ Message _withArgumentsBuiltInIdentifierInDeclaration(Token token) {
460460
arguments: {'token': token});
461461
}
462462

463+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
464+
const Code<Null> codeBytecodeLimitExceededTooManyArguments =
465+
messageBytecodeLimitExceededTooManyArguments;
466+
467+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
468+
const MessageCode messageBytecodeLimitExceededTooManyArguments =
469+
const MessageCode("BytecodeLimitExceededTooManyArguments",
470+
message: r"""Dart bytecode limit exceeded: too many arguments.""");
471+
463472
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
464473
const Code<Null> codeCandidateFound = messageCandidateFound;
465474

pkg/front_end/messages.status

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ AwaitNotAsync/example: Fail
2828
BadTypeVariableInSupertype/analyzerCode: Fail
2929
BuiltInIdentifierAsType/example: Fail
3030
BuiltInIdentifierInDeclaration/example: Fail
31+
BytecodeLimitExceededTooManyArguments/analyzerCode: Fail
32+
BytecodeLimitExceededTooManyArguments/example: Fail
3133
CannotAssignToParenthesizedExpression/example: Fail
3234
CannotAssignToSuper/example: Fail
3335
CannotReadPackagesFile/analyzerCode: Fail

pkg/front_end/messages.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3566,3 +3566,6 @@ IllegalRecursiveType:
35663566
script: >
35673567
class Base<T> {}
35683568
class Derived<T> extends Base<Derived<Derived<T>>> {}
3569+
3570+
BytecodeLimitExceededTooManyArguments:
3571+
template: "Dart bytecode limit exceeded: too many arguments."

pkg/vm/lib/bytecode/dbc.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,9 @@ const int capturedVariableIndexLimit = 1 << 32;
645645
// Context IDs are referenced using 8-bit unsigned operands.
646646
const int contextIdLimit = 1 << 8;
647647

648+
// Number of arguments is encoded as 8-bit unsigned operand.
649+
const int argumentsLimit = 1 << 8;
650+
648651
// Base class for exceptions thrown when certain limit of bytecode
649652
// format is exceeded.
650653
abstract class BytecodeLimitExceededException {}

pkg/vm/lib/bytecode/gen_bytecode.dart

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ library vm.bytecode.gen_bytecode;
99
import 'package:front_end/src/api_prototype/constant_evaluator.dart'
1010
show ConstantEvaluator, EvaluationEnvironment, ErrorReporter;
1111
import 'package:front_end/src/api_unstable/vm.dart'
12-
show CompilerContext, Severity, templateIllegalRecursiveType;
12+
show
13+
CompilerContext,
14+
Severity,
15+
messageBytecodeLimitExceededTooManyArguments,
16+
noLength,
17+
templateIllegalRecursiveType;
1318

1419
import 'package:kernel/ast.dart' hide MapEntry, Component, FunctionDeclaration;
1520
import 'package:kernel/ast.dart' as ast show Component, FunctionDeclaration;
@@ -691,9 +696,11 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
691696
throw 'Unexpected member ${node.runtimeType} $node';
692697
}
693698
end(node, hasCode);
694-
} on BytecodeLimitExceededException {
695-
// Do not generate bytecode and fall back to using kernel AST.
696-
// TODO(alexmarkov): issue compile-time error
699+
} on TooManyArgumentsException catch (e) {
700+
CompilerContext.current.options.report(
701+
messageBytecodeLimitExceededTooManyArguments.withLocation(
702+
node.fileUri, e.fileOffset, noLength),
703+
Severity.error);
697704
hasErrors = true;
698705
end(node, false);
699706
}
@@ -970,18 +977,21 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
970977
}
971978

972979
void _genDirectCall(Member target, ObjectHandle argDesc, int totalArgCount,
973-
{bool isGet: false, bool isSet: false}) {
980+
{bool isGet: false, bool isSet: false, TreeNode context}) {
974981
assert(!isGet || !isSet);
975982
final kind = isGet
976983
? InvocationKind.getter
977984
: (isSet ? InvocationKind.setter : InvocationKind.method);
978985
final cpIndex = cp.addDirectCall(kind, target, argDesc);
979986

987+
if (totalArgCount >= argumentsLimit) {
988+
throw new TooManyArgumentsException(context.fileOffset);
989+
}
980990
asm.emitDirectCall(cpIndex, totalArgCount);
981991
}
982992

983993
void _genDirectCallWithArgs(Member target, Arguments args,
984-
{bool hasReceiver: false, bool isFactory: false}) {
994+
{bool hasReceiver: false, bool isFactory: false, TreeNode context}) {
985995
final argDesc = objectTable.getArgDescHandleByArguments(args,
986996
hasReceiver: hasReceiver, isFactory: isFactory);
987997

@@ -995,7 +1005,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
9951005
totalArgCount++;
9961006
}
9971007

998-
_genDirectCall(target, argDesc, totalArgCount);
1008+
_genDirectCall(target, argDesc, totalArgCount, context: context);
9991009
}
10001010

10011011
void _genTypeArguments(List<DartType> typeArgs, {Class instantiatingClass}) {
@@ -2359,7 +2369,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
23592369
new Arguments(node.arguments.positional, named: node.arguments.named)
23602370
..parent = node;
23612371
_genArguments(null, args);
2362-
_genDirectCallWithArgs(node.target, args, hasReceiver: true);
2372+
_genDirectCallWithArgs(node.target, args, hasReceiver: true, context: node);
23632373
asm.emitDrop1();
23642374
}
23652375

@@ -2369,7 +2379,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
23692379
_genArguments(node.receiver, args);
23702380
final target = node.target;
23712381
if (target is Procedure && !target.isGetter && !target.isSetter) {
2372-
_genDirectCallWithArgs(target, args, hasReceiver: true);
2382+
_genDirectCallWithArgs(target, args, hasReceiver: true, context: node);
23732383
} else {
23742384
throw new UnsupportedOperationError(
23752385
'Unsupported DirectMethodInvocation with target ${target.runtimeType} $target');
@@ -2624,7 +2634,11 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
26242634
}
26252635

26262636
void _genInstanceCall(
2627-
int totalArgCount, int callCpIndex, bool isDynamic, bool isUnchecked) {
2637+
int totalArgCount, int callCpIndex, bool isDynamic, bool isUnchecked,
2638+
[TreeNode context]) {
2639+
if (totalArgCount >= argumentsLimit) {
2640+
throw new TooManyArgumentsException(context.fileOffset);
2641+
}
26282642
if (isDynamic) {
26292643
assert(!isUnchecked);
26302644
asm.emitDynamicCall(callCpIndex, totalArgCount);
@@ -2662,7 +2676,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
26622676
args.named.length +
26632677
1 /* receiver */ +
26642678
(args.types.isNotEmpty ? 1 : 0) /* type arguments */;
2665-
_genInstanceCall(totalArgCount, callCpIndex, isDynamic, isUnchecked);
2679+
_genInstanceCall(totalArgCount, callCpIndex, isDynamic, isUnchecked, node);
26662680
}
26672681

26682682
@override
@@ -2719,7 +2733,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
27192733
return;
27202734
}
27212735
_genArguments(new ThisExpression(), args);
2722-
_genDirectCallWithArgs(target, args, hasReceiver: true);
2736+
_genDirectCallWithArgs(target, args, hasReceiver: true, context: node);
27232737
}
27242738

27252739
@override
@@ -2872,7 +2886,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
28722886
..parent = node;
28732887
}
28742888
_genArguments(null, args);
2875-
_genDirectCallWithArgs(target, args, isFactory: target.isFactory);
2889+
_genDirectCallWithArgs(target, args,
2890+
isFactory: target.isFactory, context: node);
28762891
}
28772892

28782893
@override
@@ -3700,7 +3715,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
37003715
final args = node.arguments;
37013716
assert(args.types.isEmpty);
37023717
_genArguments(new ThisExpression(), args);
3703-
_genDirectCallWithArgs(node.target, args, hasReceiver: true);
3718+
_genDirectCallWithArgs(node.target, args, hasReceiver: true, context: node);
37043719
asm.emitDrop1();
37053720
}
37063721

@@ -3718,7 +3733,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
37183733
}
37193734
}
37203735
assert(target != null);
3721-
_genDirectCallWithArgs(target, args, hasReceiver: true);
3736+
_genDirectCallWithArgs(target, args, hasReceiver: true, context: node);
37223737
asm.emitDrop1();
37233738
}
37243739

@@ -3746,6 +3761,11 @@ class UnsupportedOperationError {
37463761
String toString() => message;
37473762
}
37483763

3764+
class TooManyArgumentsException extends BytecodeLimitExceededException {
3765+
final int fileOffset;
3766+
TooManyArgumentsException(this.fileOffset);
3767+
}
3768+
37493769
typedef void GenerateContinuation();
37503770

37513771
class FinallyBlock {

0 commit comments

Comments
 (0)