diff --git a/pkg/dart2bytecode/docs/bytecode.md b/pkg/dart2bytecode/docs/bytecode.md index ec9bb799677..66a79d002bc 100644 --- a/pkg/dart2bytecode/docs/bytecode.md +++ b/pkg/dart2bytecode/docs/bytecode.md @@ -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 parameterFlags; PackedObject returnType; + + if hasAnnotations + // Offset of closure annotations in ‘annotations’ section of + // component, followed by parameter annotations. + UInt annotationsOffset; } type ClosureCode { diff --git a/pkg/dart2bytecode/lib/bytecode_generator.dart b/pkg/dart2bytecode/lib/bytecode_generator.dart index 37a74c62447..963bee78821 100644 --- a/pkg/dart2bytecode/lib/bytecode_generator.dart +++ b/pkg/dart2bytecode/lib/bytecode_generator.dart @@ -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 annotations, FunctionNode function) { final parameterNodeLists = >[]; - 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 functionConstants = functionNodes.map(_getConstant).toList(); + List 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 [], + 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( diff --git a/pkg/dart2bytecode/lib/declarations.dart b/pkg/dart2bytecode/lib/declarations.dart index fe6681b58eb..75f2113b976 100644 --- a/pkg/dart2bytecode/lib/declarations.dart +++ b/pkg/dart2bytecode/lib/declarations.dart @@ -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? 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() + : 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'); } diff --git a/runtime/vm/bytecode_reader.cc b/runtime/vm/bytecode_reader.cc index 417ef1c29d0..967e35395bc 100644 --- a/runtime/vm/bytecode_reader.cc +++ b/runtime/vm/bytecode_reader.cc @@ -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(