diff --git a/pkg/cfg/lib/front_end/ast_to_ir.dart b/pkg/cfg/lib/front_end/ast_to_ir.dart index 8222f45395b..67b903dcdc9 100644 --- a/pkg/cfg/lib/front_end/ast_to_ir.dart +++ b/pkg/cfg/lib/front_end/ast_to_ir.dart @@ -1531,7 +1531,8 @@ class AstToIr extends ast.RecursiveVisitor { _typeTranslator.translate(node.constructedType), typeArguments: typeArguments, ); - final argsWithoutTypes = ast.Arguments(args.positional, named: args.named); + final argsWithoutTypes = ast.Arguments(args.positional, named: args.named) + ..parent = node; final inputCount = _translateArguments(null, argsWithoutTypes); if (_handleUnreachableExpression(inputCount + 1)) return; builder.addDirectCall( diff --git a/pkg/dart2bytecode/docs/bytecode.md b/pkg/dart2bytecode/docs/bytecode.md index ccd6b1c5c14..29b5b46589b 100644 --- a/pkg/dart2bytecode/docs/bytecode.md +++ b/pkg/dart2bytecode/docs/bytecode.md @@ -47,7 +47,7 @@ which reside in different sections such as libraries, classes, members, code, et ``` type BytecodeFile { UInt32 magic = 0x44424333; // 'DBC3' - UInt32 formatVersion = 1; + UInt32 formatVersion = 2; // Descriptors of the sections below. // Each section has a fixed index in the descriptors array. @@ -816,6 +816,14 @@ type ConstantDeferredLibraryPrefix extends ConstantPoolEntry { PackedObject enclosingLibrary; PackedObject targetLibrary; } + +// Occupies 2 entries in the constant pool +type ConstantAllocateClosure extends ConstantPoolEntry { + Byte tag = 18; + UInt closureIndex; + UInt numElements; + UInt flags = (hasDelayedTypeArguments, hasInstantiatorTypeArguments, hasFunctionTypeArguments); +} ``` ### Exceptions table @@ -1423,7 +1431,15 @@ SP[0] = SP[-1] SP[0] ? true : false #### AllocateClosure D -Allocate closure object for closure function ConstantPool[D]. +Allocate closure object described by ConstantAllocateClosure in ConstantPool[D]. + +#### LoadClosureElement D + +Load element [D] from closure SP[0] and push it onto the stack. + +#### StoreClosureElement D + +Store object SP[0] into the element [D] of closure SP[-1]. #### Nop diff --git a/pkg/dart2bytecode/lib/assembler.dart b/pkg/dart2bytecode/lib/assembler.dart index c72d9125477..ec576bdee10 100644 --- a/pkg/dart2bytecode/lib/assembler.dart +++ b/pkg/dart2bytecode/lib/assembler.dart @@ -787,9 +787,21 @@ class BytecodeAssembler { } @pragma('vm:prefer-inline') - void emitAllocateClosure() { + void emitAllocateClosure(int rd) { emitSourcePosition(); - _emitInstruction0(Opcode.kAllocateClosure); + _emitInstructionD(Opcode.kAllocateClosure, rd); + } + + @pragma('vm:prefer-inline') + void emitLoadClosureElement(int rd) { + emitSourcePosition(); + _emitInstructionD(Opcode.kLoadClosureElement, rd); + } + + @pragma('vm:prefer-inline') + void emitStoreClosureElement(int rd) { + emitSourcePosition(); + _emitInstructionD(Opcode.kStoreClosureElement, rd); } @pragma('vm:prefer-inline') diff --git a/pkg/dart2bytecode/lib/bytecode_generator.dart b/pkg/dart2bytecode/lib/bytecode_generator.dart index 7ba96aed5f4..667b6179558 100644 --- a/pkg/dart2bytecode/lib/bytecode_generator.dart +++ b/pkg/dart2bytecode/lib/bytecode_generator.dart @@ -1010,8 +1010,6 @@ class BytecodeGenerator extends RecursiveVisitor { '_interpolate', ); - late Class closureClass = libraryIndex.getClass('dart:core', '_Closure'); - late Procedure objectInstanceOf = libraryIndex.getProcedure( 'dart:core', 'Object', @@ -1024,36 +1022,6 @@ class BytecodeGenerator extends RecursiveVisitor { '_simpleInstanceOf', ); - late Field closureInstantiatorTypeArguments = libraryIndex.getField( - 'dart:core', - '_Closure', - '_instantiator_type_arguments', - ); - - late Field closureFunctionTypeArguments = libraryIndex.getField( - 'dart:core', - '_Closure', - '_function_type_arguments', - ); - - late Field closureDelayedTypeArguments = libraryIndex.getField( - 'dart:core', - '_Closure', - '_delayed_type_arguments', - ); - - late Field closureFunction = libraryIndex.getField( - 'dart:core', - '_Closure', - '_function', - ); - - late Field closureContext = libraryIndex.getField( - 'dart:core', - '_Closure', - '_context', - ); - late Procedure prependTypeArguments = libraryIndex.getTopLevelProcedure( 'dart:_internal', '_prependTypeArguments', @@ -2226,7 +2194,7 @@ class BytecodeGenerator extends RecursiveVisitor { if (isClosure) { asm.emitPush(locals.closureVarIndexInFrame); - asm.emitLoadFieldTOS(cp.addInstanceField(closureContext)); + asm.emitLoadClosureElement(contextClosureElement); asm.emitPopLocal(locals.contextVarIndexInFrame); } @@ -2294,7 +2262,7 @@ class BytecodeGenerator extends RecursiveVisitor { final int numParentTypeArgs = locals.numParentTypeArguments; asm.emitPush(locals.functionTypeArgsVarIndexInFrame); asm.emitPush(locals.closureVarIndexInFrame); - asm.emitLoadFieldTOS(cp.addInstanceField(closureFunctionTypeArguments)); + asm.emitLoadClosureElement(functionTypeArgumentsClosureElement); _genPushInt(numParentTypeArgs); _genPushInt(numParentTypeArgs + function.typeParameters.length); _genDirectCall( @@ -2305,17 +2273,35 @@ class BytecodeGenerator extends RecursiveVisitor { asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame); } else { asm.emitPush(locals.closureVarIndexInFrame); - asm.emitLoadFieldTOS(cp.addInstanceField(closureFunctionTypeArguments)); + asm.emitLoadClosureElement(functionTypeArgumentsClosureElement); asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame); } } } + bool get closureHasDelayedTypeArguments => + enclosingFunction!.typeParameters.isNotEmpty; + bool get closureHasInstantiatorTypeArguments => + instantiatorTypeArguments != null; + bool get closureHasFunctionTypeArguments => + locals.hasFunctionTypeArgsVar && locals.numParentTypeArguments > 0; + + int get delayedTypeArgumentsClosureElement => 0; + int get instantiatorTypeArgumentsClosureElement => + (closureHasDelayedTypeArguments ? 1 : 0); + int get functionTypeArgumentsClosureElement => + (closureHasDelayedTypeArguments ? 1 : 0) + + (closureHasInstantiatorTypeArguments ? 1 : 0); + int get contextClosureElement => + (closureHasDelayedTypeArguments ? 1 : 0) + + (closureHasInstantiatorTypeArguments ? 1 : 0) + + (closureHasFunctionTypeArguments ? 1 : 0); + void _handleDelayedTypeArguments(Label doneCheckingTypeArguments) { Label noDelayedTypeArgs = new Label(); asm.emitPush(locals.closureVarIndexInFrame); - asm.emitLoadFieldTOS(cp.addInstanceField(closureDelayedTypeArguments)); + asm.emitLoadClosureElement(delayedTypeArgumentsClosureElement); asm.emitStoreLocal(locals.functionTypeArgsVarIndexInFrame); asm.emitPushConstant(cp.addEmptyTypeArguments()); asm.emitJumpIfEqStrict(noDelayedTypeArgs); @@ -2347,7 +2333,7 @@ class BytecodeGenerator extends RecursiveVisitor { (t) => containsTypeParameter(t, functionTypeParametersSet!), )) { asm.emitPush(locals.closureVarIndexInFrame); - asm.emitLoadFieldTOS(cp.addInstanceField(closureFunctionTypeArguments)); + asm.emitLoadClosureElement(functionTypeArgumentsClosureElement); asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame); } @@ -2802,7 +2788,7 @@ class BytecodeGenerator extends RecursiveVisitor { ); closures.add(closure); - final int closureFunctionIndex = cp.addClosureFunction(closureIndex); + cp.addClosureFunction(closureIndex); _recordSourcePosition(function.fileOffset, SourcePositions.syntheticFlag); _genPrologue(node, function); @@ -2856,7 +2842,7 @@ class BytecodeGenerator extends RecursiveVisitor { _popAssemblerState(); - return closureFunctionIndex; + return closureIndex; } ClosureDeclaration getClosureDeclaration( @@ -2972,40 +2958,59 @@ class BytecodeGenerator extends RecursiveVisitor { void _genAllocateClosureInstance( TreeNode node, - int closureFunctionIndex, + int closureIndex, FunctionNode function, ) { - asm.emitPushConstant(closureFunctionIndex); - asm.emitPush(locals.contextVarIndexInFrame); - _genPushInstantiatorTypeArguments(); - asm.emitAllocateClosure(); + final bool hasDelayedTypeArguments = function.typeParameters.isNotEmpty; + final bool hasInstantiatorTypeArguments = instantiatorTypeArguments != null; + final bool hasFunctionTypeArguments = locals.hasFunctionTypeArgsVar; + final numElements = + (hasDelayedTypeArguments ? 1 : 0) + + (hasInstantiatorTypeArguments ? 1 : 0) + + (hasFunctionTypeArguments ? 1 : 0) + /* context */ + 1; - final bool storeFunctionTAV = locals.hasFunctionTypeArgsVar; - final bool setEmptyDelayedTAV = function.typeParameters.isNotEmpty; + asm.emitAllocateClosure( + cp.addAllocateClosure( + closureIndex, + numElements, + hasDelayedTypeArguments: hasDelayedTypeArguments, + hasInstantiatorTypeArguments: hasInstantiatorTypeArguments, + hasFunctionTypeArguments: hasFunctionTypeArguments, + ), + ); - if (storeFunctionTAV || setEmptyDelayedTAV) { - final int temp = locals.tempIndexInFrame(node); - asm.emitStoreLocal(temp); + final int temp = locals.tempIndexInFrame(node); + asm.emitStoreLocal(temp); - if (storeFunctionTAV) { - asm.emitPush(temp); - _genPushFunctionTypeArguments(); - asm.emitStoreFieldTOS( - cp.addInstanceField(closureFunctionTypeArguments), - ); - } - - if (setEmptyDelayedTAV) { - asm.emitPush(temp); - asm.emitPushConstant(cp.addEmptyTypeArguments()); - asm.emitStoreFieldTOS(cp.addInstanceField(closureDelayedTypeArguments)); - } + var elementIndex = 0; + if (hasDelayedTypeArguments) { + asm.emitPush(temp); + asm.emitPushConstant(cp.addEmptyTypeArguments()); + asm.emitStoreClosureElement(elementIndex++); } + + if (hasInstantiatorTypeArguments) { + asm.emitPush(temp); + _genPushInstantiatorTypeArguments(); + asm.emitStoreClosureElement(elementIndex++); + } + + if (hasFunctionTypeArguments) { + asm.emitPush(temp); + _genPushFunctionTypeArguments(); + asm.emitStoreClosureElement(elementIndex++); + } + + asm.emitPush(temp); + asm.emitPush(locals.contextVarIndexInFrame); + asm.emitStoreClosureElement(elementIndex++); + assert(elementIndex == numElements); } void _genClosure(LocalFunction node, String name, FunctionNode function) { - final int closureFunctionIndex = _genClosureBytecode(node, name, function); - _genAllocateClosureInstance(node, closureFunctionIndex, function); + final int closureIndex = _genClosureBytecode(node, name, function); + _genAllocateClosureInstance(node, closureIndex, function); } void _allocateContextIfNeeded() { @@ -4654,7 +4659,7 @@ class BytecodeGenerator extends RecursiveVisitor { // 1. Restore context from closure var. // This context has a context level at frame entry. asm.emitPush(locals.closureVarIndexInFrame); - asm.emitLoadFieldTOS(cp.addInstanceField(closureContext)); + asm.emitLoadClosureElement(contextClosureElement); asm.emitPopLocal(locals.contextVarIndexInFrame); // 2. Restore context from captured :saved_try_context_var${depth}. diff --git a/pkg/dart2bytecode/lib/constant_pool.dart b/pkg/dart2bytecode/lib/constant_pool.dart index d9a844afefd..c2f520b6aed 100644 --- a/pkg/dart2bytecode/lib/constant_pool.dart +++ b/pkg/dart2bytecode/lib/constant_pool.dart @@ -33,6 +33,7 @@ enum ConstantTag { kExternalCall, kFfiCall, kDeferredLibraryPrefix, + kAllocateClosure, } String constantTagToString(ConstantTag tag) => @@ -93,6 +94,8 @@ abstract class ConstantPoolEntry { return new ConstantFfiCall.read(reader); case ConstantTag.kDeferredLibraryPrefix: return new ConstantDeferredLibraryPrefix.read(reader); + case ConstantTag.kAllocateClosure: + return new ConstantAllocateClosure.read(reader); } throw 'Unexpected constant tag $tag'; } @@ -607,6 +610,52 @@ class ConstantDeferredLibraryPrefix extends ConstantPoolEntry { this.targetLibrary == other.targetLibrary; } +class ConstantAllocateClosure extends ConstantPoolEntry { + static const int hasDelayedTypeArguments = 1 << 0; + static const int hasInstantiatorTypeArguments = 1 << 1; + static const int hasFunctionTypeArguments = 1 << 2; + + final int closureIndex; + final int numElements; + final int flags; + + ConstantAllocateClosure(this.closureIndex, this.numElements, this.flags); + + @override + ConstantTag get tag => ConstantTag.kAllocateClosure; + + // 2 slots: function, encoded length and flags. + @override + int get numReservedEntries => 1; + + @override + void writeValue(BufferedWriter writer) { + writer.writePackedUInt30(closureIndex); + writer.writePackedUInt30(numElements); + writer.writePackedUInt30(flags); + } + + ConstantAllocateClosure.read(BufferedReader reader) + : closureIndex = reader.readPackedUInt30(), + numElements = reader.readPackedUInt30(), + flags = reader.readPackedUInt30(); + + @override + String toString() { + return 'AllocateClosure $closureIndex, num-elements: $numElements, flags: $flags'; + } + + @override + int get hashCode => closureIndex.hashCode; + + @override + bool operator ==(other) => + other is ConstantAllocateClosure && + this.closureIndex == other.closureIndex && + this.flags == other.flags && + this.numElements == other.numElements; +} + /// Reserved constant pool entry. class _ReservedConstantPoolEntry extends ConstantPoolEntry { const _ReservedConstantPoolEntry(); @@ -788,6 +837,28 @@ class ConstantPool { ), ); + int addAllocateClosure( + int closureIndex, + int numElements, { + required bool hasDelayedTypeArguments, + required bool hasInstantiatorTypeArguments, + required bool hasFunctionTypeArguments, + }) => _add( + ConstantAllocateClosure( + closureIndex, + numElements, + (hasDelayedTypeArguments + ? ConstantAllocateClosure.hasDelayedTypeArguments + : 0) | + (hasInstantiatorTypeArguments + ? ConstantAllocateClosure.hasInstantiatorTypeArguments + : 0) | + (hasFunctionTypeArguments + ? ConstantAllocateClosure.hasFunctionTypeArguments + : 0), + ), + ); + int _add(ConstantPoolEntry entry) { int? index = _canonicalizationCache[entry]; if (index == null) { diff --git a/pkg/dart2bytecode/lib/dbc.dart b/pkg/dart2bytecode/lib/dbc.dart index d803cfe8dba..2141fd3b488 100644 --- a/pkg/dart2bytecode/lib/dbc.dart +++ b/pkg/dart2bytecode/lib/dbc.dart @@ -7,7 +7,7 @@ library; /// Version of bytecode format /// (should match runtime/vm/constants_kbc.h). -const int bytecodeFormatVersion = 1; +const int bytecodeFormatVersion = 2; enum Opcode { kTrap, @@ -34,8 +34,14 @@ enum Opcode { kAllocate_Wide, kAllocateT, kCreateArrayTOS, + + // Closure allocation and access. kAllocateClosure, - kUnused03, + kAllocateClosure_Wide, + kLoadClosureElement, + kLoadClosureElement_Wide, + kStoreClosureElement, + kStoreClosureElement_Wide, // Context allocation and access. kAllocateContext, @@ -677,9 +683,19 @@ const Map BytecodeFormats = const { Operand.imm, Operand.none, ]), - Opcode.kAllocateClosure: const Format(Encoding.k0, const [ + Opcode.kAllocateClosure: const Format(Encoding.kD, const [ + Operand.lit, Operand.none, Operand.none, + ]), + Opcode.kLoadClosureElement: const Format(Encoding.kD, const [ + Operand.imm, + Operand.none, + Operand.none, + ]), + Opcode.kStoreClosureElement: const Format(Encoding.kD, const [ + Operand.imm, + Operand.none, Operand.none, ]), Opcode.kUncheckedClosureCall: const Format(Encoding.kDF, const [ diff --git a/pkg/dart2bytecode/lib/local_vars.dart b/pkg/dart2bytecode/lib/local_vars.dart index dd78b20367e..ab5b9f3b334 100644 --- a/pkg/dart2bytecode/lib/local_vars.dart +++ b/pkg/dart2bytecode/lib/local_vars.dart @@ -1076,37 +1076,19 @@ class _Allocator extends RecursiveVisitor { _visitFunction(node); } - // A temporary is only needed for function declarations or expressions when: - // * There are function type arguments to capture. - // * The function is generic and so the delayed type arguments field of the - // closure must be empty-initialized, not null-initialized. - bool _closureAllocationNeedsTemp(FunctionNode function) => - _currentFrame.functionTypeArgsVar != null || - function.typeParameters.isNotEmpty; - @override void visitFunctionDeclaration(FunctionDeclaration node) { _allocateVariable(node.variable); - final needsTemp = _closureAllocationNeedsTemp(node.function); - if (needsTemp) { - _allocateTemp(node); - } + _allocateTemp(node); _visitFunction(node); - if (needsTemp) { - _freeTemp(node); - } + _freeTemp(node); } @override void visitFunctionExpression(FunctionExpression node) { - final needsTemp = _closureAllocationNeedsTemp(node.function); - if (needsTemp) { - _allocateTemp(node); - } + _allocateTemp(node); _visitFunction(node); - if (needsTemp) { - _freeTemp(node); - } + _freeTemp(node); } @override diff --git a/pkg/dart2bytecode/testcases/async.dart.expect b/pkg/dart2bytecode/testcases/async.dart.expect index fcc7274fdb9..d25bb9b0260 100644 --- a/pkg/dart2bytecode/testcases/async.dart.expect +++ b/pkg/dart2bytecode/testcases/async.dart.expect @@ -9,52 +9,53 @@ Class '', script = 'DART_SDK/pkg/dart2bytecode/testcases/async.dart' Field 'asyncInFieldInitializer', type = FunctionType (dart:async::Future < dart:core::int >) -> dart:async::Future < Null >, getter = 'get:asyncInFieldInitializer', reflectable, static, is-late, has-initializer initializer Bytecode { - Entry 2 + Entry 3 CheckStack 0 - PushConstant CP#0 + AllocateClosure CP#15 + StoreLocal r2 + Push r2 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 ReturnTOS } ConstantPool { [0] = ClosureFunction 0 - [1] = InstanceField dart:core::_Closure::_context (field) - [2] = Reserved - [3] = Type dart:async::Future < dart:core::int > - [4] = ObjectRef 'x' - [5] = SubtypeTestCache - [6] = ObjectRef < Null > - [7] = DirectCall 'dart:async::_SuspendState::_initAsync', ArgDesc num-args 0, num-type-args 1, names [] - [8] = Reserved - [9] = Type dynamic - [10] = DirectCall 'dart:async::_SuspendState::_await', ArgDesc num-args 2, num-type-args 0, names [] + [1] = Type dart:async::Future < dart:core::int > + [2] = ObjectRef 'x' + [3] = SubtypeTestCache + [4] = ObjectRef < Null > + [5] = DirectCall 'dart:async::_SuspendState::_initAsync', ArgDesc num-args 0, num-type-args 1, names [] + [6] = Reserved + [7] = Type dynamic + [8] = DirectCall 'dart:async::_SuspendState::_await', ArgDesc num-args 2, num-type-args 0, names [] + [9] = Reserved + [10] = DirectCall 'dart:async::_SuspendState::_returnAsync', ArgDesc num-args 2, num-type-args 0, names [] [11] = Reserved - [12] = DirectCall 'dart:async::_SuspendState::_returnAsync', ArgDesc num-args 2, num-type-args 0, names [] + [12] = DirectCall 'dart:async::_SuspendState::_handleException', ArgDesc num-args 3, num-type-args 0, names [] [13] = Reserved - [14] = DirectCall 'dart:async::_SuspendState::_handleException', ArgDesc num-args 3, num-type-args 0, names [] - [15] = Reserved - [16] = EndClosureFunctionScope + [14] = EndClosureFunctionScope + [15] = AllocateClosure 0, num-elements: 1, flags: 0 + [16] = Reserved } Closure DART_SDK/pkg/dart2bytecode/testcases/async.dart::asyncInFieldInitializer (field)::'' async (dart:async::Future < dart:core::int > x) -> dart:async::Future < Null > ClosureCode { EntrySuspendable 2, 0, 0 Frame 5 Push r1 - LoadFieldTOS CP#1 + LoadClosureElement 0 PopLocal r3 CheckStack 0 JumpIfUnchecked L1 Push r2 - PushConstant CP#3 + PushConstant CP#1 PushNull PushNull - PushConstant CP#4 - AssertAssignable 0, CP#5 + PushConstant CP#2 + AssertAssignable 0, CP#3 Drop1 L1: - PushConstant CP#6 - DirectCall CP#7, 1 + PushConstant CP#4 + DirectCall CP#5, 1 PopLocal r0 Try #0 start: Push r2 @@ -62,7 +63,7 @@ Try #0 start: Suspend L2 Push r0 Push r6 - DirectCall CP#10, 2 + DirectCall CP#8, 2 ReturnTOS L2: Drop1 @@ -72,7 +73,7 @@ L2: Push r5 PushNull PopLocal r0 - DirectCall CP#12, 2 + DirectCall CP#10, 2 ReturnTOS Try #0 end: Try #0 handler: @@ -84,7 +85,7 @@ Try #0 handler: Push r0 MoveSpecial stackTrace, r0 Push r0 - DirectCall CP#14, 3 + DirectCall CP#12, 3 ReturnTOS L3: MoveSpecial exception, r0 @@ -529,7 +530,7 @@ Function 'closure', static, reflectable, debuggable return-type dynamic Bytecode { - Entry 3 + Entry 4 CheckStack 0 AllocateContext 0, 2 PopLocal r0 @@ -539,43 +540,44 @@ Bytecode { Push r0 PushInt 3 StoreContextVar 0, 1 - PushConstant CP#0 + AllocateClosure CP#15 + StoreLocal r3 + Push r3 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 PopLocal r2 Push r2 ReturnTOS } ConstantPool { [0] = ClosureFunction 0 - [1] = InstanceField dart:core::_Closure::_context (field) - [2] = Reserved - [3] = ObjectRef < dart:core::int > - [4] = DirectCall 'dart:async::_SuspendState::_initAsync', ArgDesc num-args 0, num-type-args 1, names [] - [5] = Reserved - [6] = Type dynamic - [7] = DirectCall 'dart:async::_SuspendState::_await', ArgDesc num-args 2, num-type-args 0, names [] - [8] = Reserved - [9] = ObjectRef 'fin' - [10] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] + [1] = ObjectRef < dart:core::int > + [2] = DirectCall 'dart:async::_SuspendState::_initAsync', ArgDesc num-args 0, num-type-args 1, names [] + [3] = Reserved + [4] = Type dynamic + [5] = DirectCall 'dart:async::_SuspendState::_await', ArgDesc num-args 2, num-type-args 0, names [] + [6] = Reserved + [7] = ObjectRef 'fin' + [8] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] + [9] = Reserved + [10] = DirectCall 'dart:async::_SuspendState::_returnAsync', ArgDesc num-args 2, num-type-args 0, names [] [11] = Reserved - [12] = DirectCall 'dart:async::_SuspendState::_returnAsync', ArgDesc num-args 2, num-type-args 0, names [] + [12] = DirectCall 'dart:async::_SuspendState::_handleException', ArgDesc num-args 3, num-type-args 0, names [] [13] = Reserved - [14] = DirectCall 'dart:async::_SuspendState::_handleException', ArgDesc num-args 3, num-type-args 0, names [] - [15] = Reserved - [16] = EndClosureFunctionScope + [14] = EndClosureFunctionScope + [15] = AllocateClosure 0, num-elements: 1, flags: 0 + [16] = Reserved } Closure DART_SDK/pkg/dart2bytecode/testcases/async.dart::closure::'nested' async () -> dart:async::Future < dart:core::int > ClosureCode { EntrySuspendable 1, 0, 0 Frame 8 Push r1 - LoadFieldTOS CP#1 + LoadClosureElement 0 PopLocal r2 CheckStack 0 - PushConstant CP#3 - DirectCall CP#4, 1 + PushConstant CP#1 + DirectCall CP#2, 1 PopLocal r0 Try #0 start: PushInt 4 @@ -592,7 +594,7 @@ Try #1 start: Suspend L1 Push r0 Push r8 - DirectCall CP#7, 2 + DirectCall CP#5, 2 ReturnTOS L1: PopLocal r5 @@ -609,8 +611,8 @@ Try #1 handler: PopLocal r2 MoveSpecial exception, r6 MoveSpecial stackTrace, r7 - PushConstant CP#9 - DirectCall CP#10, 1 + PushConstant CP#7 + DirectCall CP#8, 1 Drop1 Push r6 Push r7 @@ -618,8 +620,8 @@ Try #1 handler: L2: Push r6 PopLocal r2 - PushConstant CP#9 - DirectCall CP#10, 1 + PushConstant CP#7 + DirectCall CP#8, 1 Drop1 Push r4 PopLocal r4 @@ -627,7 +629,7 @@ L2: Push r4 PushNull PopLocal r0 - DirectCall CP#12, 2 + DirectCall CP#10, 2 ReturnTOS Try #0 end: Try #0 handler: @@ -639,7 +641,7 @@ Try #0 handler: Push r0 MoveSpecial stackTrace, r0 Push r0 - DirectCall CP#14, 3 + DirectCall CP#12, 3 ReturnTOS L3: MoveSpecial exception, r0 diff --git a/pkg/dart2bytecode/testcases/closures.dart.expect b/pkg/dart2bytecode/testcases/closures.dart.expect index 1e86b299931..4d5116b5df3 100644 --- a/pkg/dart2bytecode/testcases/closures.dart.expect +++ b/pkg/dart2bytecode/testcases/closures.dart.expect @@ -19,10 +19,11 @@ Bytecode { Push r0 PushInt 5 StoreContextVar 0, 0 - PushConstant CP#0 + AllocateClosure CP#5 + StoreLocal r3 + Push r3 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 PopLocal r2 Push r2 StoreLocal r3 @@ -36,28 +37,28 @@ Bytecode { } ConstantPool { [0] = ClosureFunction 0 - [1] = InstanceField dart:core::_Closure::_context (field) - [2] = Reserved - [3] = Type dart:core::int - [4] = ObjectRef 'y' - [5] = SubtypeTestCache - [6] = EndClosureFunctionScope + [1] = Type dart:core::int + [2] = ObjectRef 'y' + [3] = SubtypeTestCache + [4] = EndClosureFunctionScope + [5] = AllocateClosure 0, num-elements: 1, flags: 0 + [6] = Reserved [7] = ObjectRef ArgDesc num-args 2, num-type-args 0, names [] } Closure DART_SDK/pkg/dart2bytecode/testcases/closures.dart::simpleClosure::'' (dart:core::int y) -> Null ClosureCode { Entry 2 Push FP[-6] - LoadFieldTOS CP#1 + LoadClosureElement 0 PopLocal r0 CheckStack 0 JumpIfUnchecked L1 Push FP[-5] - PushConstant CP#3 + PushConstant CP#1 PushNull PushNull - PushConstant CP#4 - AssertAssignable 1, CP#5 + PushConstant CP#2 + AssertAssignable 1, CP#3 Drop1 L1: Push r0 @@ -188,51 +189,47 @@ Function 'testPartialInstantiation', static, reflectable, debuggable Bytecode { Entry 5 CheckStack 0 - PushConstant CP#0 - Push r0 - PushNull - AllocateClosure + AllocateClosure CP#8 StoreLocal r3 Push r3 - PushConstant CP#5 - StoreFieldTOS CP#3 + PushConstant CP#1 + StoreClosureElement 0 + Push r3 + Push r0 + StoreClosureElement 1 PopLocal r2 Push r2 - PushConstant CP#14 - DirectCall CP#15, 2 + PushConstant CP#10 + DirectCall CP#11, 2 PopLocal r4 Push r4 ReturnTOS } ConstantPool { [0] = ClosureFunction 0 - [1] = InstanceField dart:core::_Closure::_context (field) - [2] = Reserved - [3] = InstanceField dart:core::_Closure::_delayed_type_arguments (field) - [4] = Reserved - [5] = EmptyTypeArguments - [6] = InstanceField dart:core::_Closure::_function_type_arguments (field) - [7] = Reserved - [8] = DirectCall 'dart:_internal::_prependTypeArguments', ArgDesc num-args 4, num-type-args 0, names [] + [1] = EmptyTypeArguments + [2] = DirectCall 'dart:_internal::_prependTypeArguments', ArgDesc num-args 4, num-type-args 0, names [] + [3] = Reserved + [4] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::testPartialInstantiation::Closure/0::TypeParam/0 + [5] = ObjectRef 't' + [6] = SubtypeTestCache + [7] = EndClosureFunctionScope + [8] = AllocateClosure 0, num-elements: 2, flags: 1 [9] = Reserved - [10] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::testPartialInstantiation::Closure/0::TypeParam/0 - [11] = ObjectRef 't' - [12] = SubtypeTestCache - [13] = EndClosureFunctionScope - [14] = ObjectRef < dart:core::int > - [15] = DirectCall 'dart:_internal::_instantiateClosure', ArgDesc num-args 2, num-type-args 0, names [] - [16] = Reserved + [10] = ObjectRef < dart:core::int > + [11] = DirectCall 'dart:_internal::_instantiateClosure', ArgDesc num-args 2, num-type-args 0, names [] + [12] = Reserved } Closure DART_SDK/pkg/dart2bytecode/testcases/closures.dart::testPartialInstantiation::'foo' type-params <'T' extends dart:core::Object? (default dynamic)> (DART_SDK/pkg/dart2bytecode/testcases/closures.dart::testPartialInstantiation::Closure/0::TypeParam/0 t) -> void ClosureCode { Entry 3 Push FP[-6] - LoadFieldTOS CP#1 + LoadClosureElement 1 PopLocal r1 Push FP[-6] - LoadFieldTOS CP#3 + LoadClosureElement 0 StoreLocal r0 - PushConstant CP#5 + PushConstant CP#1 JumpIfEqStrict L1 CheckFunctionTypeArgs 0, r2 Jump L2 @@ -242,18 +239,18 @@ L2: CheckStack 0 Push r0 Push FP[-6] - LoadFieldTOS CP#6 + LoadClosureElement 1 PushInt 0 PushInt 1 - DirectCall CP#8, 4 + DirectCall CP#2, 4 PopLocal r0 JumpIfUnchecked L3 Push FP[-5] - PushConstant CP#10 + PushConstant CP#4 PushNull Push r0 - PushConstant CP#11 - AssertAssignable 0, CP#12 + PushConstant CP#5 + AssertAssignable 0, CP#6 Drop1 L3: PushNull @@ -488,69 +485,72 @@ Bytecode { Push r1 Push FP[-5] StoreContextVar 0, 0 - PushConstant CP#0 - Push r1 - Push FP[-5] - LoadTypeArgumentsField CP#13 - AllocateClosure + AllocateClosure CP#34 StoreLocal r4 Push r4 - Push r0 - StoreFieldTOS CP#6 + PushConstant CP#1 + StoreClosureElement 0 Push r4 - PushConstant CP#5 - StoreFieldTOS CP#3 + Push FP[-5] + LoadTypeArgumentsField CP#7 + StoreClosureElement 1 + Push r4 + Push r0 + StoreClosureElement 2 + Push r4 + Push r1 + StoreClosureElement 3 PopLocal r3 PushConstant CP#36 Push r3 Push r3 - UncheckedClosureCall CP#33, 2 + UncheckedClosureCall CP#31, 2 Drop1 PushConstant CP#37 Push r3 Push r3 - UncheckedClosureCall CP#33, 2 + UncheckedClosureCall CP#31, 2 Drop1 PushNull ReturnTOS } ConstantPool { [0] = ClosureFunction 0 - [1] = InstanceField dart:core::_Closure::_context (field) - [2] = Reserved - [3] = InstanceField dart:core::_Closure::_delayed_type_arguments (field) - [4] = Reserved - [5] = EmptyTypeArguments - [6] = InstanceField dart:core::_Closure::_function_type_arguments (field) - [7] = Reserved - [8] = DirectCall 'dart:_internal::_prependTypeArguments', ArgDesc num-args 4, num-type-args 0, names [] - [9] = Reserved - [10] = ClosureFunction 1 - [11] = ClosureFunction 2 - [12] = ObjectRef < dart:core::Type > - [13] = TypeArgumentsField DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A - [14] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::TypeParam/0 - [15] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::TypeParam/1 - [16] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::TypeParam/0 - [17] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::TypeParam/1 - [18] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/0::TypeParam/0 - [19] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/0::TypeParam/1 - [20] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/1::TypeParam/0 - [21] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/1::TypeParam/1 - [22] = DirectCall 'dart:core::_GrowableList::_literal8 (constructor)', ArgDesc num-args 9, num-type-args 0, names [] - [23] = Reserved - [24] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] + [1] = EmptyTypeArguments + [2] = DirectCall 'dart:_internal::_prependTypeArguments', ArgDesc num-args 4, num-type-args 0, names [] + [3] = Reserved + [4] = ClosureFunction 1 + [5] = ClosureFunction 2 + [6] = ObjectRef < dart:core::Type > + [7] = TypeArgumentsField DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A + [8] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::TypeParam/0 + [9] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::TypeParam/1 + [10] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::TypeParam/0 + [11] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::TypeParam/1 + [12] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/0::TypeParam/0 + [13] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/0::TypeParam/1 + [14] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/1::TypeParam/0 + [15] = Type DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/1::TypeParam/1 + [16] = DirectCall 'dart:core::_GrowableList::_literal8 (constructor)', ArgDesc num-args 9, num-type-args 0, names [] + [17] = Reserved + [18] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] + [19] = Reserved + [20] = ObjectRef < DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::TypeParam/0, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::TypeParam/1, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::TypeParam/0, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::TypeParam/1, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/0::TypeParam/0, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/0::TypeParam/1, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/1::TypeParam/0, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/1::TypeParam/1 > + [21] = DirectCall 'DART_SDK/pkg/dart2bytecode/testcases/closures.dart::callWithArgs', ArgDesc num-args 0, num-type-args 8, names [] + [22] = Reserved + [23] = EndClosureFunctionScope + [24] = AllocateClosure 2, num-elements: 3, flags: 6 [25] = Reserved - [26] = ObjectRef < DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::TypeParam/0, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::TypeParam/1, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::TypeParam/0, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::TypeParam/1, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/0::TypeParam/0, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/0::TypeParam/1, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/1::TypeParam/0, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/1::TypeParam/1 > - [27] = DirectCall 'DART_SDK/pkg/dart2bytecode/testcases/closures.dart::callWithArgs', ArgDesc num-args 0, num-type-args 8, names [] - [28] = Reserved - [29] = EndClosureFunctionScope - [30] = ObjectRef ArgDesc num-args 1, num-type-args 0, names [] - [31] = EndClosureFunctionScope - [32] = ObjectRef < DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C7, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C8 > - [33] = ObjectRef ArgDesc num-args 1, num-type-args 2, names [] - [34] = ObjectRef < dart:core::List < DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C7 >, dart:core::List < DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C8 > > - [35] = EndClosureFunctionScope + [26] = ObjectRef ArgDesc num-args 1, num-type-args 0, names [] + [27] = EndClosureFunctionScope + [28] = AllocateClosure 1, num-elements: 4, flags: 7 + [29] = Reserved + [30] = ObjectRef < DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C7, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C8 > + [31] = ObjectRef ArgDesc num-args 1, num-type-args 2, names [] + [32] = ObjectRef < dart:core::List < DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C7 >, dart:core::List < DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C8 > > + [33] = EndClosureFunctionScope + [34] = AllocateClosure 0, num-elements: 4, flags: 7 + [35] = Reserved [36] = ObjectRef < DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C5, DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C6 > [37] = ObjectRef < dart:core::List < DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C5 >, dart:core::List < DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C6 > > } @@ -558,12 +558,12 @@ Closure DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::'nested1' ty ClosureCode { Entry 5 Push FP[-5] - LoadFieldTOS CP#1 + LoadClosureElement 3 PopLocal r1 Push FP[-5] - LoadFieldTOS CP#3 + LoadClosureElement 0 StoreLocal r0 - PushConstant CP#5 + PushConstant CP#1 JumpIfEqStrict L1 CheckFunctionTypeArgs 0, r2 Jump L2 @@ -573,34 +573,37 @@ L2: CheckStack 0 Push r0 Push FP[-5] - LoadFieldTOS CP#6 + LoadClosureElement 2 PushInt 2 PushInt 4 - DirectCall CP#8, 4 + DirectCall CP#2, 4 PopLocal r0 - PushConstant CP#10 - Push r1 - Push r1 - LoadContextVar 0, 0 - LoadTypeArgumentsField CP#13 - AllocateClosure + AllocateClosure CP#28 StoreLocal r4 Push r4 - Push r0 - StoreFieldTOS CP#6 + PushConstant CP#1 + StoreClosureElement 0 Push r4 - PushConstant CP#5 - StoreFieldTOS CP#3 + Push r1 + LoadContextVar 0, 0 + LoadTypeArgumentsField CP#7 + StoreClosureElement 1 + Push r4 + Push r0 + StoreClosureElement 2 + Push r4 + Push r1 + StoreClosureElement 3 PopLocal r3 + PushConstant CP#30 + Push r3 + Push r3 + UncheckedClosureCall CP#31, 2 + Drop1 PushConstant CP#32 Push r3 Push r3 - UncheckedClosureCall CP#33, 2 - Drop1 - PushConstant CP#34 - Push r3 - Push r3 - UncheckedClosureCall CP#33, 2 + UncheckedClosureCall CP#31, 2 Drop1 PushNull ReturnTOS @@ -610,12 +613,12 @@ Closure DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/0::' ClosureCode { Entry 5 Push FP[-5] - LoadFieldTOS CP#1 + LoadClosureElement 3 PopLocal r1 Push FP[-5] - LoadFieldTOS CP#3 + LoadClosureElement 0 StoreLocal r0 - PushConstant CP#5 + PushConstant CP#1 JumpIfEqStrict L1 CheckFunctionTypeArgs 0, r2 Jump L2 @@ -625,26 +628,29 @@ L2: CheckStack 0 Push r0 Push FP[-5] - LoadFieldTOS CP#6 + LoadClosureElement 2 PushInt 4 PushInt 6 - DirectCall CP#8, 4 + DirectCall CP#2, 4 PopLocal r0 - PushConstant CP#11 - Push r1 - Push r1 - LoadContextVar 0, 0 - LoadTypeArgumentsField CP#13 - AllocateClosure + AllocateClosure CP#24 StoreLocal r4 Push r4 + Push r1 + LoadContextVar 0, 0 + LoadTypeArgumentsField CP#7 + StoreClosureElement 0 + Push r4 Push r0 - StoreFieldTOS CP#6 + StoreClosureElement 1 + Push r4 + Push r1 + StoreClosureElement 2 PopLocal r3 Push r3 StoreLocal r4 Push r4 - UncheckedClosureCall CP#30, 1 + UncheckedClosureCall CP#26, 1 Drop1 PushNull ReturnTOS @@ -654,50 +660,50 @@ Closure DART_SDK/pkg/dart2bytecode/testcases/closures.dart::A::foo::Closure/1::' ClosureCode { Entry 3 Push FP[-5] - LoadFieldTOS CP#1 + LoadClosureElement 2 PopLocal r1 CheckStack 0 Push FP[-5] - LoadFieldTOS CP#6 + LoadClosureElement 1 PopLocal r0 - PushConstant CP#12 + PushConstant CP#6 Push r1 LoadContextVar 0, 0 - LoadTypeArgumentsField CP#13 + LoadTypeArgumentsField CP#7 PushNull + InstantiateType CP#8 + Push r1 + LoadContextVar 0, 0 + LoadTypeArgumentsField CP#7 + PushNull + InstantiateType CP#9 + PushNull + Push r0 + InstantiateType CP#10 + PushNull + Push r0 + InstantiateType CP#11 + PushNull + Push r0 + InstantiateType CP#12 + PushNull + Push r0 + InstantiateType CP#13 + PushNull + Push r0 InstantiateType CP#14 - Push r1 - LoadContextVar 0, 0 - LoadTypeArgumentsField CP#13 PushNull + Push r0 InstantiateType CP#15 - PushNull - Push r0 - InstantiateType CP#16 - PushNull - Push r0 - InstantiateType CP#17 - PushNull - Push r0 - InstantiateType CP#18 - PushNull - Push r0 - InstantiateType CP#19 - PushNull - Push r0 - InstantiateType CP#20 - PushNull - Push r0 - InstantiateType CP#21 - DirectCall CP#22, 9 - DirectCall CP#24, 1 + DirectCall CP#16, 9 + DirectCall CP#18, 1 Drop1 Push r1 LoadContextVar 0, 0 - LoadTypeArgumentsField CP#13 + LoadTypeArgumentsField CP#7 Push r0 - InstantiateTypeArgumentsTOS 0, CP#26 - DirectCall CP#27, 1 + InstantiateTypeArgumentsTOS 0, CP#20 + DirectCall CP#21, 1 Drop1 PushNull ReturnTOS @@ -753,22 +759,23 @@ Bytecode { Push r0 PushInt 3 StoreContextVar 0, 2 - PushConstant CP#0 + AllocateClosure CP#14 + StoreLocal r4 + Push r4 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 PopLocal r3 Push r3 StoreLocal r4 PushInt 10 Push r4 - UncheckedClosureCall CP#14, 2 + UncheckedClosureCall CP#16, 2 Drop1 Push r3 StoreLocal r4 PushInt 11 Push r4 - UncheckedClosureCall CP#14, 2 + UncheckedClosureCall CP#16, 2 Drop1 Push r2 DirectCall CP#11, 1 @@ -784,10 +791,11 @@ Bytecode { Push r0 PushInt 42 StoreContextVar 0, 3 - PushConstant CP#15 + AllocateClosure CP#21 + StoreLocal r3 + Push r3 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 PopLocal r2 Push r2 StoreLocal r3 @@ -799,30 +807,34 @@ Bytecode { } ConstantPool { [0] = ClosureFunction 0 - [1] = InstanceField dart:core::_Closure::_context (field) - [2] = Reserved - [3] = Type dart:core::int - [4] = ObjectRef 'y' - [5] = SubtypeTestCache - [6] = ClosureFunction 1 - [7] = InterfaceCall 'DART_SDK/pkg/dart2bytecode/testcases/closures.dart::B::get:foo', ArgDesc num-args 1, num-type-args 0, names [] - [8] = Reserved - [9] = EndClosureFunctionScope + [1] = Type dart:core::int + [2] = ObjectRef 'y' + [3] = SubtypeTestCache + [4] = ClosureFunction 1 + [5] = InterfaceCall 'DART_SDK/pkg/dart2bytecode/testcases/closures.dart::B::get:foo', ArgDesc num-args 1, num-type-args 0, names [] + [6] = Reserved + [7] = EndClosureFunctionScope + [8] = AllocateClosure 1, num-elements: 1, flags: 0 + [9] = Reserved [10] = ObjectRef ArgDesc num-args 1, num-type-args 0, names [] [11] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] [12] = Reserved [13] = EndClosureFunctionScope - [14] = ObjectRef ArgDesc num-args 2, num-type-args 0, names [] - [15] = ClosureFunction 2 - [16] = InterfaceCall 'DART_SDK/pkg/dart2bytecode/testcases/closures.dart::B::set:foo', ArgDesc num-args 2, num-type-args 0, names [] - [17] = Reserved - [18] = EndClosureFunctionScope + [14] = AllocateClosure 0, num-elements: 1, flags: 0 + [15] = Reserved + [16] = ObjectRef ArgDesc num-args 2, num-type-args 0, names [] + [17] = ClosureFunction 2 + [18] = InterfaceCall 'DART_SDK/pkg/dart2bytecode/testcases/closures.dart::B::set:foo', ArgDesc num-args 2, num-type-args 0, names [] + [19] = Reserved + [20] = EndClosureFunctionScope + [21] = AllocateClosure 2, num-elements: 1, flags: 0 + [22] = Reserved } Closure DART_SDK/pkg/dart2bytecode/testcases/closures.dart::B::topLevel::'' (dart:core::int y) -> Null ClosureCode { Entry 4 Push FP[-6] - LoadFieldTOS CP#1 + LoadClosureElement 0 PopLocal r0 CheckStack 0 AllocateContext 1, 2 @@ -836,11 +848,11 @@ ClosureCode { StoreContextVar 1, 0 JumpIfUnchecked L1 Push FP[-5] - PushConstant CP#3 + PushConstant CP#1 PushNull PushNull - PushConstant CP#4 - AssertAssignable 1, CP#5 + PushConstant CP#2 + AssertAssignable 1, CP#3 Drop1 L1: Push r0 @@ -859,10 +871,11 @@ L1: Push r0 PushInt 4 StoreContextVar 1, 1 - PushConstant CP#6 + AllocateClosure CP#8 + StoreLocal r3 + Push r3 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 PopLocal r2 Push r2 Push r2 @@ -881,7 +894,7 @@ Closure DART_SDK/pkg/dart2bytecode/testcases/closures.dart::B::topLevel::Closure ClosureCode { Entry 2 Push FP[-5] - LoadFieldTOS CP#1 + LoadClosureElement 0 PopLocal r0 CheckStack 0 Push r0 @@ -896,7 +909,7 @@ ClosureCode { Push r0 LoadContextParent LoadContextVar 0, 0 - InterfaceCall CP#7, 1 + InterfaceCall CP#5, 1 Push r0 LoadContextVar 1, 0 AddInt @@ -909,14 +922,14 @@ Closure DART_SDK/pkg/dart2bytecode/testcases/closures.dart::B::topLevel::' [8] = Reserved [9] = Reserved @@ -1034,12 +1049,14 @@ ConstantPool { [12] = ObjectRef 'ii' [13] = SubtypeTestCache [14] = EndClosureFunctionScope + [15] = AllocateClosure 1, num-elements: 1, flags: 0 + [16] = Reserved } Closure DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C::testForLoop::'' () -> dart:core::int ClosureCode { Entry 2 Push FP[-5] - LoadFieldTOS CP#4 + LoadClosureElement 0 PopLocal r0 CheckStack 0 Push r0 @@ -1055,7 +1072,7 @@ Closure DART_SDK/pkg/dart2bytecode/testcases/closures.dart::C::testForLoop::'' () -> DART_SDK/pkg/dart2bytecode/testcases/closures.dart::D::TypeParam/0 ClosureCode { Entry 2 Push FP[-5] - LoadFieldTOS CP#5 + LoadClosureElement 1 PopLocal r0 CheckStack 0 Push r0 @@ -1236,43 +1258,53 @@ Function 'bar', reflectable, debuggable return-type dynamic Bytecode { - Entry 2 + Entry 3 CheckStack 0 AllocateContext 0, 1 PopLocal r0 Push r0 Push FP[-5] StoreContextVar 0, 0 - PushConstant CP#0 - Push r0 + AllocateClosure CP#8 + StoreLocal r2 + Push r2 Push FP[-5] LoadTypeArgumentsField CP#5 - AllocateClosure + StoreClosureElement 0 + Push r2 + Push r0 + StoreClosureElement 1 ReturnTOS } ConstantPool { [0] = ClosureFunction 0 - [1] = InstanceField dart:core::_Closure::_context (field) - [2] = Reserved - [3] = ClosureFunction 1 - [4] = EndClosureFunctionScope + [1] = ClosureFunction 1 + [2] = EndClosureFunctionScope + [3] = AllocateClosure 1, num-elements: 2, flags: 2 + [4] = Reserved [5] = TypeArgumentsField DART_SDK/pkg/dart2bytecode/testcases/closures.dart::D [6] = ObjectRef ArgDesc num-args 1, num-type-args 0, names [] [7] = EndClosureFunctionScope + [8] = AllocateClosure 0, num-elements: 2, flags: 2 + [9] = Reserved } Closure DART_SDK/pkg/dart2bytecode/testcases/closures.dart::D::bar::'' () -> Null ClosureCode { Entry 4 Push FP[-5] - LoadFieldTOS CP#1 + LoadClosureElement 1 PopLocal r0 CheckStack 0 - PushConstant CP#3 - Push r0 + AllocateClosure CP#3 + StoreLocal r3 + Push r3 Push r0 LoadContextVar 0, 0 LoadTypeArgumentsField CP#5 - AllocateClosure + StoreClosureElement 0 + Push r3 + Push r0 + StoreClosureElement 1 PopLocal r2 Push r2 Push r2 @@ -1286,7 +1318,7 @@ Closure DART_SDK/pkg/dart2bytecode/testcases/closures.dart::D::bar::Closure/0::' ClosureCode { Entry 2 Push FP[-5] - LoadFieldTOS CP#1 + LoadClosureElement 1 PopLocal r0 CheckStack 0 PushNull diff --git a/pkg/dart2bytecode/testcases/ffi.dart.expect b/pkg/dart2bytecode/testcases/ffi.dart.expect index d4b75f76254..d66075845b1 100644 --- a/pkg/dart2bytecode/testcases/ffi.dart.expect +++ b/pkg/dart2bytecode/testcases/ffi.dart.expect @@ -13,7 +13,7 @@ Function 'testVoidNoArg', static, reflectable, debuggable return-type dynamic Bytecode { - Entry 5 + Entry 6 CheckStack 0 PushConstant CP#0 PushConstant CP#1 @@ -24,10 +24,11 @@ Bytecode { Push r0 Push r2 StoreContextVar 0, 0 - PushConstant CP#4 + AllocateClosure CP#7 + StoreLocal r5 + Push r5 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 PopLocal r4 Push r4 Push r0 @@ -48,10 +49,10 @@ ConstantPool { [2] = DirectCall 'dart:ffi::Pointer::fromAddress (constructor)', ArgDesc num-args 2, num-type-args 0, names [] [3] = Reserved [4] = ClosureFunction 0 - [5] = InstanceField dart:core::_Closure::_context (field) - [6] = Reserved - [7] = FfiCall - [8] = EndClosureFunctionScope + [5] = FfiCall + [6] = EndClosureFunctionScope + [7] = AllocateClosure 0, num-elements: 1, flags: 0 + [8] = Reserved [9] = ObjectRef ArgDesc num-args 1, num-type-args 0, names [] } Closure DART_SDK/pkg/dart2bytecode/testcases/ffi.dart::testVoidNoArg::'#ffiClosure0' annotations const List [const dart:core::pragma {dart:core::pragma::name (field): 'vm:ffi:call-closure', dart:core::pragma::options (field): const dart:ffi::_FfiCall < FunctionType () -> dart:ffi::Void > {dart:ffi::_FfiCall::isLeaf (field): const false}}] @@ -59,12 +60,12 @@ Closure DART_SDK/pkg/dart2bytecode/testcases/ffi.dart::testVoidNoArg::'#ffiClosu ClosureCode { Entry 2 Push FP[-5] - LoadFieldTOS CP#5 + LoadClosureElement 0 PopLocal r0 CheckStack 0 Push r0 LoadContextVar 0, 0 - FfiCall CP#7 + FfiCall CP#5 ReturnTOS } @@ -74,7 +75,7 @@ Function 'testIntInt', static, reflectable, debuggable return-type dynamic Bytecode { - Entry 5 + Entry 6 CheckStack 0 PushConstant CP#0 PushConstant CP#1 @@ -85,10 +86,11 @@ Bytecode { Push r0 Push r2 StoreContextVar 0, 0 - PushConstant CP#4 + AllocateClosure CP#10 + StoreLocal r5 + Push r5 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 PopLocal r4 Push r4 Push r0 @@ -108,13 +110,13 @@ ConstantPool { [2] = DirectCall 'dart:ffi::Pointer::fromAddress (constructor)', ArgDesc num-args 2, num-type-args 0, names [] [3] = Reserved [4] = ClosureFunction 0 - [5] = InstanceField dart:core::_Closure::_context (field) - [6] = Reserved - [7] = Type dart:core::int - [8] = ObjectRef 'arg1' - [9] = SubtypeTestCache - [10] = FfiCall - [11] = EndClosureFunctionScope + [5] = Type dart:core::int + [6] = ObjectRef 'arg1' + [7] = SubtypeTestCache + [8] = FfiCall + [9] = EndClosureFunctionScope + [10] = AllocateClosure 0, num-elements: 1, flags: 0 + [11] = Reserved [12] = ObjectRef ArgDesc num-args 2, num-type-args 0, names [] } Closure DART_SDK/pkg/dart2bytecode/testcases/ffi.dart::testIntInt::'#ffiClosure1' annotations const List [const dart:core::pragma {dart:core::pragma::name (field): 'vm:ffi:call-closure', dart:core::pragma::options (field): const dart:ffi::_FfiCall < FunctionType (dart:ffi::Int64) -> dart:ffi::Int32 > {dart:ffi::_FfiCall::isLeaf (field): const false}}] @@ -122,16 +124,16 @@ Closure DART_SDK/pkg/dart2bytecode/testcases/ffi.dart::testIntInt::'#ffiClosure1 ClosureCode { Entry 2 Push FP[-6] - LoadFieldTOS CP#5 + LoadClosureElement 0 PopLocal r0 CheckStack 0 JumpIfUnchecked L1 Push FP[-5] - PushConstant CP#7 + PushConstant CP#5 PushNull PushNull - PushConstant CP#8 - AssertAssignable 1, CP#9 + PushConstant CP#6 + AssertAssignable 1, CP#7 Drop1 L1: PushNull @@ -139,7 +141,7 @@ L1: Push FP[-5] Push r0 LoadContextVar 0, 0 - FfiCall CP#10 + FfiCall CP#8 ReturnTOS } diff --git a/pkg/dart2bytecode/testcases/invisible.dart.expect b/pkg/dart2bytecode/testcases/invisible.dart.expect index 07283fe9360..47b3a55137e 100644 --- a/pkg/dart2bytecode/testcases/invisible.dart.expect +++ b/pkg/dart2bytecode/testcases/invisible.dart.expect @@ -72,43 +72,44 @@ Bytecode { Push r0 Push FP[-5] StoreContextVar 0, 0 - PushConstant CP#0 + AllocateClosure CP#6 + StoreLocal r3 + Push r3 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 PopLocal r2 Push r2 Push r2 - UncheckedClosureCall CP#6, 1 + UncheckedClosureCall CP#4, 1 Drop1 PushNull ReturnTOS } ConstantPool { [0] = ClosureFunction 0 - [1] = InstanceField dart:core::_Closure::_context (field) - [2] = Reserved - [3] = ObjectRef 'visibleInner' - [4] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] - [5] = Reserved - [6] = ObjectRef ArgDesc num-args 1, num-type-args 0, names [] - [7] = EndClosureFunctionScope + [1] = ObjectRef 'visibleInner' + [2] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] + [3] = Reserved + [4] = ObjectRef ArgDesc num-args 1, num-type-args 0, names [] + [5] = EndClosureFunctionScope + [6] = AllocateClosure 0, num-elements: 1, flags: 0 + [7] = Reserved } Closure DART_SDK/pkg/dart2bytecode/testcases/invisible.dart::visibleClosure::'visibleInner' () -> Null ClosureCode { Entry 3 Push FP[-5] - LoadFieldTOS CP#1 + LoadClosureElement 0 PopLocal r0 CheckStack 0 - PushConstant CP#3 - DirectCall CP#4, 1 + PushConstant CP#1 + DirectCall CP#2, 1 Drop1 Push r0 LoadContextVar 0, 0 StoreLocal r2 Push r2 - UncheckedClosureCall CP#6, 1 + UncheckedClosureCall CP#4, 1 Drop1 PushNull ReturnTOS @@ -127,44 +128,45 @@ Bytecode { Push r0 Push FP[-5] StoreContextVar 0, 0 - PushConstant CP#0 + AllocateClosure CP#6 + StoreLocal r3 + Push r3 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 PopLocal r2 Push r2 Push r2 - UncheckedClosureCall CP#6, 1 + UncheckedClosureCall CP#4, 1 Drop1 PushNull ReturnTOS } ConstantPool { [0] = ClosureFunction 0 - [1] = InstanceField dart:core::_Closure::_context (field) - [2] = Reserved - [3] = ObjectRef 'invisibleInner' - [4] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] - [5] = Reserved - [6] = ObjectRef ArgDesc num-args 1, num-type-args 0, names [] - [7] = EndClosureFunctionScope + [1] = ObjectRef 'invisibleInner' + [2] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] + [3] = Reserved + [4] = ObjectRef ArgDesc num-args 1, num-type-args 0, names [] + [5] = EndClosureFunctionScope + [6] = AllocateClosure 0, num-elements: 1, flags: 0 + [7] = Reserved } Closure DART_SDK/pkg/dart2bytecode/testcases/invisible.dart::invisibleClosure::'invisibleInner' invisible annotations const List [const dart:core::pragma {dart:core::pragma::name (field): 'vm:invisible', dart:core::pragma::options (field): null}] () -> Null ClosureCode { Entry 3 Push FP[-5] - LoadFieldTOS CP#1 + LoadClosureElement 0 PopLocal r0 CheckStack 0 - PushConstant CP#3 - DirectCall CP#4, 1 + PushConstant CP#1 + DirectCall CP#2, 1 Drop1 Push r0 LoadContextVar 0, 0 StoreLocal r2 Push r2 - UncheckedClosureCall CP#6, 1 + UncheckedClosureCall CP#4, 1 Drop1 PushNull ReturnTOS diff --git a/pkg/dart2bytecode/testcases/try_blocks.dart.expect b/pkg/dart2bytecode/testcases/try_blocks.dart.expect index 09ee8162869..33db8cd14fe 100644 --- a/pkg/dart2bytecode/testcases/try_blocks.dart.expect +++ b/pkg/dart2bytecode/testcases/try_blocks.dart.expect @@ -215,10 +215,11 @@ Try #0 start: Push r0 PushInt 2 StoreContextVar 0, 1 - PushConstant CP#0 + AllocateClosure CP#6 + StoreLocal r5 + Push r5 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 PopLocal r4 Push r4 Push r4 @@ -226,7 +227,7 @@ Try #0 start: Drop1 Push r0 LoadContextVar 0, 1 - DirectCall CP#4, 1 + DirectCall CP#2, 1 Drop1 Jump L1 Try #0 end: @@ -263,12 +264,13 @@ Try #0 handler: LoadContextVar 0, 2 StoreIndexedTOS DirectCall CP#11, 1 - DirectCall CP#4, 1 + DirectCall CP#2, 1 Drop1 - PushConstant CP#13 + AllocateClosure CP#21 + StoreLocal r5 + Push r5 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 PopLocal r6 Push r6 ReturnTOS @@ -280,17 +282,17 @@ L1: ReturnTOS } ExceptionsTable { - try-index 0, outer -1, start 20, end 56, handler 56, needs-stack-trace, types [CP#6] + try-index 0, outer -1, start 20, end 60, handler 60, needs-stack-trace, types [CP#4] } ConstantPool { [0] = ClosureFunction 0 - [1] = InstanceField dart:core::_Closure::_context (field) - [2] = Reserved - [3] = ObjectRef 'danger foo' - [4] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] - [5] = Reserved - [6] = Type dart:core::Object - [7] = EndClosureFunctionScope + [1] = ObjectRef 'danger foo' + [2] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] + [3] = Reserved + [4] = Type dart:core::Object + [5] = EndClosureFunctionScope + [6] = AllocateClosure 0, num-elements: 1, flags: 0 + [7] = Reserved [8] = ObjectRef ArgDesc num-args 1, num-type-args 0, names [] [9] = ObjectRef 'caught ' [10] = ObjectRef ' ' @@ -304,19 +306,21 @@ ConstantPool { [18] = ObjectRef 'error ' [19] = ObjectRef ', captured stack trace: ' [20] = EndClosureFunctionScope + [21] = AllocateClosure 1, num-elements: 1, flags: 0 + [22] = Reserved } Closure DART_SDK/pkg/dart2bytecode/testcases/try_blocks.dart::testTryCatch3::'foo' () -> void ClosureCode { Entry 5 Push FP[-5] - LoadFieldTOS CP#1 + LoadClosureElement 0 PopLocal r0 CheckStack 0 Push r0 PopLocal r2 Try #0 start: - PushConstant CP#3 - DirectCall CP#4, 1 + PushConstant CP#1 + DirectCall CP#2, 1 Drop1 Jump L1 Try #0 end: @@ -330,7 +334,7 @@ Try #0 handler: PopLocal r4 Push r0 LoadContextVar 0, 0 - DirectCall CP#4, 1 + DirectCall CP#2, 1 Drop1 Push r0 PushInt 3 @@ -345,14 +349,14 @@ Closure DART_SDK/pkg/dart2bytecode/testcases/try_blocks.dart::testTryCatch3::'ba ClosureCode { Entry 6 Push FP[-5] - LoadFieldTOS CP#1 + LoadClosureElement 0 PopLocal r0 CheckStack 0 Push r0 PopLocal r2 Try #0 start: PushConstant CP#14 - DirectCall CP#4, 1 + DirectCall CP#2, 1 Drop1 Jump L1 Try #0 end: @@ -390,7 +394,7 @@ Try #0 handler: LoadContextVar 0, 2 StoreIndexedTOS DirectCall CP#11, 1 - DirectCall CP#4, 1 + DirectCall CP#2, 1 Drop1 Jump L1 L2: @@ -588,10 +592,11 @@ Try #1 start: PushConstant CP#5 DirectCall CP#3, 1 Drop1 - PushConstant CP#6 + AllocateClosure CP#8 + StoreLocal r8 + Push r8 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 PopLocal r7 Push r7 Push r7 @@ -648,8 +653,8 @@ L3: ReturnTOS } ExceptionsTable { - try-index 0, outer -1, start 53, end 134, handler 134, needs-stack-trace, synthetic, types [CP#11] - try-index 1, outer 0, start 70, end 96, handler 96, needs-stack-trace, synthetic, types [CP#11] + try-index 0, outer -1, start 53, end 138, handler 138, needs-stack-trace, synthetic, types [CP#11] + try-index 1, outer 0, start 70, end 100, handler 100, needs-stack-trace, synthetic, types [CP#11] } ConstantPool { [0] = InterfaceCall 'dart:core::Object::==', ArgDesc num-args 2, num-type-args 0, names [] @@ -659,9 +664,9 @@ ConstantPool { [4] = Reserved [5] = ObjectRef 'try' [6] = ClosureFunction 0 - [7] = InstanceField dart:core::_Closure::_context (field) - [8] = Reserved - [9] = EndClosureFunctionScope + [7] = EndClosureFunctionScope + [8] = AllocateClosure 0, num-elements: 1, flags: 0 + [9] = Reserved [10] = ObjectRef ArgDesc num-args 1, num-type-args 0, names [] [11] = Type dynamic [12] = ObjectRef 'finally 1' @@ -673,7 +678,7 @@ Closure DART_SDK/pkg/dart2bytecode/testcases/try_blocks.dart::testTryFinally2::' ClosureCode { Entry 2 Push FP[-5] - LoadFieldTOS CP#7 + LoadClosureElement 0 PopLocal r0 CheckStack 0 Push r0 @@ -694,7 +699,7 @@ Function 'testTryFinally3', static, reflectable, debuggable return-type dynamic Bytecode { - Entry 5 + Entry 6 CheckStack 0 AllocateContext 0, 1 PopLocal r0 @@ -706,22 +711,23 @@ Bytecode { Push r0 PopLocal r3 Try #0 start: - PushConstant CP#0 + AllocateClosure CP#7 + StoreLocal r5 + Push r5 Push r0 - PushNull - AllocateClosure + StoreClosureElement 0 PopLocal r2 Jump L1 Try #0 end: Try #0 handler: - SetFrame 5 + SetFrame 6 Push r3 PopLocal r0 MoveSpecial exception, r3 MoveSpecial stackTrace, r4 Push r0 LoadContextVar 0, 0 - DirectCall CP#3, 1 + DirectCall CP#1, 1 Drop1 Push r2 DynamicCall CP#9, 1 @@ -734,7 +740,7 @@ L1: PopLocal r0 Push r0 LoadContextVar 0, 0 - DirectCall CP#3, 1 + DirectCall CP#1, 1 Drop1 Push r2 DynamicCall CP#9, 1 @@ -746,18 +752,18 @@ L1: ReturnTOS } ExceptionsTable { - try-index 0, outer -1, start 23, end 35, handler 35, needs-stack-trace, synthetic, types [CP#6] + try-index 0, outer -1, start 23, end 39, handler 39, needs-stack-trace, synthetic, types [CP#4] } ConstantPool { [0] = ClosureFunction 0 - [1] = InstanceField dart:core::_Closure::_context (field) + [1] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] [2] = Reserved - [3] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names [] - [4] = Reserved - [5] = ObjectRef 'try 1' - [6] = Type dynamic - [7] = ObjectRef 'try 2' - [8] = EndClosureFunctionScope + [3] = ObjectRef 'try 1' + [4] = Type dynamic + [5] = ObjectRef 'try 2' + [6] = EndClosureFunctionScope + [7] = AllocateClosure 0, num-elements: 1, flags: 0 + [8] = Reserved [9] = DynamicCall 'implicit:call', ArgDesc num-args 1, num-type-args 0, names [] [10] = Reserved } @@ -765,18 +771,18 @@ Closure DART_SDK/pkg/dart2bytecode/testcases/try_blocks.dart::testTryFinally3::' ClosureCode { Entry 6 Push FP[-5] - LoadFieldTOS CP#1 + LoadClosureElement 0 PopLocal r0 CheckStack 0 Push r0 LoadContextVar 0, 0 - DirectCall CP#3, 1 + DirectCall CP#1, 1 Drop1 Push r0 PopLocal r2 Try #0 start: - PushConstant CP#5 - DirectCall CP#3, 1 + PushConstant CP#3 + DirectCall CP#1, 1 Drop1 Jump L1 Try #0 end: @@ -789,8 +795,8 @@ Try #0 handler: Push r0 PopLocal r4 Try #1 start: - PushConstant CP#7 - DirectCall CP#3, 1 + PushConstant CP#5 + DirectCall CP#1, 1 Drop1 Jump L2 Try #1 end: @@ -802,7 +808,7 @@ Try #1 handler: MoveSpecial stackTrace, r5 Push r0 LoadContextVar 0, 0 - DirectCall CP#3, 1 + DirectCall CP#1, 1 Drop1 Push r4 Push r5 @@ -812,7 +818,7 @@ L2: PopLocal r0 Push r0 LoadContextVar 0, 0 - DirectCall CP#3, 1 + DirectCall CP#1, 1 Drop1 PushInt 43 ReturnTOS @@ -822,8 +828,8 @@ L1: Push r0 PopLocal r4 Try #2 start: - PushConstant CP#7 - DirectCall CP#3, 1 + PushConstant CP#5 + DirectCall CP#1, 1 Drop1 Jump L3 Try #2 end: @@ -835,7 +841,7 @@ Try #2 handler: MoveSpecial stackTrace, r5 Push r0 LoadContextVar 0, 0 - DirectCall CP#3, 1 + DirectCall CP#1, 1 Drop1 Push r4 Push r5 @@ -845,7 +851,7 @@ L3: PopLocal r0 Push r0 LoadContextVar 0, 0 - DirectCall CP#3, 1 + DirectCall CP#1, 1 Drop1 PushInt 43 ReturnTOS diff --git a/pkg/native_compiler/lib/back_end/arm64/code_generator.dart b/pkg/native_compiler/lib/back_end/arm64/code_generator.dart index 6aac9552057..67994ca374a 100644 --- a/pkg/native_compiler/lib/back_end/arm64/code_generator.dart +++ b/pkg/native_compiler/lib/back_end/arm64/code_generator.dart @@ -7,7 +7,6 @@ import 'dart:math' as math; import 'package:cfg/ir/constant_value.dart'; import 'package:cfg/ir/field.dart'; import 'package:cfg/ir/functions.dart'; -import 'package:cfg/ir/global_context.dart'; import 'package:cfg/ir/instructions.dart'; import 'package:cfg/ir/types.dart'; import 'package:cfg/utils/misc.dart'; @@ -1203,18 +1202,50 @@ final class Arm64CodeGenerator extends CodeGenerator { @override void visitAllocateClosure(AllocateClosure instr) { - final cls = GlobalContext.instance.coreTypes.index.getClass( - 'dart:core', - '_Closure', + final function = instr.function; + final hasDelayedTypeArgs = function.hasFunctionTypeParameters; + final hasInstantiatorTypeArgs = switch (function) { + LocalFunction() => containsClassTypeParameters( + function.functionNode!.computeFunctionType(ast.Nullability.nonNullable), + ), + TearOffFunction() => + function.member.isInstanceMember && + containsClassTypeParameters( + function.member.function!.computeFunctionType( + ast.Nullability.nonNullable, + ), + ), + }; + final hasFunctionTypeArgs = switch (function) { + LocalFunction() => hasGenericEnclosingFunction(function.localFunction), + TearOffFunction() => false, + }; + final numElements = + (hasDelayedTypeArgs ? 1 : 0) + + (hasInstantiatorTypeArgs ? 1 : 0) + + (hasFunctionTypeArgs ? 1 : 0) + + 1 /* context */; + final lengthAndFlags = vmOffsets.encodeClosureLengthAndFlags( + numElements, + hasDelayedTypeArgs: hasDelayedTypeArgs, + hasInstantiatorTypeArgs: hasInstantiatorTypeArgs, + hasFunctionTypeArgs: hasFunctionTypeArgs, ); - final instanceSize = objectLayout.getInstanceSize(cls); + final instanceSize = roundUp( + vmOffsets.Closure_elementsStartOffset + + numElements * objectLayout.compressedWordSize, + objectAlignment(wordSize), + ); + final resultReg = AllocationStub.resultReg; assert(outputReg(instr) == resultReg); - final initializeObject = Label(); + final done = Label(); Label slowPath = addSlowPath(() { - _asm.callStub(backEndState.stubFactory.getAllocationStub(cls)); - _asm.b(initializeObject); + _asm.unimplemented( + 'Unimplemented: code generation for AllocateClosure slow path', + ); + _asm.b(done); }); _asm.loadImmediate( @@ -1234,16 +1265,21 @@ final class Arm64CodeGenerator extends CodeGenerator { slowPath, initializeFields: true, ); - - _asm.bind(initializeObject); final fieldReg = AllocationStub.scratch1Reg; - _asm.loadFromPool(fieldReg, instr.function); + _asm.loadFromPool(fieldReg, function); _asm.str( fieldReg, _asm.fieldAddress(resultReg, vmOffsets.Closure_function_offset), ); + _asm.loadImmediate(fieldReg, lengthAndFlags << smiShift); + _asm.str( + fieldReg, + _asm.fieldAddress(resultReg, vmOffsets.Closure_length_and_flags_offset), + ); + _asm.str(ZR, _asm.fieldAddress(resultReg, vmOffsets.Closure_hash_offset)); // TODO: initialize the rest of the fields. assert(instr.inputCount == 0); + _asm.bind(done); } @override diff --git a/pkg/native_compiler/lib/runtime/type_utils.dart b/pkg/native_compiler/lib/runtime/type_utils.dart index 70c90d77904..c9003ac774c 100644 --- a/pkg/native_compiler/lib/runtime/type_utils.dart +++ b/pkg/native_compiler/lib/runtime/type_utils.dart @@ -150,3 +150,35 @@ bool hasNonTrivialInitializer(ast.Field field) { }; } } + +/// Returns true if [type] references class type parameters. +bool containsClassTypeParameters(ast.DartType type) { + final visitor = _FindClassTypeParameters(); + type.accept(visitor); + return visitor.containsClassTypeParams; +} + +class _FindClassTypeParameters extends ast.RecursiveVisitor { + bool containsClassTypeParams = false; + + _FindClassTypeParameters(); + + @override + void visitTypeParameterType(ast.TypeParameterType node) { + if (node.parameter.declaration is ast.Class) { + containsClassTypeParams = true; + } + } +} + +bool hasGenericEnclosingFunction(ast.TreeNode node) { + for (;;) { + node = node.parent!; + if (node is ast.Member) { + return false; + } + if (node is ast.FunctionNode && node.typeParameters.isNotEmpty) { + return true; + } + } +} diff --git a/pkg/native_compiler/lib/runtime/vm_defs.dart b/pkg/native_compiler/lib/runtime/vm_defs.dart index ac180ccef28..952f6d1f343 100644 --- a/pkg/native_compiler/lib/runtime/vm_defs.dart +++ b/pkg/native_compiler/lib/runtime/vm_defs.dart @@ -111,6 +111,36 @@ extension ComputedOffsets on VMOffsets { (encodedSize << UntaggedObject_kSizeTagPos) | (cid.index << UntaggedObject_kClassIdTagPos); } + + int encodeClosureLengthAndFlags( + int numElements, { + required bool hasDelayedTypeArgs, + required bool hasInstantiatorTypeArgs, + required bool hasFunctionTypeArgs, + }) { + assert( + (0 <= numElements) && + (numElements < (1 << UntaggedClosure_kLengthBitsSize)), + ); + final functionTypeArgsIndex = + (hasDelayedTypeArgs ? 1 : 0) + (hasInstantiatorTypeArgs ? 1 : 0); + assert( + functionTypeArgsIndex < + (1 << UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize), + ); + return (hasDelayedTypeArgs + ? (1 << UntaggedClosure_kHasDelayedTypeArgumentsBit) + : 0) | + (hasInstantiatorTypeArgs + ? (1 << UntaggedClosure_kHasInstantiatorTypeArgumentsBit) + : 0) | + (hasFunctionTypeArgs + ? ((1 << UntaggedClosure_kHasFunctionTypeArgumentsBit) | + (functionTypeArgsIndex << + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos)) + : 0) | + (numElements << UntaggedClosure_kLengthBitsPos); + } } // Symbol names used in Dart snapshots. diff --git a/pkg/native_compiler/lib/runtime/vm_offsets.g.dart b/pkg/native_compiler/lib/runtime/vm_offsets.g.dart index a1684ed522b..a7692af3142 100644 --- a/pkg/native_compiler/lib/runtime/vm_offsets.g.dart +++ b/pkg/native_compiler/lib/runtime/vm_offsets.g.dart @@ -48,6 +48,14 @@ base class VMOffsets { int get SubtypeTestCache_kMaxInputs => throw 'Unknown'; int get SubtypeTestCache_kTestResult => throw 'Unknown'; int get TypeArguments_kMaxElements => throw 'Unknown'; + int get UntaggedClosure_kHasDelayedTypeArgumentsBit => throw 'Unknown'; + int get UntaggedClosure_kHasInstantiatorTypeArgumentsBit => throw 'Unknown'; + int get UntaggedClosure_kHasFunctionTypeArgumentsBit => throw 'Unknown'; + int get UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos => throw 'Unknown'; + int get UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize => + throw 'Unknown'; + int get UntaggedClosure_kLengthBitsPos => throw 'Unknown'; + int get UntaggedClosure_kLengthBitsSize => throw 'Unknown'; int get UntaggedObject_kCardRememberedBit => throw 'Unknown'; int get UntaggedObject_kCanonicalBit => throw 'Unknown'; int get UntaggedObject_kNotMarkedBit => throw 'Unknown'; @@ -86,12 +94,9 @@ base class VMOffsets { int get Class_host_type_arguments_field_offset_in_words_offset => throw 'Unknown'; int get ClassTable_allocation_tracing_state_table_offset => throw 'Unknown'; - int get Closure_context_offset => throw 'Unknown'; - int get Closure_delayed_type_arguments_offset => throw 'Unknown'; int get Closure_function_offset => throw 'Unknown'; - int get Closure_function_type_arguments_offset => throw 'Unknown'; int get Closure_hash_offset => throw 'Unknown'; - int get Closure_instantiator_type_arguments_offset => throw 'Unknown'; + int get Closure_length_and_flags_offset => throw 'Unknown'; int get ClosureData_packed_fields_offset => throw 'Unknown'; int get Code_instructions_offset => throw 'Unknown'; int get Code_object_pool_offset => throw 'Unknown'; @@ -405,7 +410,6 @@ base class VMOffsets { int get Bytecode_InstanceSize => throw 'Unknown'; int get Capability_InstanceSize => throw 'Unknown'; int get Class_InstanceSize => throw 'Unknown'; - int get Closure_InstanceSize => throw 'Unknown'; int get ClosureData_InstanceSize => throw 'Unknown'; int get CodeSourceMap_HeaderSize => throw 'Unknown'; int get CompressedStackMaps_ObjectHeaderSize => throw 'Unknown'; @@ -484,6 +488,10 @@ base class VMOffsets { int get ClassTable_elementSize => throw 'Unknown'; int ClassTable_elementOffset(int index) => ClassTable_elementsStartOffset + index * ClassTable_elementSize; + int get Closure_elementsStartOffset => throw 'Unknown'; + int get Closure_elementSize => throw 'Unknown'; + int Closure_elementOffset(int index) => + Closure_elementsStartOffset + index * Closure_elementSize; int get Code_elementsStartOffset => throw 'Unknown'; int get Code_elementSize => throw 'Unknown'; int Code_elementOffset(int index) => @@ -548,6 +556,10 @@ final class Arm64VMOffsets extends VMOffsets { @override int get ClassTable_elementSize => 0x1; @override + int get Closure_elementsStartOffset => 0x20; + @override + int get Closure_elementSize => 0x8; + @override int get Code_elementsStartOffset => 0xb0; @override int get Code_elementSize => 0x4; @@ -654,6 +666,20 @@ final class Arm64VMOffsets extends VMOffsets { @override int get TypeArguments_kMaxElements => 0x7ffffffffffffff; @override + int get UntaggedClosure_kHasDelayedTypeArgumentsBit => 0x0; + @override + int get UntaggedClosure_kHasInstantiatorTypeArgumentsBit => 0x1; + @override + int get UntaggedClosure_kHasFunctionTypeArgumentsBit => 0x2; + @override + int get UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos => 0x3; + @override + int get UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize => 0x2; + @override + int get UntaggedClosure_kLengthBitsPos => 0x5; + @override + int get UntaggedClosure_kLengthBitsSize => 0x39; + @override int get UntaggedObject_kCardRememberedBit => 0x0; @override int get UntaggedObject_kCanonicalBit => 0x1; @@ -728,17 +754,11 @@ final class Arm64VMOffsets extends VMOffsets { @override int get ClassTable_allocation_tracing_state_table_offset => 0x8; @override - int get Closure_context_offset => 0x28; + int get Closure_function_offset => 0x18; @override - int get Closure_delayed_type_arguments_offset => 0x18; + int get Closure_hash_offset => 0x10; @override - int get Closure_function_offset => 0x20; - @override - int get Closure_function_type_arguments_offset => 0x10; - @override - int get Closure_hash_offset => 0x30; - @override - int get Closure_instantiator_type_arguments_offset => 0x8; + int get Closure_length_and_flags_offset => 0x8; @override int get ClosureData_packed_fields_offset => 0x20; @override @@ -1342,8 +1362,6 @@ final class Arm64VMOffsets extends VMOffsets { @override int get Class_InstanceSize => 0xc8; @override - int get Closure_InstanceSize => 0x38; - @override int get ClosureData_InstanceSize => 0x28; @override int get CodeSourceMap_HeaderSize => 0x10; @@ -1499,6 +1517,10 @@ final class Arm64ProductVMOffsets extends VMOffsets { @override int get Array_elementSize => 0x8; @override + int get Closure_elementsStartOffset => 0x20; + @override + int get Closure_elementSize => 0x8; + @override int get Code_elementsStartOffset => 0x90; @override int get Code_elementSize => 0x4; @@ -1605,6 +1627,20 @@ final class Arm64ProductVMOffsets extends VMOffsets { @override int get TypeArguments_kMaxElements => 0x7ffffffffffffff; @override + int get UntaggedClosure_kHasDelayedTypeArgumentsBit => 0x0; + @override + int get UntaggedClosure_kHasInstantiatorTypeArgumentsBit => 0x1; + @override + int get UntaggedClosure_kHasFunctionTypeArgumentsBit => 0x2; + @override + int get UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos => 0x3; + @override + int get UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize => 0x2; + @override + int get UntaggedClosure_kLengthBitsPos => 0x5; + @override + int get UntaggedClosure_kLengthBitsSize => 0x39; + @override int get UntaggedObject_kCardRememberedBit => 0x0; @override int get UntaggedObject_kCanonicalBit => 0x1; @@ -1677,17 +1713,11 @@ final class Arm64ProductVMOffsets extends VMOffsets { @override int get Class_host_type_arguments_field_offset_in_words_offset => 0xb4; @override - int get Closure_context_offset => 0x28; + int get Closure_function_offset => 0x18; @override - int get Closure_delayed_type_arguments_offset => 0x18; + int get Closure_hash_offset => 0x10; @override - int get Closure_function_offset => 0x20; - @override - int get Closure_function_type_arguments_offset => 0x10; - @override - int get Closure_hash_offset => 0x30; - @override - int get Closure_instantiator_type_arguments_offset => 0x8; + int get Closure_length_and_flags_offset => 0x8; @override int get ClosureData_packed_fields_offset => 0x20; @override @@ -2287,8 +2317,6 @@ final class Arm64ProductVMOffsets extends VMOffsets { @override int get Class_InstanceSize => 0xc0; @override - int get Closure_InstanceSize => 0x38; - @override int get ClosureData_InstanceSize => 0x28; @override int get CodeSourceMap_HeaderSize => 0x10; @@ -2431,7 +2459,6 @@ final class Arm64ProductVMOffsets extends VMOffsets { } enum StubCode { - GetCStackPointer, JumpToFrame, RunExceptionHandler, RunExceptionHandlerUnbox, @@ -2462,10 +2489,10 @@ enum StubCode { AllocateFloat64x2Array, AllocateMintSharedWithFPURegs, AllocateMintSharedWithoutFPURegs, - AllocateClosure, - AllocateClosureGeneric, - AllocateClosureTA, - AllocateClosureTAGeneric, + AllocateClosure1, + AllocateClosure2, + AllocateClosure3, + AllocateClosure4, AllocateContext, AllocateGrowableArray, AllocateObject, diff --git a/pkg/vm_snapshot_analysis/test/instruction_sizes_test.dart b/pkg/vm_snapshot_analysis/test/instruction_sizes_test.dart index a3632f0d30d..68647a7f565 100644 --- a/pkg/vm_snapshot_analysis/test/instruction_sizes_test.dart +++ b/pkg/vm_snapshot_analysis/test/instruction_sizes_test.dart @@ -806,6 +806,7 @@ void main() async { '#type': 'class', 'makeSomeClosures': { '#type': 'function', + '#size': lessThan(0), '': { '#type': 'function', '#size': lessThan(0), diff --git a/runtime/tests/vm/dart/heap_snapshot_regress_49711_test.dart b/runtime/tests/vm/dart/heap_snapshot_regress_49711_test.dart index c8f593a9cb4..18379f25a75 100644 --- a/runtime/tests/vm/dart/heap_snapshot_regress_49711_test.dart +++ b/runtime/tests/vm/dart/heap_snapshot_regress_49711_test.dart @@ -59,7 +59,12 @@ main() async { if (uri == '') { // We don't verify non-user-visible objects. } else if (uri.startsWith('dart') && - ['Array', 'List', 'Record'].any((p) => klass.name.contains(p))) { + [ + 'Array', + 'Closure', + 'List', + 'Record', + ].any((p) => klass.name.contains(p))) { Expect.isTrue(fields.length <= object.references.length); } else { // For objects with vm-defined layouts, this fails if a new field is diff --git a/runtime/tests/vm/dart/regress_48764_il_test.dart b/runtime/tests/vm/dart/regress_48764_il_test.dart index cc94122d99c..3d47d0baa4b 100644 --- a/runtime/tests/vm/dart/regress_48764_il_test.dart +++ b/runtime/tests/vm/dart/regress_48764_il_test.dart @@ -34,7 +34,7 @@ void matchIL$main_testForIn(FlowGraph graph) { match.block('Graph'), match.block('Function', [ 'v2' << match.Parameter(index: 0), - 'v3' << match.LoadField('v2', slot: 'Closure.context'), + 'v3' << match.LoadField('v2', slot: ':closure_element[0]'), 'v4' << match.LoadField('v3', slot: 'list'), 'v92' << match.LoadField('v4', slot: 'GrowableObjectArray.length'), if (!is32BitConfiguration) 'v112' << match.UnboxInt64('v92'), diff --git a/runtime/tests/vm/dart/tearoff_optimizations_il_test.dart b/runtime/tests/vm/dart/tearoff_optimizations_il_test.dart index 68b64e13831..f1670ed3c6d 100644 --- a/runtime/tests/vm/dart/tearoff_optimizations_il_test.dart +++ b/runtime/tests/vm/dart/tearoff_optimizations_il_test.dart @@ -116,7 +116,8 @@ void matchIL$testCSE2(FlowGraph graph) { 'b' << match.Parameter(index: 0), match.CheckStackOverflow(), 'b_type_args' << match.LoadField('b'), - 'b_bar' << match.AllocateClosure(match.any, 'b', 'b_type_args'), + 'b_bar' << match.AllocateClosure(match.any, 'b'), + match.StoreField('b_bar', 'b_type_args', slot: ':closure_element[1]'), match.MoveArgument('b_bar'), match.StaticCall(), 'cond' << match.LoadStaticField(), @@ -145,7 +146,8 @@ void matchIL$testCSE3(FlowGraph graph) { 'b' << match.Parameter(index: 0), match.CheckStackOverflow(), 'b_type_args' << match.LoadField('b'), - 'b_bar' << match.AllocateClosure(match.any, 'b', 'b_type_args'), + 'b_bar' << match.AllocateClosure(match.any, 'b'), + match.StoreField('b_bar', 'b_type_args', slot: ':closure_element[1]'), match.MoveArgument('b_bar'), match.MoveArgument(match.any), 'b_bar_int' << match.StaticCall(), // _instantiateClosure @@ -212,7 +214,8 @@ void matchIL$testLICM2(FlowGraph graph) { 'b' << match.Parameter(index: 0), match.CheckStackOverflow(), 'b_type_args' << match.LoadField('b'), - 'b_bar' << match.AllocateClosure(match.any, 'b', 'b_type_args'), + 'b_bar' << match.AllocateClosure(match.any, 'b'), + match.StoreField('b_bar', 'b_type_args', slot: ':closure_element[1]'), match.Goto('B5'), ]), 'B5' << diff --git a/runtime/vm/app_snapshot.cc b/runtime/vm/app_snapshot.cc index ee6f700f60a..0c438edddab 100644 --- a/runtime/vm/app_snapshot.cc +++ b/runtime/vm/app_snapshot.cc @@ -5257,7 +5257,7 @@ class ClosureSerializationCluster : public SerializationCluster { ClosureSerializationCluster(bool is_canonical, bool is_deeply_immutable) : SerializationCluster("Closure", kClosureCid, - compiler::target::Closure::InstanceSize(), + kSizeVaries, is_canonical, is_deeply_immutable) {} ~ClosureSerializationCluster() {} @@ -5265,7 +5265,9 @@ class ClosureSerializationCluster : public SerializationCluster { void Trace(Serializer* s, ObjectPtr object) { ClosurePtr closure = Closure::RawCast(object); objects_.Add(closure); - PushFromTo(closure); + const intptr_t length = UntaggedClosure::LengthBits::decode( + Smi::Value(closure->untag()->length_and_flags())); + PushFromTo(closure, length); } void WriteAlloc(Serializer* s) { @@ -5274,6 +5276,11 @@ class ClosureSerializationCluster : public SerializationCluster { for (intptr_t i = 0; i < count; i++) { ClosurePtr closure = objects_[i]; s->AssignRef(closure); + AutoTraceObject(closure); + const intptr_t length = UntaggedClosure::LengthBits::decode( + Smi::Value(closure->untag()->length_and_flags())); + s->WriteUnsigned(length); + target_memory_size_ += compiler::target::Closure::InstanceSize(length); } } @@ -5281,8 +5288,11 @@ class ClosureSerializationCluster : public SerializationCluster { const intptr_t count = objects_.length(); for (intptr_t i = 0; i < count; i++) { ClosurePtr closure = objects_[i]; + const intptr_t length = UntaggedClosure::LengthBits::decode( + Smi::Value(closure->untag()->length_and_flags())); AutoTraceObject(closure); - WriteFromTo(closure); + s->WriteUnsigned(length); + WriteFromTo(closure, length); } } @@ -5304,7 +5314,13 @@ class ClosureDeserializationCluster ~ClosureDeserializationCluster() {} void ReadAlloc(Deserializer* d) override { - ReadAllocFixedSize(d, Closure::InstanceSize()); + start_index_ = d->next_index(); + const intptr_t count = d->ReadUnsigned(); + for (intptr_t i = 0; i < count; i++) { + const intptr_t length = d->ReadUnsigned(); + d->AssignRef(d->Allocate(Closure::InstanceSize(length))); + } + stop_index_ = d->next_index(); } void ReadFill(Deserializer* d_) override { @@ -5313,10 +5329,11 @@ class ClosureDeserializationCluster const bool mark_canonical = is_root_unit_ && is_canonical(); for (intptr_t id = start_index_, n = stop_index_; id < n; id++) { ClosurePtr closure = static_cast(d.Ref(id)); + const intptr_t length = d.ReadUnsigned(); Deserializer::InitializeHeader(closure, kClosureCid, - Closure::InstanceSize(), mark_canonical, - is_deeply_immutable()); - d.ReadFromTo(closure); + Closure::InstanceSize(length), + mark_canonical, is_deeply_immutable()); + d.ReadFromTo(closure, length); #if defined(DART_PRECOMPILED_RUNTIME) closure->untag()->entry_point_ = 0; #endif diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc index 387ba171d50..d971f822055 100644 --- a/runtime/vm/bootstrap.cc +++ b/runtime/vm/bootstrap.cc @@ -55,40 +55,6 @@ static void Finish(Thread* thread) { Class& cls = Class::Handle(zone, object_store->closure_class()); cls.EnsureIsFinalized(thread); - // Make sure _Closure fields are not marked as unboxed as they are accessed - // with plain loads. - const Array& fields = Array::Handle(zone, cls.fields()); - Field& field = Field::Handle(zone); - for (intptr_t i = 0; i < fields.Length(); ++i) { - field ^= fields.At(i); - field.set_is_unboxed(false); - } - // _Closure._hash field should be explicitly marked as nullable because - // VM creates instances of _Closure without compiling its constructors, - // so it won't get nullability info from a constructor. - field ^= fields.At(fields.Length() - 1); - // Note that UserVisibleName depends on --show-internal-names. - ASSERT(strncmp(field.UserVisibleNameCString(), "_hash", 5) == 0); - field.RecordStore(Object::null_object()); - -#if defined(DEBUG) - // Verify that closure field offsets are identical in Dart and C++. - ASSERT_EQUAL(fields.Length(), 6); - field ^= fields.At(0); - ASSERT_EQUAL(field.HostOffset(), - Closure::instantiator_type_arguments_offset()); - field ^= fields.At(1); - ASSERT_EQUAL(field.HostOffset(), Closure::function_type_arguments_offset()); - field ^= fields.At(2); - ASSERT_EQUAL(field.HostOffset(), Closure::delayed_type_arguments_offset()); - field ^= fields.At(3); - ASSERT_EQUAL(field.HostOffset(), Closure::function_offset()); - field ^= fields.At(4); - ASSERT_EQUAL(field.HostOffset(), Closure::context_offset()); - field ^= fields.At(5); - ASSERT_EQUAL(field.HostOffset(), Closure::hash_offset()); -#endif // defined(DEBUG) - // Eagerly compile to avoid repeated checks when loading constants or // serializing. cls = object_store->null_class(); diff --git a/runtime/vm/bytecode_reader.cc b/runtime/vm/bytecode_reader.cc index 715a34730ab..404d4663496 100644 --- a/runtime/vm/bytecode_reader.cc +++ b/runtime/vm/bytecode_reader.cc @@ -574,6 +574,7 @@ intptr_t BytecodeReaderHelper::ReadConstantPool(const Function& function, kExternalCall, kFfiCall, kDeferredLibraryPrefix, + kAllocateClosure, }; Object& obj = Object::Handle(Z); @@ -766,6 +767,32 @@ intptr_t BytecodeReaderHelper::ReadConstantPool(const Function& function, } ASSERT(LibraryPrefix::Cast(obj).GetLibrary(0) == target_library.ptr()); } break; + case ConstantPoolTag::kAllocateClosure: { + const intptr_t closure_index = reader_.ReadUInt(); + const intptr_t num_elements = reader_.ReadUInt(); + const intptr_t flags = reader_.ReadUInt(); + // AllocateClosure flags, must be in sync with ConstantAllocateClosure + // constants in pkg/dart2bytecode/lib/constant_pool.dart. + const intptr_t kHasDelayedTypeArguments = 1 << 0; + const intptr_t kHasInstantiatorTypeArguments = 1 << 1; + const intptr_t kHasFunctionTypeArguments = 1 << 2; + // AllocateClosure constant occupies 2 entries: + // function and length_and_flags. + obj = closures_->At(closure_index); + ASSERT(obj.IsFunction()); + // Set current entry. + pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject, + ObjectPool::Patchability::kNotPatchable, + ObjectPool::SnapshotBehavior::kNotSnapshotable); + pool.SetObjectAt(i, obj); + ++i; + ASSERT(i < obj_count); + // The second entry is used for encoded length and flags. + obj = Smi::New(UntaggedClosure::EncodeLengthAndFlags( + (flags & kHasDelayedTypeArguments) != 0, + (flags & kHasInstantiatorTypeArguments) != 0, + (flags & kHasFunctionTypeArguments) != 0, num_elements)); + } break; default: UNREACHABLE(); } diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h index 649ce565f07..00bf7cd07e0 100644 --- a/runtime/vm/compiler/assembler/assembler_arm.h +++ b/runtime/vm/compiler/assembler/assembler_arm.h @@ -1098,6 +1098,13 @@ class Assembler : public AssemblerBase { // Stores a Smi value into a heap object field that always contains a Smi. void StoreIntoSmiField(const Address& dest, Register value); + void ExtractBitField(Register dst, + Register src, + intptr_t low_bit, + intptr_t width) override { + ubfx(dst, src, low_bit, width); + } + void ExtractClassIdFromTags(Register result, Register tags, Condition cond = AL); diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h index 2f22f61c609..64e767a244a 100644 --- a/runtime/vm/compiler/assembler/assembler_arm64.h +++ b/runtime/vm/compiler/assembler/assembler_arm64.h @@ -2103,6 +2103,13 @@ class Assembler : public AssemblerBase { void PushImmediate(Immediate immediate) { PushImmediate(immediate.value()); } void CompareObject(Register reg, const Object& object); + void ExtractBitField(Register dst, + Register src, + intptr_t low_bit, + intptr_t width) override { + ubfx(dst, src, low_bit, width); + } + void ExtractClassIdFromTags(Register result, Register tags); void ExtractInstanceSizeFromTags(Register result, Register tags); diff --git a/runtime/vm/compiler/assembler/assembler_base.h b/runtime/vm/compiler/assembler/assembler_base.h index 2f50bc064f8..efb6e6a1f52 100644 --- a/runtime/vm/compiler/assembler/assembler_base.h +++ b/runtime/vm/compiler/assembler/assembler_base.h @@ -1174,6 +1174,11 @@ class AssemblerBase : public StackResource { // or the architecture must define a TMP register, which is clobbered. virtual void LslRegister(Register dst, Register shift) = 0; + virtual void ExtractBitField(Register dst, + Register src, + intptr_t low_bit, + intptr_t width) = 0; + // Performs CombineHashes from runtime/vm/hash.h on the hashes contained in // dst and other. Puts the result in dst. Clobbers other. // diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc index a4fed057ba8..e61b84dec4e 100644 --- a/runtime/vm/compiler/assembler/assembler_ia32.cc +++ b/runtime/vm/compiler/assembler/assembler_ia32.cc @@ -3032,6 +3032,17 @@ void Assembler::EmitGenericShift(int rm, EmitOperand(rm, Operand(operand)); } +void Assembler::ExtractBitField(Register dst, + Register src, + intptr_t low_bit, + intptr_t width) { + MoveRegister(dst, src); + if (low_bit > 0) { + LsrImmediate(dst, low_bit); + } + AndImmediate(dst, (1 << width) - 1); +} + void Assembler::LoadClassId(Register result, Register object) { ASSERT(target::UntaggedObject::kClassIdTagPos == 12); ASSERT(target::UntaggedObject::kClassIdTagSize == 20); diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h index 823bb16c372..b37e1bb8660 100644 --- a/runtime/vm/compiler/assembler/assembler_ia32.h +++ b/runtime/vm/compiler/assembler/assembler_ia32.h @@ -942,6 +942,11 @@ class Assembler : public AssemblerBase { RangeCheckCondition condition, Label* target) override; + void ExtractBitField(Register dst, + Register src, + intptr_t low_bit, + intptr_t width) override; + /* * Loading and comparing classes of objects. */ diff --git a/runtime/vm/compiler/assembler/assembler_riscv.cc b/runtime/vm/compiler/assembler/assembler_riscv.cc index 618c40cec08..03252f38312 100644 --- a/runtime/vm/compiler/assembler/assembler_riscv.cc +++ b/runtime/vm/compiler/assembler/assembler_riscv.cc @@ -4799,6 +4799,26 @@ void Assembler::CompareObject(Register reg, const Object& object) { } } +void Assembler::ExtractBitField(Register dst, + Register src, + intptr_t low_bit, + intptr_t width) { + ASSERT((0 <= low_bit) && (low_bit + width <= XLEN)); + if (width == 1) { + if (low_bit == 0) { + andi(dst, src, 1); + return; + } else if (Supports(RV_Zbs)) { + bexti(dst, src, low_bit); + return; + } + } + if (low_bit + width < XLEN) { + slli(dst, src, XLEN - (low_bit + width)); + } + srli(dst, dst, XLEN - width); +} + void Assembler::ExtractClassIdFromTags(Register result, Register tags) { ASSERT(target::UntaggedObject::kClassIdTagPos == 12); ASSERT(target::UntaggedObject::kClassIdTagSize == 20); diff --git a/runtime/vm/compiler/assembler/assembler_riscv.h b/runtime/vm/compiler/assembler/assembler_riscv.h index f92039d6db5..96305ccebf6 100644 --- a/runtime/vm/compiler/assembler/assembler_riscv.h +++ b/runtime/vm/compiler/assembler/assembler_riscv.h @@ -1494,6 +1494,11 @@ class Assembler : public MicroAssembler { } void CompareObject(Register reg, const Object& object); + void ExtractBitField(Register dst, + Register src, + intptr_t low_bit, + intptr_t width) override; + void ExtractClassIdFromTags(Register result, Register tags); void ExtractInstanceSizeFromTags(Register result, Register tags); diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc index 1b3d9ed61dd..9ffc11b8b44 100644 --- a/runtime/vm/compiler/assembler/assembler_x64.cc +++ b/runtime/vm/compiler/assembler/assembler_x64.cc @@ -2770,6 +2770,17 @@ void Assembler::EmitGenericShift(bool wide, EmitOperand(rm, Operand(operand)); } +void Assembler::ExtractBitField(Register dst, + Register src, + intptr_t low_bit, + intptr_t width) { + MoveRegister(dst, src); + if (low_bit > 0) { + LsrImmediate(dst, low_bit); + } + AndImmediate(dst, Immediate((1 << width) - 1)); +} + void Assembler::ExtractClassIdFromTags(Register result, Register tags) { ASSERT(target::UntaggedObject::kClassIdTagPos == 12); ASSERT(target::UntaggedObject::kClassIdTagSize == 20); diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h index 129761813e5..ffa3dad8081 100644 --- a/runtime/vm/compiler/assembler/assembler_x64.h +++ b/runtime/vm/compiler/assembler/assembler_x64.h @@ -979,6 +979,11 @@ class Assembler : public AssemblerBase { void CallCFunction(Register reg, bool restore_rsp = false); void CallCFunction(Address address, bool restore_rsp = false); + void ExtractBitField(Register dst, + Register src, + intptr_t low_bit, + intptr_t width) override; + void ExtractClassIdFromTags(Register result, Register tags); void ExtractInstanceSizeFromTags(Register result, Register tags); diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index 0f0f3f994f7..10ad89da01e 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -61,6 +61,12 @@ DEFINE_FLAG(bool, DECLARE_FLAG(bool, inline_alloc); DECLARE_FLAG(bool, use_slow_path); +// Macro for shared code generation methods (EmitNativeCode and +// MakeLocationSummary). Only assembly code that can be shared across all +// architectures can be used. Machine specific register allocation and code +// generation is located in il_.cc +#define __ compiler->assembler()-> + class SubtypeFinder { public: SubtypeFinder(Zone* zone, @@ -961,11 +967,6 @@ LocationSummary* AllocateClosureInstr::MakeLocationSummary(Zone* zone, Location::RegisterLocation(AllocateClosureABI::kFunctionReg)); locs->set_in(kContextPos, Location::RegisterLocation(AllocateClosureABI::kContextReg)); - if (has_instantiator_type_args()) { - locs->set_in(kInstantiatorTypeArgsPos, - Location::RegisterLocation( - AllocateClosureABI::kInstantiatorTypeArgsReg)); - } locs->set_out(0, Location::RegisterLocation(AllocateClosureABI::kResultReg)); return locs; } @@ -973,19 +974,25 @@ LocationSummary* AllocateClosureInstr::MakeLocationSummary(Zone* zone, void AllocateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { auto object_store = compiler->isolate_group()->object_store(); Code& stub = Code::ZoneHandle(compiler->zone()); - if (has_instantiator_type_args()) { - if (is_generic()) { - stub = object_store->allocate_closure_ta_generic_stub(); - } else { - stub = object_store->allocate_closure_ta_stub(); - } - } else { - if (is_generic()) { - stub = object_store->allocate_closure_generic_stub(); - } else { - stub = object_store->allocate_closure_stub(); - } + const intptr_t num_elements = NumElements(); + switch (num_elements) { + case 1: + stub = object_store->allocate_closure1_stub(); + break; + case 2: + stub = object_store->allocate_closure2_stub(); + break; + case 3: + stub = object_store->allocate_closure3_stub(); + break; + case 4: + stub = object_store->allocate_closure4_stub(); + break; + default: + UNREACHABLE(); } + __ LoadImmediate(AllocateClosureABI::kLengthAndFlagsReg, + compiler::target::ToRawSmi(EncodedLengthAndFlags())); compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther, locs(), deopt_id(), env()); } @@ -2754,8 +2761,21 @@ bool LoadFieldInstr::TryEvaluateLoad(const Object& instance, const Record& record = Record::Cast(instance); if (index < record.num_fields()) { *result = record.FieldAt(index); + return true; + } + } + return false; + + case Slot::Kind::kClosureElement: + if (instance.IsClosure()) { + const intptr_t index = + compiler::target::Closure::element_index_at_offset( + field.offset_in_bytes()); + const Closure& closure = Closure::Cast(instance); + if (index < closure.length()) { + *result = closure.ElementAt(index); + return true; } - return true; } return false; @@ -4247,13 +4267,6 @@ void CallTargets::Print() const { } } -// Shared code generation methods (EmitNativeCode and -// MakeLocationSummary). Only assembly code that can be shared across all -// architectures can be used. Machine specific register allocation and code -// generation is located in intermediate_language_.cc - -#define __ compiler->assembler()-> - LocationSummary* GraphEntryInstr::MakeLocationSummary(Zone* zone, bool optimizing) const { UNREACHABLE(); diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h index 673e07fd16f..532a222a95a 100644 --- a/runtime/vm/compiler/backend/il.h +++ b/runtime/vm/compiler/backend/il.h @@ -7584,49 +7584,53 @@ class AllocateObjectInstr : public AllocationInstr { DISALLOW_COPY_AND_ASSIGN(AllocateObjectInstr); }; -// Allocates and null initializes a closure object, given the closure function -// and the context as values. -class AllocateClosureInstr : public TemplateAllocation<3> { +// Allocates and null initializes a closure object. +class AllocateClosureInstr : public TemplateAllocation<2> { public: enum Inputs { kFunctionPos = 0, kContextPos = 1, - kInstantiatorTypeArgsPos = 2, }; AllocateClosureInstr(const InstructionSource& source, Value* closure_function, Value* context, - Value* instantiator_type_args, // Optional. - bool is_generic, + bool has_delayed_type_args, + bool has_instantiator_type_args, + bool has_function_type_args, bool is_tear_off, intptr_t deopt_id) : TemplateAllocation(source, deopt_id), - has_instantiator_type_args_(instantiator_type_args != nullptr), - is_generic_(is_generic), + has_delayed_type_args_(has_delayed_type_args), + has_instantiator_type_args_(has_instantiator_type_args), + has_function_type_args_(has_function_type_args), is_tear_off_(is_tear_off) { SetInputAt(kFunctionPos, closure_function); SetInputAt(kContextPos, context); - if (has_instantiator_type_args_) { - SetInputAt(kInstantiatorTypeArgsPos, instantiator_type_args); - } } DECLARE_INSTRUCTION(AllocateClosure) virtual CompileType ComputeType() const; - virtual intptr_t InputCount() const { - return has_instantiator_type_args() ? 3 : 2; - } + virtual intptr_t InputCount() const { return 2; } Value* closure_function() const { return inputs_[kFunctionPos]; } Value* context() const { return inputs_[kContextPos]; } - bool has_instantiator_type_args() const { - return has_instantiator_type_args_; - } - bool is_generic() const { return is_generic_; } bool is_tear_off() const { return is_tear_off_; } + intptr_t NumElements() const { + return UntaggedClosure::ContextIndex(has_delayed_type_args_, + has_instantiator_type_args_, + has_function_type_args_) + + 1; + } + + intptr_t EncodedLengthAndFlags() const { + return UntaggedClosure::EncodeLengthAndFlags( + has_delayed_type_args_, has_instantiator_type_args_, + has_function_type_args_, NumElements()); + } + const Function& known_function() const { Value* const value = closure_function(); if (value->BindsToConstant()) { @@ -7641,11 +7645,12 @@ class AllocateClosureInstr : public TemplateAllocation<3> { case kFunctionPos: return &Slot::Closure_function(); case kContextPos: - return &Slot::Closure_context(); - case kInstantiatorTypeArgsPos: - return has_instantiator_type_args() - ? &Slot::Closure_instantiator_type_arguments() - : nullptr; + return &Slot::GetClosureElementSlot( + Thread::Current(), + compiler::target::Closure::element_offset( + UntaggedClosure::ContextIndex(has_delayed_type_args_, + has_instantiator_type_args_, + has_function_type_args_))); default: return TemplateAllocation::SlotForInput(pos); } @@ -7659,20 +7664,22 @@ class AllocateClosureInstr : public TemplateAllocation<3> { virtual bool AttributesEqual(const Instruction& other) const { const auto other_ac = other.AsAllocateClosure(); - return (other_ac->has_instantiator_type_args() == - has_instantiator_type_args()) && - (other_ac->is_generic() == is_generic()) && + return (other_ac->has_delayed_type_args_ == has_delayed_type_args_) && + (other_ac->has_instantiator_type_args_ == + has_instantiator_type_args_) && + (other_ac->has_function_type_args_ == has_function_type_args_) && (other_ac->is_tear_off() == is_tear_off()); } virtual bool WillAllocateNewOrRemembered() const { return compiler::target::Heap::IsAllocatableInNewSpace( - compiler::target::Closure::InstanceSize()); + compiler::target::Closure::InstanceSize(NumElements())); } #define FIELD_LIST(F) \ + F(const bool, has_delayed_type_args_) \ F(const bool, has_instantiator_type_args_) \ - F(const bool, is_generic_) \ + F(const bool, has_function_type_args_) \ F(const bool, is_tear_off_) DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(AllocateClosureInstr, diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc index bef19b22278..1abf6b8cb3d 100644 --- a/runtime/vm/compiler/backend/il_arm.cc +++ b/runtime/vm/compiler/backend/il_arm.cc @@ -2265,7 +2265,8 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { const Register result = locs()->out(0).reg(); ASSERT(rep == kTagged); ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid) || - (class_id() == kTypeArgumentsCid) || (class_id() == kRecordCid)); + (class_id() == kTypeArgumentsCid) || (class_id() == kClosureCid) || + (class_id() == kRecordCid)); __ ldr(result, element_address); } } diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc index ba50347edaf..dd67996b87b 100644 --- a/runtime/vm/compiler/backend/il_arm64.cc +++ b/runtime/vm/compiler/backend/il_arm64.cc @@ -1978,7 +1978,8 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { const Register result = locs()->out(0).reg(); ASSERT(representation() == kTagged); ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid) || - (class_id() == kTypeArgumentsCid) || (class_id() == kRecordCid)); + (class_id() == kTypeArgumentsCid) || (class_id() == kClosureCid) || + (class_id() == kRecordCid)); __ LoadCompressed(result, element_address); } } diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc index a5b32102b38..4dc7c17d183 100644 --- a/runtime/vm/compiler/backend/il_ia32.cc +++ b/runtime/vm/compiler/backend/il_ia32.cc @@ -1673,7 +1673,8 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { const Register result = locs()->out(0).reg(); ASSERT(representation() == kTagged); ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid) || - (class_id() == kTypeArgumentsCid) || (class_id() == kRecordCid)); + (class_id() == kTypeArgumentsCid) || (class_id() == kClosureCid) || + (class_id() == kRecordCid)); __ movl(result, element_address); } } diff --git a/runtime/vm/compiler/backend/il_riscv.cc b/runtime/vm/compiler/backend/il_riscv.cc index 84e17950db8..8ae5d41fb1d 100644 --- a/runtime/vm/compiler/backend/il_riscv.cc +++ b/runtime/vm/compiler/backend/il_riscv.cc @@ -2067,7 +2067,8 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } else { ASSERT(rep == kTagged); ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid) || - (class_id() == kTypeArgumentsCid) || (class_id() == kRecordCid)); + (class_id() == kTypeArgumentsCid) || (class_id() == kClosureCid) || + (class_id() == kRecordCid)); const Register result = locs()->out(0).reg(); __ Load(result, element_address); } diff --git a/runtime/vm/compiler/backend/il_serializer.cc b/runtime/vm/compiler/backend/il_serializer.cc index ead05549dfb..d2976955815 100644 --- a/runtime/vm/compiler/backend/il_serializer.cc +++ b/runtime/vm/compiler/backend/il_serializer.cc @@ -2413,6 +2413,9 @@ void Slot::Write(FlowGraphSerializer* s) const { case Kind::kRecordField: s->Write(offset_in_bytes_); break; + case Kind::kClosureElement: + s->Write(offset_in_bytes_); + break; case Kind::kCapturedVariable: s->Write(flags_); s->Write(offset_in_bytes_); @@ -2463,6 +2466,14 @@ const Slot& Slot::Read(FlowGraphDeserializer* d) { data = ":record_field"; type = CompileType::Dynamic(); break; + case Kind::kClosureElement: + flags = IsCompressedBit::encode(Closure::ContainsCompressedPointers()); + offset = d->Read(); + data = OS::SCreate( + d->zone(), ":closure_element[%" Pd "]", + compiler::target::Closure::element_index_at_offset(offset)); + type = CompileType::Dynamic(); + break; case Kind::kCapturedVariable: flags = d->Read(); offset = d->Read(); diff --git a/runtime/vm/compiler/backend/il_test.cc b/runtime/vm/compiler/backend/il_test.cc index a2ccc4477ca..280bd747c7d 100644 --- a/runtime/vm/compiler/backend/il_test.cc +++ b/runtime/vm/compiler/backend/il_test.cc @@ -182,10 +182,10 @@ ISOLATE_UNIT_TEST_CASE(IRTest_InitializingStores) { expected_stores_jit.insert( expected_stores_jit.end(), {"value", "Context.parent", "Context.parent", "value", - "Closure.function_type_arguments", "Closure.context"}); + ":closure_element[0]", ":closure_element[0]"}); expected_stores_aot.insert( expected_stores_aot.end(), - {"value", "Closure.function_type_arguments", "Closure.context"}); + {"value", ":closure_element[0]", ":closure_element[0]"}); RunInitializingStoresTest(root_library, "f4", CompilerPass::kJIT, expected_stores_jit); diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc index d35cf8b7641..f1d0ce7dc4d 100644 --- a/runtime/vm/compiler/backend/il_x64.cc +++ b/runtime/vm/compiler/backend/il_x64.cc @@ -1885,7 +1885,8 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } else { ASSERT(rep == kTagged); ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid) || - (class_id() == kTypeArgumentsCid) || (class_id() == kRecordCid)); + (class_id() == kTypeArgumentsCid) || (class_id() == kClosureCid) || + (class_id() == kRecordCid)); Register result = locs()->out(0).reg(); __ LoadCompressed(result, element_address); } diff --git a/runtime/vm/compiler/backend/locations.cc b/runtime/vm/compiler/backend/locations.cc index c24fef5ca96..f7964c7fd5f 100644 --- a/runtime/vm/compiler/backend/locations.cc +++ b/runtime/vm/compiler/backend/locations.cc @@ -93,6 +93,7 @@ Representation RepresentationUtils::RepresentationOfArrayElement( #define ARRAY_CASE(Name) case k##Name##Cid: CLASS_LIST_ARRAYS(ARRAY_CASE) #undef ARRAY_CASE + case kClosureCid: case kRecordCid: case kTypeArgumentsCid: return kTagged; diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc index 6885b576723..9dee89e579d 100644 --- a/runtime/vm/compiler/backend/range_analysis.cc +++ b/runtime/vm/compiler/backend/range_analysis.cc @@ -2843,6 +2843,7 @@ void LoadFieldInstr::InferRange(RangeAnalysis* analysis, Range* range) { break; case Slot::Kind::kDartField: + case Slot::Kind::kClosureElement: case Slot::Kind::kCapturedVariable: case Slot::Kind::kRecordField: // Use default value. @@ -2872,6 +2873,7 @@ void LoadFieldInstr::InferRange(RangeAnalysis* analysis, Range* range) { break; case Slot::Kind::kClosure_hash: + case Slot::Kind::kClosure_length_and_flags: case Slot::Kind::kLinkedHashBase_hash_mask: case Slot::Kind::kLinkedHashBase_used_data: case Slot::Kind::kLinkedHashBase_deleted_keys: diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc index 1ef81f5d327..5ae10709bf8 100644 --- a/runtime/vm/compiler/backend/redundancy_elimination.cc +++ b/runtime/vm/compiler/backend/redundancy_elimination.cc @@ -1478,6 +1478,13 @@ static bool IsLoopInvariantLoad(ZoneGrowableArray* sets, (*sets)[loop_header_index]->Contains(GetPlaceId(instr)); } +static bool IsInitializingStore(Instruction* instr) { + if (auto store = instr->AsStoreField()) { + return store->is_initialization(); + } + return false; +} + LICM::LICM(FlowGraph* flow_graph) : flow_graph_(flow_graph) { ASSERT(flow_graph->is_licm_allowed()); } @@ -1647,9 +1654,10 @@ void LICM::Optimize() { // instructions can be hoisted as long as its exception is still // the very first "visible" effect of the loop. bool is_loop_invariant = false; - if ((current->AllowsCSE() || - IsLoopInvariantLoad(loop_invariant_loads, i, current)) && - (!seen_visible_effect || !current->MayHaveVisibleEffect())) { + if (((current->AllowsCSE() || + IsLoopInvariantLoad(loop_invariant_loads, i, current)) && + (!seen_visible_effect || !current->MayHaveVisibleEffect())) || + IsInitializingStore(current)) { is_loop_invariant = true; for (intptr_t i = 0; i < current->InputCount(); ++i) { Definition* input_def = current->InputAt(i)->definition(); @@ -3991,9 +3999,10 @@ void AllocationSinking::CreateMaterializationAt( intptr_t length_or_shape = -1; if (auto instr = alloc->AsAllocateObject()) { cls = &(instr->cls()); - } else if (alloc->IsAllocateClosure()) { + } else if (auto instr = alloc->AsAllocateClosure()) { cls = &Class::ZoneHandle( flow_graph_->isolate_group()->object_store()->closure_class()); + length_or_shape = instr->EncodedLengthAndFlags(); } else if (auto instr = alloc->AsAllocateContext()) { cls = &Class::ZoneHandle(Object::context_class()); length_or_shape = instr->num_context_variables(); diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc index 4bd712bdd96..34342e8c4eb 100644 --- a/runtime/vm/compiler/backend/slot.cc +++ b/runtime/vm/compiler/backend/slot.cc @@ -317,6 +317,34 @@ const Slot& Slot::GetRecordFieldSlot(Thread* thread, intptr_t offset_in_bytes) { offset_in_bytes, ":record_field", CompileType::Dynamic(), kTagged); } +const Slot& Slot::GetClosureElementSlot(Thread* thread, + intptr_t offset_in_bytes) { + const char* name = OS::SCreate( + thread->zone(), ":closure_element[%" Pd "]", + compiler::target::Closure::element_index_at_offset(offset_in_bytes)); + return GetCanonicalSlot( + thread, Kind::kClosureElement, + IsImmutableBit::encode(true) | + IsCompressedBit::encode(Closure::ContainsCompressedPointers()), + offset_in_bytes, name, CompileType::Dynamic(), kTagged); +} + +const Slot& Slot::GetClosureContextSlot(Thread* thread, + const Function& function) { + ASSERT(function.IsClosureFunction()); + const bool has_delayed_type_args = + Closure::HasDelayedTypeArgumentsField(function); + const bool has_instantiator_type_args = + Closure::HasInstantiatorTypeArgumentsField(function); + const bool has_function_type_args = + Closure::HasFunctionTypeArgumentsField(function); + return Slot::GetClosureElementSlot( + thread, + compiler::target::Closure::element_offset(UntaggedClosure::ContextIndex( + has_delayed_type_args, has_instantiator_type_args, + has_function_type_args))); +} + const Slot& Slot::GetCanonicalSlot(Thread* thread, Slot::Kind kind, int8_t flags, @@ -487,6 +515,7 @@ bool Slot::Equals(const Slot& other) const { case Kind::kTypeArgumentsIndex: case Kind::kArrayElement: case Kind::kRecordField: + case Kind::kClosureElement: return true; case Kind::kCapturedVariable: { diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h index 25a74bf066c..7953598bd74 100644 --- a/runtime/vm/compiler/backend/slot.h +++ b/runtime/vm/compiler/backend/slot.h @@ -64,10 +64,6 @@ class ParsedFunction; V(FinalizerEntry, UntaggedFinalizerEntry, next, FinalizerEntry, VAR) \ V(Function, UntaggedFunction, signature, FunctionType, FINAL) \ V(Context, UntaggedContext, parent, Context, FINAL) \ - V(Closure, UntaggedClosure, instantiator_type_arguments, TypeArguments, \ - FINAL) \ - V(Closure, UntaggedClosure, delayed_type_arguments, TypeArguments, FINAL) \ - V(Closure, UntaggedClosure, function_type_arguments, TypeArguments, FINAL) \ V(FunctionType, UntaggedFunctionType, type_parameters, TypeParameters, \ FINAL) \ V(ReceivePort, UntaggedReceivePort, send_port, SendPort, FINAL) \ @@ -101,6 +97,7 @@ class ParsedFunction; // that) or like a non-final field. #define NONNULLABLE_INT_TAGGED_NATIVE_DART_SLOTS_LIST(V) \ V(Array, UntaggedArray, length, Smi, FINAL) \ + V(Closure, UntaggedClosure, length_and_flags, Smi, FINAL) \ V(Closure, UntaggedClosure, hash, Smi, VAR_NOSANITIZETHREAD) \ V(GrowableObjectArray, UntaggedGrowableObjectArray, length, Smi, VAR) \ V(TypedDataBase, UntaggedTypedDataBase, length, Smi, FINAL) \ @@ -133,7 +130,6 @@ class ParsedFunction; // that) or like a non-final field. #define NONNULLABLE_NONINT_TAGGED_NATIVE_DART_SLOTS_LIST(V) \ V(Closure, UntaggedClosure, function, Function, FINAL) \ - V(Closure, UntaggedClosure, context, Dynamic, FINAL) \ V(Finalizer, UntaggedFinalizer, callback, Closure, FINAL) \ V(NativeFinalizer, UntaggedFinalizer, callback, Pointer, FINAL) \ V(Function, UntaggedFunction, data, Dynamic, FINAL) \ @@ -455,6 +451,9 @@ class Slot : public ZoneObject { // A slot corresponding to a record field at the given offset. kRecordField, + // A slot corresponding to a Closure element at given offset. + kClosureElement, + // A slot within a Context object that contains a value of a captured // local variable. kCapturedVariable, @@ -486,6 +485,14 @@ class Slot : public ZoneObject { static const Slot& GetRecordFieldSlot(Thread* thread, intptr_t offset_in_bytes); + // Returns a slot corresponding to a Closure element at [offset_in_bytes]. + static const Slot& GetClosureElementSlot(Thread* thread, + intptr_t offset_in_bytes); + + // Returns 'Closure.context' slot for the given closure [function]. + static const Slot& GetClosureContextSlot(Thread* thread, + const Function& function); + // Returns a slot that represents the given captured local variable. static const Slot& GetContextVariableSlotFor(Thread* thread, const LocalVariable& var); @@ -510,6 +517,7 @@ class Slot : public ZoneObject { bool IsArgumentOfType() const { return kind() == Kind::kTypeArgumentsIndex; } bool IsArrayElement() const { return kind() == Kind::kArrayElement; } bool IsRecordField() const { return kind() == Kind::kRecordField; } + bool IsClosureElement() const { return kind() == Kind::kClosureElement; } bool IsLengthSlot() const; bool IsImmutableLengthSlot() const; diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc index 92dd13db25e..8a5d15e172c 100644 --- a/runtime/vm/compiler/backend/type_propagator.cc +++ b/runtime/vm/compiler/backend/type_propagator.cc @@ -1881,6 +1881,7 @@ CompileType LoadIndexedInstr::ComputeType() const { CompileType::kCannotBeNull, CompileType::kCannotBeSentinel); + case kClosureCid: case kRecordCid: return CompileType::Dynamic(); diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc index 1f7b9c4896f..a2b08047608 100644 --- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc +++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc @@ -389,13 +389,20 @@ Fragment BaseFlowGraphBuilder::TestTypeArgsLen(Fragment eq_branch, Fragment BaseFlowGraphBuilder::TestDelayedTypeArgs(LocalVariable* closure, Fragment present, Fragment absent) { - Fragment test; + const auto& function = parsed_function_->function(); + ASSERT(function.IsClosureFunction()); + if (!function.IsGeneric()) { + return absent; + } + + Fragment test; TargetEntryInstr* absent_entry; TargetEntryInstr* present_entry; - test += LoadLocal(closure); - test += LoadNativeField(Slot::Closure_delayed_type_arguments()); + test += LoadNativeField(Slot::GetClosureElementSlot( + thread_, compiler::target::Closure::element_offset( + UntaggedClosure::kDelayedTypeArgumentsIndex))); test += Constant(Object::empty_type_arguments()); test += BranchIfEqual(&absent_entry, &present_entry); @@ -997,16 +1004,16 @@ Fragment BaseFlowGraphBuilder::AllocateContext( } Fragment BaseFlowGraphBuilder::AllocateClosure(TokenPosition position, + bool has_delayed_type_args, bool has_instantiator_type_args, - bool is_generic, + bool has_function_type_args, bool is_tear_off) { - Value* instantiator_type_args = - (has_instantiator_type_args ? Pop() : nullptr); auto const context = Pop(); auto const function = Pop(); auto* allocate = new (Z) AllocateClosureInstr( - InstructionSource(position), function, context, instantiator_type_args, - is_generic, is_tear_off, GetNextDeoptId()); + InstructionSource(position), function, context, has_delayed_type_args, + has_instantiator_type_args, has_function_type_args, is_tear_off, + GetNextDeoptId()); Push(allocate); return Fragment(allocate); } diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h index abe739bcb0c..8d23695a8ce 100644 --- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h +++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h @@ -399,8 +399,9 @@ class BaseFlowGraphBuilder { Fragment AllocateContext(const ZoneGrowableArray& scope); // Top of the stack should be the closure function. Fragment AllocateClosure(TokenPosition position, + bool has_delayed_type_args, bool has_instantiator_type_args, - bool is_generic, + bool has_function_type_args, bool is_tear_off); Fragment CreateArray(); Fragment AllocateRecord(TokenPosition position, RecordShape shape); diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc index 5b1170cd431..5d8221ccb54 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc @@ -502,12 +502,22 @@ Fragment StreamingFlowGraphBuilder::TypeArgumentsHandling( LocalVariable* closure = parsed_function()->ParameterVariable(0); LocalVariable* fn_type_args = parsed_function()->function_type_arguments(); ASSERT(fn_type_args != nullptr && closure != nullptr); + ASSERT(Closure::HasFunctionTypeArgumentsField(dart_function)); + + const bool has_instantiator_type_args = + Closure::HasInstantiatorTypeArgumentsField(dart_function); if (dart_function.IsGeneric()) { + ASSERT(Closure::HasDelayedTypeArgumentsField(dart_function)); + const intptr_t function_type_args_index = + UntaggedClosure::FunctionTypeArgumentsIndex( + /*has_delayed_type_args=*/true, has_instantiator_type_args); prologue += LoadLocal(fn_type_args); prologue += LoadLocal(closure); - prologue += LoadNativeField(Slot::Closure_function_type_arguments()); + prologue += LoadNativeField(Slot::GetClosureElementSlot( + thread(), + compiler::target::Closure::element_offset(function_type_args_index))); prologue += IntConstant(dart_function.NumParentTypeArguments()); @@ -521,8 +531,14 @@ Fragment StreamingFlowGraphBuilder::TypeArgumentsHandling( prologue += StoreLocal(TokenPosition::kNoSource, fn_type_args); prologue += Drop(); } else { + ASSERT(!Closure::HasDelayedTypeArgumentsField(dart_function)); + const intptr_t function_type_args_index = + UntaggedClosure::FunctionTypeArgumentsIndex( + /*has_delayed_type_args=*/false, has_instantiator_type_args); prologue += LoadLocal(closure); - prologue += LoadNativeField(Slot::Closure_function_type_arguments()); + prologue += LoadNativeField(Slot::GetClosureElementSlot( + thread(), + compiler::target::Closure::element_offset(function_type_args_index))); prologue += StoreLocal(TokenPosition::kNoSource, fn_type_args); prologue += Drop(); } @@ -5938,6 +5954,13 @@ Fragment StreamingFlowGraphBuilder::BuildFunctionNode( ASSERT(function.kernel_offset() == func_node_offset); SkipFunctionNode(); + const bool has_delayed_type_args = + Closure::HasDelayedTypeArgumentsField(function); + const bool has_instantiator_type_args = + Closure::HasInstantiatorTypeArgumentsField(function); + const bool has_function_type_args = + Closure::HasFunctionTypeArgumentsField(function); + Fragment instructions; instructions += Constant(function); if (scopes()->IsClosureWithEmptyContext(func_node_offset)) { @@ -5945,24 +5968,37 @@ Fragment StreamingFlowGraphBuilder::BuildFunctionNode( } else { instructions += LoadLocal(parsed_function()->current_context_var()); } - // The function signature can have uninstantiated class type parameters. - const bool has_instantiator_type_args = - !function.HasInstantiatedSignature(kCurrentClass); - if (has_instantiator_type_args) { - instructions += LoadInstantiatorTypeArguments(); - } instructions += flow_graph_builder_->AllocateClosure( - function.token_pos(), has_instantiator_type_args, function.IsGeneric(), + function.token_pos(), has_delayed_type_args, has_instantiator_type_args, + has_function_type_args, /*is_tear_off=*/false); LocalVariable* closure = MakeTemporary(); - // TODO(30455): We only need to save these if the closure uses any captured - // type parameters. - instructions += LoadLocal(closure); - instructions += LoadFunctionTypeArguments(); - instructions += flow_graph_builder_->StoreNativeField( - Slot::Closure_function_type_arguments(), - StoreFieldInstr::Kind::kInitializing); + // The function signature can have uninstantiated class type parameters. + if (has_instantiator_type_args) { + instructions += LoadLocal(closure); + instructions += LoadInstantiatorTypeArguments(); + instructions += flow_graph_builder_->StoreNativeField( + Slot::GetClosureElementSlot( + thread(), compiler::target::Closure::element_offset( + UntaggedClosure::InstantiatorTypeArgumentsIndex( + has_delayed_type_args))), + StoreFieldInstr::Kind::kInitializing); + } + + if (has_function_type_args) { + // TODO(30455): We only need to save these if the closure uses any captured + // type parameters. + instructions += LoadLocal(closure); + instructions += LoadFunctionTypeArguments(); + instructions += flow_graph_builder_->StoreNativeField( + Slot::GetClosureElementSlot( + thread(), + compiler::target::Closure::element_offset( + UntaggedClosure::FunctionTypeArgumentsIndex( + has_delayed_type_args, has_instantiator_type_args))), + StoreFieldInstr::Kind::kInitializing); + } return instructions; } diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc index 7d6a6d516c2..2daf19e0735 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -278,12 +278,14 @@ Fragment FlowGraphBuilder::CatchBlockEntry(const Array& handler_types, CurrentException()->is_captured() || CurrentCatchContext()->is_captured(); LocalVariable* context_variable = parsed_function_->current_context_var(); if (should_restore_closure_context) { - ASSERT(parsed_function_->function().IsClosureFunction()); + const auto& function = parsed_function_->function(); + ASSERT(function.IsClosureFunction()); LocalVariable* closure_parameter = parsed_function_->ParameterVariable(0); ASSERT(!closure_parameter->is_captured()); instructions += LoadLocal(closure_parameter); - instructions += LoadNativeField(Slot::Closure_context()); + instructions += + LoadNativeField(Slot::GetClosureContextSlot(thread_, function)); instructions += StoreLocal(TokenPosition::kNoSource, context_variable); instructions += Drop(); } @@ -895,6 +897,7 @@ const Function& TypedListGetNativeFunction(Thread* thread, classid_t cid) { V(ByteDataViewLength, TypedDataBase_length) \ V(ByteDataViewOffsetInBytes, TypedDataView_offset_in_bytes) \ V(ByteDataViewTypedData, TypedDataView_typed_data) \ + V(Closure_hash, Closure_hash) \ V(Finalizer_getCallback, Finalizer_callback) \ V(FinalizerBase_getAllEntries, FinalizerBase_all_entries) \ V(FinalizerBase_getDetachments, FinalizerBase_detachments) \ @@ -2280,17 +2283,31 @@ Fragment FlowGraphBuilder::BuildImplicitClosureCreation( ASSERT(!target.HasGenericParent()); ASSERT(target.IsImplicitInstanceClosureFunction()); + const bool has_delayed_type_args = + Closure::HasDelayedTypeArgumentsField(target); + const bool has_instantiator_type_args = + Closure::HasInstantiatorTypeArgumentsField(target); + ASSERT(!Closure::HasFunctionTypeArgumentsField(target)); + Fragment fragment; fragment += Constant(target); fragment += LoadLocal(parsed_function_->receiver_var()); + fragment += AllocateClosure( + position, has_delayed_type_args, has_instantiator_type_args, + /*has_function_type_args=*/false, /*is_tear_off=*/true); + // The function signature can have uninstantiated class type parameters. - const bool has_instantiator_type_args = - !target.HasInstantiatedSignature(kCurrentClass); if (has_instantiator_type_args) { + LocalVariable* closure = MakeTemporary(); + fragment += LoadLocal(closure); fragment += LoadInstantiatorTypeArguments(); + fragment += StoreNativeField( + Slot::GetClosureElementSlot( + thread_, compiler::target::Closure::element_offset( + UntaggedClosure::InstantiatorTypeArgumentsIndex( + has_delayed_type_args))), + StoreFieldInstr::Kind::kInitializing); } - fragment += AllocateClosure(position, has_instantiator_type_args, - target.IsGeneric(), /*is_tear_off=*/true); return fragment; } @@ -2890,10 +2907,9 @@ struct FlowGraphBuilder::ClosureCallInfo { LocalVariable* named_parameter_names = nullptr; LocalVariable* parameter_types = nullptr; LocalVariable* type_parameters = nullptr; + LocalVariable* closure_length_and_flags = nullptr; LocalVariable* num_type_parameters = nullptr; LocalVariable* type_parameter_flags = nullptr; - LocalVariable* instantiator_type_args = nullptr; - LocalVariable* parent_function_type_args = nullptr; LocalVariable* num_parent_type_args = nullptr; }; @@ -3002,9 +3018,17 @@ Fragment FlowGraphBuilder::BuildClosureCallDefaultTypeHandling( return store_provided; } + Fragment instructions; + JoinEntryInstr* end = BuildJoinEntry(); + TargetEntryInstr *has_delayed_type_args, *no_delayed_type_args; + + instructions += LoadLocal(info.vars->delayed_type_args); + instructions += Constant(Object::empty_type_arguments()); + instructions += BranchIfEqual(&no_delayed_type_args, &has_delayed_type_args); + // Load the defaults, instantiating or replacing them with the other type // arguments as appropriate. - Fragment store_default; + Fragment store_default(no_delayed_type_args); store_default += LoadLocal(info.closure); store_default += LoadNativeField(Slot::Closure_function()); store_default += LoadNativeField(Slot::Function_data()); @@ -3048,10 +3072,10 @@ Fragment FlowGraphBuilder::BuildClosureCallDefaultTypeHandling( Fragment do_instantiation(needs_instantiation); // Load the instantiator type arguments. - do_instantiation += LoadLocal(info.instantiator_type_args); + do_instantiation += LoadLocal(info.vars->instantiator_type_args); // Load the parent function type arguments. (No local function type arguments // can be used within the defaults). - do_instantiation += LoadLocal(info.parent_function_type_args); + do_instantiation += LoadLocal(info.vars->parent_function_type_args); // Load the default type arguments to instantiate. do_instantiation += LoadLocal(info.type_parameters); do_instantiation += LoadNativeField(Slot::TypeParameters_defaults()); @@ -3061,7 +3085,7 @@ Fragment FlowGraphBuilder::BuildClosureCallDefaultTypeHandling( do_instantiation += Goto(done); Fragment share_instantiator(can_share_instantiator); - share_instantiator += LoadLocal(info.instantiator_type_args); + share_instantiator += LoadLocal(info.vars->instantiator_type_args); share_instantiator += StoreLocal(info.vars->function_type_args); share_instantiator += Drop(); share_instantiator += Goto(done); @@ -3069,7 +3093,7 @@ Fragment FlowGraphBuilder::BuildClosureCallDefaultTypeHandling( Fragment share_function(can_share_function); // Since the defaults won't have local type parameters, these must all be // from the parent function type arguments, so we can just use it. - share_function += LoadLocal(info.parent_function_type_args); + share_function += LoadLocal(info.vars->parent_function_type_args); share_function += StoreLocal(info.vars->function_type_args); share_function += Drop(); share_function += Goto(done); @@ -3077,15 +3101,16 @@ Fragment FlowGraphBuilder::BuildClosureCallDefaultTypeHandling( store_default.current = done; // Return here after branching. store_default += DropTemporary(&default_tav_kind); store_default += DropTemporary(&closure_data); + store_default += Goto(end); - Fragment store_delayed; - store_delayed += LoadLocal(info.closure); - store_delayed += LoadNativeField(Slot::Closure_delayed_type_arguments()); + Fragment store_delayed(has_delayed_type_args); + store_delayed += LoadLocal(info.vars->delayed_type_args); store_delayed += StoreLocal(info.vars->function_type_args); store_delayed += Drop(); + store_delayed += Goto(end); - // Use the delayed type args if present, else the default ones. - return TestDelayedTypeArgs(info.closure, store_delayed, store_default); + instructions.current = end; + return instructions; } Fragment FlowGraphBuilder::BuildClosureCallNamedArgumentsCheck( @@ -3230,12 +3255,15 @@ Fragment FlowGraphBuilder::BuildClosureCallArgumentsValidCheck( Fragment check_entry; // We only need to check the length of any explicitly provided type arguments. if (info.descriptor.TypeArgsLen() > 0) { - Fragment check_type_args_length; - check_type_args_length += LoadLocal(info.type_parameters); - TargetEntryInstr* null; - TargetEntryInstr* not_null; - check_type_args_length += BranchIfNull(&null, ¬_null); - check_type_args_length.current = not_null; // Continue in non-error case. + TargetEntryInstr *has_delayed_type_args, *no_delayed_type_args; + + check_entry += LoadLocal(info.vars->delayed_type_args); + check_entry += Constant(Object::empty_type_arguments()); + check_entry += BranchIfEqual(&no_delayed_type_args, &has_delayed_type_args); + + Fragment(has_delayed_type_args) + Goto(info.throw_no_such_method); + + Fragment check_type_args_length(no_delayed_type_args); check_type_args_length += LoadLocal(info.signature); check_type_args_length += BuildExtractUnboxedSlotBitFieldIntoSmi< UntaggedFunctionType::PackedNumTypeParameters>( @@ -3244,19 +3272,11 @@ Fragment FlowGraphBuilder::BuildClosureCallArgumentsValidCheck( TargetEntryInstr* equal; TargetEntryInstr* not_equal; check_type_args_length += BranchIfEqual(&equal, ¬_equal); - check_type_args_length.current = equal; // Continue in non-error case. - - // The function is not generic. - Fragment(null) + Goto(info.throw_no_such_method); // An incorrect number of type arguments were passed. Fragment(not_equal) + Goto(info.throw_no_such_method); - // Type arguments should not be provided if there are delayed type - // arguments, as then the closure itself is not generic. - check_entry += TestDelayedTypeArgs( - info.closure, /*present=*/Goto(info.throw_no_such_method), - /*absent=*/check_type_args_length); + check_entry.current = equal; // Continue in non-error case. } check_entry += LoadLocal(info.has_named_params); @@ -3424,7 +3444,7 @@ Fragment FlowGraphBuilder::BuildClosureCallTypeArgumentsTypeCheck( Fragment loop_call_check(call); // Load instantiators. - loop_call_check += LoadLocal(info.instantiator_type_args); + loop_call_check += LoadLocal(info.vars->instantiator_type_args); loop_call_check += LoadLocal(info.vars->function_type_args); // Load instantiated type parameter. loop_call_check += LoadLocal(info.vars->current_type_param); @@ -3471,7 +3491,7 @@ Fragment FlowGraphBuilder::BuildClosureCallArgumentTypeCheck( instructions += LoadIndexed( kArrayCid, /*index_scale*/ compiler::target::kCompressedWordSize); // Load instantiator type arguments. - instructions += LoadLocal(info.instantiator_type_args); + instructions += LoadLocal(info.vars->instantiator_type_args); // Load the full set of function type arguments. instructions += LoadLocal(info.vars->function_type_args); // Check that the value has the right type. @@ -3513,6 +3533,51 @@ Fragment FlowGraphBuilder::BuildClosureCallArgumentTypeChecks( return instructions; } +Fragment FlowGraphBuilder::BuildLoadDynamicClosureElement( + LocalVariable* closure, + LocalVariable* length_and_flags, + LocalVariable* result, + intptr_t present_mask, + intptr_t element_offset, + intptr_t index_mask, + intptr_t index_shift) { + Fragment instructions; + TargetEntryInstr *present, *absent; + JoinEntryInstr* done = BuildJoinEntry(); + + instructions += LoadLocal(length_and_flags); + instructions += IntConstant(present_mask); + instructions += SmiBinaryOp(Token::kBIT_AND); + instructions += IntConstant(0); + instructions += BranchIfEqual(&absent, &present); + + Fragment load(present); + load += LoadLocal(closure); + if (element_offset >= 0) { + load += + LoadNativeField(Slot::GetClosureElementSlot(thread_, element_offset)); + } else { + load += LoadLocal(length_and_flags); + load += IntConstant(index_mask); + load += SmiBinaryOp(Token::kBIT_AND); + load += IntConstant(index_shift); + load += SmiBinaryOp(Token::kSHR); + load += LoadIndexed(kClosureCid, compiler::target::kCompressedWordSize); + } + load += StoreLocal(result); + load += Drop(); + load += Goto(done); + + Fragment store_null(absent); + store_null += NullConstant(); + store_null += StoreLocal(result); + store_null += Drop(); + store_null += Goto(done); + + instructions.current = done; + return instructions; +} + Fragment FlowGraphBuilder::BuildDynamicClosureCallChecks( LocalVariable* closure) { ClosureCallInfo info(closure, BuildThrowNoSuchMethod(), @@ -3564,12 +3629,29 @@ Fragment FlowGraphBuilder::BuildDynamicClosureCallChecks( info.type_parameters = MakeTemporary("type_parameters"); body += LoadLocal(info.closure); - body += LoadNativeField(Slot::Closure_instantiator_type_arguments()); - info.instantiator_type_args = MakeTemporary("instantiator_type_args"); + body += LoadNativeField(Slot::Closure_length_and_flags()); + info.closure_length_and_flags = MakeTemporary("closure_length_and_flags"); - body += LoadLocal(info.closure); - body += LoadNativeField(Slot::Closure_function_type_arguments()); - info.parent_function_type_args = MakeTemporary("parent_function_type_args"); + body += BuildLoadDynamicClosureElement( + info.closure, info.closure_length_and_flags, + info.vars->instantiator_type_args, + UntaggedClosure::HasInstantiatorTypeArgumentsBit::mask_in_place(), -1, + UntaggedClosure::InstantiatorTypeArgumentsIndexBits::mask_in_place(), + UntaggedClosure::InstantiatorTypeArgumentsIndexBits::shift()); + + body += BuildLoadDynamicClosureElement( + info.closure, info.closure_length_and_flags, + info.vars->parent_function_type_args, + UntaggedClosure::HasFunctionTypeArgumentsBit::mask_in_place(), -1, + UntaggedClosure::FunctionTypeArgumentsIndexBits::mask_in_place(), + UntaggedClosure::FunctionTypeArgumentsIndexBits::shift()); + + body += BuildLoadDynamicClosureElement( + info.closure, info.closure_length_and_flags, info.vars->delayed_type_args, + UntaggedClosure::HasDelayedTypeArgumentsBit::mask_in_place(), + compiler::target::Closure::element_offset( + UntaggedClosure::kDelayedTypeArgumentsIndex), + 0, 0); // At this point, all the read-only temporaries stored in the ClosureCallInfo // should be either loaded or still nullptr, if not needed for this function. @@ -3580,7 +3662,7 @@ Fragment FlowGraphBuilder::BuildDynamicClosureCallChecks( // args. Thus, use whatever was stored for the parent function type arguments, // which has already been checked against any parent type parameter bounds. Fragment not_generic; - not_generic += LoadLocal(info.parent_function_type_args); + not_generic += LoadLocal(info.vars->parent_function_type_args); not_generic += StoreLocal(info.vars->function_type_args); not_generic += Drop(); @@ -3615,7 +3697,7 @@ Fragment FlowGraphBuilder::BuildDynamicClosureCallChecks( // Load the local function type args. generic += LoadLocal(info.vars->function_type_args); // Load the parent function type args. - generic += LoadLocal(info.parent_function_type_args); + generic += LoadLocal(info.vars->parent_function_type_args); // Load the number of parent type parameters. generic += LoadLocal(info.num_parent_type_args); // Load the number of total type parameters. @@ -3635,8 +3717,21 @@ Fragment FlowGraphBuilder::BuildDynamicClosureCallChecks( // the type system and need not be checked again at the call site. auto const check_bounds = BuildClosureCallTypeArgumentsTypeCheck(info); if (FLAG_eliminate_type_checks) { - generic += TestDelayedTypeArgs(info.closure, /*present=*/{}, - /*absent=*/check_bounds); + JoinEntryInstr* done = BuildJoinEntry(); + TargetEntryInstr *has_delayed_type_args, *no_delayed_type_args; + + generic += LoadLocal(info.vars->delayed_type_args); + generic += Constant(Object::empty_type_arguments()); + generic += BranchIfEqual(&no_delayed_type_args, &has_delayed_type_args); + + Fragment present(has_delayed_type_args); + present += Goto(done); + + Fragment absent(no_delayed_type_args); + absent += check_bounds; + absent += Goto(done); + + generic.current = done; } else { generic += check_bounds; } @@ -3653,8 +3748,7 @@ Fragment FlowGraphBuilder::BuildDynamicClosureCallChecks( body += BuildClosureCallArgumentTypeChecks(info); // Drop all the read-only temporaries at the end of the fragment. - body += DropTemporary(&info.parent_function_type_args); - body += DropTemporary(&info.instantiator_type_args); + body += DropTemporary(&info.closure_length_and_flags); body += DropTemporary(&info.type_parameters); body += DropTemporary(&info.parameter_types); body += DropTemporary(&info.named_parameter_names); @@ -4074,35 +4168,55 @@ Fragment FlowGraphBuilder::BuildDefaultTypeHandling(const Function& function) { // the closure object instead. LocalVariable* const closure = parsed_function_->ParameterVariable(0); auto const mode = function.default_type_arguments_instantiation_mode(); + const bool has_delayed_type_args = + Closure::HasDelayedTypeArgumentsField(function); + const bool has_instantiator_type_args = + Closure::HasInstantiatorTypeArgumentsField(function); + const bool has_function_type_args = + Closure::HasFunctionTypeArgumentsField(function); switch (mode) { case InstantiationMode::kIsInstantiated: use_defaults += Constant(default_types); break; case InstantiationMode::kSharesInstantiatorTypeArguments: + ASSERT(has_instantiator_type_args); use_defaults += LoadLocal(closure); - use_defaults += - LoadNativeField(Slot::Closure_instantiator_type_arguments()); + use_defaults += LoadNativeField(Slot::GetClosureElementSlot( + thread_, compiler::target::Closure::element_offset( + UntaggedClosure::InstantiatorTypeArgumentsIndex( + has_delayed_type_args)))); break; case InstantiationMode::kSharesFunctionTypeArguments: + ASSERT(has_function_type_args); use_defaults += LoadLocal(closure); - use_defaults += - LoadNativeField(Slot::Closure_function_type_arguments()); + use_defaults += LoadNativeField(Slot::GetClosureElementSlot( + thread_, + compiler::target::Closure::element_offset( + UntaggedClosure::FunctionTypeArgumentsIndex( + has_delayed_type_args, has_instantiator_type_args)))); break; case InstantiationMode::kNeedsInstantiation: // Only load the instantiator or function type arguments from the // closure if they're needed for instantiation. if (!default_types.IsInstantiated(kCurrentClass)) { + ASSERT(has_instantiator_type_args); use_defaults += LoadLocal(closure); - use_defaults += - LoadNativeField(Slot::Closure_instantiator_type_arguments()); + use_defaults += LoadNativeField(Slot::GetClosureElementSlot( + thread_, compiler::target::Closure::element_offset( + UntaggedClosure::InstantiatorTypeArgumentsIndex( + has_delayed_type_args)))); } else { use_defaults += NullConstant(); } - if (!default_types.IsInstantiated(kFunctions)) { + if (has_function_type_args && + !default_types.IsInstantiated(kFunctions)) { use_defaults += LoadLocal(closure); - use_defaults += - LoadNativeField(Slot::Closure_function_type_arguments()); + use_defaults += LoadNativeField(Slot::GetClosureElementSlot( + thread_, + compiler::target::Closure::element_offset( + UntaggedClosure::FunctionTypeArgumentsIndex( + has_delayed_type_args, has_instantiator_type_args)))); } else { use_defaults += NullConstant(); } @@ -4278,7 +4392,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfImplicitClosureFunction( } else if (!target.is_static()) { // The closure context is the receiver. closure += LoadLocal(parsed_function_->ParameterVariable(0)); - closure += LoadNativeField(Slot::Closure_context()); + closure += LoadNativeField(Slot::GetClosureContextSlot(thread_, function)); } closure += PushExplicitParameters(function); diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h index b0959862ee6..e3528dbfafd 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.h +++ b/runtime/vm/compiler/frontend/kernel_to_il.h @@ -145,6 +145,21 @@ class FlowGraphBuilder : public BaseFlowGraphBuilder { // information for the function retrieved at runtime from the closure. Fragment BuildClosureCallArgumentTypeChecks(const ClosureCallInfo& info); + // Generate fragment which loads an optional element from an unknown closure. + // + // 1) Test if element is present: ([length_and_flags] & [present_mask]) != 0. + // 2a) If present and [element_offset] >= 0, then load element using offset. + // 2b) If present and [element_offset] < 0, then load element using + // ([length_and_flags] & [index_mask] >> [index_shift]) index. + // 3) If element is absent, the [result] is set to null. + Fragment BuildLoadDynamicClosureElement(LocalVariable* closure, + LocalVariable* length_and_flags, + LocalVariable* result, + intptr_t present_mask, + intptr_t element_offset, + intptr_t index_mask, + intptr_t index_shift); + // Main entry point for building checks. Fragment BuildDynamicClosureCallChecks(LocalVariable* closure); diff --git a/runtime/vm/compiler/frontend/prologue_builder.cc b/runtime/vm/compiler/frontend/prologue_builder.cc index e8b88bec096..7a20e28df1d 100644 --- a/runtime/vm/compiler/frontend/prologue_builder.cc +++ b/runtime/vm/compiler/frontend/prologue_builder.cc @@ -326,6 +326,8 @@ Fragment PrologueBuilder::BuildParameterHandling() { } Fragment PrologueBuilder::BuildClosureContextHandling() { + const auto& function = parsed_function_->function(); + ASSERT(function.IsClosureFunction()); LocalVariable* closure_parameter = parsed_function_->ParameterVariable(0); LocalVariable* context = parsed_function_->current_context_var(); @@ -333,7 +335,8 @@ Fragment PrologueBuilder::BuildClosureContextHandling() { // (both load/store happen on the copied-down places). Fragment populate_context; populate_context += LoadLocal(closure_parameter); - populate_context += LoadNativeField(Slot::Closure_context()); + populate_context += + LoadNativeField(Slot::GetClosureContextSlot(thread_, function)); populate_context += StoreLocal(TokenPosition::kNoSource, context); populate_context += Drop(); return populate_context; @@ -368,7 +371,7 @@ Fragment PrologueBuilder::BuildTypeArgumentsHandling() { Fragment PrologueBuilder::BuildClosureDelayedTypeArgumentsHandling() { const auto& function = parsed_function_->function(); - ASSERT(function.IsClosureFunction()); + ASSERT(function.IsClosureFunction() && function.IsGeneric()); LocalVariable* const type_args_var = parsed_function_->RawTypeArgumentsVariable(); ASSERT(type_args_var != nullptr); @@ -380,8 +383,9 @@ Fragment PrologueBuilder::BuildClosureDelayedTypeArgumentsHandling() { // correct in number and bound. Fragment use_delayed_type_args; use_delayed_type_args += LoadLocal(closure); - use_delayed_type_args += - LoadNativeField(Slot::Closure_delayed_type_arguments()); + use_delayed_type_args += LoadNativeField(Slot::GetClosureElementSlot( + thread_, compiler::target::Closure::element_offset( + UntaggedClosure::kDelayedTypeArgumentsIndex))); use_delayed_type_args += StoreLocal(TokenPosition::kNoSource, type_args_var); use_delayed_type_args += Drop(); diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h index acc216892b9..da396614b09 100644 --- a/runtime/vm/compiler/recognized_methods_list.h +++ b/runtime/vm/compiler/recognized_methods_list.h @@ -40,6 +40,7 @@ namespace dart { V(CoreLibrary, _GrowableList, []=, GrowableArraySetIndexed, 0x3a23c6fa) \ V(CoreLibrary, _GrowableList, get:_emptyList, GrowableArrayGetEmptyList, \ 0x735785f0) \ + V(CoreLibrary, _Closure, get:_hash, Closure_hash, 0x6e92d1d5) \ V(CoreLibrary, _Record, get:_fieldNames, Record_fieldNames, 0x68c8319e) \ V(CoreLibrary, _Record, get:_numFields, Record_numFields, 0x7ba4f393) \ V(CoreLibrary, _Record, get:_shape, Record_shape, 0x70c40933) \ diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc index c6836154958..c2f9fb6b297 100644 --- a/runtime/vm/compiler/runtime_api.cc +++ b/runtime/vm/compiler/runtime_api.cc @@ -422,8 +422,6 @@ static uword GetInstanceSizeImpl(const dart::Class& handle) { return Instance::InstanceSize(); case kGrowableObjectArrayCid: return GrowableObjectArray::InstanceSize(); - case kClosureCid: - return Closure::InstanceSize(); case kTypedDataBaseCid: return TypedDataBase::InstanceSize(); case kMapCid: @@ -517,6 +515,8 @@ word Instance::DataOffsetFor(intptr_t cid) { case kArrayCid: case kImmutableArrayCid: return Array::data_offset(); + case kClosureCid: + return Closure::element_offset(0); case kTypeArgumentsCid: return TypeArguments::types_offset(); case kOneByteStringCid: @@ -1020,6 +1020,15 @@ intptr_t Array::index_at_offset(intptr_t offset_in_bytes) { TranslateOffsetInWordsToHost(offset_in_bytes)); } +intptr_t Closure::element_index_at_offset(intptr_t offset_in_bytes) { + // Note: cannot delegate to dart::Closure::element_index_at_offset as + // Closure layout is different between AOT and precompiler. + const intptr_t index = + (offset_in_bytes - Closure::element_offset(0)) / kCompressedWordSize; + ASSERT(index >= 0); + return index; +} + intptr_t Record::field_index_at_offset(intptr_t offset_in_bytes) { return dart::Record::field_index_at_offset( TranslateOffsetInWordsToHost(offset_in_bytes)); diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h index 3dee1476a78..4136b328c48 100644 --- a/runtime/vm/compiler/runtime_api.h +++ b/runtime/vm/compiler/runtime_api.h @@ -429,6 +429,16 @@ class UntaggedObject : public AllStatic { static bool IsTypedDataClassId(intptr_t cid); }; +class UntaggedClosure : public AllStatic { + static const word kHasDelayedTypeArgumentsBit; + static const word kHasInstantiatorTypeArgumentsBit; + static const word kHasFunctionTypeArgumentsBit; + static const word kFunctionTypeArgumentsIndexBitsPos; + static const word kFunctionTypeArgumentsIndexBitsSize; + static const word kLengthBitsPos; + static const word kLengthBitsSize; +}; + class UntaggedAbstractType : public AllStatic { public: static const word kTypeStateFinalizedInstantiated; @@ -1472,13 +1482,13 @@ class Context : public AllStatic { class Closure : public AllStatic { public: - static word context_offset(); - static word delayed_type_arguments_offset(); static word entry_point_offset(); static word function_offset(); - static word function_type_arguments_offset(); - static word instantiator_type_arguments_offset(); static word hash_offset(); + static word length_and_flags_offset(); + static word element_offset(intptr_t index); + static intptr_t element_index_at_offset(intptr_t offset_in_bytes); + static word InstanceSize(intptr_t length); static word InstanceSize(); FINAL_CLASS(); }; diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h index d791ef72830..c26d7a9f2a3 100644 --- a/runtime/vm/compiler/runtime_offsets_extracted.h +++ b/runtime/vm/compiler/runtime_offsets_extracted.h @@ -30,6 +30,9 @@ static constexpr dart::compiler::target::word Array_element_size = 0x4; static constexpr dart::compiler::target::word ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x10; +static constexpr dart::compiler::target::word Closure_element_size = 0x4; static constexpr dart::compiler::target::word Code_elements_start_offset = 0x60; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -119,6 +122,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x19; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -180,15 +197,10 @@ static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0x6c; static constexpr dart::compiler::target::word ClassTable_allocation_tracing_state_table_offset = 0x4; -static constexpr dart::compiler::target::word Closure_context_offset = 0x14; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word Closure_function_offset = 0x10; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0x8; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x18; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x4; +static constexpr dart::compiler::target::word Closure_function_offset = 0xc; +static constexpr dart::compiler::target::word Closure_hash_offset = 0x8; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x4; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x10; static constexpr dart::compiler::target::word Code_instructions_offset = 0x18; @@ -668,7 +680,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x8; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x38; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0x78; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x1c; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x14; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x8; static constexpr dart::compiler::target::word @@ -781,6 +792,9 @@ static constexpr dart::compiler::target::word Array_element_size = 0x8; static constexpr dart::compiler::target::word ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x20; +static constexpr dart::compiler::target::word Closure_element_size = 0x8; static constexpr dart::compiler::target::word Code_elements_start_offset = 0xb0; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -873,6 +887,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0x7ffffffffffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x39; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -937,15 +965,10 @@ static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0xbc; static constexpr dart::compiler::target::word ClassTable_allocation_tracing_state_table_offset = 0x8; -static constexpr dart::compiler::target::word Closure_context_offset = 0x28; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0x18; -static constexpr dart::compiler::target::word Closure_function_offset = 0x20; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x30; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x8; +static constexpr dart::compiler::target::word Closure_function_offset = 0x18; +static constexpr dart::compiler::target::word Closure_hash_offset = 0x10; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x8; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x20; static constexpr dart::compiler::target::word Code_instructions_offset = 0x30; @@ -1430,7 +1453,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x10; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x60; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0xc8; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x38; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x28; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x10; static constexpr dart::compiler::target::word @@ -1543,6 +1565,9 @@ static constexpr dart::compiler::target::word Array_element_size = 0x4; static constexpr dart::compiler::target::word ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x10; +static constexpr dart::compiler::target::word Closure_element_size = 0x4; static constexpr dart::compiler::target::word Code_elements_start_offset = 0x60; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -1632,6 +1657,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x19; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -1693,15 +1732,10 @@ static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0x6c; static constexpr dart::compiler::target::word ClassTable_allocation_tracing_state_table_offset = 0x4; -static constexpr dart::compiler::target::word Closure_context_offset = 0x14; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word Closure_function_offset = 0x10; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0x8; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x18; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x4; +static constexpr dart::compiler::target::word Closure_function_offset = 0xc; +static constexpr dart::compiler::target::word Closure_hash_offset = 0x8; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x4; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x10; static constexpr dart::compiler::target::word Code_instructions_offset = 0x18; @@ -2180,7 +2214,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x8; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x38; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0x78; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x1c; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x14; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x8; static constexpr dart::compiler::target::word @@ -2293,6 +2326,9 @@ static constexpr dart::compiler::target::word Array_element_size = 0x8; static constexpr dart::compiler::target::word ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x20; +static constexpr dart::compiler::target::word Closure_element_size = 0x8; static constexpr dart::compiler::target::word Code_elements_start_offset = 0xb0; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -2385,6 +2421,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0x7ffffffffffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x39; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -2449,15 +2499,10 @@ static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0xbc; static constexpr dart::compiler::target::word ClassTable_allocation_tracing_state_table_offset = 0x8; -static constexpr dart::compiler::target::word Closure_context_offset = 0x28; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0x18; -static constexpr dart::compiler::target::word Closure_function_offset = 0x20; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x30; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x8; +static constexpr dart::compiler::target::word Closure_function_offset = 0x18; +static constexpr dart::compiler::target::word Closure_hash_offset = 0x10; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x8; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x20; static constexpr dart::compiler::target::word Code_instructions_offset = 0x30; @@ -2944,7 +2989,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x10; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x60; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0xc8; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x38; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x28; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x10; static constexpr dart::compiler::target::word @@ -3058,6 +3102,9 @@ static constexpr dart::compiler::target::word Array_element_size = 0x4; static constexpr dart::compiler::target::word ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x18; +static constexpr dart::compiler::target::word Closure_element_size = 0x4; static constexpr dart::compiler::target::word Code_elements_start_offset = 0xb0; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -3147,6 +3194,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x19; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -3211,15 +3272,10 @@ static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0x70; static constexpr dart::compiler::target::word ClassTable_allocation_tracing_state_table_offset = 0x8; -static constexpr dart::compiler::target::word Closure_context_offset = 0x18; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word Closure_function_offset = 0x14; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x1c; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x8; +static constexpr dart::compiler::target::word Closure_function_offset = 0x10; +static constexpr dart::compiler::target::word Closure_hash_offset = 0xc; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x8; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x14; static constexpr dart::compiler::target::word Code_instructions_offset = 0x30; @@ -3703,7 +3759,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x10; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x48; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0x80; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x20; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x18; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x10; static constexpr dart::compiler::target::word @@ -3817,6 +3872,9 @@ static constexpr dart::compiler::target::word Array_element_size = 0x4; static constexpr dart::compiler::target::word ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x18; +static constexpr dart::compiler::target::word Closure_element_size = 0x4; static constexpr dart::compiler::target::word Code_elements_start_offset = 0xb0; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -3906,6 +3964,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x19; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -3970,15 +4042,10 @@ static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0x70; static constexpr dart::compiler::target::word ClassTable_allocation_tracing_state_table_offset = 0x8; -static constexpr dart::compiler::target::word Closure_context_offset = 0x18; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word Closure_function_offset = 0x14; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x1c; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x8; +static constexpr dart::compiler::target::word Closure_function_offset = 0x10; +static constexpr dart::compiler::target::word Closure_hash_offset = 0xc; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x8; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x14; static constexpr dart::compiler::target::word Code_instructions_offset = 0x30; @@ -4464,7 +4531,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x10; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x48; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0x80; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x20; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x18; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x10; static constexpr dart::compiler::target::word @@ -4577,6 +4643,9 @@ static constexpr dart::compiler::target::word Array_element_size = 0x4; static constexpr dart::compiler::target::word ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x10; +static constexpr dart::compiler::target::word Closure_element_size = 0x4; static constexpr dart::compiler::target::word Code_elements_start_offset = 0x60; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -4666,6 +4735,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x19; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -4727,15 +4810,10 @@ static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0x6c; static constexpr dart::compiler::target::word ClassTable_allocation_tracing_state_table_offset = 0x4; -static constexpr dart::compiler::target::word Closure_context_offset = 0x14; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word Closure_function_offset = 0x10; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0x8; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x18; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x4; +static constexpr dart::compiler::target::word Closure_function_offset = 0xc; +static constexpr dart::compiler::target::word Closure_hash_offset = 0x8; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x4; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x10; static constexpr dart::compiler::target::word Code_instructions_offset = 0x18; @@ -5216,7 +5294,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x8; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x38; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0x78; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x1c; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x14; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x8; static constexpr dart::compiler::target::word @@ -5329,6 +5406,9 @@ static constexpr dart::compiler::target::word Array_element_size = 0x8; static constexpr dart::compiler::target::word ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x20; +static constexpr dart::compiler::target::word Closure_element_size = 0x8; static constexpr dart::compiler::target::word Code_elements_start_offset = 0xb0; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -5421,6 +5501,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0x7ffffffffffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x39; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -5485,15 +5579,10 @@ static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0xbc; static constexpr dart::compiler::target::word ClassTable_allocation_tracing_state_table_offset = 0x8; -static constexpr dart::compiler::target::word Closure_context_offset = 0x28; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0x18; -static constexpr dart::compiler::target::word Closure_function_offset = 0x20; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x30; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x8; +static constexpr dart::compiler::target::word Closure_function_offset = 0x18; +static constexpr dart::compiler::target::word Closure_hash_offset = 0x10; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x8; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x20; static constexpr dart::compiler::target::word Code_instructions_offset = 0x30; @@ -5979,7 +6068,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x10; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x60; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0xc8; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x38; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x28; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x10; static constexpr dart::compiler::target::word @@ -6089,6 +6177,9 @@ static constexpr dart::compiler::target::word SuspendState_frame_capacity_offset = 0x4; static constexpr dart::compiler::target::word Array_elements_start_offset = 0xc; static constexpr dart::compiler::target::word Array_element_size = 0x4; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x10; +static constexpr dart::compiler::target::word Closure_element_size = 0x4; static constexpr dart::compiler::target::word Code_elements_start_offset = 0x4c; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -6178,6 +6269,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x19; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -6237,15 +6342,10 @@ static constexpr dart::compiler::target::word Class_num_type_arguments_offset = static constexpr dart::compiler::target::word Class_super_type_offset = 0x28; static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0x68; -static constexpr dart::compiler::target::word Closure_context_offset = 0x14; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word Closure_function_offset = 0x10; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0x8; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x18; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x4; +static constexpr dart::compiler::target::word Closure_function_offset = 0xc; +static constexpr dart::compiler::target::word Closure_hash_offset = 0x8; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x4; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x10; static constexpr dart::compiler::target::word Code_instructions_offset = 0x18; @@ -6722,7 +6822,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x8; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x30; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0x74; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x1c; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x14; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x8; static constexpr dart::compiler::target::word @@ -6832,6 +6931,9 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word Array_elements_start_offset = 0x18; static constexpr dart::compiler::target::word Array_element_size = 0x8; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x20; +static constexpr dart::compiler::target::word Closure_element_size = 0x8; static constexpr dart::compiler::target::word Code_elements_start_offset = 0x90; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -6924,6 +7026,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0x7ffffffffffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x39; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -6986,15 +7102,10 @@ static constexpr dart::compiler::target::word Class_num_type_arguments_offset = static constexpr dart::compiler::target::word Class_super_type_offset = 0x50; static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0xb4; -static constexpr dart::compiler::target::word Closure_context_offset = 0x28; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0x18; -static constexpr dart::compiler::target::word Closure_function_offset = 0x20; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x30; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x8; +static constexpr dart::compiler::target::word Closure_function_offset = 0x18; +static constexpr dart::compiler::target::word Closure_hash_offset = 0x10; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x8; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x20; static constexpr dart::compiler::target::word Code_instructions_offset = 0x30; @@ -7476,7 +7587,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x10; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x58; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0xc0; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x38; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x28; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x10; static constexpr dart::compiler::target::word @@ -7586,6 +7696,9 @@ static constexpr dart::compiler::target::word SuspendState_frame_capacity_offset = 0x4; static constexpr dart::compiler::target::word Array_elements_start_offset = 0xc; static constexpr dart::compiler::target::word Array_element_size = 0x4; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x10; +static constexpr dart::compiler::target::word Closure_element_size = 0x4; static constexpr dart::compiler::target::word Code_elements_start_offset = 0x4c; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -7675,6 +7788,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x19; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -7734,15 +7861,10 @@ static constexpr dart::compiler::target::word Class_num_type_arguments_offset = static constexpr dart::compiler::target::word Class_super_type_offset = 0x28; static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0x68; -static constexpr dart::compiler::target::word Closure_context_offset = 0x14; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word Closure_function_offset = 0x10; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0x8; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x18; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x4; +static constexpr dart::compiler::target::word Closure_function_offset = 0xc; +static constexpr dart::compiler::target::word Closure_hash_offset = 0x8; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x4; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x10; static constexpr dart::compiler::target::word Code_instructions_offset = 0x18; @@ -8218,7 +8340,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x8; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x30; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0x74; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x1c; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x14; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x8; static constexpr dart::compiler::target::word @@ -8328,6 +8449,9 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word Array_elements_start_offset = 0x18; static constexpr dart::compiler::target::word Array_element_size = 0x8; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x20; +static constexpr dart::compiler::target::word Closure_element_size = 0x8; static constexpr dart::compiler::target::word Code_elements_start_offset = 0x90; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -8420,6 +8544,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0x7ffffffffffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x39; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -8482,15 +8620,10 @@ static constexpr dart::compiler::target::word Class_num_type_arguments_offset = static constexpr dart::compiler::target::word Class_super_type_offset = 0x50; static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0xb4; -static constexpr dart::compiler::target::word Closure_context_offset = 0x28; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0x18; -static constexpr dart::compiler::target::word Closure_function_offset = 0x20; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x30; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x8; +static constexpr dart::compiler::target::word Closure_function_offset = 0x18; +static constexpr dart::compiler::target::word Closure_hash_offset = 0x10; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x8; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x20; static constexpr dart::compiler::target::word Code_instructions_offset = 0x30; @@ -8974,7 +9107,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x10; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x58; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0xc0; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x38; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x28; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x10; static constexpr dart::compiler::target::word @@ -9085,6 +9217,9 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word Array_elements_start_offset = 0x10; static constexpr dart::compiler::target::word Array_element_size = 0x4; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x18; +static constexpr dart::compiler::target::word Closure_element_size = 0x4; static constexpr dart::compiler::target::word Code_elements_start_offset = 0x90; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -9174,6 +9309,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x19; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -9236,15 +9385,10 @@ static constexpr dart::compiler::target::word Class_num_type_arguments_offset = static constexpr dart::compiler::target::word Class_super_type_offset = 0x2c; static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0x6c; -static constexpr dart::compiler::target::word Closure_context_offset = 0x18; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word Closure_function_offset = 0x14; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x1c; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x8; +static constexpr dart::compiler::target::word Closure_function_offset = 0x10; +static constexpr dart::compiler::target::word Closure_hash_offset = 0xc; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x8; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x14; static constexpr dart::compiler::target::word Code_instructions_offset = 0x30; @@ -9725,7 +9869,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x10; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x40; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0x78; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x20; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x18; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x10; static constexpr dart::compiler::target::word @@ -9836,6 +9979,9 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word Array_elements_start_offset = 0x10; static constexpr dart::compiler::target::word Array_element_size = 0x4; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x18; +static constexpr dart::compiler::target::word Closure_element_size = 0x4; static constexpr dart::compiler::target::word Code_elements_start_offset = 0x90; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -9925,6 +10071,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x19; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -9987,15 +10147,10 @@ static constexpr dart::compiler::target::word Class_num_type_arguments_offset = static constexpr dart::compiler::target::word Class_super_type_offset = 0x2c; static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0x6c; -static constexpr dart::compiler::target::word Closure_context_offset = 0x18; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word Closure_function_offset = 0x14; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x1c; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x8; +static constexpr dart::compiler::target::word Closure_function_offset = 0x10; +static constexpr dart::compiler::target::word Closure_hash_offset = 0xc; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x8; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x14; static constexpr dart::compiler::target::word Code_instructions_offset = 0x30; @@ -10478,7 +10633,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x10; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x40; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0x78; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x20; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x18; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x10; static constexpr dart::compiler::target::word @@ -10588,6 +10742,9 @@ static constexpr dart::compiler::target::word SuspendState_frame_capacity_offset = 0x4; static constexpr dart::compiler::target::word Array_elements_start_offset = 0xc; static constexpr dart::compiler::target::word Array_element_size = 0x4; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x10; +static constexpr dart::compiler::target::word Closure_element_size = 0x4; static constexpr dart::compiler::target::word Code_elements_start_offset = 0x4c; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -10677,6 +10834,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x19; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -10736,15 +10907,10 @@ static constexpr dart::compiler::target::word Class_num_type_arguments_offset = static constexpr dart::compiler::target::word Class_super_type_offset = 0x28; static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0x68; -static constexpr dart::compiler::target::word Closure_context_offset = 0x14; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word Closure_function_offset = 0x10; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0x8; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x18; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x4; +static constexpr dart::compiler::target::word Closure_function_offset = 0xc; +static constexpr dart::compiler::target::word Closure_hash_offset = 0x8; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x4; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x10; static constexpr dart::compiler::target::word Code_instructions_offset = 0x18; @@ -11222,7 +11388,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x8; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x30; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0x74; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x1c; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x14; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x8; static constexpr dart::compiler::target::word @@ -11332,6 +11497,9 @@ static constexpr dart::compiler::target::word static constexpr dart::compiler::target::word Array_elements_start_offset = 0x18; static constexpr dart::compiler::target::word Array_element_size = 0x8; +static constexpr dart::compiler::target::word Closure_elements_start_offset = + 0x20; +static constexpr dart::compiler::target::word Closure_element_size = 0x8; static constexpr dart::compiler::target::word Code_elements_start_offset = 0x90; static constexpr dart::compiler::target::word Code_element_size = 0x4; static constexpr dart::compiler::target::word Context_elements_start_offset = @@ -11424,6 +11592,20 @@ static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word TypeArguments_kMaxElements = 0x7ffffffffffffff; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsPos = + 0x5; +static constexpr dart::compiler::target::word UntaggedClosure_kLengthBitsSize = + 0x39; static constexpr dart::compiler::target::word UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word UntaggedObject_kCanonicalBit = @@ -11486,15 +11668,10 @@ static constexpr dart::compiler::target::word Class_num_type_arguments_offset = static constexpr dart::compiler::target::word Class_super_type_offset = 0x50; static constexpr dart::compiler::target::word Class_host_type_arguments_field_offset_in_words_offset = 0xb4; -static constexpr dart::compiler::target::word Closure_context_offset = 0x28; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 0x18; -static constexpr dart::compiler::target::word Closure_function_offset = 0x20; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word Closure_hash_offset = 0x30; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 0x8; +static constexpr dart::compiler::target::word Closure_function_offset = 0x18; +static constexpr dart::compiler::target::word Closure_hash_offset = 0x10; +static constexpr dart::compiler::target::word Closure_length_and_flags_offset = + 0x8; static constexpr dart::compiler::target::word ClosureData_packed_fields_offset = 0x20; static constexpr dart::compiler::target::word Code_instructions_offset = 0x30; @@ -11977,7 +12154,6 @@ static constexpr dart::compiler::target::word Bool_InstanceSize = 0x10; static constexpr dart::compiler::target::word Bytecode_InstanceSize = 0x58; static constexpr dart::compiler::target::word Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word Class_InstanceSize = 0xc0; -static constexpr dart::compiler::target::word Closure_InstanceSize = 0x38; static constexpr dart::compiler::target::word ClosureData_InstanceSize = 0x28; static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 0x10; static constexpr dart::compiler::target::word @@ -12078,13 +12254,16 @@ static constexpr dart::compiler::target::word #if !defined(PRODUCT) && defined(TARGET_ARCH_ARM) && \ !defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x1c; + 0x4; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0xc; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x4; static constexpr dart::compiler::target::word AOT_ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word AOT_ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x14; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x4; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x58; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -12183,6 +12362,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x19; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -12250,16 +12443,11 @@ static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0x58; static constexpr dart::compiler::target::word AOT_ClassTable_allocation_tracing_state_table_offset = 0x4; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x14; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0xc; static constexpr dart::compiler::target::word AOT_Closure_function_offset = 0x10; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0xc; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0x8; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x18; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x4; + AOT_Closure_length_and_flags_offset = 0x8; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x10; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -12793,7 +12981,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x30; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0x60; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x20; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x14; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = @@ -12914,13 +13101,16 @@ static constexpr dart::compiler::target::word #if !defined(PRODUCT) && defined(TARGET_ARCH_X64) && \ !defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x38; + 0x8; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0x18; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x8; static constexpr dart::compiler::target::word AOT_ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word AOT_ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x28; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x8; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x98; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -13019,6 +13209,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0x7ffffffffffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x39; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -13090,16 +13294,11 @@ static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0xa0; static constexpr dart::compiler::target::word AOT_ClassTable_allocation_tracing_state_table_offset = 0x8; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x28; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0x18; static constexpr dart::compiler::target::word AOT_Closure_function_offset = 0x20; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x18; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x30; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x8; + AOT_Closure_length_and_flags_offset = 0x10; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x20; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -13633,7 +13832,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x58; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0xa8; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x40; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x28; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = @@ -13761,13 +13959,16 @@ static constexpr dart::compiler::target::word #if !defined(PRODUCT) && defined(TARGET_ARCH_ARM64) && \ !defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x38; + 0x8; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0x18; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x8; static constexpr dart::compiler::target::word AOT_ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word AOT_ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x28; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x8; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x98; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -13866,6 +14067,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0x7ffffffffffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x39; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -13937,16 +14152,11 @@ static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0xa0; static constexpr dart::compiler::target::word AOT_ClassTable_allocation_tracing_state_table_offset = 0x8; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x28; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0x18; static constexpr dart::compiler::target::word AOT_Closure_function_offset = 0x20; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x18; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x30; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x8; + AOT_Closure_length_and_flags_offset = 0x10; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x20; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -14482,7 +14692,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x58; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0xa8; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x40; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x28; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = @@ -14604,13 +14813,16 @@ static constexpr dart::compiler::target::word #if !defined(PRODUCT) && defined(TARGET_ARCH_X64) && \ defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x20; + 0x8; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0x10; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x4; static constexpr dart::compiler::target::word AOT_ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word AOT_ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x20; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x4; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x98; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -14709,6 +14921,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x19; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -14780,16 +15006,11 @@ static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0x5c; static constexpr dart::compiler::target::word AOT_ClassTable_allocation_tracing_state_table_offset = 0x8; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x18; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0x10; static constexpr dart::compiler::target::word AOT_Closure_function_offset = - 0x14; + 0x18; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x14; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x1c; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x8; + AOT_Closure_length_and_flags_offset = 0x10; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x14; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -15325,7 +15546,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x40; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0x68; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x28; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x18; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = @@ -15447,13 +15667,16 @@ static constexpr dart::compiler::target::word #if !defined(PRODUCT) && defined(TARGET_ARCH_ARM64) && \ defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x20; + 0x8; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0x10; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x4; static constexpr dart::compiler::target::word AOT_ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word AOT_ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x20; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x4; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x98; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -15552,6 +15775,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x19; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -15623,16 +15860,11 @@ static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0x5c; static constexpr dart::compiler::target::word AOT_ClassTable_allocation_tracing_state_table_offset = 0x8; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x18; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0x10; static constexpr dart::compiler::target::word AOT_Closure_function_offset = - 0x14; + 0x18; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x14; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x1c; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x8; + AOT_Closure_length_and_flags_offset = 0x10; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x14; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -16170,7 +16402,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x40; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0x68; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x28; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x18; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = @@ -16292,13 +16523,16 @@ static constexpr dart::compiler::target::word #if !defined(PRODUCT) && defined(TARGET_ARCH_RISCV32) && \ !defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x1c; + 0x4; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0xc; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x4; static constexpr dart::compiler::target::word AOT_ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word AOT_ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x14; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x4; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x58; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -16397,6 +16631,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x19; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -16464,16 +16712,11 @@ static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0x58; static constexpr dart::compiler::target::word AOT_ClassTable_allocation_tracing_state_table_offset = 0x4; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x14; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0xc; static constexpr dart::compiler::target::word AOT_Closure_function_offset = 0x10; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0xc; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0x8; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x18; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x4; + AOT_Closure_length_and_flags_offset = 0x8; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x10; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -17008,7 +17251,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x30; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0x60; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x20; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x14; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = @@ -17129,13 +17371,16 @@ static constexpr dart::compiler::target::word #if !defined(PRODUCT) && defined(TARGET_ARCH_RISCV64) && \ !defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x38; + 0x8; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0x18; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x8; static constexpr dart::compiler::target::word AOT_ClassTable_elements_start_offset = 0x0; static constexpr dart::compiler::target::word AOT_ClassTable_element_size = 0x1; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x28; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x8; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x98; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -17234,6 +17479,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0x7ffffffffffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x39; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -17305,16 +17564,11 @@ static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0xa0; static constexpr dart::compiler::target::word AOT_ClassTable_allocation_tracing_state_table_offset = 0x8; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x28; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0x18; static constexpr dart::compiler::target::word AOT_Closure_function_offset = 0x20; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x18; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x30; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x8; + AOT_Closure_length_and_flags_offset = 0x10; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x20; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -17849,7 +18103,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x58; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0xa8; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x40; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x28; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = @@ -17971,10 +18224,13 @@ static constexpr dart::compiler::target::word #if defined(PRODUCT) && defined(TARGET_ARCH_ARM) && \ !defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x1c; + 0x4; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0xc; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x4; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x14; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x4; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x40; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -18073,6 +18329,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x19; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -18138,16 +18408,11 @@ static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 0x28; static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0x4c; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x14; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0xc; static constexpr dart::compiler::target::word AOT_Closure_function_offset = 0x10; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0xc; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0x8; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x18; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x4; + AOT_Closure_length_and_flags_offset = 0x8; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x10; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -18677,7 +18942,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x30; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0x54; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x20; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x14; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = @@ -18798,10 +19062,13 @@ static constexpr dart::compiler::target::word #if defined(PRODUCT) && defined(TARGET_ARCH_X64) && \ !defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x38; + 0x8; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0x18; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x8; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x28; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x8; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x78; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -18900,6 +19167,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0x7ffffffffffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x39; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -18969,16 +19250,11 @@ static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 0x50; static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0x88; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x28; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0x18; static constexpr dart::compiler::target::word AOT_Closure_function_offset = 0x20; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x18; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x30; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x8; + AOT_Closure_length_and_flags_offset = 0x10; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x20; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -19508,7 +19784,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x58; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0x90; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x40; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x28; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = @@ -19636,10 +19911,13 @@ static constexpr dart::compiler::target::word #if defined(PRODUCT) && defined(TARGET_ARCH_ARM64) && \ !defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x38; + 0x8; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0x18; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x8; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x28; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x8; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x78; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -19738,6 +20016,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0x7ffffffffffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x39; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -19807,16 +20099,11 @@ static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 0x50; static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0x88; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x28; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0x18; static constexpr dart::compiler::target::word AOT_Closure_function_offset = 0x20; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x18; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x30; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x8; + AOT_Closure_length_and_flags_offset = 0x10; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x20; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -20348,7 +20635,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x58; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0x90; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x40; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x28; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = @@ -20470,10 +20756,13 @@ static constexpr dart::compiler::target::word #if defined(PRODUCT) && defined(TARGET_ARCH_X64) && \ defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x20; + 0x8; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0x10; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x4; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x20; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x4; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x78; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -20572,6 +20861,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x19; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -20641,16 +20944,11 @@ static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 0x2c; static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0x50; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x18; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0x10; static constexpr dart::compiler::target::word AOT_Closure_function_offset = - 0x14; + 0x18; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x14; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x1c; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x8; + AOT_Closure_length_and_flags_offset = 0x10; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x14; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -21182,7 +21480,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x40; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0x58; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x28; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x18; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = @@ -21304,10 +21601,13 @@ static constexpr dart::compiler::target::word #if defined(PRODUCT) && defined(TARGET_ARCH_ARM64) && \ defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x20; + 0x8; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0x10; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x4; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x20; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x4; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x78; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -21406,6 +21706,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x19; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -21475,16 +21789,11 @@ static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 0x2c; static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0x50; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x18; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0x10; static constexpr dart::compiler::target::word AOT_Closure_function_offset = - 0x14; + 0x18; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x14; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0xc; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x1c; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x8; + AOT_Closure_length_and_flags_offset = 0x10; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x14; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -22018,7 +22327,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x40; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0x58; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x28; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x18; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = @@ -22140,10 +22448,13 @@ static constexpr dart::compiler::target::word #if defined(PRODUCT) && defined(TARGET_ARCH_RISCV32) && \ !defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x1c; + 0x4; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0xc; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x4; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x14; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x4; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x40; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -22242,6 +22553,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0xfffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x19; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -22307,16 +22632,11 @@ static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 0x28; static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0x4c; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x14; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0xc; static constexpr dart::compiler::target::word AOT_Closure_function_offset = 0x10; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0xc; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0x8; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x18; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x4; + AOT_Closure_length_and_flags_offset = 0x8; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x10; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -22847,7 +23167,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x30; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0x54; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x20; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x14; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = @@ -22968,10 +23287,13 @@ static constexpr dart::compiler::target::word #if defined(PRODUCT) && defined(TARGET_ARCH_RISCV64) && \ !defined(DART_COMPRESSED_POINTERS) static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset = - 0x38; + 0x8; static constexpr dart::compiler::target::word AOT_Array_elements_start_offset = 0x18; static constexpr dart::compiler::target::word AOT_Array_element_size = 0x8; +static constexpr dart::compiler::target::word + AOT_Closure_elements_start_offset = 0x28; +static constexpr dart::compiler::target::word AOT_Closure_element_size = 0x8; static constexpr dart::compiler::target::word AOT_Code_elements_start_offset = 0x78; static constexpr dart::compiler::target::word AOT_Code_element_size = 0x4; @@ -23070,6 +23392,20 @@ static constexpr dart::compiler::target::word AOT_SubtypeTestCache_kTestResult = 0x7; static constexpr dart::compiler::target::word AOT_TypeArguments_kMaxElements = 0x7ffffffffffffff; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasDelayedTypeArgumentsBit = 0x0; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasInstantiatorTypeArgumentsBit = 0x1; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kHasFunctionTypeArgumentsBit = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos = 0x3; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize = 0x2; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsPos = 0x5; +static constexpr dart::compiler::target::word + AOT_UntaggedClosure_kLengthBitsSize = 0x39; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCardRememberedBit = 0x0; static constexpr dart::compiler::target::word AOT_UntaggedObject_kCanonicalBit = @@ -23139,16 +23475,11 @@ static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 0x50; static constexpr dart::compiler::target::word AOT_Class_host_type_arguments_field_offset_in_words_offset = 0x88; -static constexpr dart::compiler::target::word AOT_Closure_context_offset = 0x28; -static constexpr dart::compiler::target::word - AOT_Closure_delayed_type_arguments_offset = 0x18; static constexpr dart::compiler::target::word AOT_Closure_function_offset = 0x20; +static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x18; static constexpr dart::compiler::target::word - AOT_Closure_function_type_arguments_offset = 0x10; -static constexpr dart::compiler::target::word AOT_Closure_hash_offset = 0x30; -static constexpr dart::compiler::target::word - AOT_Closure_instantiator_type_arguments_offset = 0x8; + AOT_Closure_length_and_flags_offset = 0x10; static constexpr dart::compiler::target::word AOT_ClosureData_packed_fields_offset = 0x20; static constexpr dart::compiler::target::word AOT_Code_instructions_offset = @@ -23679,7 +24010,6 @@ static constexpr dart::compiler::target::word AOT_Bytecode_InstanceSize = 0x58; static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 0x10; static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 0x90; -static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 0x40; static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 0x28; static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h index 469a664b107..267121398e2 100644 --- a/runtime/vm/compiler/runtime_offsets_list.h +++ b/runtime/vm/compiler/runtime_offsets_list.h @@ -60,6 +60,7 @@ PAYLOAD_SIZEOF, RANGE, CONSTANT, ENUM) \ ARRAY(Array, element_offset) \ NOT_IN_PRODUCT(ARRAY(ClassTable, AllocationTracingStateSlotOffsetFor)) \ + ARRAY(Closure, element_offset) \ ARRAY(Code, element_offset) \ ARRAY(Context, variable_offset) \ ARRAY(ContextScope, element_offset) \ @@ -71,6 +72,7 @@ ARRAY(TwoByteString, element_offset) \ ARRAY(WeakArray, element_offset) \ ARRAY_SIZEOF(Array, InstanceSize, element_offset) \ + ARRAY_SIZEOF(Closure, InstanceSize, element_offset) \ ARRAY_SIZEOF(Code, InstanceSize, element_offset) \ ARRAY_SIZEOF(Context, InstanceSize, variable_offset) \ ARRAY_SIZEOF(ContextScope, InstanceSize, element_offset) \ @@ -114,6 +116,13 @@ CONSTANT(SubtypeTestCache, kMaxInputs) \ CONSTANT(SubtypeTestCache, kTestResult) \ CONSTANT(TypeArguments, kMaxElements) \ + CONSTANT(UntaggedClosure, kHasDelayedTypeArgumentsBit) \ + CONSTANT(UntaggedClosure, kHasInstantiatorTypeArgumentsBit) \ + CONSTANT(UntaggedClosure, kHasFunctionTypeArgumentsBit) \ + CONSTANT(UntaggedClosure, kFunctionTypeArgumentsIndexBitsPos) \ + CONSTANT(UntaggedClosure, kFunctionTypeArgumentsIndexBitsSize) \ + CONSTANT(UntaggedClosure, kLengthBitsPos) \ + CONSTANT(UntaggedClosure, kLengthBitsSize) \ CONSTANT(UntaggedObject, kCardRememberedBit) \ CONSTANT(UntaggedObject, kCanonicalBit) \ CONSTANT(UntaggedObject, kNotMarkedBit) \ @@ -151,12 +160,9 @@ FIELD(Class, super_type_offset) \ FIELD(Class, host_type_arguments_field_offset_in_words_offset) \ NOT_IN_PRODUCT(FIELD(ClassTable, allocation_tracing_state_table_offset)) \ - FIELD(Closure, context_offset) \ - FIELD(Closure, delayed_type_arguments_offset) \ FIELD(Closure, function_offset) \ - FIELD(Closure, function_type_arguments_offset) \ FIELD(Closure, hash_offset) \ - FIELD(Closure, instantiator_type_arguments_offset) \ + FIELD(Closure, length_and_flags_offset) \ FIELD(ClosureData, packed_fields_offset) \ FIELD(Code, instructions_offset) \ FIELD(Code, object_pool_offset) \ @@ -444,7 +450,6 @@ SIZEOF(Bytecode, InstanceSize, UntaggedBytecode) \ SIZEOF(Capability, InstanceSize, UntaggedCapability) \ SIZEOF(Class, InstanceSize, UntaggedClass) \ - SIZEOF(Closure, InstanceSize, UntaggedClosure) \ SIZEOF(ClosureData, InstanceSize, UntaggedClosureData) \ SIZEOF(CodeSourceMap, HeaderSize, UntaggedCodeSourceMap) \ SIZEOF(CompressedStackMaps, ObjectHeaderSize, UntaggedCompressedStackMaps) \ diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc index 822052c62f1..584edce98e1 100644 --- a/runtime/vm/compiler/stub_code_compiler.cc +++ b/runtime/vm/compiler/stub_code_compiler.cc @@ -1234,19 +1234,21 @@ VM_TYPE_TESTING_STUB_CODE_LIST(GENERATE_BREAKPOINT_STUB) // Called for inline allocation of closure. // Input (preserved): // AllocateClosureABI::kFunctionReg: closure function. +// AllocateClosureABI::kLengthAndFlagsReg: encoded length_and_flags. // AllocateClosureABI::kContextReg: closure context. -// AllocateClosureABI::kInstantiatorTypeArgs: instantiator type arguments. // Output: // AllocateClosureABI::kResultReg: new allocated Closure object. // Clobbered: // AllocateClosureABI::kScratchReg -void StubCodeCompiler::GenerateAllocateClosureStub( - bool has_instantiator_type_args, - bool is_generic) { - const intptr_t instance_size = - target::RoundedAllocationSize(target::Closure::InstanceSize()); +void StubCodeCompiler::GenerateAllocateClosureStub(intptr_t num_elements) { + const intptr_t instance_size = target::RoundedAllocationSize( + target::Closure::InstanceSize(num_elements)); + const Register result_reg = AllocateClosureABI::kResultReg; + const Register scratch_reg = AllocateClosureABI::kScratchReg; + __ EnsureHasClassIdInDEBUG(kFunctionCid, AllocateClosureABI::kFunctionReg, - AllocateClosureABI::kScratchReg); + scratch_reg); + if (!FLAG_use_slow_path && FLAG_inline_alloc) { Label slow_case; __ Comment("Inline allocation of uninitialized closure"); @@ -1257,63 +1259,59 @@ void StubCodeCompiler::GenerateAllocateClosureStub( const auto distance = Assembler::kNearJump; #endif __ TryAllocateObject(kClosureCid, instance_size, &slow_case, distance, - AllocateClosureABI::kResultReg, - AllocateClosureABI::kScratchReg); + result_reg, scratch_reg); __ Comment("Inline initialization of allocated closure"); // Put null in the scratch register for initializing most boxed fields. // We initialize the fields in offset order below. // Since the TryAllocateObject above did not go to the slow path, we're // guaranteed an object in new space here, and thus no barriers are needed. - __ LoadObject(AllocateClosureABI::kScratchReg, NullObject()); - if (has_instantiator_type_args) { - __ StoreToSlotNoBarrier(AllocateClosureABI::kInstantiatorTypeArgsReg, - AllocateClosureABI::kResultReg, - Slot::Closure_instantiator_type_arguments()); - } else { - __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg, - AllocateClosureABI::kResultReg, - Slot::Closure_instantiator_type_arguments()); - } - __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg, - AllocateClosureABI::kResultReg, - Slot::Closure_function_type_arguments()); - if (!is_generic) { - __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg, - AllocateClosureABI::kResultReg, - Slot::Closure_delayed_type_arguments()); - } - __ StoreToSlotNoBarrier(AllocateClosureABI::kFunctionReg, - AllocateClosureABI::kResultReg, + __ LoadObject(scratch_reg, NullObject()); + __ StoreToSlotNoBarrier(AllocateClosureABI::kFunctionReg, result_reg, Slot::Closure_function()); - __ StoreToSlotNoBarrier(AllocateClosureABI::kContextReg, - AllocateClosureABI::kResultReg, - Slot::Closure_context()); - __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg, - AllocateClosureABI::kResultReg, - Slot::Closure_hash()); - if (is_generic) { - __ LoadObject(AllocateClosureABI::kScratchReg, EmptyTypeArguments()); - __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg, - AllocateClosureABI::kResultReg, - Slot::Closure_delayed_type_arguments()); + __ StoreToSlotNoBarrier(AllocateClosureABI::kLengthAndFlagsReg, result_reg, + Slot::Closure_length_and_flags()); + for (intptr_t i = 0; i < num_elements - 1; ++i) { + __ StoreCompressedIntoObjectNoBarrier( + result_reg, + FieldAddress(result_reg, target::Closure::element_offset(i)), + scratch_reg); } + __ StoreCompressedIntoObjectNoBarrier( + result_reg, + FieldAddress(result_reg, + target::Closure::element_offset(num_elements - 1)), + AllocateClosureABI::kContextReg); + if (num_elements >= 2) { + Label initialized; + __ BranchIfBit( + AllocateClosureABI::kLengthAndFlagsReg, + UntaggedClosure::kHasDelayedTypeArgumentsBit + kSmiTagShift, ZERO, + &initialized); + __ LoadObject(scratch_reg, EmptyTypeArguments()); + __ StoreCompressedIntoObjectNoBarrier( + result_reg, + FieldAddress(result_reg, + target::Closure::element_offset( + UntaggedClosure::kDelayedTypeArgumentsIndex)), + scratch_reg); + __ Bind(&initialized); + } + __ LoadImmediate(scratch_reg, target::ToRawSmi(0)); + __ StoreToSlotNoBarrier(scratch_reg, result_reg, Slot::Closure_hash()); #if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) if (FLAG_precompiled_mode) { // Set the closure entry point in precompiled mode, either to the function // entry point in bare instructions mode or to 0 otherwise (to catch - // misuse). This overwrites the scratch register, but there are no more - // boxed fields. - __ LoadFromSlot(AllocateClosureABI::kScratchReg, - AllocateClosureABI::kFunctionReg, + // misuse). + __ LoadFromSlot(scratch_reg, AllocateClosureABI::kFunctionReg, Slot::Function_entry_point()); - __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg, - AllocateClosureABI::kResultReg, + __ StoreToSlotNoBarrier(scratch_reg, result_reg, Slot::Closure_entry_point()); } #endif - // AllocateClosureABI::kResultReg: new object. + // result_reg: new object. __ Ret(); __ Bind(&slow_case); @@ -1322,26 +1320,12 @@ void StubCodeCompiler::GenerateAllocateClosureStub( __ Comment("Closure allocation via runtime"); __ EnterStubFrame(); __ PushObject(NullObject()); // Space on the stack for the return value. - __ PushRegistersInOrder( - {AllocateClosureABI::kFunctionReg, AllocateClosureABI::kContextReg}); - if (has_instantiator_type_args) { - __ PushRegister(AllocateClosureABI::kInstantiatorTypeArgsReg); - } else { - __ PushObject(NullObject()); - } - if (is_generic) { - __ PushObject(EmptyTypeArguments()); - } else { - __ PushObject(NullObject()); - } - __ CallRuntime(kAllocateClosureRuntimeEntry, 4); - if (has_instantiator_type_args) { - __ Drop(1); - __ PopRegister(AllocateClosureABI::kInstantiatorTypeArgsReg); - } else { - __ Drop(2); - } + __ PushRegistersInOrder({AllocateClosureABI::kFunctionReg, + AllocateClosureABI::kLengthAndFlagsReg, + AllocateClosureABI::kContextReg}); + __ CallRuntime(kAllocateClosureRuntimeEntry, 3); __ PopRegister(AllocateClosureABI::kContextReg); + __ PopRegister(AllocateClosureABI::kLengthAndFlagsReg); __ PopRegister(AllocateClosureABI::kFunctionReg); __ PopRegister(AllocateClosureABI::kResultReg); ASSERT(target::WillAllocateNewOrRememberedObject(instance_size)); @@ -1350,26 +1334,26 @@ void StubCodeCompiler::GenerateAllocateClosureStub( // AllocateClosureABI::kResultReg: new object __ Ret(); + + if (FLAG_use_slow_path || !FLAG_inline_alloc) { + // Make sure AllocateClosureN stubs have different code as + // precompiler chokes on distinct stub Code objects with the same + // (de-duplicated) instructions. + __ LoadImmediate(scratch_reg, num_elements); + } } -void StubCodeCompiler::GenerateAllocateClosureStub() { - GenerateAllocateClosureStub(/*has_instantiator_type_args=*/false, - /*is_generic=*/false); +void StubCodeCompiler::GenerateAllocateClosure1Stub() { + GenerateAllocateClosureStub(1); } - -void StubCodeCompiler::GenerateAllocateClosureGenericStub() { - GenerateAllocateClosureStub(/*has_instantiator_type_args=*/false, - /*is_generic=*/true); +void StubCodeCompiler::GenerateAllocateClosure2Stub() { + GenerateAllocateClosureStub(2); } - -void StubCodeCompiler::GenerateAllocateClosureTAStub() { - GenerateAllocateClosureStub(/*has_instantiator_type_args=*/true, - /*is_generic=*/false); +void StubCodeCompiler::GenerateAllocateClosure3Stub() { + GenerateAllocateClosureStub(3); } - -void StubCodeCompiler::GenerateAllocateClosureTAGenericStub() { - GenerateAllocateClosureStub(/*has_instantiator_type_args=*/true, - /*is_generic=*/true); +void StubCodeCompiler::GenerateAllocateClosure4Stub() { + GenerateAllocateClosureStub(4); } // Generates allocation stub for _GrowableList class. @@ -3348,22 +3332,55 @@ void StubCodeCompiler::GenerateSubtypeTestCacheSearch( FieldAddress(instance_cid_or_sig_reg, target::Function::signature_offset())); if (n >= 2) { - __ LoadCompressed( - instance_type_args_reg, + __ LoadCompressedSmi( + TypeTestABI::kScratchReg, FieldAddress(TypeTestABI::kInstanceReg, - target::Closure::instantiator_type_arguments_offset())); - } - if (n >= 5) { - __ LoadCompressed( - parent_fun_type_args_reg, - FieldAddress(TypeTestABI::kInstanceReg, - target::Closure::function_type_arguments_offset())); - } - if (n >= 6) { - __ LoadCompressed( - delayed_type_args_reg, - FieldAddress(TypeTestABI::kInstanceReg, - target::Closure::delayed_type_arguments_offset())); + target::Closure::length_and_flags_offset())); + + Label load_function_type_arguments, load_delayed_type_arguments; + __ MoveRegister(instance_type_args_reg, null_reg); + __ BranchIfBit( + TypeTestABI::kScratchReg, + UntaggedClosure::kHasInstantiatorTypeArgumentsBit + kSmiTagShift, + ZERO, (n >= 5) ? &load_function_type_arguments : &initialized); + __ ExtractBitField( + instance_type_args_reg, TypeTestABI::kScratchReg, + UntaggedClosure::InstantiatorTypeArgumentsIndexBits::shift(), + UntaggedClosure::InstantiatorTypeArgumentsIndexBits::bitsize()); + __ LoadIndexedCompressed( + instance_type_args_reg, TypeTestABI::kInstanceReg, + target::Closure::element_offset(0), instance_type_args_reg); + if (n >= 5) { + __ Bind(&load_function_type_arguments); + + __ MoveRegister(parent_fun_type_args_reg, null_reg); + __ BranchIfBit( + TypeTestABI::kScratchReg, + UntaggedClosure::kHasFunctionTypeArgumentsBit + kSmiTagShift, ZERO, + (n >= 6) ? &load_delayed_type_arguments : &initialized); + __ ExtractBitField( + parent_fun_type_args_reg, TypeTestABI::kScratchReg, + UntaggedClosure::FunctionTypeArgumentsIndexBits::shift(), + UntaggedClosure::FunctionTypeArgumentsIndexBits::bitsize()); + __ LoadIndexedCompressed( + parent_fun_type_args_reg, TypeTestABI::kInstanceReg, + target::Closure::element_offset(0), parent_fun_type_args_reg); + } + + if (n >= 6) { + __ Bind(&load_delayed_type_arguments); + + __ MoveRegister(delayed_type_args_reg, null_reg); + __ BranchIfBit( + TypeTestABI::kScratchReg, + UntaggedClosure::kHasDelayedTypeArgumentsBit + kSmiTagShift, ZERO, + &initialized); + __ LoadCompressed( + delayed_type_args_reg, + FieldAddress(TypeTestABI::kInstanceReg, + target::Closure::element_offset( + UntaggedClosure::kDelayedTypeArgumentsIndex))); + } } __ Jump(&initialized, Assembler::kNearJump); diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h index c7bfc0c37de..48e441e372a 100644 --- a/runtime/vm/compiler/stub_code_compiler.h +++ b/runtime/vm/compiler/stub_code_compiler.h @@ -196,9 +196,8 @@ class StubCodeCompiler { // InitLateFinalInstanceField stubs. void GenerateInitLateInstanceFieldStub(bool is_final); - // Common function for generating AllocateClosure[TA][Generic] stubs. - void GenerateAllocateClosureStub(bool has_instantiator_type_args, - bool is_generic); + // Common function for generating AllocateClosure stubs. + void GenerateAllocateClosureStub(intptr_t num_elements); // Common function for generating AllocateArray stubs. void GenerateAllocateTypedDataArrayStub(intptr_t cid); diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc index bd6a96792ac..ac5418ebc09 100644 --- a/runtime/vm/compiler/stub_code_compiler_ia32.cc +++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc @@ -2780,20 +2780,70 @@ void StubCodeCompiler::GenerateSubtypeNTestCacheStub(Assembler* assembler, __ movl(STCInternal::kInstanceCidOrSignatureReg, FieldAddress(STCInternal::kInstanceCidOrSignatureReg, target::Function::signature_offset())); + if (n >= 2) { - __ movl( + __ movl(STCInternal::kScratchReg, + FieldAddress(TypeTestABI::kInstanceReg, + target::Closure::length_and_flags_offset())); + + Label load_function_type_arguments, load_delayed_type_arguments; + __ movl(STCInternal::kInstanceInstantiatorTypeArgumentsReg, raw_null); + __ BranchIfBit( + STCInternal::kScratchReg, + UntaggedClosure::kHasInstantiatorTypeArgumentsBit + kSmiTagShift, + ZERO, (n >= 5) ? &load_function_type_arguments : &loop); + __ ExtractBitField( + STCInternal::kInstanceInstantiatorTypeArgumentsReg, + STCInternal::kScratchReg, + UntaggedClosure::InstantiatorTypeArgumentsIndexBits::shift(), + UntaggedClosure::InstantiatorTypeArgumentsIndexBits::bitsize()); + __ Load( STCInternal::kInstanceInstantiatorTypeArgumentsReg, FieldAddress(TypeTestABI::kInstanceReg, - target::Closure::instantiator_type_arguments_offset())); - } - if (n >= 5) { - __ pushl(FieldAddress(TypeTestABI::kInstanceReg, - target::Closure::function_type_arguments_offset())); - } - if (n >= 6) { - __ pushl(FieldAddress(TypeTestABI::kInstanceReg, - target::Closure::delayed_type_arguments_offset())); + STCInternal::kInstanceInstantiatorTypeArgumentsReg, + TIMES_WORD_SIZE, target::Closure::element_offset(0))); + if (n >= 5) { + Label no_function_type_arguments; + __ Bind(&load_function_type_arguments); + + __ BranchIfBit( + STCInternal::kScratchReg, + UntaggedClosure::kHasFunctionTypeArgumentsBit + kSmiTagShift, ZERO, + &no_function_type_arguments); + __ ExtractBitField( + STCInternal::kScratchReg, STCInternal::kScratchReg, + UntaggedClosure::FunctionTypeArgumentsIndexBits::shift(), + UntaggedClosure::FunctionTypeArgumentsIndexBits::bitsize()); + __ pushl(FieldAddress(TypeTestABI::kInstanceReg, + STCInternal::kScratchReg, TIMES_WORD_SIZE, + target::Closure::element_offset(0))); + __ jmp((n >= 6) ? &load_delayed_type_arguments : &loop, + Assembler::kNearJump); + + __ Bind(&no_function_type_arguments); + __ pushl(raw_null); + } + + if (n >= 6) { + Label no_delayed_type_arguments; + __ Bind(&load_delayed_type_arguments); + + __ testl(FieldAddress(TypeTestABI::kInstanceReg, + target::Closure::length_and_flags_offset()), + Immediate(UntaggedClosure::kHasDelayedTypeArgumentsBit + + kSmiTagShift)); + __ j(ZERO, &no_delayed_type_arguments, Assembler::kNearJump); + __ pushl( + FieldAddress(TypeTestABI::kInstanceReg, + target::Closure::element_offset( + UntaggedClosure::kDelayedTypeArgumentsIndex))); + __ jmp(&loop, Assembler::kNearJump); + + __ Bind(&no_delayed_type_arguments); + __ pushl(raw_null); + } } + __ jmp(&loop, Assembler::kNearJump); } diff --git a/runtime/vm/compiler/write_barrier_elimination.cc b/runtime/vm/compiler/write_barrier_elimination.cc index e9e790b222f..eba0a4c2bff 100644 --- a/runtime/vm/compiler/write_barrier_elimination.cc +++ b/runtime/vm/compiler/write_barrier_elimination.cc @@ -357,6 +357,7 @@ bool WriteBarrierElimination::SlotEligibleForWBE(const Slot& slot) { // RestoreWriteBarrierInvariantVisitor::VisitPointers. switch (slot.kind()) { + case Slot::Kind::kClosureElement: // Closure case Slot::Kind::kCapturedVariable: // Context case Slot::Kind::kDartField: // Instance case Slot::Kind::kRecordField: // Instance diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h index 24870ceaa35..390eee345fd 100644 --- a/runtime/vm/constants_arm.h +++ b/runtime/vm/constants_arm.h @@ -503,8 +503,8 @@ struct AllocateObjectABI { struct AllocateClosureABI { static constexpr Register kResultReg = AllocateObjectABI::kResultReg; static constexpr Register kFunctionReg = R1; - static constexpr Register kContextReg = R2; - static constexpr Register kInstantiatorTypeArgsReg = R3; + static constexpr Register kLengthAndFlagsReg = R2; + static constexpr Register kContextReg = R3; static constexpr Register kScratchReg = R4; }; diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h index dbf99bd2195..4d46a466a68 100644 --- a/runtime/vm/constants_arm64.h +++ b/runtime/vm/constants_arm64.h @@ -341,8 +341,8 @@ struct AllocateObjectABI { struct AllocateClosureABI { static constexpr Register kResultReg = AllocateObjectABI::kResultReg; static constexpr Register kFunctionReg = R1; - static constexpr Register kContextReg = R2; - static constexpr Register kInstantiatorTypeArgsReg = R3; + static constexpr Register kLengthAndFlagsReg = R2; + static constexpr Register kContextReg = R3; static constexpr Register kScratchReg = R4; }; diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h index 50bcfd38e76..d7460eadb6a 100644 --- a/runtime/vm/constants_ia32.h +++ b/runtime/vm/constants_ia32.h @@ -243,8 +243,8 @@ struct AllocateBoxABI { struct AllocateClosureABI { static constexpr Register kResultReg = AllocateObjectABI::kResultReg; static constexpr Register kFunctionReg = EBX; - static constexpr Register kContextReg = ECX; - static constexpr Register kInstantiatorTypeArgsReg = EDI; + static constexpr Register kLengthAndFlagsReg = ECX; + static constexpr Register kContextReg = EDI; static constexpr Register kScratchReg = EDX; }; diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h index bbe97900951..bef6687b460 100644 --- a/runtime/vm/constants_kbc.h +++ b/runtime/vm/constants_kbc.h @@ -55,8 +55,12 @@ namespace dart { V(Allocate_Wide, D, WIDE, lit, ___, ___) \ V(AllocateT, 0, ORDN, ___, ___, ___) \ V(CreateArrayTOS, 0, ORDN, ___, ___, ___) \ - V(AllocateClosure, 0, ORDN, ___, ___, ___) \ - V(Unused03, 0, RESV, ___, ___, ___) \ + V(AllocateClosure, D, ORDN, lit, ___, ___) \ + V(AllocateClosure_Wide, D, WIDE, lit, ___, ___) \ + V(LoadClosureElement, D, ORDN, num, ___, ___) \ + V(LoadClosureElement_Wide, D, WIDE, num, ___, ___) \ + V(StoreClosureElement, D, ORDN, num, ___, ___) \ + V(StoreClosureElement_Wide, D, WIDE, num, ___, ___) \ V(AllocateContext, A_E, ORDN, num, num, ___) \ V(AllocateContext_Wide, A_E, WIDE, num, num, ___) \ V(CloneContext, A_E, ORDN, num, num, ___) \ @@ -223,7 +227,8 @@ namespace dart { V(VMInternal_ImplicitSharedStaticGetter, 0, ORDN, ___, ___, ___) \ V(VMInternal_ImplicitStaticSetter, 0, ORDN, ___, ___, ___) \ V(VMInternal_ImplicitSharedStaticSetter, 0, ORDN, ___, ___, ___) \ - V(VMInternal_MethodExtractor, 0, ORDN, ___, ___, ___) \ + V(VMInternal_MethodExtractorWithITA, 0, ORDN, ___, ___, ___) \ + V(VMInternal_MethodExtractorWithoutITA, 0, ORDN, ___, ___, ___) \ V(VMInternal_InvokeClosure, 0, ORDN, ___, ___, ___) \ V(VMInternal_InvokeField, 0, ORDN, ___, ___, ___) \ V(VMInternal_ForwardDynamicInvocation, 0, ORDN, ___, ___, ___) \ @@ -265,7 +270,7 @@ class KernelBytecode { static const intptr_t kMagicValue = 0x44424333; // 'DBC3' // Bytecode format version supported by the VM // (should match pkg/dart2bytecode/lib/dbc.dart). - static const intptr_t kBytecodeFormatVersion = 1; + static const intptr_t kBytecodeFormatVersion = 2; enum Opcode { #define DECLARE_BYTECODE(name, encoding, kind, op1, op2, op3) k##name, diff --git a/runtime/vm/constants_riscv.h b/runtime/vm/constants_riscv.h index ddaaacaea8c..c7eecf22803 100644 --- a/runtime/vm/constants_riscv.h +++ b/runtime/vm/constants_riscv.h @@ -385,8 +385,8 @@ struct AllocateObjectABI { struct AllocateClosureABI { static constexpr Register kResultReg = AllocateObjectABI::kResultReg; static constexpr Register kFunctionReg = T1; - static constexpr Register kContextReg = T2; - static constexpr Register kInstantiatorTypeArgsReg = T3; + static constexpr Register kLengthAndFlagsReg = T2; + static constexpr Register kContextReg = T3; static constexpr Register kScratchReg = T4; }; diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h index 32b39ae6dd9..efd71f5ace6 100644 --- a/runtime/vm/constants_x64.h +++ b/runtime/vm/constants_x64.h @@ -307,8 +307,8 @@ struct AllocateObjectABI { struct AllocateClosureABI { static constexpr Register kResultReg = AllocateObjectABI::kResultReg; static constexpr Register kFunctionReg = RBX; - static constexpr Register kContextReg = RDX; - static constexpr Register kInstantiatorTypeArgsReg = RCX; + static constexpr Register kLengthAndFlagsReg = RDX; + static constexpr Register kContextReg = RCX; static constexpr Register kScratchReg = R13; }; diff --git a/runtime/vm/deferred_objects.cc b/runtime/vm/deferred_objects.cc index 94c9dbab338..4cdeab8e474 100644 --- a/runtime/vm/deferred_objects.cc +++ b/runtime/vm/deferred_objects.cc @@ -227,6 +227,17 @@ void DeferredObject::Create() { cls ^= GetClass(); switch (cls.id()) { + case kClosureCid: { + const intptr_t length_and_flags = + Smi::Cast(Object::Handle(GetLengthOrShape())).Value(); + if (FLAG_trace_deoptimization_verbose) { + OS::PrintErr("materializing closure with length and flags %" Px " (%" Px + ", %" Pd " fields)\n", + length_and_flags, reinterpret_cast(args_), + field_count_); + } + object_ = &Closure::ZoneHandle(Closure::New(length_and_flags)); + } break; case kContextCid: { const intptr_t num_variables = Smi::Cast(Object::Handle(GetLengthOrShape())).Value(); @@ -296,6 +307,35 @@ void DeferredObject::Fill() { cls ^= GetClass(); switch (cls.id()) { + case kClosureCid: { + const Closure& closure = Closure::Cast(*object_); + + Smi& offset = Smi::Handle(); + Object& value = Object::Handle(); + + for (intptr_t i = 0; i < field_count_; i++) { + offset ^= GetFieldOffset(i); + if (offset.Value() == Closure::function_offset()) { + Function& function = Function::Handle(); + function ^= GetValue(i); + closure.set_function(function); + if (FLAG_trace_deoptimization_verbose) { + OS::PrintErr(" closure@function (offset %" Pd ") <- %s\n", + offset.Value(), function.ToCString()); + } + } else { + ASSERT(offset.Value() >= Closure::element_offset(0)); + const intptr_t index = + Closure::element_index_at_offset(offset.Value()); + value = GetValue(i); + closure.SetElementAt(index, value); + if (FLAG_trace_deoptimization_verbose) { + OS::PrintErr(" closure@%" Pd " (offset %" Pd ") <- %s\n", index, + offset.Value(), value.ToCString()); + } + } + } + } break; case kContextCid: { const Context& context = Context::Cast(*object_); diff --git a/runtime/vm/deferred_objects.h b/runtime/vm/deferred_objects.h index 60738bacbc9..30507a30824 100644 --- a/runtime/vm/deferred_objects.h +++ b/runtime/vm/deferred_objects.h @@ -202,6 +202,7 @@ class DeferredObject { enum { kClassIndex = 0, + // For closure: encoded length and flags. // For contexts: number of context variables. // For arrays and typed data objects: number of elements. // For records: shape. diff --git a/runtime/vm/ffi_callback_metadata_test.cc b/runtime/vm/ffi_callback_metadata_test.cc index 8496a6b3ff2..982e65d7063 100644 --- a/runtime/vm/ffi_callback_metadata_test.cc +++ b/runtime/vm/ffi_callback_metadata_test.cc @@ -288,9 +288,9 @@ VM_UNIT_TEST_CASE(FfiCallbackMetadata_CreateIsolateLocalFfiCallback) { const Code& code = Code::Handle(func.EnsureHasCode()); EXPECT(!code.IsNull()); - // Using a FfiCallbackKind::kSync function as a dummy closure. + // Using a tear-off of target of the callback function as a dummy closure. const Function& closure_func = Function::Handle( - CreateTestFunction(FfiCallbackKind::kIsolateLocalStaticCallback)); + Function::Handle(func.FfiCallbackTarget()).ImplicitClosureFunction()); const Context& context = Context::Handle(Context::null()); const Closure& closure1 = Closure::Handle( Closure::New(Object::null_type_arguments(), diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc index ea93d56714b..b4106906d11 100644 --- a/runtime/vm/interpreter.cc +++ b/runtime/vm/interpreter.cc @@ -1263,11 +1263,11 @@ bool Interpreter::AssertAssignable(Thread* thread, TypeArgumentsPtr delayed_function_type_arguments; if (cid == kClosureCid) { ClosurePtr closure = static_cast(instance); - instance_type_arguments = closure->untag()->instantiator_type_arguments(); + instance_type_arguments = Closure::instantiator_type_arguments(closure); parent_function_type_arguments = - closure->untag()->function_type_arguments(); + Closure::function_type_arguments(closure); delayed_function_type_arguments = - closure->untag()->delayed_type_arguments(); + Closure::delayed_type_arguments(closure); instance_cid_or_function = closure->untag()->function()->untag()->signature(); } else { @@ -1656,10 +1656,14 @@ bool Interpreter::AllocateContext(Thread* thread, // Allocate a _Closure and put it into SP[0]. // Returns false on exception. bool Interpreter::AllocateClosure(Thread* thread, + FunctionPtr function, + SmiPtr length_and_flags, const KBCInstr* pc, ObjectPtr* FP, ObjectPtr* SP) { - const intptr_t instance_size = Closure::InstanceSize(); + const intptr_t length = + UntaggedClosure::LengthBits::decode(Smi::Value(length_and_flags)); + const intptr_t instance_size = Closure::InstanceSize(length); ClosurePtr result; if (TryAllocate(thread, kClosureCid, instance_size, reinterpret_cast(&result))) { @@ -1668,15 +1672,21 @@ bool Interpreter::AllocateClosure(Thread* thread, Closure::ContainsCompressedPointers(), Object::from_offset(), Object::to_offset()); + result->untag()->set_function(function); + ONLY_IN_PRECOMPILED(result->untag()->entry_point_ = + function->untag()->entry_point_); + result->untag()->set_length_and_flags(length_and_flags); + result->untag()->set_hash(Smi::New(0)); SP[0] = result; return true; } else { SP[0] = 0; // Space for the result. - SP[1] = thread->isolate_group()->object_store()->closure_class(); - SP[2] = Object::null(); // Type arguments. - Exit(thread, FP, SP + 3, pc); - NativeArguments args(thread, 2, SP + 1, SP); - return InvokeRuntime(thread, this, DRT_AllocateObject, args); + SP[1] = function; + SP[2] = length_and_flags; + SP[3] = Object::null(); // Context. + Exit(thread, FP, SP + 4, pc); + NativeArguments args(thread, 3, SP + 1, SP); + return InvokeRuntime(thread, this, DRT_AllocateClosure, args); } } @@ -3371,28 +3381,36 @@ SwitchDispatchNoSingleStep: } { - BYTECODE(AllocateClosure, 0); - ++SP; - if (!AllocateClosure(thread, pc, FP, SP)) { - HANDLE_EXCEPTION; - } - ClosurePtr closure = Closure::RawCast(SP[0]); - FunctionPtr function = Function::RawCast(SP[-3]); - ObjectPtr context = SP[-2]; - TypeArgumentsPtr instantiator_type_arguments = - TypeArguments::RawCast(SP[-1]); - + BYTECODE(AllocateClosure, D); + FunctionPtr function = Function::RawCast(LOAD_CONSTANT(rD)); ASSERT((Function::KindOf(function) == UntaggedFunction::kClosureFunction) || (Function::KindOf(function) == UntaggedFunction::kImplicitClosureFunction)); - closure->untag()->set_function(function); - ONLY_IN_PRECOMPILED(closure->untag()->entry_point_ = - function->untag()->entry_point_); - closure->untag()->set_context(context); - closure->untag()->set_instantiator_type_arguments( - instantiator_type_arguments); - SP -= 3; - SP[0] = closure; + SmiPtr length_and_flags = Smi::RawCast(LOAD_CONSTANT(rD + 1)); + ++SP; + if (!AllocateClosure(thread, function, length_and_flags, pc, FP, SP)) { + HANDLE_EXCEPTION; + } + DISPATCH(); + } + + { + BYTECODE(LoadClosureElement, D); + ClosurePtr instance = Closure::RawCast(SP[0]); + ASSERT((0 <= rD) && (rD < UntaggedClosure::LengthBits::decode(Smi::Value( + instance->untag()->length_and_flags())))); + SP[0] = instance->untag()->element(rD); + DISPATCH(); + } + + { + BYTECODE(StoreClosureElement, D); + ClosurePtr instance = Closure::RawCast(SP[-1]); + ObjectPtr value = static_cast(SP[0]); + ASSERT((0 <= rD) && (rD < UntaggedClosure::LengthBits::decode(Smi::Value( + instance->untag()->length_and_flags())))); + instance->untag()->set_element(rD, value); + SP -= 2; DISPATCH(); } @@ -3713,34 +3731,87 @@ SwitchDispatchNoSingleStep: } { - BYTECODE(VMInternal_MethodExtractor, 0); + BYTECODE(VMInternal_MethodExtractorWithITA, 0); FunctionPtr function = FrameFunction(FP); ASSERT(Function::KindOf(function) == UntaggedFunction::kMethodExtractor); function = Function::RawCast(function->untag()->data()); ASSERT(Function::KindOf(function) == UntaggedFunction::kImplicitClosureFunction); - ASSERT(InterpreterHelpers::ArgDescTypeArgsLen(argdesc_) == 0); + const bool has_delayed_type_args = + FunctionType::RawCast(function->untag()->signature()) + ->untag() + ->type_parameters() != TypeParameters::null(); + const bool has_instantiator_type_args = true; + const bool has_function_type_args = false; + const intptr_t length = + UntaggedClosure::ContextIndex(has_delayed_type_args, + has_instantiator_type_args, + has_function_type_args) + + 1; + SmiPtr length_and_flags = Smi::New(UntaggedClosure::EncodeLengthAndFlags( + has_delayed_type_args, has_instantiator_type_args, + has_function_type_args, length)); ++SP; - if (!AllocateClosure(thread, pc, FP, SP)) { + if (!AllocateClosure(thread, function, length_and_flags, pc, FP, SP)) { HANDLE_EXCEPTION; } + ClosurePtr closure = Closure::RawCast(SP[0]); InstancePtr instance = Instance::RawCast(FrameArguments(FP, 1)[0]); + intptr_t index = 0; + if (has_delayed_type_args) { + closure->untag()->set_element(index++, + Object::empty_type_arguments().ptr()); + } + closure->untag()->set_element( + index++, InterpreterHelpers::GetTypeArguments(thread, instance)); + closure->untag()->set_element(index++, instance); + ASSERT(index == length); - ClosurePtr closure = Closure::RawCast(*SP); - closure->untag()->set_instantiator_type_arguments( - InterpreterHelpers::GetTypeArguments(thread, instance)); - // function_type_arguments is already null - closure->untag()->set_delayed_type_arguments( - Object::empty_type_arguments().ptr()); - closure->untag()->set_function(function); - ONLY_IN_PRECOMPILED(closure->untag()->entry_point_ = - function->untag()->entry_point_); - closure->untag()->set_context(instance); - // hash is already null + DISPATCH(); + } + + { + BYTECODE(VMInternal_MethodExtractorWithoutITA, 0); + + FunctionPtr function = FrameFunction(FP); + ASSERT(Function::KindOf(function) == UntaggedFunction::kMethodExtractor); + function = Function::RawCast(function->untag()->data()); + ASSERT(Function::KindOf(function) == + UntaggedFunction::kImplicitClosureFunction); + ASSERT(InterpreterHelpers::ArgDescTypeArgsLen(argdesc_) == 0); + const bool has_delayed_type_args = + FunctionType::RawCast(function->untag()->signature()) + ->untag() + ->type_parameters() != TypeParameters::null(); + const bool has_instantiator_type_args = false; + const bool has_function_type_args = false; + const intptr_t length = + UntaggedClosure::ContextIndex(has_delayed_type_args, + has_instantiator_type_args, + has_function_type_args) + + 1; + SmiPtr length_and_flags = Smi::New(UntaggedClosure::EncodeLengthAndFlags( + has_delayed_type_args, has_instantiator_type_args, + has_function_type_args, length)); + + ++SP; + if (!AllocateClosure(thread, function, length_and_flags, pc, FP, SP)) { + HANDLE_EXCEPTION; + } + + ClosurePtr closure = Closure::RawCast(SP[0]); + InstancePtr instance = Instance::RawCast(FrameArguments(FP, 1)[0]); + intptr_t index = 0; + if (has_delayed_type_args) { + closure->untag()->set_element(index++, + Object::empty_type_arguments().ptr()); + } + closure->untag()->set_element(index++, instance); + ASSERT(index == length); DISPATCH(); } @@ -4016,9 +4087,7 @@ SwitchDispatchNoSingleStep: } } else { TypeArgumentsPtr delayed_type_arguments = - Closure::RawCast(argv[receiver_idx]) - ->untag() - ->delayed_type_arguments(); + Closure::delayed_type_arguments(Closure::RawCast(argv[receiver_idx])); if (delayed_type_arguments != Object::empty_type_arguments().ptr()) { if (type_args_len > 0) { SP[1] = function; @@ -4080,7 +4149,7 @@ SwitchDispatchNoSingleStep: } } else { TypeArgumentsPtr delayed_type_arguments = - closure->untag()->delayed_type_arguments(); + Closure::delayed_type_arguments(closure); if (delayed_type_arguments != Object::empty_type_arguments().ptr()) { if (type_args_len > 0) { SP[1] = function; @@ -4091,7 +4160,7 @@ SwitchDispatchNoSingleStep: *++SP = delayed_type_arguments; ObjectPtr* call_base = SP; // Captured receiver. - *++SP = closure->untag()->context(); + *++SP = Closure::RawContextOf(closure); // Copy the rest of the arguments. for (intptr_t i = receiver_idx + 1; i < argc; i++) { *++SP = argv[i]; @@ -4121,7 +4190,7 @@ SwitchDispatchNoSingleStep: // Replace closure receiver with captured receiver // and call target function. - argv[receiver_idx] = closure->untag()->context(); + argv[receiver_idx] = Closure::RawContextOf(closure); SP[1] = target; goto TailCallSP1; @@ -4167,9 +4236,7 @@ SwitchDispatchNoSingleStep: type_args = TypeArguments::null(); } else { TypeArgumentsPtr delayed_type_arguments = - Closure::RawCast(argv[receiver_idx]) - ->untag() - ->delayed_type_arguments(); + Closure::delayed_type_arguments(Closure::RawCast(argv[receiver_idx])); if (delayed_type_arguments != Object::empty_type_arguments().ptr()) { if (type_args_len > 0) { SP[1] = function; diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h index 11b9f95f335..0f9610e9706 100644 --- a/runtime/vm/interpreter.h +++ b/runtime/vm/interpreter.h @@ -243,6 +243,8 @@ class Interpreter { ObjectPtr* FP, ObjectPtr* SP); bool AllocateClosure(Thread* thread, + FunctionPtr function, + SmiPtr length_and_flags, const KBCInstr* pc, ObjectPtr* FP, ObjectPtr* SP); diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 0d20513b2d8..4d733e461c4 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -1229,8 +1229,11 @@ void Object::Init(IsolateGroup* isolate_group) { Roots::implicit_shared_static_setter_bytecode().initRO( CreateVMInternalBytecode( KernelBytecode::kVMInternal_ImplicitSharedStaticSetter)); - Roots::method_extractor_bytecode().initRO( - CreateVMInternalBytecode(KernelBytecode::kVMInternal_MethodExtractor)); + Roots::method_extractor_with_ita_bytecode().initRO(CreateVMInternalBytecode( + KernelBytecode::kVMInternal_MethodExtractorWithITA)); + Roots::method_extractor_without_ita_bytecode().initRO( + CreateVMInternalBytecode( + KernelBytecode::kVMInternal_MethodExtractorWithoutITA)); Roots::invoke_closure_bytecode().initRO( CreateVMInternalBytecode(KernelBytecode::kVMInternal_InvokeClosure)); Roots::invoke_field_bytecode().initRO( @@ -1254,7 +1257,8 @@ void Object::Init(IsolateGroup* isolate_group) { Roots::implicit_shared_static_getter_bytecode().initRO(Bytecode::null()); Roots::implicit_static_setter_bytecode().initRO(Bytecode::null()); Roots::implicit_shared_static_setter_bytecode().initRO(Bytecode::null()); - Roots::method_extractor_bytecode().initRO(Bytecode::null()); + Roots::method_extractor_with_ita_bytecode().initRO(Bytecode::null()); + Roots::method_extractor_without_ita_bytecode().initRO(Bytecode::null()); Roots::invoke_closure_bytecode().initRO(Bytecode::null()); Roots::invoke_field_bytecode().initRO(Bytecode::null()); Roots::nsm_dispatcher_bytecode().initRO(Bytecode::null()); @@ -1356,8 +1360,10 @@ void Object::Init(IsolateGroup* isolate_group) { ASSERT(Roots::implicit_static_getter_bytecode().IsBytecode()); ASSERT(!Roots::implicit_static_setter_bytecode().IsSmi()); ASSERT(Roots::implicit_static_setter_bytecode().IsBytecode()); - ASSERT(!Roots::method_extractor_bytecode().IsSmi()); - ASSERT(Roots::method_extractor_bytecode().IsBytecode()); + ASSERT(!Roots::method_extractor_with_ita_bytecode().IsSmi()); + ASSERT(Roots::method_extractor_with_ita_bytecode().IsBytecode()); + ASSERT(!Roots::method_extractor_without_ita_bytecode().IsSmi()); + ASSERT(Roots::method_extractor_without_ita_bytecode().IsBytecode()); ASSERT(!Roots::invoke_closure_bytecode().IsSmi()); ASSERT(Roots::invoke_closure_bytecode().IsBytecode()); ASSERT(!Roots::invoke_field_bytecode().IsSmi()); @@ -4151,7 +4157,18 @@ FunctionPtr Function::CreateMethodExtractor(const String& getter_name) const { const bool attach_bytecode = is_declared_in_bytecode(); #endif if (attach_bytecode) { - extractor.AttachBytecode(Object::method_extractor_bytecode()); + // Bytecode method extractor may be used to create a closure instance + // with a compiled closure function, so layout of the closure object + // has to be compatible between them. + // 'Closure::HasInstantiatorTypeArgumentsField' involves a heavy signature + // type inspection which is not feasible to perform in the method + // extractor. So it is performed here to select a variant of the bytecode + // method extractor. + if (Closure::HasInstantiatorTypeArgumentsField(closure_function)) { + extractor.AttachBytecode(Object::method_extractor_with_ita_bytecode()); + } else { + extractor.AttachBytecode(Object::method_extractor_without_ita_bytecode()); + } } #endif // defined(DART_DYNAMIC_MODULES) @@ -19365,8 +19382,12 @@ static const char* BytecodeStubName(const Bytecode& bytecode) { } else if (bytecode.ptr() == Object::implicit_shared_static_setter_bytecode().ptr()) { return "[Bytecode Stub] VMInternal_ImplicitSharedStaticSetter"; - } else if (bytecode.ptr() == Object::method_extractor_bytecode().ptr()) { - return "[Bytecode Stub] VMInternal_MethodExtractor"; + } else if (bytecode.ptr() == + Object::method_extractor_with_ita_bytecode().ptr()) { + return "[Bytecode Stub] VMInternal_MethodExtractorWithITA"; + } else if (bytecode.ptr() == + Object::method_extractor_without_ita_bytecode().ptr()) { + return "[Bytecode Stub] VMInternal_MethodExtractorWithoutITA"; } else if (bytecode.ptr() == Object::invoke_closure_bytecode().ptr()) { return "[Bytecode Stub] VMInternal_InvokeClosure"; } else if (bytecode.ptr() == Object::invoke_field_bytecode().ptr()) { @@ -26763,18 +26784,35 @@ uword Closure::ComputeHash() const { return FinalizeHash(result, String::kHashBits); } +ClosurePtr Closure::New(intptr_t length_and_flags, Heap::Space space) { + const intptr_t num_elements = + UntaggedClosure::LengthBits::decode(length_and_flags); + ASSERT(num_elements >= 0); + if (!IsValidLength(num_elements)) { + // This should be caught before we reach here. + FATAL("Fatal error in Closure::New: invalid num_elements %" Pd "\n", + num_elements); + } + auto raw = Object::Allocate(space, num_elements); + NoSafepointScope no_safepoint; + raw->untag()->set_length_and_flags(Smi::New(length_and_flags)); + raw->untag()->set_hash(Smi::New(0)); + if (UntaggedClosure::HasDelayedTypeArgumentsBit::decode(length_and_flags)) { + raw->untag()->set_element(UntaggedClosure::kDelayedTypeArgumentsIndex, + Object::empty_type_arguments().ptr()); + } + return raw; +} + ClosurePtr Closure::New(const TypeArguments& instantiator_type_arguments, const TypeArguments& function_type_arguments, const Function& function, const Object& context, Heap::Space space) { - // We store null delayed type arguments, not empty ones, in closures with - // non-generic functions a) to make method extraction slightly faster and - // b) to make the Closure::IsGeneric check fast. - // Keep in sync with StubCodeCompiler::GenerateAllocateClosureStub. return Closure::New(instantiator_type_arguments, function_type_arguments, - function.IsGeneric() ? Object::empty_type_arguments() - : Object::null_type_arguments(), + Closure::HasDelayedTypeArgumentsField(function) + ? Object::empty_type_arguments() + : Object::null_type_arguments(), function, context, space); } @@ -26787,21 +26825,39 @@ ClosurePtr Closure::New(const TypeArguments& instantiator_type_arguments, ASSERT(instantiator_type_arguments.IsCanonical()); ASSERT(function_type_arguments.IsCanonical()); ASSERT(delayed_type_arguments.IsCanonical()); + ASSERT(function.IsClosureFunction()); ASSERT(FunctionType::Handle(function.signature()).IsCanonical()); ASSERT( (function.IsImplicitInstanceClosureFunction() && context.IsInstance()) || (function.IsNonImplicitClosureFunction() && context.IsContext()) || context.IsNull()); - const auto& result = Closure::Handle(Object::Allocate(space)); - result.untag()->set_instantiator_type_arguments( - instantiator_type_arguments.ptr()); - result.untag()->set_function_type_arguments(function_type_arguments.ptr()); - result.untag()->set_delayed_type_arguments(delayed_type_arguments.ptr()); - result.untag()->set_function(function.ptr()); - result.untag()->set_context(context.ptr()); -#if defined(DART_PRECOMPILED_RUNTIME) - result.set_entry_point(function.entry_point()); -#endif + + const bool has_delayed_type_args = + Closure::HasDelayedTypeArgumentsField(function); + const bool has_instantiator_type_args = + Closure::HasInstantiatorTypeArgumentsField(function); + const bool has_function_type_args = + Closure::HasFunctionTypeArgumentsField(function); + const intptr_t context_index = UntaggedClosure::ContextIndex( + has_delayed_type_args, has_instantiator_type_args, + has_function_type_args); + const intptr_t num_elements = context_index + 1; + const intptr_t length_and_flags = UntaggedClosure::EncodeLengthAndFlags( + has_delayed_type_args, has_instantiator_type_args, has_function_type_args, + num_elements); + + const auto& result = Closure::Handle(Closure::New(length_and_flags, space)); + result.set_function(function); + if (has_delayed_type_args) { + result.set_delayed_type_arguments(delayed_type_arguments); + } + if (has_instantiator_type_args) { + result.set_instantiator_type_arguments(instantiator_type_arguments); + } + if (has_function_type_args) { + result.set_function_type_arguments(function_type_arguments); + } + result.SetElementAt(context_index, context); return result.ptr(); } diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 4a2eed62652..28b1894e938 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -548,7 +548,8 @@ class Object { V(Bytecode, implicit_shared_static_getter_bytecode) \ V(Bytecode, implicit_static_setter_bytecode) \ V(Bytecode, implicit_shared_static_setter_bytecode) \ - V(Bytecode, method_extractor_bytecode) \ + V(Bytecode, method_extractor_with_ita_bytecode) \ + V(Bytecode, method_extractor_without_ita_bytecode) \ V(Bytecode, invoke_closure_bytecode) \ V(Bytecode, invoke_field_bytecode) \ V(Bytecode, nsm_dispatcher_bytecode) \ @@ -12652,35 +12653,17 @@ class Closure : public Instance { } #endif - TypeArgumentsPtr instantiator_type_arguments() const { - return untag()->instantiator_type_arguments(); + static intptr_t LengthOf(ClosurePtr ptr) { + return UntaggedClosure::LengthBits::decode( + Smi::Value(ptr->untag()->length_and_flags())); } - void set_instantiator_type_arguments(const TypeArguments& args) const { - untag()->set_instantiator_type_arguments(args.ptr()); - } - static intptr_t instantiator_type_arguments_offset() { - return OFFSET_OF(UntaggedClosure, instantiator_type_arguments_); + intptr_t length() const { return LengthOf(ptr()); } + static intptr_t length_and_flags_offset() { + return OFFSET_OF(UntaggedClosure, length_and_flags_); } - TypeArgumentsPtr function_type_arguments() const { - return untag()->function_type_arguments(); - } - void set_function_type_arguments(const TypeArguments& args) const { - untag()->set_function_type_arguments(args.ptr()); - } - static intptr_t function_type_arguments_offset() { - return OFFSET_OF(UntaggedClosure, function_type_arguments_); - } - - TypeArgumentsPtr delayed_type_arguments() const { - return untag()->delayed_type_arguments(); - } - void set_delayed_type_arguments(const TypeArguments& args) const { - untag()->set_delayed_type_arguments(args.ptr()); - } - static intptr_t delayed_type_arguments_offset() { - return OFFSET_OF(UntaggedClosure, delayed_type_arguments_); - } + SmiPtr hash() const { return untag()->hash(); } + static intptr_t hash_offset() { return OFFSET_OF(UntaggedClosure, hash_); } FunctionPtr function() const { return untag()->function(); } static intptr_t function_offset() { @@ -12689,8 +12672,149 @@ class Closure : public Instance { static FunctionPtr FunctionOf(ClosurePtr closure) { return closure.untag()->function(); } + void set_function(const Function& function) const { + untag()->set_function(function.ptr()); +#if defined(DART_PRECOMPILED_RUNTIME) + untag()->entry_point_ = function.entry_point(); +#endif + } - ObjectPtr RawContext() const { return untag()->context(); } + ObjectPtr ElementAt(intptr_t index) const { + ASSERT((0 <= index) && (index < length())); + return untag()->element(index); + } + void SetElementAt(intptr_t index, const Object& value) const { + ASSERT((0 <= index) && (index < length())); + untag()->set_element(index, value.ptr()); + } + + static constexpr intptr_t kBytesPerElement = kCompressedWordSize; + static constexpr intptr_t kMaxElements = + UntaggedClosure::LengthBits::max() / kBytesPerElement; + + static constexpr bool IsValidLength(intptr_t length) { + return 0 <= length && length <= kMaxElements; + } + + struct ArrayTraits { + static intptr_t elements_start_offset() { return sizeof(UntaggedClosure); } + static constexpr intptr_t kElementSize = kBytesPerElement; + }; + + static intptr_t element_offset(intptr_t index) { + return OFFSET_OF_RETURNED_VALUE(UntaggedClosure, data) + + kBytesPerElement * index; + } + static intptr_t element_index_at_offset(intptr_t offset_in_bytes) { + const intptr_t index = + (offset_in_bytes - OFFSET_OF_RETURNED_VALUE(UntaggedClosure, data)) / + kBytesPerElement; + ASSERT(index >= 0); + return index; + } + + static intptr_t InstanceSize() { + ASSERT(sizeof(UntaggedClosure) == + OFFSET_OF_RETURNED_VALUE(UntaggedClosure, data)); + return 0; + } + + static intptr_t InstanceSize(intptr_t num_elements) { + return RoundedAllocationSize(sizeof(UntaggedClosure) + + (num_elements * kBytesPerElement)); + } + + bool has_delayed_type_arguments() const { + return UntaggedClosure::HasDelayedTypeArgumentsBit::decode( + Smi::Value(untag()->length_and_flags())); + } + bool has_instantiator_type_arguments() const { + return UntaggedClosure::HasInstantiatorTypeArgumentsBit::decode( + Smi::Value(untag()->length_and_flags())); + } + bool has_function_type_arguments() const { + return UntaggedClosure::HasFunctionTypeArgumentsBit::decode( + Smi::Value(untag()->length_and_flags())); + } + + intptr_t delayed_type_arguments_index() const { + ASSERT(has_delayed_type_arguments()); + return UntaggedClosure::kDelayedTypeArgumentsIndex; + } + intptr_t instantiator_type_arguments_index() const { + ASSERT(has_instantiator_type_arguments()); + return UntaggedClosure::InstantiatorTypeArgumentsIndexBits::decode( + Smi::Value(untag()->length_and_flags())); + } + intptr_t function_type_arguments_index() const { + ASSERT(has_function_type_arguments()); + return UntaggedClosure::FunctionTypeArgumentsIndexBits::decode( + Smi::Value(untag()->length_and_flags())); + } + + TypeArgumentsPtr delayed_type_arguments() const { + return has_delayed_type_arguments() ? TypeArguments::RawCast(ElementAt( + delayed_type_arguments_index())) + : TypeArguments::null(); + } + static TypeArgumentsPtr delayed_type_arguments(ClosurePtr ptr) { + return UntaggedClosure::HasDelayedTypeArgumentsBit::decode( + Smi::Value(ptr.untag()->length_and_flags())) + ? TypeArguments::RawCast(ptr.untag()->element( + UntaggedClosure::kDelayedTypeArgumentsIndex)) + : TypeArguments::null(); + } + void set_delayed_type_arguments(const TypeArguments& args) const { + SetElementAt(delayed_type_arguments_index(), args); + } + + TypeArgumentsPtr instantiator_type_arguments() const { + return has_instantiator_type_arguments() + ? TypeArguments::RawCast( + ElementAt(instantiator_type_arguments_index())) + : TypeArguments::null(); + } + static TypeArgumentsPtr instantiator_type_arguments(ClosurePtr ptr) { + const intptr_t length_and_flags = + Smi::Value(ptr.untag()->length_and_flags()); + return UntaggedClosure::HasInstantiatorTypeArgumentsBit::decode( + length_and_flags) + ? TypeArguments::RawCast(ptr.untag()->element( + UntaggedClosure::InstantiatorTypeArgumentsIndexBits:: + decode(length_and_flags))) + : TypeArguments::null(); + } + void set_instantiator_type_arguments(const TypeArguments& args) const { + SetElementAt(instantiator_type_arguments_index(), args); + } + + TypeArgumentsPtr function_type_arguments() const { + return has_function_type_arguments() ? TypeArguments::RawCast(ElementAt( + function_type_arguments_index())) + : TypeArguments::null(); + } + static TypeArgumentsPtr function_type_arguments(ClosurePtr ptr) { + const intptr_t length_and_flags = + Smi::Value(ptr.untag()->length_and_flags()); + return UntaggedClosure::HasFunctionTypeArgumentsBit::decode( + length_and_flags) + ? TypeArguments::RawCast(ptr.untag()->element( + UntaggedClosure::FunctionTypeArgumentsIndexBits::decode( + length_and_flags))) + : TypeArguments::null(); + } + void set_function_type_arguments(const TypeArguments& args) const { + SetElementAt(function_type_arguments_index(), args); + } + + static ObjectPtr RawContextOf(ClosurePtr ptr) { + return ptr->untag()->element(LengthOf(ptr) - 1); + } + ObjectPtr RawContext() const { return RawContextOf(ptr()); } + + void SetRawContext(const Object& context) const { + SetElementAt(length() - 1, context); + } ContextPtr GetContext() const { ASSERT(!Function::IsImplicitClosureFunction(function())); @@ -12702,21 +12826,11 @@ class Closure : public Instance { return Instance::RawCast(RawContext()); } - static intptr_t context_offset() { - return OFFSET_OF(UntaggedClosure, context_); - } - // Returns whether the closure is generic, that is, it has a generic closure // function and no delayed type arguments. bool IsGeneric() const { - return delayed_type_arguments() == Object::empty_type_arguments().ptr(); - } - - SmiPtr hash() const { return untag()->hash(); } - static intptr_t hash_offset() { return OFFSET_OF(UntaggedClosure, hash_); } - - static intptr_t InstanceSize() { - return RoundedAllocationSize(sizeof(UntaggedClosure)); + return has_delayed_type_arguments() && + (delayed_type_arguments() == Object::empty_type_arguments().ptr()); } virtual void CanonicalizeFieldsLocked(Thread* thread) const; @@ -12726,6 +12840,24 @@ class Closure : public Instance { } uword ComputeHash() const; + static bool HasDelayedTypeArgumentsField(const Function& function) { + ASSERT(function.IsClosureFunction()); + return function.IsGeneric(); + } + + static bool HasInstantiatorTypeArgumentsField(const Function& function) { + ASSERT(function.IsClosureFunction()); + return !function.HasInstantiatedSignature(kCurrentClass); + } + + static bool HasFunctionTypeArgumentsField(const Function& function) { + ASSERT(function.IsClosureFunction()); + return function.HasGenericParent(); + } + + static ClosurePtr New(intptr_t length_and_flags, + Heap::Space space = Heap::kNew); + static ClosurePtr New(const TypeArguments& instantiator_type_arguments, const TypeArguments& function_type_arguments, const Function& function, diff --git a/runtime/vm/object_graph_copy.cc b/runtime/vm/object_graph_copy.cc index 9dbbb4e5e7a..5e16127e42f 100644 --- a/runtime/vm/object_graph_copy.cc +++ b/runtime/vm/object_graph_copy.cc @@ -167,7 +167,7 @@ static bool CanShareObject(ObjectPtr obj, uword tags) { if (cid == kClosureCid) { // We can share a closure iff it doesn't close over any state. - return Closure::RawCast(obj)->untag()->context() == Object::null(); + return Closure::RawContextOf(Closure::RawCast(obj)) == Object::null(); } // All other objects that have immutability bit set are deeply immutable. @@ -290,6 +290,9 @@ void UpdateLengthField(intptr_t cid, ObjectPtr from, ObjectPtr to) { if (cid == kArrayCid || cid == kImmutableArrayCid) { static_cast(to.untag())->length_ = static_cast(from.untag())->length_; + } else if (cid == kClosureCid) { + static_cast(to.untag())->length_and_flags_ = + static_cast(from.untag())->length_and_flags_; } else if (cid == kContextCid) { static_cast(to.untag())->num_variables_ = static_cast(from.untag())->num_variables_; @@ -1779,14 +1782,16 @@ class ObjectCopy : public Base { Base::ForwardCompressedPointers(from, to, kWordSize, instance_size); } void CopyClosure(typename Types::Closure from, typename Types::Closure to) { - Base::StoreCompressedPointers( - from, to, OFFSET_OF(UntaggedClosure, instantiator_type_arguments_), - OFFSET_OF(UntaggedClosure, function_)); - Base::ForwardCompressedPointer(from, to, - OFFSET_OF(UntaggedClosure, context_)); - Base::StoreCompressedPointersNoBarrier(from, to, - OFFSET_OF(UntaggedClosure, hash_), - OFFSET_OF(UntaggedClosure, hash_)); + const intptr_t length = Closure::LengthOf(Types::GetClosurePtr(from)); + Base::StoreCompressedPointersNoBarrier( + from, to, OFFSET_OF(UntaggedClosure, length_and_flags_), + OFFSET_OF(UntaggedClosure, hash_)); + Base::StoreCompressedPointers(from, to, + OFFSET_OF(UntaggedClosure, function_), + OFFSET_OF(UntaggedClosure, function_)); + Base::ForwardCompressedPointers( + from, to, Closure::element_offset(0), + Closure::element_offset(0) + Closure::kBytesPerElement * length); ONLY_IN_PRECOMPILED(UntagClosure(to)->entry_point_ = UntagClosure(from)->entry_point_); } diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h index 5dc06570bd7..9feb53b6581 100644 --- a/runtime/vm/object_store.h +++ b/runtime/vm/object_store.h @@ -250,10 +250,10 @@ class ObjectPointerVisitor; RW(Code, allocate_float32x4_array_stub) \ RW(Code, allocate_int32x4_array_stub) \ RW(Code, allocate_float64x2_array_stub) \ - RW(Code, allocate_closure_stub) \ - RW(Code, allocate_closure_generic_stub) \ - RW(Code, allocate_closure_ta_stub) \ - RW(Code, allocate_closure_ta_generic_stub) \ + RW(Code, allocate_closure1_stub) \ + RW(Code, allocate_closure2_stub) \ + RW(Code, allocate_closure3_stub) \ + RW(Code, allocate_closure4_stub) \ RW(Code, allocate_context_stub) \ RW(Code, allocate_growable_array_stub) \ RW(Code, allocate_object_stub) \ @@ -358,10 +358,10 @@ class ObjectPointerVisitor; DO(allocate_float32x4_array_stub, AllocateFloat32x4Array) \ DO(allocate_int32x4_array_stub, AllocateInt32x4Array) \ DO(allocate_float64x2_array_stub, AllocateFloat64x2Array) \ - DO(allocate_closure_stub, AllocateClosure) \ - DO(allocate_closure_generic_stub, AllocateClosureGeneric) \ - DO(allocate_closure_ta_stub, AllocateClosureTA) \ - DO(allocate_closure_ta_generic_stub, AllocateClosureTAGeneric) \ + DO(allocate_closure1_stub, AllocateClosure1) \ + DO(allocate_closure2_stub, AllocateClosure2) \ + DO(allocate_closure3_stub, AllocateClosure3) \ + DO(allocate_closure4_stub, AllocateClosure4) \ DO(allocate_context_stub, AllocateContext) \ DO(allocate_growable_array_stub, AllocateGrowableArray) \ DO(allocate_object_stub, AllocateObject) \ diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h index 7f1ddf9ff90..150ed5cac09 100644 --- a/runtime/vm/parser.h +++ b/runtime/vm/parser.h @@ -256,7 +256,10 @@ class ParsedFunction : public ZoneObject { V(current_num_processed, Smi, CurrentNumProcessed) \ V(current_param_index, Smi, CurrentParamIndex) \ V(current_type_param, Dynamic, CurrentTypeParam) \ - V(function_type_args, Dynamic, FunctionTypeArgs) + V(function_type_args, Dynamic, FunctionTypeArgs) \ + V(instantiator_type_args, Dynamic, InstantiatorTypeArgs) \ + V(parent_function_type_args, Dynamic, ParentFunctionTypeArgs) \ + V(delayed_type_args, Dynamic, DelayedTypeArgs) #define DEFINE_FIELD(Name, _, __) LocalVariable* Name = nullptr; FOR_EACH_DYNAMIC_CLOSURE_CALL_VARIABLE(DEFINE_FIELD) diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc index 9512d7e8a09..3a454e6e333 100644 --- a/runtime/vm/profiler_test.cc +++ b/runtime/vm/profiler_test.cc @@ -1020,7 +1020,7 @@ ISOLATE_UNIT_TEST_CASE(Profiler_ClosureAllocation) { ProfileStackWalker walker(&profile); EXPECT_SUBSTRING("DRT_AllocateClosure", walker.VMTagName()); - EXPECT_STREQ("[Stub] AllocateClosure", walker.CurrentName()); + EXPECT_STREQ("[Stub] AllocateClosure1", walker.CurrentName()); EXPECT(walker.Down()); EXPECT_SUBSTRING("foo", walker.CurrentName()); EXPECT(!walker.Down()); diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc index 9c56e16738c..72d2ef8abee 100644 --- a/runtime/vm/raw_object.cc +++ b/runtime/vm/raw_object.cc @@ -103,6 +103,13 @@ intptr_t UntaggedObject::HeapSizeFromClass(uword tags) const { instance_size = InstructionsSection::InstanceSize(section_size); break; } + case kClosureCid: { + const ClosurePtr raw_closure = static_cast(this); + intptr_t num_elements = UntaggedClosure::LengthBits::decode( + Smi::Value(raw_closure->untag()->length_and_flags())); + instance_size = Closure::InstanceSize(num_elements); + break; + } case kContextCid: { const ContextPtr raw_context = static_cast(this); intptr_t num_variables = raw_context->untag()->num_variables_; @@ -526,7 +533,9 @@ COMPRESSED_VISITOR(FunctionType) COMPRESSED_VISITOR(RecordType) COMPRESSED_VISITOR(TypeParameter) COMPRESSED_VISITOR(Function) -COMPRESSED_VISITOR(Closure) +VARIABLE_COMPRESSED_VISITOR(Closure, + UntaggedClosure::LengthBits::decode(Smi::Value( + raw_obj->untag()->length_and_flags()))) COMPRESSED_VISITOR(LibraryPrefix) COMPRESSED_VISITOR(Bytecode) REGULAR_VISITOR(SingleTargetCache) diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 23ac3dc7327..65fcd12a780 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -3100,53 +3100,106 @@ class UntaggedTypeParameter : public UntaggedAbstractType { }; class UntaggedClosure : public UntaggedInstance { + public: + using HasDelayedTypeArgumentsBit = BitField; + static constexpr intptr_t kHasDelayedTypeArgumentsBit = + HasDelayedTypeArgumentsBit::shift(); + + using HasInstantiatorTypeArgumentsBit = + BitField; + static constexpr intptr_t kHasInstantiatorTypeArgumentsBit = + HasInstantiatorTypeArgumentsBit::shift(); + + using HasFunctionTypeArgumentsBit = + BitField; + static constexpr intptr_t kHasFunctionTypeArgumentsBit = + HasFunctionTypeArgumentsBit::shift(); + + // Same as HasDelayedTypeArgumentsBit. + using InstantiatorTypeArgumentsIndexBits = + BitField; + + using FunctionTypeArgumentsIndexBits = + BitField; + static constexpr intptr_t kFunctionTypeArgumentsIndexBitsPos = + FunctionTypeArgumentsIndexBits::shift(); + static constexpr intptr_t kFunctionTypeArgumentsIndexBitsSize = + FunctionTypeArgumentsIndexBits::bitsize(); + + using LengthBits = BitField; + static_assert(LengthBits::kNextBit <= compiler::target::kSmiBits, + "Length and flags should fit into a Smi"); + static constexpr intptr_t kLengthBitsPos = LengthBits::shift(); + static constexpr intptr_t kLengthBitsSize = LengthBits::bitsize(); + + static constexpr intptr_t kDelayedTypeArgumentsIndex = 0; + + static intptr_t InstantiatorTypeArgumentsIndex(bool has_delayed_type_args) { + return static_cast(has_delayed_type_args); + } + static intptr_t FunctionTypeArgumentsIndex(bool has_delayed_type_args, + bool has_instantiator_type_args) { + return static_cast(has_delayed_type_args) + + static_cast(has_instantiator_type_args); + } + static intptr_t ContextIndex(bool has_delayed_type_args, + bool has_instantiator_type_args, + bool has_function_type_args) { + return static_cast(has_delayed_type_args) + + static_cast(has_instantiator_type_args) + + static_cast(has_function_type_args); + } + + static intptr_t EncodeLengthAndFlags(bool has_delayed_type_args, + bool has_instantiator_type_args, + bool has_function_type_args, + intptr_t num_elements) { + return HasDelayedTypeArgumentsBit::encode(has_delayed_type_args) | + HasInstantiatorTypeArgumentsBit::encode(has_instantiator_type_args) | + HasFunctionTypeArgumentsBit::encode(has_function_type_args) | + FunctionTypeArgumentsIndexBits::encode( + has_function_type_args + ? FunctionTypeArgumentsIndex(has_delayed_type_args, + has_instantiator_type_args) + : 0) | + LengthBits::encode(num_elements); + } + private: RAW_HEAP_OBJECT_IMPLEMENTATION(Closure); - // The following fields are also declared in the Dart source of class - // _Closure, and so must be the first fields in the object and must appear - // in the same order, so the offsets are identical in Dart and C++. - // - // Note that the type of a closure is defined by instantiating the - // signature of the closure function with the instantiator, function, and - // delayed (if non-empty) type arguments stored in the closure value. - - // Stores the instantiator type arguments provided when the closure was - // created. - COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, instantiator_type_arguments) - VISIT_FROM(instantiator_type_arguments) - // Stores the function type arguments provided for any generic parent - // functions when the closure was created. - COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, function_type_arguments) - // If this field contains the empty type argument vector, then the closure - // value is generic. - // - // To create a new closure that is a specific type instantiation of a generic - // closure, a copy of the closure is created where the empty type argument - // vector in this field is replaced with the vector of local type arguments. - // The resulting closure value is not generic, and so an attempt to provide - // type arguments when invoking the new closure value is treated the same as - // calling any other non-generic function with unneeded type arguments. - // - // If the signature for the closure function has no local type parameters, - // the only guarantee about this field is that it never contains the empty - // type arguments vector. Thus, only this field need be inspected to - // determine whether a given closure value is generic. - COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, delayed_type_arguments) - COMPRESSED_POINTER_FIELD(FunctionPtr, function) - // For tear-offs - captured receiver. - // For ordinary closures - Context object with captured variables. - COMPRESSED_POINTER_FIELD(ObjectPtr, context) - COMPRESSED_POINTER_FIELD(SmiPtr, hash) - VISIT_TO(hash) - - // We have an extra word in the object due to alignment rounding, so use it in - // bare instructions mode to cache the entry point from the closure function - // to avoid an extra redirection on call. Closure functions only have - // one entry point, as dynamic calls use dynamic closure call dispatchers. + // Cached entry point from the closure function to avoid an extra + // indirection on call. Closure functions only have one entry point, + // as dynamic calls use dynamic closure call dispatchers. ONLY_IN_PRECOMPILED(uword entry_point_); - CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); } + COMPRESSED_SMI_FIELD(SmiPtr, length_and_flags) + VISIT_FROM(length_and_flags) + COMPRESSED_SMI_FIELD(SmiPtr, hash) + COMPRESSED_POINTER_FIELD(FunctionPtr, function) + + // Variable length data follows here. + // It contains (in order): + // - delayed type arguments (if function is generic); + // - instantiator type arguments (if enclosing class is generic); + // - parent function type arguments (if enclosing function has type args); + // - captured values and contexts. + COMPRESSED_VARIABLE_POINTER_FIELDS(ObjectPtr, element, data) + + CompressedObjectPtr* to_snapshot(Snapshot::Kind kind, intptr_t num_elements) { + return to(num_elements); + } + + friend void UpdateLengthField(intptr_t, + ObjectPtr, + ObjectPtr); // length_and_flags friend class Interpreter; friend class UnitDeserializationRoots; diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc index d08b3d2a36d..8ad2257de96 100644 --- a/runtime/vm/raw_object_fields.cc +++ b/runtime/vm/raw_object_fields.cc @@ -151,11 +151,8 @@ namespace dart { F(TypeParameters, flags_) \ F(TypeParameters, bounds_) \ F(TypeParameters, defaults_) \ - F(Closure, instantiator_type_arguments_) \ - F(Closure, function_type_arguments_) \ - F(Closure, delayed_type_arguments_) \ F(Closure, function_) \ - F(Closure, context_) \ + F(Closure, length_and_flags_) \ F(Closure, hash_) \ F(String, length_) \ F(Array, type_arguments_) \ diff --git a/runtime/vm/roots.h b/runtime/vm/roots.h index 4228cbdf9f9..977ffde4faf 100644 --- a/runtime/vm/roots.h +++ b/runtime/vm/roots.h @@ -89,7 +89,8 @@ namespace dart { V(Bytecode, implicit_shared_static_getter_bytecode) \ V(Bytecode, implicit_static_setter_bytecode) \ V(Bytecode, implicit_shared_static_setter_bytecode) \ - V(Bytecode, method_extractor_bytecode) \ + V(Bytecode, method_extractor_with_ita_bytecode) \ + V(Bytecode, method_extractor_without_ita_bytecode) \ V(Bytecode, invoke_closure_bytecode) \ V(Bytecode, invoke_field_bytecode) \ V(Bytecode, nsm_dispatcher_bytecode) \ diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc index 342a3847b84..8c517c1514b 100644 --- a/runtime/vm/runtime_entry.cc +++ b/runtime/vm/runtime_entry.cc @@ -852,24 +852,21 @@ DEFINE_RUNTIME_ENTRY(SubtypeCheck, 5) { UNREACHABLE(); } -// Allocate a new closure and initializes its function, context, -// instantiator type arguments and delayed type arguments fields. +// Allocate a new closure and initializes its function, length, +// flags, context, hash and entry point. // Arg0: function. -// Arg1: context. -// Arg2: instantiator type arguments. -// Arg3: delayed type arguments. +// Arg1: length and flags. +// Arg2: context. // Return value: newly allocated closure. -DEFINE_RUNTIME_ENTRY(AllocateClosure, 4) { +DEFINE_RUNTIME_ENTRY(AllocateClosure, 3) { const auto& function = Function::CheckedHandle(zone, arguments.ArgAt(0)); - const auto& context = Object::Handle(zone, arguments.ArgAt(1)); - const auto& instantiator_type_args = - TypeArguments::CheckedHandle(zone, arguments.ArgAt(2)); - const auto& delayed_type_args = - TypeArguments::CheckedHandle(zone, arguments.ArgAt(3)); + const intptr_t length_and_flags = + Smi::CheckedHandle(zone, arguments.ArgAt(1)).Value(); + const auto& context = Object::Handle(zone, arguments.ArgAt(2)); const Closure& closure = Closure::Handle( - zone, Closure::New(instantiator_type_args, Object::null_type_arguments(), - delayed_type_args, function, context, - SpaceForRuntimeAllocation())); + zone, Closure::New(length_and_flags, SpaceForRuntimeAllocation())); + closure.set_function(function); + closure.SetRawContext(context); arguments.SetReturn(closure); RuntimeAllocationEpilogue(thread); } diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc index a5038520cdc..99c5f6274b0 100644 --- a/runtime/vm/stub_code.cc +++ b/runtime/vm/stub_code.cc @@ -226,7 +226,7 @@ CodePtr StubCode::GetAllocationStubForClass(const Class& cls) { case kInt32x4Cid: return object_store->allocate_int32x4_stub(); case kClosureCid: - return object_store->allocate_closure_stub(); + return object_store->allocate_closure1_stub(); case kRecordCid: return object_store->allocate_record_stub(); } diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h index 9625918343c..88ba1a99d48 100644 --- a/runtime/vm/stub_code_list.h +++ b/runtime/vm/stub_code_list.h @@ -59,10 +59,10 @@ namespace dart { V(AllocateFloat64x2Array) \ V(AllocateMintSharedWithFPURegs) \ V(AllocateMintSharedWithoutFPURegs) \ - V(AllocateClosure) \ - V(AllocateClosureGeneric) \ - V(AllocateClosureTA) \ - V(AllocateClosureTAGeneric) \ + V(AllocateClosure1) \ + V(AllocateClosure2) \ + V(AllocateClosure3) \ + V(AllocateClosure4) \ V(AllocateContext) \ V(AllocateGrowableArray) \ V(AllocateObject) \ diff --git a/runtime/vm/symbol_list.h b/runtime/vm/symbol_list.h index a4d6ae90f70..b7da24a873b 100644 --- a/runtime/vm/symbol_list.h +++ b/runtime/vm/symbol_list.h @@ -97,7 +97,11 @@ namespace dart { V(DynamicCallCurrentNumProcessedVar, ":dyn_call_current_num_processed") \ V(DynamicCallCurrentParamIndexVar, ":dyn_call_current_param_index") \ V(DynamicCallCurrentTypeParamVar, ":dyn_call_current_type_param") \ + V(DynamicCallDelayedTypeArgsVar, ":dyn_call_delayed_type_args") \ V(DynamicCallFunctionTypeArgsVar, ":dyn_call_function_type_args") \ + V(DynamicCallInstantiatorTypeArgsVar, ":dyn_call_instantiator_type_args") \ + V(DynamicCallParentFunctionTypeArgsVar, \ + ":dyn_call_parent_function_type_args") \ V(DynamicImplicitCall, "dyn:implicit:call") \ V(DynamicPrefix, "dyn:") \ V(EntryPointsTemp, ":entry_points_temp") \ diff --git a/sdk/lib/_internal/vm/lib/function.dart b/sdk/lib/_internal/vm/lib/function.dart index 62cbe0a1b41..253bea112fc 100644 --- a/sdk/lib/_internal/vm/lib/function.dart +++ b/sdk/lib/_internal/vm/lib/function.dart @@ -14,44 +14,21 @@ final class _Closure implements Function { external bool operator ==(Object other); int get hashCode { - _hash ??= _computeHash(); - return _hash; + int hash = _hash; + if (hash == 0) { + hash = _computeHash(); + } + return hash; } @pragma("vm:entry-point") _Closure get call => this; + @pragma("vm:recognized", "other") + @pragma("vm:prefer-inline") + external int get _hash; + @pragma("vm:external-name", "Closure_computeHash") + @pragma("vm:exact-result-type", "dart:core#_Smi") external int _computeHash(); - - // No instance fields should be declared before the following fields whose - // offsets must be identical in Dart and C++. - - // The following fields are declared both in raw_object.h (for direct access - // from C++ code) and also here so that the offset-to-field map used by - // deferred objects is properly initialized. - // Caution: These fields are not Dart instances, but VM objects. Their Dart - // names do not need to match the C++ names, but they must be private. - @pragma("vm:entry-point") - var _instantiator_type_arguments; - @pragma("vm:entry-point") - var _function_type_arguments; - @pragma("vm:entry-point") - var _delayed_type_arguments; - @pragma("vm:entry-point") - var _function; - @pragma("vm:entry-point") - var _context; - - // Note: _Closure objects are created by VM "magically", without invoking - // constructor. So, _Closure default constructor is never compiled and - // detection of default-initialized fields is not performed. - // As a consequence, VM incorrectly assumes that _hash field is not - // nullable and may incorrectly remove 'if (_hash == null)' in get:hashCode. - // This initializer makes _hash field nullable even without constructor - // compilation. - @pragma("vm:entry-point") - // Harmless race lazily computing the hash. - @pragma("vm:no-sanitize-thread") - var _hash = null; }