| // Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'package:kernel/ast.dart' as ast show Class; | |
| import 'package:native_compiler/back_end/code.dart'; | |
| import 'package:native_compiler/back_end/locations.dart'; | |
| /// Interface class for architecture-specific stub code generator. | |
| abstract interface class StubCodeGenerator { | |
| Code generate(String name); | |
| } | |
| /// Base class for architecture-specific stub factory. | |
| /// | |
| /// Generates and caches stubs on demand. | |
| abstract base class StubFactory { | |
| final CodeConsumer consumeGeneratedCode; | |
| Map<ast.Class, Code> _allocationStubs = {}; | |
| Map<(Register, Register, bool), Code> _writeBarrierStubs = {}; | |
| List<Code?> _subtypeTestCacheStubs = List<Code?>.filled(8, null); | |
| late final Code dynamicCallStub = _generateCode( | |
| 'DynamicCallStub', | |
| dynamicCallStubGenerator(), | |
| ); | |
| late final Code dynamicInvocationForwarderStub = _generateCode( | |
| 'DynamicInvocationForwarderStub', | |
| dynamicInvocationForwarderStubGenerator(), | |
| ); | |
| StubFactory(this.consumeGeneratedCode); | |
| StubCodeGenerator allocationStubGenerator(ast.Class cls); | |
| StubCodeGenerator writeBarrierStubGenerator( | |
| Register objectReg, | |
| Register valueReg, | |
| bool isArray, | |
| ); | |
| StubCodeGenerator dynamicCallStubGenerator(); | |
| StubCodeGenerator dynamicInvocationForwarderStubGenerator(); | |
| StubCodeGenerator subtypeTestCacheStubGenerator(int n); | |
| Code _generateCode(String name, StubCodeGenerator generator) { | |
| final code = generator.generate(name); | |
| consumeGeneratedCode(code); | |
| return code; | |
| } | |
| Code getAllocationStub(ast.Class cls) => _allocationStubs[cls] ??= | |
| _generateCode('AllocationStub for ${cls}', allocationStubGenerator(cls)); | |
| Code getWriteBarrierStub( | |
| Register objectReg, | |
| Register valueReg, | |
| bool isArray, | |
| ) => _writeBarrierStubs[(objectReg, valueReg, isArray)] ??= _generateCode( | |
| 'WriteBarrierStub for $objectReg, $valueReg${isArray ? ' array' : ''}', | |
| writeBarrierStubGenerator(objectReg, valueReg, isArray), | |
| ); | |
| Code getSubtypeTestCacheStub(int numInputs) => | |
| _subtypeTestCacheStubs[numInputs] ??= _generateCode( | |
| 'SubtypeTestCacheStub', | |
| subtypeTestCacheStubGenerator(numInputs), | |
| ); | |
| } |