[vm,dyn_modules] Support pragmas on local functions in bytecode

Pragmas on local functions are used internally by FFI.

TEST=ci

Change-Id: I3ffb9984d8fcd943b22a98746faa915b2ce7c9fa
Cq-Include-Trybots: luci.dart.try:vm-aot-dyn-linux-debug-x64-try,vm-aot-dyn-linux-product-x64-try,vm-dyn-linux-debug-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/446121
Reviewed-by: Tess Strickland <sstrickl@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Alexander Markov
2025-08-21 07:00:49 -07:00
committed by Commit Queue
parent 6157e8d741
commit a3038b85f8
4 changed files with 53 additions and 12 deletions
+6 -1
View File
@@ -647,7 +647,7 @@ type ClosureDeclaration {
UInt flags = (hasOptionalPositionalParams, hasOptionalNamedParams,
hasTypeParams, hasSourcePositions,
isAsync, isAsyncStar, isSyncStar, isDebuggable,
hasParameterFlags)
hasParameterFlags, hasAnnotations, hasPragma)
// Member or Closure.
PackedObject parent;
@@ -672,6 +672,11 @@ type ClosureDeclaration {
List<UInt> parameterFlags;
PackedObject returnType;
if hasAnnotations
// Offset of closure annotations in annotations section of
// component, followed by parameter annotations.
UInt annotationsOffset;
}
type ClosureCode {
+22 -9
View File
@@ -403,23 +403,22 @@ class BytecodeGenerator extends RecursiveVisitor {
// section. Return the annotations for the function only. The bytecode reader
// will implicitly find the parameter annotations by reading N packed objects
// after reading the function's annotations, one for each parameter.
Annotations getFunctionAnnotations(Member member) {
final functionNodes = member.annotations;
Annotations getFunctionAnnotations(
List<Expression> annotations, FunctionNode function) {
final parameterNodeLists = <List<Expression>>[];
for (VariableDeclaration variable
in member.function!.positionalParameters) {
for (VariableDeclaration variable in function.positionalParameters) {
parameterNodeLists.add(variable.annotations);
}
for (VariableDeclaration variable in member.function!.namedParameters) {
for (VariableDeclaration variable in function.namedParameters) {
parameterNodeLists.add(variable.annotations);
}
if (functionNodes.isEmpty &&
if (annotations.isEmpty &&
parameterNodeLists.every((nodes) => nodes.isEmpty)) {
return const Annotations(null, false);
}
List<Constant> functionConstants = functionNodes.map(_getConstant).toList();
List<Constant> functionConstants = annotations.map(_getConstant).toList();
bool hasPragma = functionConstants.any(_isPragma);
if (!options.emitAnnotations && !hasPragma) {
return const Annotations(null, false);
@@ -677,7 +676,8 @@ class BytecodeGenerator extends RecursiveVisitor {
}
endPosition = member.fileEndOffset;
}
final Annotations annotations = getFunctionAnnotations(member);
final Annotations annotations =
getFunctionAnnotations(member.annotations, function);
if (annotations.object != null) {
flags |= FunctionDeclaration.hasAnnotationsFlag;
if (annotations.hasPragma) {
@@ -2548,6 +2548,18 @@ class BytecodeGenerator extends RecursiveVisitor {
flags |= ClosureDeclaration.hasParameterFlagsFlag;
}
final Annotations annotations = getFunctionAnnotations(
node is ast.FunctionDeclaration
? node.variable.annotations
: const <Expression>[],
function);
if (annotations.object != null) {
flags |= ClosureDeclaration.hasAnnotationsFlag;
if (annotations.hasPragma) {
flags |= ClosureDeclaration.hasPragmaFlag;
}
}
return new ClosureDeclaration(
flags,
objectTable.getHandle(parent)!,
@@ -2559,7 +2571,8 @@ class BytecodeGenerator extends RecursiveVisitor {
function.namedParameters.length,
parameters,
parameterFlags,
objectTable.getHandle(function.returnType)!);
objectTable.getHandle(function.returnType)!,
annotations.object);
}
void _genAllocateClosureInstance(
+16 -2
View File
@@ -947,6 +947,8 @@ class ClosureDeclaration {
static const isSyncStarFlag = 1 << 6;
static const isDebuggableFlag = 1 << 7;
static const hasParameterFlagsFlag = 1 << 8;
static const hasAnnotationsFlag = 1 << 9;
static const hasPragmaFlag = 1 << 10;
int flags;
final ObjectHandle parent;
@@ -960,6 +962,7 @@ class ClosureDeclaration {
// Only contains the required flag for named parameters when present.
final List<int>? parameterFlags;
final ObjectHandle returnType;
final AnnotationsDeclaration? annotations;
ClosureCode? code;
ClosureDeclaration(
@@ -973,7 +976,8 @@ class ClosureDeclaration {
this.numNamedParams,
this.parameters,
this.parameterFlags,
this.returnType);
this.returnType,
this.annotations);
void write(BufferedWriter writer) {
writer.writePackedUInt30(flags);
@@ -1006,6 +1010,9 @@ class ClosureDeclaration {
}
}
writer.writePackedObject(returnType);
if ((flags & hasAnnotationsFlag) != 0) {
writer.writeLinkOffset(annotations!);
}
}
factory ClosureDeclaration.read(BufferedReader reader) {
@@ -1043,6 +1050,9 @@ class ClosureDeclaration {
numParameterFlags, (_) => reader.readPackedUInt30());
}
final ObjectHandle returnType = reader.readPackedObject();
final annotations = ((flags & hasAnnotationsFlag) != 0)
? reader.readLinkOffset<AnnotationsDeclaration>()
: null;
return new ClosureDeclaration(
flags,
parent,
@@ -1054,7 +1064,8 @@ class ClosureDeclaration {
numNamedParams,
parameters,
parameterFlags,
returnType);
returnType,
annotations);
}
void _writeParamsToBuffer(
@@ -1088,6 +1099,9 @@ class ClosureDeclaration {
if (position != TreeNode.noOffset) {
sb.write(' pos = $position, end-pos = $endPosition');
}
if ((flags & hasAnnotationsFlag) != 0) {
sb.write(' annotations $annotations\n');
}
if ((flags & hasTypeParamsFlag) != 0) {
sb.write(' type-params $typeParameters');
}
+9
View File
@@ -322,8 +322,11 @@ void BytecodeReaderHelper::ReadClosureDeclaration(const Function& function,
const int kIsSyncStarFlag = 1 << 6;
const int kIsDebuggableFlag = 1 << 7;
const int kHasParameterFlagsFlag = 1 << 8;
const int kHasAnnotationsFlag = 1 << 9;
const int kHasPragmaFlag = 1 << 10;
const intptr_t flags = reader_.ReadUInt();
const bool has_pragma = (flags & kHasPragmaFlag) != 0;
Object& parent = Object::Handle(Z, ReadObject());
if (!parent.IsFunction()) {
@@ -359,6 +362,7 @@ void BytecodeReaderHelper::ReadClosureDeclaration(const Function& function,
closure.set_is_inlinable(false);
}
closure.set_is_debuggable((flags & kIsDebuggableFlag) != 0);
closure.set_has_pragma(has_pragma);
closures_->SetAt(closureIndex, closure);
@@ -371,6 +375,11 @@ void BytecodeReaderHelper::ReadClosureDeclaration(const Function& function,
(flags & kHasParameterFlagsFlag) != 0);
closure.SetSignature(signature);
if ((flags & kHasAnnotationsFlag) != 0) {
ReadAnnotations(Class::Handle(Z, Function::Cast(parent).Owner()), closure,
has_pragma);
}
}
FunctionTypePtr BytecodeReaderHelper::ReadFunctionSignature(