From 0c481a196ce3747663750559469b0c32449e7a5f Mon Sep 17 00:00:00 2001 From: Alexander Aprelev Date: Thu, 12 Sep 2019 00:10:09 +0000 Subject: [PATCH] Revert Reland '[vm/ffi] Implement FFI callbacks on AOT for ELF and Asm snapshots (excl. blobs).' as it breaks flutter profile execution on ios 32-bit platform. Fixes https://github.com/flutter/flutter/issues/40114 Change-Id: If8d71e9c19c2e794d29f7ecbacb87457890a2fd5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/116883 Reviewed-by: Alexander Markov Commit-Queue: Alexander Aprelev --- pkg/front_end/lib/src/api_unstable/vm.dart | 16 +- .../lib/src/fasta/fasta_codes_generated.dart | 87 +- pkg/front_end/messages.status | 4 - pkg/front_end/messages.yaml | 26 +- .../test/spell_checking_list_common.txt | 1 - pkg/vm/lib/transformations/ffi.dart | 6 - pkg/vm/lib/transformations/ffi_use_sites.dart | 186 +-- runtime/bin/ffi_test/ffi_test_functions.cc | 2 +- runtime/lib/ffi.cc | 245 ++-- runtime/lib/ffi_patch.dart | 29 +- runtime/vm/bootstrap_natives.h | 3 +- runtime/vm/bss_relocs.cc | 17 - runtime/vm/bss_relocs.h | 29 - runtime/vm/clustered_snapshot.cc | 24 +- runtime/vm/code_descriptors.cc | 7 +- runtime/vm/compiler/assembler/assembler.cc | 25 - runtime/vm/compiler/assembler/assembler.h | 6 +- runtime/vm/compiler/assembler/assembler_arm.h | 2 +- .../vm/compiler/assembler/assembler_arm64.h | 2 +- runtime/vm/compiler/assembler/assembler_dbc.h | 1 - .../vm/compiler/assembler/assembler_ia32.h | 2 +- runtime/vm/compiler/assembler/assembler_x64.h | 2 +- .../compiler/backend/flow_graph_compiler.cc | 11 +- .../vm/compiler/backend/flow_graph_compiler.h | 2 - runtime/vm/compiler/backend/il_arm.cc | 49 +- runtime/vm/compiler/backend/il_arm64.cc | 35 +- runtime/vm/compiler/backend/il_ia32.cc | 5 +- runtime/vm/compiler/backend/il_x64.cc | 41 +- runtime/vm/compiler/ffi.cc | 73 +- runtime/vm/compiler/ffi.h | 7 +- .../frontend/bytecode_flow_graph_builder.cc | 50 +- .../frontend/bytecode_flow_graph_builder.h | 1 - .../frontend/kernel_binary_flowgraph.cc | 67 +- .../frontend/kernel_binary_flowgraph.h | 4 - runtime/vm/compiler/frontend/kernel_to_il.cc | 26 +- runtime/vm/compiler/recognized_methods_list.h | 2 - runtime/vm/compiler/runtime_api.h | 1 - runtime/vm/elf.cc | 49 +- runtime/vm/elf.h | 3 - runtime/vm/ffi_callback_trampolines.cc | 22 +- runtime/vm/ffi_callback_trampolines.h | 6 +- runtime/vm/image_snapshot.cc | 120 +- runtime/vm/image_snapshot.h | 14 +- runtime/vm/native_entry.h | 21 +- runtime/vm/object.cc | 23 +- runtime/vm/object.h | 3 - runtime/vm/raw_object.h | 4 +- runtime/vm/symbols.h | 1 - runtime/vm/thread.cc | 22 +- runtime/vm/thread.h | 8 +- runtime/vm/vm_sources.gni | 2 - sdk/lib/ffi/ffi.dart | 3 +- sdk_nnbd/lib/ffi/ffi.dart | 3 +- tests/ffi/ffi.status | 14 +- tests/ffi/function_callbacks_test.dart | 1036 +---------------- .../function_callbacks_unsupported_test.dart | 19 - tests/ffi/static_checks_test.dart | 5 - tools/VERSION | 4 +- 58 files changed, 360 insertions(+), 2118 deletions(-) delete mode 100644 runtime/vm/bss_relocs.cc delete mode 100644 runtime/vm/bss_relocs.h delete mode 100644 tests/ffi/function_callbacks_unsupported_test.dart diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart index 38dc0425983..47691d791f9 100644 --- a/pkg/front_end/lib/src/api_unstable/vm.dart +++ b/pkg/front_end/lib/src/api_unstable/vm.dart @@ -40,23 +40,19 @@ export '../fasta/fasta_codes.dart' show LocatedMessage, messageBytecodeLimitExceededTooManyArguments, - messageFfiExceptionalReturnNull, - messageFfiExpectedConstant, noLength, - templateFfiDartTypeMismatch, - templateFfiExpectedExceptionalReturn, - templateFfiExpectedNoExceptionalReturn, - templateFfiExtendsOrImplementsSealedClass, templateFfiFieldAnnotation, - templateFfiFieldInitializer, templateFfiFieldNoAnnotation, templateFfiNotStatic, - templateFfiStructGeneric, templateFfiTypeInvalid, templateFfiTypeMismatch, templateFfiTypeUnsized, - templateFfiWrongStructInheritance, - templateIllegalRecursiveType; + templateFfiFieldInitializer, + templateIllegalRecursiveType, + templateFfiDartTypeMismatch, + templateFfiExtendsOrImplementsSealedClass, + templateFfiStructGeneric, + templateFfiWrongStructInheritance; export '../fasta/hybrid_file_system.dart' show HybridFileSystem; diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart index d5482bf6946..c03ad77d7e1 100644 --- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart +++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart @@ -3754,81 +3754,6 @@ Message _withArgumentsFfiDartTypeMismatch(DartType _type, DartType _type2) { arguments: {'type': _type, 'type2': _type2}); } -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -const Code codeFfiExceptionalReturnNull = messageFfiExceptionalReturnNull; - -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -const MessageCode messageFfiExceptionalReturnNull = const MessageCode( - "FfiExceptionalReturnNull", - message: r"""Exceptional return value must not be null."""); - -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -const Code codeFfiExpectedConstant = messageFfiExpectedConstant; - -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -const MessageCode messageFfiExpectedConstant = const MessageCode( - "FfiExpectedConstant", - message: r"""Exceptional return value must be a constant."""); - -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -const Template< - Message Function( - DartType - _type)> templateFfiExpectedExceptionalReturn = const Template< - Message Function(DartType _type)>( - messageTemplate: - r"""Expected an exceptional return value for a native callback returning '#type'.""", - withArguments: _withArgumentsFfiExpectedExceptionalReturn); - -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -const Code codeFfiExpectedExceptionalReturn = - const Code( - "FfiExpectedExceptionalReturn", - templateFfiExpectedExceptionalReturn, -); - -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -Message _withArgumentsFfiExpectedExceptionalReturn(DartType _type) { - TypeLabeler labeler = new TypeLabeler(); - List typeParts = labeler.labelType(_type); - String type = typeParts.join(); - return new Message(codeFfiExpectedExceptionalReturn, - message: - """Expected an exceptional return value for a native callback returning '${type}'.""" + - labeler.originMessages, - arguments: {'type': _type}); -} - -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -const Template< - Message Function( - DartType - _type)> templateFfiExpectedNoExceptionalReturn = const Template< - Message Function(DartType _type)>( - messageTemplate: - r"""Exceptional return value cannot be provided for a native callback returning '#type'.""", - withArguments: _withArgumentsFfiExpectedNoExceptionalReturn); - -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -const Code - codeFfiExpectedNoExceptionalReturn = - const Code( - "FfiExpectedNoExceptionalReturn", - templateFfiExpectedNoExceptionalReturn, -); - -// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. -Message _withArgumentsFfiExpectedNoExceptionalReturn(DartType _type) { - TypeLabeler labeler = new TypeLabeler(); - List typeParts = labeler.labelType(_type); - String type = typeParts.join(); - return new Message(codeFfiExpectedNoExceptionalReturn, - message: - """Exceptional return value cannot be provided for a native callback returning '${type}'.""" + - labeler.originMessages, - arguments: {'type': _type}); -} - // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. const Template templateFfiExtendsOrImplementsSealedClass = @@ -3859,7 +3784,7 @@ const Template< Message Function(String name)> templateFfiFieldAnnotation = const Template< Message Function(String name)>( messageTemplate: - r"""Field '#name' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields.""", + r"""Field '#name' requires exactly one annotation to declare its C++ type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields.""", withArguments: _withArgumentsFfiFieldAnnotation); // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. @@ -3875,7 +3800,7 @@ Message _withArgumentsFfiFieldAnnotation(String name) { name = demangleMixinApplicationName(name); return new Message(codeFfiFieldAnnotation, message: - """Field '${name}' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields.""", + """Field '${name}' requires exactly one annotation to declare its C++ type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields.""", arguments: {'name': name}); } @@ -3911,7 +3836,7 @@ const Template< name)> templateFfiFieldNoAnnotation = const Template< Message Function(String name)>( messageTemplate: - r"""Field '#name' requires no annotation to declare its native type, it is a Pointer which is represented by the same type in Dart and native code.""", + r"""Field '#name' requires no annotation to declare its C++ type, it is a Pointer which is represented by the same type in Dart and C++.""", withArguments: _withArgumentsFfiFieldNoAnnotation); // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. @@ -3927,7 +3852,7 @@ Message _withArgumentsFfiFieldNoAnnotation(String name) { name = demangleMixinApplicationName(name); return new Message(codeFfiFieldNoAnnotation, message: - """Field '${name}' requires no annotation to declare its native type, it is a Pointer which is represented by the same type in Dart and native code.""", + """Field '${name}' requires no annotation to declare its C++ type, it is a Pointer which is represented by the same type in Dart and C++.""", arguments: {'name': name}); } @@ -3936,7 +3861,7 @@ const Template< Message Function(String name)> templateFfiNotStatic = const Template< Message Function(String name)>( messageTemplate: - r"""#name expects a static function as parameter. dart:ffi only supports calling static Dart functions from native code.""", + r"""#name expects a static function as parameter. dart:ffi only supports calling static Dart functions from c.""", withArguments: _withArgumentsFfiNotStatic); // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. @@ -3952,7 +3877,7 @@ Message _withArgumentsFfiNotStatic(String name) { name = demangleMixinApplicationName(name); return new Message(codeFfiNotStatic, message: - """${name} expects a static function as parameter. dart:ffi only supports calling static Dart functions from native code.""", + """${name} expects a static function as parameter. dart:ffi only supports calling static Dart functions from c.""", arguments: {'name': name}); } diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status index 8d11e08ce7a..c3a823c1a05 100644 --- a/pkg/front_end/messages.status +++ b/pkg/front_end/messages.status @@ -265,10 +265,6 @@ FfiDartTypeMismatch/analyzerCode: Fail FfiExtendsOrImplementsSealedClass/analyzerCode: Fail FfiStructGeneric/analyzerCode: Fail FfiWrongStructInheritance/analyzerCode: Fail -FfiExpectedExceptionalReturn/analyzerCode: Fail -FfiExpectedNoExceptionalReturn/analyzerCode: Fail -FfiExpectedConstant/analyzerCode: Fail -FfiExceptionalReturnNull/analyzerCode: Fail FieldInitializedOutsideDeclaringClass/part_wrapped_script1: Fail FieldInitializedOutsideDeclaringClass/script1: Fail FieldInitializerOutsideConstructor/part_wrapped_script1: Fail diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml index a1b889cdbe3..773b2675155 100644 --- a/pkg/front_end/messages.yaml +++ b/pkg/front_end/messages.yaml @@ -3495,17 +3495,17 @@ FfiTypeUnsized: FfiFieldAnnotation: # Used by dart:ffi - template: "Field '#name' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields." + template: "Field '#name' requires exactly one annotation to declare its C++ type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields." external: test/ffi_test.dart FfiFieldNoAnnotation: # Used by dart:ffi - template: "Field '#name' requires no annotation to declare its native type, it is a Pointer which is represented by the same type in Dart and native code." + template: "Field '#name' requires no annotation to declare its C++ type, it is a Pointer which is represented by the same type in Dart and C++." external: test/ffi_test.dart FfiNotStatic: # Used by dart:ffi - template: "#name expects a static function as parameter. dart:ffi only supports calling static Dart functions from native code." + template: "#name expects a static function as parameter. dart:ffi only supports calling static Dart functions from c." external: test/ffi_test.dart FfiFieldInitializer: @@ -3533,26 +3533,6 @@ FfiDartTypeMismatch: template: "Expected '#type' to be a subtype of '#type2'." external: test/ffi_test.dart -FfiExpectedExceptionalReturn: - # Used by dart:ffi - template: "Expected an exceptional return value for a native callback returning '#type'." - external: test/ffi_test.dart - -FfiExpectedNoExceptionalReturn: - # Used by dart:ffi - template: "Exceptional return value cannot be provided for a native callback returning '#type'." - external: test/ffi_test.dart - -FfiExpectedConstant: - # Used by dart:ffi - template: "Exceptional return value must be a constant." - external: test/ffi_test.dart - -FfiExceptionalReturnNull: - # Used by dart:ffi - template: "Exceptional return value must not be null." - external: test/ffi_test.dart - SpreadTypeMismatch: template: "Unexpected type '#type' of a spread. Expected 'dynamic' or an Iterable." script: diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt index f27e9504c18..0e5098d0b56 100644 --- a/pkg/front_end/test/spell_checking_list_common.txt +++ b/pkg/front_end/test/spell_checking_list_common.txt @@ -941,7 +941,6 @@ examples exceeded except exception -exceptional exceptions exclamation exclude diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart index 6b473242c0e..667a2e9b261 100644 --- a/pkg/vm/lib/transformations/ffi.dart +++ b/pkg/vm/lib/transformations/ffi.dart @@ -186,8 +186,6 @@ class FfiTransformer extends Transformer { final Constructor structFromPointer; final Procedure libraryLookupMethod; final Procedure abiMethod; - final Procedure pointerFromFunctionProcedure; - final Procedure nativeCallbackFunctionProcedure; /// Classes corresponding to [NativeType], indexed by [NativeType]. final List nativeTypesClasses; @@ -222,10 +220,6 @@ class FfiTransformer extends Transformer { libraryLookupMethod = index.getMember('dart:ffi', 'DynamicLibrary', 'lookup'), abiMethod = index.getTopLevelMember('dart:ffi', '_abi'), - pointerFromFunctionProcedure = - index.getTopLevelMember('dart:ffi', '_pointerFromFunction'), - nativeCallbackFunctionProcedure = - index.getTopLevelMember('dart:ffi', '_nativeCallbackFunction'), nativeTypesClasses = nativeTypeClassNames .map((name) => index.getClass('dart:ffi', name)) .toList(); diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart index d7cc4b5209b..062f3ed9d69 100644 --- a/pkg/vm/lib/transformations/ffi_use_sites.dart +++ b/pkg/vm/lib/transformations/ffi_use_sites.dart @@ -6,16 +6,12 @@ library vm.transformations.ffi_use_sites; import 'package:front_end/src/api_unstable/vm.dart' show - messageFfiExceptionalReturnNull, - messageFfiExpectedConstant, - templateFfiDartTypeMismatch, - templateFfiExpectedExceptionalReturn, - templateFfiExpectedNoExceptionalReturn, - templateFfiExtendsOrImplementsSealedClass, - templateFfiNotStatic, templateFfiTypeInvalid, templateFfiTypeMismatch, - templateFfiTypeUnsized; + templateFfiDartTypeMismatch, + templateFfiTypeUnsized, + templateFfiNotStatic, + templateFfiExtendsOrImplementsSealedClass; import 'package:kernel/ast.dart'; import 'package:kernel/class_hierarchy.dart' show ClassHierarchy; @@ -59,12 +55,7 @@ class _FfiUseSiteTransformer extends FfiTransformer { final Map replacedGetters; final Map replacedSetters; - Library currentLibrary; - bool get isFfiLibrary => currentLibrary == ffiLibrary; - - // Used to create private top-level fields with unique names for each - // callback. - int callbackCount = 0; + bool isFfiLibrary; _FfiUseSiteTransformer( LibraryIndex index, @@ -77,8 +68,7 @@ class _FfiUseSiteTransformer extends FfiTransformer { @override TreeNode visitLibrary(Library node) { - currentLibrary = node; - callbackCount = 0; + isFfiLibrary = node == ffiLibrary; return super.visitLibrary(node); } @@ -88,11 +78,6 @@ class _FfiUseSiteTransformer extends FfiTransformer { try { _ensureNotExtendsOrImplementsSealedClass(node); return super.visitClass(node); - } on _FfiStaticTypeError { - // It's OK to swallow the exception because the diagnostics issued will - // cause compilation to fail. By continuing, we can report more - // diagnostics before compilation ends. - return super.visitClass(node); } finally { env.thisType = null; } @@ -130,89 +115,31 @@ class _FfiUseSiteTransformer extends FfiTransformer { Member target = node.target; try { if (target == fromFunctionMethod) { - final DartType nativeType = + DartType nativeType = InterfaceType(nativeFunctionClass, [node.arguments.types[0]]); - final Expression func = node.arguments.positional[0]; - final DartType dartType = func.getStaticType(env); - - _ensureIsStaticFunction(func); + Expression func = node.arguments.positional[0]; + DartType dartType = func.getStaticType(env); + _ensureIsStatic(func); // TODO(36730): Allow passing/returning structs by value. _ensureNativeTypeValid(nativeType, node); _ensureNativeTypeToDartType(nativeType, dartType, node); // Check `exceptionalReturn`'s type. final FunctionType funcType = dartType; - final NativeType expectedReturn = getType( - ((node.arguments.types[0] as FunctionType).returnType - as InterfaceType) - .classNode); + final Expression exceptionalReturn = node.arguments.positional[1]; + final DartType returnType = exceptionalReturn.getStaticType(env); - if (expectedReturn == NativeType.kVoid || - expectedReturn == NativeType.kPointer) { - if (node.arguments.positional.length > 1) { - diagnosticReporter.report( - templateFfiExpectedNoExceptionalReturn - .withArguments(funcType.returnType), - node.fileOffset, - 1, - node.location.file); - return node; - } - node.arguments.positional.add(NullLiteral()..parent = node); - } else { - // The exceptional return value is not optional for other return - // types. - if (node.arguments.positional.length < 2) { - diagnosticReporter.report( - templateFfiExpectedExceptionalReturn - .withArguments(funcType.returnType), - node.fileOffset, - 1, - node.location.file); - return node; - } - - final Expression exceptionalReturn = node.arguments.positional[1]; - - // The exceptional return value must be a constant so that it be - // referenced by precompiled trampoline's object pool. - if (exceptionalReturn is! BasicLiteral && - !(exceptionalReturn is ConstantExpression && - exceptionalReturn.constant is PrimitiveConstant)) { - diagnosticReporter.report(messageFfiExpectedConstant, - node.fileOffset, 1, node.location.file); - return node; - } - - // Moreover it may not be null. - if (exceptionalReturn is NullLiteral || - (exceptionalReturn is ConstantExpression && - exceptionalReturn.constant is NullConstant)) { - diagnosticReporter.report(messageFfiExceptionalReturnNull, - node.fileOffset, 1, node.location.file); - return node; - } - - final DartType returnType = exceptionalReturn.getStaticType(env); - - if (!env.isSubtypeOf(returnType, funcType.returnType)) { - diagnosticReporter.report( - templateFfiDartTypeMismatch.withArguments( - returnType, funcType.returnType), - exceptionalReturn.fileOffset, - 1, - exceptionalReturn.location.file); - return node; - } + if (!env.isSubtypeOf(returnType, funcType.returnType)) { + diagnosticReporter.report( + templateFfiDartTypeMismatch.withArguments( + returnType, funcType.returnType), + exceptionalReturn.fileOffset, + 1, + exceptionalReturn.location.file); } - return _replaceFromFunction(node); } - } on _FfiStaticTypeError { - // It's OK to swallow the exception because the diagnostics issued will - // cause compilation to fail. By continuing, we can report more - // diagnostics before compilation ends. - } + } on _FfiStaticTypeError {} return node; } @@ -224,10 +151,10 @@ class _FfiUseSiteTransformer extends FfiTransformer { // 'lookupFunction' are constants, so by inlining the call to 'asFunction' at // the call-site, we ensure that there are no generic calls to 'asFunction'. // - // We will not detect dynamic invocations of 'asFunction' and - // 'lookupFunction': these are handled by the stubs in 'ffi_patch.dart' and - // 'dynamic_library_patch.dart'. Dynamic invocations of 'lookupFunction' (and - // 'asFunction') are not legal and throw a runtime exception. + // We will not detect dynamic invocations of 'asFunction' -- these are handled + // by the stub in 'dynamic_library_patch.dart'. Dynamic invocations of + // 'lookupFunction' (and 'asFunction') are not legal and throw a runtime + // exception. Expression _replaceLookupFunction(MethodInvocation node) { // The generated code looks like: // @@ -249,39 +176,6 @@ class _FfiUseSiteTransformer extends FfiTransformer { Arguments([lookupResult], types: [dartSignature, nativeSignature])); } - // We need to rewrite calls to 'fromFunction' into two calls, representing the - // compile-time and run-time aspects of creating the closure: - // - // final dynamic _#ffiCallback0 = Pointer.fromFunction(f, e) => - // _pointerFromFunction>( - // _nativeCallbackFunction(f, e)); - // - // ... _#ffiCallback0 ... - // - // We must implement this as a Kernel rewrite because must be a - // compile-time constant to any invocation of '_nativeCallbackFunction'. - // - // Creating this closure requires a runtime call, so we save the result in a - // synthetic top-level field to avoid recomputing it. - Expression _replaceFromFunction(StaticInvocation node) { - final nativeFunctionType = - InterfaceType(nativeFunctionClass, node.arguments.types); - final Field field = Field( - Name("_#ffiCallback${callbackCount++}", currentLibrary), - type: InterfaceType(pointerClass, [nativeFunctionType]), - initializer: StaticInvocation( - pointerFromFunctionProcedure, - Arguments([ - StaticInvocation(nativeCallbackFunctionProcedure, node.arguments) - ], types: [ - nativeFunctionType - ])), - isStatic: true, - isFinal: true); - currentLibrary.addMember(field); - return StaticGet(field); - } - @override visitMethodInvocation(MethodInvocation node) { super.visitMethodInvocation(node); @@ -339,11 +233,7 @@ class _FfiUseSiteTransformer extends FfiTransformer { _ensureNativeTypeSized(nativeType, node, target.name); _ensureNativeTypeToDartType(nativeType, dartType, node); } - } on _FfiStaticTypeError { - // It's OK to swallow the exception because the diagnostics issued will - // cause compilation to fail. By continuing, we can report more - // diagnostics before compilation ends. - } + } on _FfiStaticTypeError {} return node; } @@ -432,17 +322,22 @@ class _FfiUseSiteTransformer extends FfiTransformer { return false; } - void _ensureIsStaticFunction(Expression node) { - if ((node is StaticGet && node.target is Procedure) || - (node is ConstantExpression && node.constant is TearOffConstant)) { - return; + void _ensureIsStatic(Expression node) { + if (!_isStatic(node)) { + diagnosticReporter.report( + templateFfiNotStatic.withArguments(fromFunctionMethod.name.name), + node.fileOffset, + 1, + node.location.file); + throw _FfiStaticTypeError(); } - diagnosticReporter.report( - templateFfiNotStatic.withArguments(fromFunctionMethod.name.name), - node.fileOffset, - 1, - node.location.file); - throw _FfiStaticTypeError(); + } + + bool _isStatic(Expression node) { + if (node is StaticGet) { + return node.target is Procedure; + } + return node is ConstantExpression; } Class _extendsOrImplementsSealedClass(Class klass) { @@ -473,7 +368,6 @@ class _FfiUseSiteTransformer extends FfiTransformer { klass.fileOffset, 1, klass.location.file); - throw _FfiStaticTypeError(); } } } diff --git a/runtime/bin/ffi_test/ffi_test_functions.cc b/runtime/bin/ffi_test/ffi_test_functions.cc index 85145b1eed0..98d60c1ce38 100644 --- a/runtime/bin/ffi_test/ffi_test_functions.cc +++ b/runtime/bin/ffi_test/ffi_test_functions.cc @@ -759,7 +759,7 @@ DART_EXPORT int TestThrowExceptionDouble(double (*fn)()) { } DART_EXPORT int TestThrowExceptionPointer(void* (*fn)()) { - CHECK_EQ(fn(), nullptr); + CHECK_EQ(fn(), reinterpret_cast(42)); return 0; } diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc index f103f2e7449..347cd0557e0 100644 --- a/runtime/lib/ffi.cc +++ b/runtime/lib/ffi.cc @@ -429,6 +429,88 @@ DEFINE_NATIVE_ENTRY(Ffi_sizeOf, 1, 0) { return Integer::New(SizeOf(type_arg)); } +#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER) && \ + !defined(TARGET_ARCH_DBC) +// Generates assembly to trampoline from native code into Dart. +static uword CompileNativeCallback(const Function& c_signature, + const Function& dart_target, + const Instance& exceptional_return) { + Thread* const thread = Thread::Current(); + + uword entry_point = 0; + const int32_t callback_id = thread->AllocateFfiCallbackId(&entry_point); + ASSERT(NativeCallbackTrampolines::Enabled() == (entry_point != 0)); + + // Create a new Function named 'FfiCallback' and stick it in the 'dart:ffi' + // library. Note that these functions will never be invoked by Dart, so it + // doesn't matter that they all have the same name. + Zone* const Z = thread->zone(); + const String& name = String::Handle(Symbols::New(thread, "FfiCallback")); + const Library& lib = Library::Handle(Z, Library::FfiLibrary()); + const Class& owner_class = Class::Handle(Z, lib.toplevel_class()); + const Function& function = + Function::Handle(Z, Function::New(name, RawFunction::kFfiTrampoline, + /*is_static=*/true, + /*is_const=*/false, + /*is_abstract=*/false, + /*is_external=*/false, + /*is_native=*/false, owner_class, + TokenPosition::kMinSource)); + function.set_is_debuggable(false); + + // Set callback-specific fields which the flow-graph builder needs to generate + // the body. + function.SetFfiCSignature(c_signature); + function.SetFfiCallbackId(callback_id); + function.SetFfiCallbackTarget(dart_target); + + // We require that the exceptional return value for functions returning 'Void' + // must be 'null', since native code should not look at the result. + if (compiler::ffi::NativeTypeIsVoid( + AbstractType::Handle(c_signature.result_type())) && + !exceptional_return.IsNull()) { + Exceptions::ThrowUnsupportedError( + "Only 'null' may be used as the exceptional return value for a " + "callback returning void."); + } + + // We need to load the exceptional return value as a constant in the generated + // function. This means we need to ensure that it's in old space and has no + // (transitively) mutable fields. This is done by checking (asserting) that + // it's a built-in FFI class, whose fields are all immutable, or a + // user-defined Pointer class, which has no fields. + // + // TODO(36730): We'll need to extend this when we support passing/returning + // structs by value. + ASSERT(exceptional_return.IsNull() || exceptional_return.IsNumber() || + exceptional_return.IsPointer()); + if (!exceptional_return.IsSmi() && exceptional_return.IsNew()) { + function.SetFfiCallbackExceptionalReturn( + Instance::Handle(exceptional_return.CopyShallowToOldSpace(thread))); + } else { + function.SetFfiCallbackExceptionalReturn(exceptional_return); + } + + // We compile the callback immediately because we need to return a pointer to + // the entry-point. Native calls do not use patching like Dart calls, so we + // cannot compile it lazily. + const Object& result = + Object::Handle(Z, Compiler::CompileOptimizedFunction(thread, function)); + if (result.IsError()) { + Exceptions::PropagateError(Error::Cast(result)); + } + ASSERT(result.IsCode()); + const Code& code = Code::Cast(result); + + thread->SetFfiCallbackCode(callback_id, code); + + if (entry_point != 0) { + return entry_point; + } else { + return code.EntryPoint(); + } +} +#endif // Static invocations to this method are translated directly in streaming FGB // and bytecode FGB. However, we can still reach this entrypoint in the bytecode @@ -463,6 +545,80 @@ DEFINE_NATIVE_ENTRY(Ffi_asFunctionInternal, 2, 1) { #endif } +DEFINE_NATIVE_ENTRY(Ffi_fromFunction, 1, 2) { +#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER) || \ + defined(TARGET_ARCH_DBC) + // https://github.com/dart-lang/sdk/issues/37295 + // FFI is supported, but callbacks are not. + Exceptions::ThrowUnsupportedError( + "FFI callbacks are not yet supported in AOT or on DBC."); +#else + GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0)); + GET_NON_NULL_NATIVE_ARGUMENT(Closure, closure, arguments->NativeArgAt(0)); + GET_NON_NULL_NATIVE_ARGUMENT(Instance, exceptional_return, + arguments->NativeArgAt(1)); + + if (!type_arg.IsInstantiated() || !type_arg.IsFunctionType()) { + // TODO(35902): Remove this when dynamic invocations of fromFunction are + // prohibited. + Exceptions::ThrowUnsupportedError( + "Type argument to fromFunction must an instantiated function type."); + } + + const Function& native_signature = + Function::Handle(Type::Cast(type_arg).signature()); + Function& func = Function::Handle(closure.function()); + TypeArguments& type_args = TypeArguments::Handle(zone); + type_args = TypeArguments::New(1); + type_args.SetTypeAt(Pointer::kNativeTypeArgPos, type_arg); + type_args = type_args.Canonicalize(); + + Class& native_function_class = + Class::Handle(isolate->class_table()->At(kFfiNativeFunctionCid)); + const auto& error = + Error::Handle(native_function_class.EnsureIsFinalized(Thread::Current())); + if (!error.IsNull()) { + Exceptions::PropagateError(error); + } + + Type& native_function_type = Type::Handle( + Type::New(native_function_class, type_args, TokenPosition::kNoSource)); + native_function_type ^= + ClassFinalizer::FinalizeType(Class::Handle(), native_function_type); + native_function_type ^= native_function_type.Canonicalize(); + + // The FE verifies that the target of a 'fromFunction' is a static method, so + // the value we see here must be a static tearoff. See ffi_use_sites.dart for + // details. + // + // TODO(36748): Define hot-reload semantics of native callbacks. We may need + // to look up the target by name. + ASSERT(func.IsImplicitClosureFunction()); + func = func.parent_function(); + ASSERT(func.is_static()); + + const AbstractType& return_type = + AbstractType::Handle(native_signature.result_type()); + if (compiler::ffi::NativeTypeIsVoid(return_type)) { + if (!exceptional_return.IsNull()) { + const String& error = String::Handle( + String::NewFormatted("Exceptional return argument to 'fromFunction' " + "must be null for functions returning void.")); + Exceptions::ThrowArgumentError(error); + } + } else if (!compiler::ffi::NativeTypeIsPointer(return_type) && + exceptional_return.IsNull()) { + const String& error = String::Handle(String::NewFormatted( + "Exceptional return argument to 'fromFunction' must not be null.")); + Exceptions::ThrowArgumentError(error); + } + + return Pointer::New( + native_function_type, + CompileNativeCallback(native_signature, func, exceptional_return)); +#endif +} + DEFINE_NATIVE_ENTRY(Ffi_asExternalTypedData, 0, 2) { GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(Integer, count, arguments->NativeArgAt(1)); @@ -536,8 +692,8 @@ DEFINE_NATIVE_ENTRY(Ffi_asExternalTypedData, 0, 2) { const auto& typed_data_class = Class::Handle(zone, isolate->class_table()->At(cid)); - const auto& error = - Error::Handle(zone, typed_data_class.EnsureIsFinalized(thread)); + const auto& error = Error::Handle( + zone, typed_data_class.EnsureIsFinalized(Thread::Current())); if (!error.IsNull()) { Exceptions::PropagateError(error); } @@ -547,91 +703,6 @@ DEFINE_NATIVE_ENTRY(Ffi_asExternalTypedData, 0, 2) { Heap::kNew); } -DEFINE_NATIVE_ENTRY(Ffi_nativeCallbackFunction, 1, 2) { -#if defined(TARGET_ARCH_DBC) - Exceptions::ThrowUnsupportedError( - "FFI callbacks are not yet supported on DBC."); -#elif defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER) - // Calls to this function are removed by the flow-graph builder in AOT. - // See StreamingFlowGraphBuilder::BuildFfiNativeCallbackFunction(). - UNREACHABLE(); -#else - GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0)); - GET_NON_NULL_NATIVE_ARGUMENT(Closure, closure, arguments->NativeArgAt(0)); - GET_NON_NULL_NATIVE_ARGUMENT(Instance, exceptional_return, - arguments->NativeArgAt(1)); - - ASSERT(type_arg.IsInstantiated() && type_arg.IsFunctionType()); - const Function& native_signature = - Function::Handle(zone, Type::Cast(type_arg).signature()); - Function& func = Function::Handle(zone, closure.function()); - - // The FE verifies that the target of a 'fromFunction' is a static method, so - // the value we see here must be a static tearoff. See ffi_use_sites.dart for - // details. - // - // TODO(36748): Define hot-reload semantics of native callbacks. We may need - // to look up the target by name. - ASSERT(func.IsImplicitClosureFunction()); - func = func.parent_function(); - ASSERT(func.is_static()); - - // We are returning an object which is not an Instance here. This is only OK - // because we know that the result will be passed directly to - // _pointerFromFunction and will not leak out into user code. - arguments->SetReturn( - Function::Handle(zone, compiler::ffi::NativeCallbackFunction( - native_signature, func, exceptional_return))); - - // Because we have already set the return value. - return Object::sentinel().raw(); -#endif -} - -DEFINE_NATIVE_ENTRY(Ffi_pointerFromFunction, 1, 1) { - GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0)); - const Function& function = - Function::CheckedHandle(zone, arguments->NativeArg0()); - - Code& code = Code::Handle(zone); - -#if defined(DART_PRECOMPILED_RUNTIME) - code = function.CurrentCode(); - - // Blobs snapshots don't support BSS-relative relocations required by native - // callbacks (yet). Issue an error if the code has an unpatched relocation. - if (!code.VerifyBSSRelocations()) { - Exceptions::ThrowUnsupportedError( - "FFI callbacks are not yet supported in blobs snapshots. Please use " - "ELF or Assembly snapshots instead."); - } -#else - // We compile the callback immediately because we need to return a pointer to - // the entry-point. Native calls do not use patching like Dart calls, so we - // cannot compile it lazily. - const Object& result = Object::Handle( - zone, Compiler::CompileOptimizedFunction(thread, function)); - if (result.IsError()) { - Exceptions::PropagateError(Error::Cast(result)); - } - ASSERT(result.IsCode()); - code ^= result.raw(); -#endif - - ASSERT(!code.IsNull()); - thread->SetFfiCallbackCode(function.FfiCallbackId(), code); - - uword entry_point = code.EntryPoint(); -#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) - if (NativeCallbackTrampolines::Enabled()) { - entry_point = isolate->native_callback_trampolines()->TrampolineForId( - function.FfiCallbackId()); - } -#endif - - return Pointer::New(type_arg, entry_point); -} - #if defined(TARGET_ARCH_DBC) void FfiMarshalledArguments::SetFunctionAddress(uint64_t value) const { diff --git a/runtime/lib/ffi_patch.dart b/runtime/lib/ffi_patch.dart index 089f0c997d8..c16cd728014 100644 --- a/runtime/lib/ffi_patch.dart +++ b/runtime/lib/ffi_patch.dart @@ -23,25 +23,6 @@ DS _asFunctionInternal( dynamic _asExternalTypedData(Pointer ptr, int count) native "Ffi_asExternalTypedData"; -// Returns a Function object for a native callback. -// -// Calls to [Pointer.fromFunction] are re-written by the FE into calls to this -// method + _pointerFromFunction. All three arguments must be constants. -// -// In AOT we evaluate calls to this function during precompilation and replace -// them with Constant instruction referencing the callback trampoline, to ensure -// that it will be precompiled. -// -// In all JIT modes we call a native runtime entry. We *cannot* use the IL -// implementation, since that would pull the callback trampoline into JIT -// snapshots. The callback trampolines can only be serialized into AOT snapshots -// because they embed the addresses of runtime routines in JIT mode. -Object _nativeCallbackFunction(Function target, - Object exceptionalReturn) native "Ffi_nativeCallbackFunction"; - -Pointer _pointerFromFunction(Object function) - native "Ffi_pointerFromFunction"; - @patch @pragma("vm:entry-point") class Pointer { @@ -51,18 +32,10 @@ class Pointer { @patch factory Pointer.fromAddress(int ptr) => _fromAddress(ptr); - // All static calls to this method are replaced by the FE into - // _nativeCallbackFunction + _pointerFromFunction. - // - // We still need to throw an error on a dynamic invocations, invocations - // through tearoffs or reflective calls. @patch static Pointer> fromFunction( @DartRepresentationOf("T") Function f, - [Object exceptionalReturn]) { - throw UnsupportedError( - "Pointer.fromFunction cannot be called dynamically."); - } + Object exceptionalReturn) native "Ffi_fromFunction"; // TODO(sjindel): When NNBD is available, we should change `value` to be // non-null. diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h index efccf88e199..876d03a7fd1 100644 --- a/runtime/vm/bootstrap_natives.h +++ b/runtime/vm/bootstrap_natives.h @@ -381,8 +381,7 @@ namespace dart { V(Ffi_cast, 1) \ V(Ffi_sizeOf, 0) \ V(Ffi_asFunctionInternal, 1) \ - V(Ffi_nativeCallbackFunction, 2) \ - V(Ffi_pointerFromFunction, 1) \ + V(Ffi_fromFunction, 2) \ V(Ffi_dl_open, 1) \ V(Ffi_dl_lookup, 2) \ V(Ffi_dl_getHandle, 1) \ diff --git a/runtime/vm/bss_relocs.cc b/runtime/vm/bss_relocs.cc deleted file mode 100644 index 7e01696657c..00000000000 --- a/runtime/vm/bss_relocs.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2019, 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. - -#include -#include -#include - -namespace dart { - -void BSS::Initialize(Thread* current, uword* bss_start) { - bss_start[BSS::RelocationIndex( - BSS::Relocation::DRT_GetThreadForNativeCallback)] = - reinterpret_cast(DLRT_GetThreadForNativeCallback); -} - -} // namespace dart diff --git a/runtime/vm/bss_relocs.h b/runtime/vm/bss_relocs.h deleted file mode 100644 index aa3c1f7fb28..00000000000 --- a/runtime/vm/bss_relocs.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2019, 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. - -#ifndef RUNTIME_VM_BSS_RELOCS_H_ -#define RUNTIME_VM_BSS_RELOCS_H_ - -#include - -namespace dart { -class Thread; - -class BSS : public AllStatic { - public: - enum class Relocation : intptr_t { - DRT_GetThreadForNativeCallback = 0, - NumRelocations = 1 - }; - - static intptr_t RelocationIndex(Relocation reloc) { - return static_cast(reloc); - } - - static void Initialize(Thread* current, uword* bss); -}; - -} // namespace dart - -#endif // RUNTIME_VM_BSS_RELOCS_H_ diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc index a5958d62660..bea03fca658 100644 --- a/runtime/vm/clustered_snapshot.cc +++ b/runtime/vm/clustered_snapshot.cc @@ -6,7 +6,6 @@ #include "platform/assert.h" #include "vm/bootstrap.h" -#include "vm/bss_relocs.h" #include "vm/class_id.h" #include "vm/code_observers.h" #include "vm/compiler/backend/code_statistics.h" @@ -801,12 +800,9 @@ class FfiTrampolineDataSerializationCluster : public SerializationCluster { AutoTraceObject(data); WriteFromTo(data); - if (s->kind() == Snapshot::kFullAOT) { - s->WriteUnsigned(data->ptr()->callback_id_); - } else { - // FFI callbacks can only be written to AOT snapshots. - ASSERT(data->ptr()->callback_target_ == Object::null()); - } + // TODO(37295): FFI callbacks shouldn't be written to a snapshot. They + // should only be referenced by the callback registry in Thread. + ASSERT(data->ptr()->callback_id_ == 0); } } @@ -838,8 +834,7 @@ class FfiTrampolineDataDeserializationCluster : public DeserializationCluster { Deserializer::InitializeHeader(data, kFfiTrampolineDataCid, FfiTrampolineData::InstanceSize()); ReadFromTo(data); - data->ptr()->callback_id_ = - d->kind() == Snapshot::kFullAOT ? d->ReadUnsigned() : 0; + data->ptr()->callback_id_ = 0; } } }; @@ -5752,17 +5747,6 @@ RawApiError* FullSnapshotReader::ReadIsolateSnapshot() { } } } - - // Initialize symbols in the BSS, if present. - ASSERT(Snapshot::IncludesCode(kind_)); - Image image(instructions_image_); - if (image.bss_offset() != 0) { - // The const cast is safe because we're translating from the start of the - // instructions (read-only) to the start of the BSS (read-write). - uword* const bss_start = const_cast(reinterpret_cast( - instructions_image_ + image.bss_offset())); - BSS::Initialize(thread_, bss_start); - } #endif // defined(DART_PRECOMPILED_RUNTIME) return ApiError::null(); diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc index 149de0803ea..7d1b7644cb7 100644 --- a/runtime/vm/code_descriptors.cc +++ b/runtime/vm/code_descriptors.cc @@ -15,13 +15,10 @@ void DescriptorList::AddDescriptor(RawPcDescriptors::Kind kind, TokenPosition token_pos, intptr_t try_index) { ASSERT((kind == RawPcDescriptors::kRuntimeCall) || - (kind == RawPcDescriptors::kBSSRelocation) || (kind == RawPcDescriptors::kOther) || (deopt_id != DeoptId::kNone)); - // When precompiling, we only use pc descriptors for exceptions and - // relocations. - if (!FLAG_precompiled_mode || try_index != -1 || - kind == RawPcDescriptors::kBSSRelocation) { + // When precompiling, we only use pc descriptors for exceptions. + if (!FLAG_precompiled_mode || try_index != -1) { int32_t merged_kind_try = RawPcDescriptors::MergedKindTry::Encode(kind, try_index); diff --git a/runtime/vm/compiler/assembler/assembler.cc b/runtime/vm/compiler/assembler/assembler.cc index 6b5427d04ad..f6c6175ebf9 100644 --- a/runtime/vm/compiler/assembler/assembler.cc +++ b/runtime/vm/compiler/assembler/assembler.cc @@ -30,31 +30,6 @@ DEFINE_FLAG(bool, use_far_branches, false, "Enable far branches for ARM."); namespace compiler { -AssemblerBase::~AssemblerBase() {} - -intptr_t AssemblerBase::InsertAlignedRelocation(BSS::Relocation reloc) { - // We cannot put a relocation at the very start (it's not a valid - // instruction)! - ASSERT(CodeSize() != 0); - - // Align to a target word boundary. - const intptr_t offset = - Utils::RoundUp(CodeSize(), compiler::target::kWordSize); - - while (CodeSize() < offset) { - Breakpoint(); - } - ASSERT(CodeSize() == offset); - - AssemblerBuffer::EnsureCapacity ensured(&buffer_); - buffer_.Emit(BSS::RelocationIndex(reloc) * - compiler::target::kWordSize); - - ASSERT(CodeSize() == (offset + compiler::target::kWordSize)); - - return offset; -} - static uword NewContents(intptr_t capacity) { Zone* zone = Thread::Current()->zone(); uword result = zone->AllocUnsafe(capacity); diff --git a/runtime/vm/compiler/assembler/assembler.h b/runtime/vm/compiler/assembler/assembler.h index 645728aba31..cf4d6e652b2 100644 --- a/runtime/vm/compiler/assembler/assembler.h +++ b/runtime/vm/compiler/assembler/assembler.h @@ -305,7 +305,7 @@ class AssemblerBase : public StackResource { prologue_offset_(-1), has_single_entry_point_(true), object_pool_builder_(object_pool_builder) {} - virtual ~AssemblerBase(); + virtual ~AssemblerBase() {} intptr_t CodeSize() const { return buffer_.Size(); } @@ -320,10 +320,6 @@ class AssemblerBase : public StackResource { void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); static bool EmittingComments(); - virtual void Breakpoint() = 0; - - intptr_t InsertAlignedRelocation(BSS::Relocation reloc); - void Unimplemented(const char* message); void Untested(const char* message); void Unreachable(const char* message); diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h index 667f8a5199c..7a552326983 100644 --- a/runtime/vm/compiler/assembler/assembler_arm.h +++ b/runtime/vm/compiler/assembler/assembler_arm.h @@ -392,7 +392,7 @@ class Assembler : public AssemblerBase { #endif // TESTING || DEBUG // Debugging and bringup support. - void Breakpoint() override { bkpt(0); } + void Breakpoint() { bkpt(0); } void Stop(const char* message) override; static void InitializeMemoryWithBreakpoints(uword data, intptr_t length); diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h index 315e72f7a6f..246efbf18a3 100644 --- a/runtime/vm/compiler/assembler/assembler_arm64.h +++ b/runtime/vm/compiler/assembler/assembler_arm64.h @@ -485,7 +485,7 @@ class Assembler : public AssemblerBase { void set_use_far_branches(bool b) { use_far_branches_ = b; } // Debugging and bringup support. - void Breakpoint() override { brk(0); } + void Breakpoint() { brk(0); } void Stop(const char* message) override; static void InitializeMemoryWithBreakpoints(uword data, intptr_t length); diff --git a/runtime/vm/compiler/assembler/assembler_dbc.h b/runtime/vm/compiler/assembler/assembler_dbc.h index 0737026cc69..df2a83c1874 100644 --- a/runtime/vm/compiler/assembler/assembler_dbc.h +++ b/runtime/vm/compiler/assembler/assembler_dbc.h @@ -43,7 +43,6 @@ class Assembler : public AssemblerBase { void MonomorphicCheckedEntryAOT() {} // Debugging and bringup support. - void Breakpoint() override { Stop("Breakpoint!"); } void Stop(const char* message) override; static void InitializeMemoryWithBreakpoints(uword data, intptr_t length); diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h index 8321841c0af..586b7dd5546 100644 --- a/runtime/vm/compiler/assembler/assembler_ia32.h +++ b/runtime/vm/compiler/assembler/assembler_ia32.h @@ -835,7 +835,7 @@ class Assembler : public AssemblerBase { Register temp); // Debugging and bringup support. - void Breakpoint() override { int3(); } + void Breakpoint() { int3(); } void Stop(const char* message) override; static void InitializeMemoryWithBreakpoints(uword data, intptr_t length); diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h index 4065bdd5c9e..57237c07ad5 100644 --- a/runtime/vm/compiler/assembler/assembler_x64.h +++ b/runtime/vm/compiler/assembler/assembler_x64.h @@ -936,7 +936,7 @@ class Assembler : public AssemblerBase { void GenerateUnRelocatedPcRelativeCall(intptr_t offset_into_target = 0); // Debugging and bringup support. - void Breakpoint() override { int3(); } + void Breakpoint() { int3(); } void Stop(const char* message) override; static void InitializeMemoryWithBreakpoints(uword data, intptr_t length); diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc index 49597bb997e..71208d80c02 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc @@ -242,13 +242,6 @@ bool FlowGraphCompiler::CanOSRFunction() const { return isolate()->use_osr() && CanOptimizeFunction() && !is_optimizing(); } -void FlowGraphCompiler::InsertBSSRelocation(BSS::Relocation reloc) { - const intptr_t offset = assembler()->InsertAlignedRelocation(reloc); - AddDescriptor(RawPcDescriptors::kBSSRelocation, /*pc_offset=*/offset, - /*deopt_id=*/DeoptId::kNone, TokenPosition::kNoSource, - /*try_index=*/-1); -} - bool FlowGraphCompiler::ForceSlowPathForStackOverflow() const { #if !defined(PRODUCT) if ((FLAG_stacktrace_every > 0) || (FLAG_deoptimize_every > 0) || @@ -1408,9 +1401,7 @@ void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id, : ic_data.arguments_descriptor()); ASSERT(ArgumentsDescriptor(arguments_descriptor).TypeArgsLen() == args_info.type_args_len); - // Force-optimized functions lack the deopt info which allows patching of - // optimized static calls. - if (is_optimizing() && (!ForcedOptimization() || FLAG_precompiled_mode)) { + if (is_optimizing() && !ForcedOptimization()) { EmitOptimizedStaticCall(function, arguments_descriptor, args_info.count_with_type_args, deopt_id, token_pos, locs, entry_kind); diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h index f07d8d764a8..fe10a80a00e 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.h +++ b/runtime/vm/compiler/backend/flow_graph_compiler.h @@ -428,8 +428,6 @@ class FlowGraphCompiler : public ValueObject { bool CanOSRFunction() const; bool is_optimizing() const { return is_optimizing_; } - void InsertBSSRelocation(BSS::Relocation reloc); - // The function was fully intrinsified, so the body is unreachable. // // We still need to compile the body in unoptimized mode because the diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc index 6f00a187f91..e747e3e2c89 100644 --- a/runtime/vm/compiler/backend/il_arm.cc +++ b/runtime/vm/compiler/backend/il_arm.cc @@ -1137,6 +1137,10 @@ void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler, } void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { + if (FLAG_precompiled_mode) { + UNREACHABLE(); + } + // Constant pool cannot be used until we enter the actual Dart frame. __ set_constant_pool_allowed(false); @@ -1161,41 +1165,8 @@ void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // Load the thread object. If we were called by a trampoline, the thread is // already loaded. - if (FLAG_precompiled_mode) { - compiler::Label skip_reloc; - __ b(&skip_reloc); - compiler->InsertBSSRelocation( - BSS::Relocation::DRT_GetThreadForNativeCallback); - __ Bind(&skip_reloc); - - // For historical reasons, the PC on ARM points 8 bytes (two instructions) - // past the current instruction. - __ sub( - R0, PC, - compiler::Operand(Instr::kPCReadOffset + compiler::target::kWordSize)); - - // R0 holds the address of the relocation. - __ ldr(R1, compiler::Address(R0)); - - // R1 holds the relocation itself: R0 - bss_start. - // R0 = R0 + (bss_start - R0) = bss_start - __ add(R0, R0, compiler::Operand(R1)); - - // R0 holds the start of the BSS section. - // Load the "get-thread" routine: *bss_start. - __ ldr(R1, compiler::Address(R0)); - } else if (!NativeCallbackTrampolines::Enabled()) { - // In JIT mode, we can just paste the address of the runtime entry into the - // generated code directly. This is not a problem since we don't save - // callbacks into JIT snapshots. - ASSERT(kWordSize == compiler::target::kWordSize); - __ LoadImmediate( - R1, static_cast( - reinterpret_cast(DLRT_GetThreadForNativeCallback))); - } - - // Load the thread object. If we were called by a trampoline, the thread is - // already loaded. + // + // TODO(35765): Fix linking issue on AOT. if (!NativeCallbackTrampolines::Enabled()) { // Create another frame to align the frame before continuing in "native" // code. @@ -1203,6 +1174,8 @@ void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ ReserveAlignedFrameSpace(0); __ LoadImmediate(R0, callback_id_); + __ LoadImmediate( + R1, reinterpret_cast(DLRT_GetThreadForNativeCallback)); __ blx(R1); __ mov(THR, compiler::Operand(R0)); @@ -6981,8 +6954,7 @@ LocationSummary* BitCastInstr::MakeLocationSummary(Zone* zone, bool opt) const { break; case kUnboxedFloat: case kUnboxedDouble: - // Choose an FPU register with corresponding D and S registers. - summary->set_in(0, Location::FpuRegisterLocation(Q0)); + summary->set_in(0, Location::RequiresFpuRegister()); break; default: UNREACHABLE(); @@ -6998,8 +6970,7 @@ LocationSummary* BitCastInstr::MakeLocationSummary(Zone* zone, bool opt) const { break; case kUnboxedFloat: case kUnboxedDouble: - // Choose an FPU register with corresponding D and S registers. - summary->set_out(0, Location::FpuRegisterLocation(Q0)); + summary->set_out(0, Location::RequiresFpuRegister()); break; default: UNREACHABLE(); diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc index 3359f05f567..774b6cb83c1 100644 --- a/runtime/vm/compiler/backend/il_arm64.cc +++ b/runtime/vm/compiler/backend/il_arm64.cc @@ -1020,6 +1020,10 @@ void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler, } void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { + if (FLAG_precompiled_mode) { + UNREACHABLE(); + } + // Constant pool cannot be used until we enter the actual Dart frame. __ set_constant_pool_allowed(false); @@ -1048,33 +1052,8 @@ void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // Load the thread object. If we were called by a trampoline, the thread is // already loaded. - if (FLAG_precompiled_mode) { - compiler::Label skip_reloc; - __ b(&skip_reloc); - compiler->InsertBSSRelocation( - BSS::Relocation::DRT_GetThreadForNativeCallback); - __ Bind(&skip_reloc); - - __ adr(R0, compiler::Immediate(-compiler::target::kWordSize)); - - // R0 holds the address of the relocation. - __ ldr(R1, compiler::Address(R0)); - - // R1 holds the relocation itself: R0 - bss_start. - // R0 = R0 + (bss_start - R0) = bss_start - __ add(R0, R0, compiler::Operand(R1)); - - // R0 holds the start of the BSS section. - // Load the "get-thread" routine: *bss_start. - __ ldr(R1, compiler::Address(R0)); - } else if (!NativeCallbackTrampolines::Enabled()) { - // In JIT mode, we can just paste the address of the runtime entry into the - // generated code directly. This is not a problem since we don't save - // callbacks into JIT snapshots. - __ LoadImmediate( - R1, reinterpret_cast(DLRT_GetThreadForNativeCallback)); - } - + // + // TODO(35765): Fix linking issue on AOT. if (!NativeCallbackTrampolines::Enabled()) { // Create another frame to align the frame before continuing in "native" // code. @@ -1082,6 +1061,8 @@ void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ ReserveAlignedFrameSpace(0); __ LoadImmediate(R0, callback_id_); + __ LoadImmediate( + R1, reinterpret_cast(DLRT_GetThreadForNativeCallback)); __ blr(R1); __ mov(THR, R0); diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc index 72bc6b37d9c..1729f425d4d 100644 --- a/runtime/vm/compiler/backend/il_ia32.cc +++ b/runtime/vm/compiler/backend/il_ia32.cc @@ -1036,16 +1036,15 @@ void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ pushl(EDI); // Load the thread object. - // + // Linking in AOT is not relevant here since we don't support AOT for IA32. // Create another frame to align the frame before continuing in "native" code. // If we were called by a trampoline, it has already loaded the thread. - ASSERT(!FLAG_precompiled_mode); // No relocation for AOT linking. if (!NativeCallbackTrampolines::Enabled()) { __ EnterFrame(0); __ ReserveAlignedFrameSpace(compiler::target::kWordSize); __ movl(compiler::Address(SPREG, 0), compiler::Immediate(callback_id_)); - __ movl(EAX, compiler::Immediate(reinterpret_cast( + __ movl(EAX, compiler::Immediate(reinterpret_cast( DLRT_GetThreadForNativeCallback))); __ call(EAX); __ movl(THR, EAX); diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc index c7612ed567f..aa1e8fe2d5d 100644 --- a/runtime/vm/compiler/backend/il_x64.cc +++ b/runtime/vm/compiler/backend/il_x64.cc @@ -1024,6 +1024,10 @@ void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler, } void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { + if (FLAG_precompiled_mode) { + UNREACHABLE(); + } + __ Bind(compiler->GetJumpLabel(this)); // Create a dummy frame holding the pushed arguments. This simplifies @@ -1051,38 +1055,9 @@ void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters, CallingConventions::kCalleeSaveXmmRegisters); - // Load the address of DLRT_GetThreadForNativeCallback without using Thread. - if (FLAG_precompiled_mode) { - compiler::Label skip_reloc; - __ jmp(&skip_reloc); - compiler->InsertBSSRelocation( - BSS::Relocation::DRT_GetThreadForNativeCallback); - const intptr_t reloc_end = __ CodeSize(); - __ Bind(&skip_reloc); - - const intptr_t kLeaqLength = 7; - __ leaq(RAX, compiler::Address::AddressRIPRelative( - -kLeaqLength - compiler::target::kWordSize)); - ASSERT((__ CodeSize() - reloc_end) == kLeaqLength); - - // RAX holds the address of the relocation. - __ movq(RCX, compiler::Address(RAX, 0)); - - // RCX holds the relocation itself: RAX - bss_start. - // RAX = RAX + (bss_start - RAX) = bss_start - __ addq(RAX, RCX); - - // RAX holds the start of the BSS section. - // Load the "get-thread" routine: *bss_start. - __ movq(RAX, compiler::Address(RAX, 0)); - } else if (!NativeCallbackTrampolines::Enabled()) { - // In JIT mode, we can just paste the address of the runtime entry into the - // generated code directly. This is not a problem since we don't save - // callbacks into JIT snapshots. - __ movq(RAX, compiler::Immediate(reinterpret_cast( - DLRT_GetThreadForNativeCallback))); - } - + // Load the thread object. + // TODO(35765): Fix linking issue on AOT. + // // Create another frame to align the frame before continuing in "native" code. // If we were called by a trampoline, it has already loaded the thread. if (!NativeCallbackTrampolines::Enabled()) { @@ -1091,6 +1066,8 @@ void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { COMPILE_ASSERT(RAX != CallingConventions::kArg1Reg); __ movq(CallingConventions::kArg1Reg, compiler::Immediate(callback_id_)); + __ movq(RAX, compiler::Immediate(reinterpret_cast( + DLRT_GetThreadForNativeCallback))); __ CallCFunction(RAX); __ movq(THR, RAX); diff --git a/runtime/vm/compiler/ffi.cc b/runtime/vm/compiler/ffi.cc index 3b3ce8c480d..5313922c2e7 100644 --- a/runtime/vm/compiler/ffi.cc +++ b/runtime/vm/compiler/ffi.cc @@ -210,58 +210,6 @@ Representation ResultRepresentationBase(const Function& signature) { #if !defined(TARGET_ARCH_DBC) -RawFunction* NativeCallbackFunction(const Function& c_signature, - const Function& dart_target, - const Instance& exceptional_return) { - Thread* const thread = Thread::Current(); - const int32_t callback_id = thread->AllocateFfiCallbackId(); - - // Create a new Function named '_FfiCallback' and stick it in the - // 'dart:ffi' library. Note that these functions will never be invoked by - // Dart, so they have may have duplicate names. - Zone* const zone = thread->zone(); - const auto& name = String::Handle( - zone, Symbols::FromConcat(thread, Symbols::FfiCallback(), - String::Handle(zone, dart_target.name()))); - const Library& lib = Library::Handle(zone, Library::FfiLibrary()); - const Class& owner_class = Class::Handle(zone, lib.toplevel_class()); - const Function& function = - Function::Handle(zone, Function::New(name, RawFunction::kFfiTrampoline, - /*is_static=*/true, - /*is_const=*/false, - /*is_abstract=*/false, - /*is_external=*/false, - /*is_native=*/false, owner_class, - TokenPosition::kNoSource)); - function.set_is_debuggable(false); - - // Set callback-specific fields which the flow-graph builder needs to generate - // the body. - function.SetFfiCSignature(c_signature); - function.SetFfiCallbackId(callback_id); - function.SetFfiCallbackTarget(dart_target); - - // We need to load the exceptional return value as a constant in the generated - // function. Even though the FE ensures that it is a constant, it could still - // be a literal allocated in new space. We need to copy it into old space in - // that case. - // - // Exceptional return values currently cannot be pointers because we don't - // have constant pointers. - // - // TODO(36730): We'll need to extend this when we support passing/returning - // structs by value. - ASSERT(exceptional_return.IsNull() || exceptional_return.IsNumber()); - if (!exceptional_return.IsSmi() && exceptional_return.IsNew()) { - function.SetFfiCallbackExceptionalReturn(Instance::Handle( - zone, exceptional_return.CopyShallowToOldSpace(thread))); - } else { - function.SetFfiCallbackExceptionalReturn(exceptional_return); - } - - return function.raw(); -} - ZoneGrowableArray* ArgumentRepresentations( const Function& signature) { return ArgumentRepresentationsBase(signature); @@ -702,6 +650,27 @@ Representation FfiSignatureDescriptor::ResultRepresentation() const { #endif // defined(TARGET_ARCH_DBC) +bool IsAsFunctionInternal(Zone* zone, Isolate* isolate, const Function& func) { + Object& asFunctionInternal = + Object::Handle(zone, isolate->object_store()->ffi_as_function_internal()); + if (asFunctionInternal.raw() == Object::null()) { + // Cache the reference. + const Library& ffi = + Library::Handle(zone, isolate->object_store()->ffi_library()); + asFunctionInternal = + ffi.LookupFunctionAllowPrivate(Symbols::AsFunctionInternal()); + // Cannot assert that 'asFunctionInternal' is found because it may have been + // tree-shaken. + if (asFunctionInternal.IsNull()) { + // Set the entry in the object store to a sentinel so we don't try to look + // it up again. + asFunctionInternal = Object::sentinel().raw(); + } + isolate->object_store()->set_ffi_as_function_internal(asFunctionInternal); + } + return func.raw() == asFunctionInternal.raw(); +} + #endif // !defined(DART_PRECOMPILED_RUNTIME) } // namespace ffi diff --git a/runtime/vm/compiler/ffi.h b/runtime/vm/compiler/ffi.h index 7922a80e2b1..5c743d4dff6 100644 --- a/runtime/vm/compiler/ffi.h +++ b/runtime/vm/compiler/ffi.h @@ -56,10 +56,6 @@ RawFunction* TrampolineFunction(const Function& dart_signature, #if !defined(TARGET_ARCH_DBC) -RawFunction* NativeCallbackFunction(const Function& c_signature, - const Function& dart_target, - const Instance& exceptional_return); - // Unboxed representations of the arguments to a C signature function. ZoneGrowableArray* ArgumentRepresentations( const Function& signature); @@ -149,8 +145,11 @@ class CallbackArgumentTranslator : public ValueObject { intptr_t argument_slots_used_ = 0; intptr_t argument_slots_required_ = 0; }; + #endif // defined(TARGET_ARCH_DBC) +bool IsAsFunctionInternal(Zone* zone, Isolate* isolate, const Function& func); + } // namespace ffi } // namespace compiler diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc index a330e142771..6dfe32a3397 100644 --- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc +++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc @@ -807,14 +807,9 @@ void BytecodeFlowGraphBuilder::BuildDirectCall() { const Function& target = Function::Cast(ConstantAt(DecodeOperandD()).value()); const intptr_t argc = DecodeOperandF().value(); - const auto recognized_kind = MethodRecognizer::RecognizeKind(target); - if (recognized_kind == MethodRecognizer::kFfiAsFunctionInternal) { + if (compiler::ffi::IsAsFunctionInternal(Z, isolate(), target)) { BuildFfiAsFunction(); return; - } else if (FLAG_precompiled_mode && - recognized_kind == MethodRecognizer::kFfiNativeCallbackFunction) { - BuildFfiNativeCallbackFunction(); - return; } // Recognize identical() call. @@ -831,7 +826,7 @@ void BytecodeFlowGraphBuilder::BuildDirectCall() { } if (!FLAG_causal_async_stacks && - recognized_kind == MethodRecognizer::kAsyncStackTraceHelper) { + target.recognized_kind() == MethodRecognizer::kAsyncStackTraceHelper) { ASSERT(argc == 1); // Drop the ignored parameter to _asyncStackTraceHelper(:async_op). code_ += B->Drop(); @@ -839,7 +834,7 @@ void BytecodeFlowGraphBuilder::BuildDirectCall() { return; } - if (recognized_kind == MethodRecognizer::kStringBaseInterpolate) { + if (target.recognized_kind() == MethodRecognizer::kStringBaseInterpolate) { ASSERT(argc == 1); code_ += B->StringInterpolate(position_); return; @@ -1829,45 +1824,6 @@ void BytecodeFlowGraphBuilder::BuildFfiAsFunction() { code_ += B->BuildFfiAsFunctionInternalCall(type_args); } -// Builds graph for a call to 'dart:ffi::_nativeCallbackFunction'. -// The call-site must look like this (guaranteed by the FE which inserts it): -// -// _nativeCallbackFunction(target, exceptionalReturn) -// -// Therefore the stack shall look like: -// -// => ensured (by FE) to be a constant -// => closure, ensured (by FE) to be a (non-partially-instantiated) -// static tearoff -// => [NativeSignatureType] -void BytecodeFlowGraphBuilder::BuildFfiNativeCallbackFunction() { -#if defined(TARGET_ARCH_DBC) - UNREACHABLE(); -#else - const TypeArguments& type_args = - TypeArguments::Cast(B->Peek(/*depth=*/2)->AsConstant()->value()); - ASSERT(type_args.IsInstantiated() && type_args.Length() == 1); - const Function& native_sig = Function::Handle( - Z, Type::Cast(AbstractType::Handle(Z, type_args.TypeAt(0))).signature()); - - const Closure& target_closure = - Closure::Cast(B->Peek(/*depth=*/1)->AsConstant()->value()); - ASSERT(!target_closure.IsNull()); - Function& target = Function::Handle(Z, target_closure.function()); - ASSERT(!target.IsNull() && target.IsImplicitClosureFunction()); - target = target.parent_function(); - - const Instance& exceptional_return = - Instance::Cast(B->Peek(/*depth=*/0)->AsConstant()->value()); - - const Function& result = - Function::ZoneHandle(Z, compiler::ffi::NativeCallbackFunction( - native_sig, target, exceptional_return)); - code_ += B->Constant(result); - code_ += B->DropTempsPreserveTop(3); -#endif -} - void BytecodeFlowGraphBuilder::BuildDebugStepCheck() { #if !defined(PRODUCT) if (build_debug_step_checks_) { diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h index 1e84f92e49c..88bfa443d06 100644 --- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h +++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h @@ -172,7 +172,6 @@ class BytecodeFlowGraphBuilder { void BuildInstruction(KernelBytecode::Opcode opcode); void BuildFfiAsFunction(); - void BuildFfiNativeCallbackFunction(); void BuildDebugStepCheck(); #define DECLARE_BUILD_METHOD(name, encoding, kind, op1, op2, op3) \ diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc index 1cfab978abc..3b1f642e9a2 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc @@ -3059,12 +3059,8 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const, ++argument_count; } - const auto recognized_kind = MethodRecognizer::RecognizeKind(target); - if (recognized_kind == MethodRecognizer::kFfiAsFunctionInternal) { + if (compiler::ffi::IsAsFunctionInternal(Z, H.isolate(), target)) { return BuildFfiAsFunctionInternal(); - } else if (FLAG_precompiled_mode && - recognized_kind == MethodRecognizer::kFfiNativeCallbackFunction) { - return BuildFfiNativeCallbackFunction(); } Fragment instructions; @@ -3072,7 +3068,7 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const, const bool special_case_nop_async_stack_trace_helper = !FLAG_causal_async_stacks && - recognized_kind == MethodRecognizer::kAsyncStackTraceHelper; + target.recognized_kind() == MethodRecognizer::kAsyncStackTraceHelper; const bool special_case_unchecked_cast = klass.IsTopLevel() && (klass.library() == Library::InternalLibrary()) && @@ -5047,65 +5043,6 @@ Fragment StreamingFlowGraphBuilder::BuildFfiAsFunctionInternal() { return code; } -Fragment StreamingFlowGraphBuilder::BuildFfiNativeCallbackFunction() { -#if defined(TARGET_ARCH_DBC) - UNREACHABLE(); -#else - // The call-site must look like this (guaranteed by the FE which inserts it): - // - // _nativeCallbackFunction(target, exceptionalReturn) - // - // The FE also guarantees that all three arguments are constants. - - const intptr_t argc = ReadUInt(); // read argument count - ASSERT(argc == 2); // target, exceptionalReturn - - const intptr_t list_length = ReadListLength(); // read types list length - ASSERT(list_length == 1); // native signature - const TypeArguments& type_arguments = - T.BuildTypeArguments(list_length); // read types. - ASSERT(type_arguments.Length() == 1 && type_arguments.IsInstantiated()); - const Function& native_sig = Function::Handle( - Z, Type::Cast(AbstractType::Handle(Z, type_arguments.TypeAt(0))) - .signature()); - - Fragment code; - const intptr_t positional_count = - ReadListLength(); // read positional argument count - ASSERT(positional_count == 2); - - // Read target expression and extract the target function. - code += BuildExpression(); // build first positional argument (target) - Definition* target_def = B->Peek(); - ASSERT(target_def->IsConstant()); - const Closure& target_closure = - Closure::Cast(target_def->AsConstant()->value()); - ASSERT(!target_closure.IsNull()); - Function& target = Function::Handle(Z, target_closure.function()); - ASSERT(!target.IsNull() && target.IsImplicitClosureFunction()); - target = target.parent_function(); - code += Drop(); - - // Build second positional argument (exceptionalReturn). - code += BuildExpression(); - Definition* exceptional_return_def = B->Peek(); - ASSERT(exceptional_return_def->IsConstant()); - const Instance& exceptional_return = - Instance::Cast(exceptional_return_def->AsConstant()->value()); - code += Drop(); - - const intptr_t named_args_len = - ReadListLength(); // skip (empty) named arguments list - ASSERT(named_args_len == 0); - - const Function& result = - Function::ZoneHandle(Z, compiler::ffi::NativeCallbackFunction( - native_sig, target, exceptional_return)); - code += Constant(result); - return code; -#endif -} - } // namespace kernel } // namespace dart diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h index 0eab5b9b3f6..e8b36bd634d 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h @@ -353,10 +353,6 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper { // Kernel buffer and pushes the resulting closure. Fragment BuildFfiAsFunctionInternal(); - // Build build FG for '_nativeCallbackFunction'. Reads an Arguments from the - // Kernel buffer and pushes the resulting Function object. - Fragment BuildFfiNativeCallbackFunction(); - FlowGraphBuilder* flow_graph_builder_; ActiveClass* const active_class_; TypeTranslator type_translator_; diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc index fbca763962a..2169ebdab10 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -2397,7 +2397,6 @@ Fragment FlowGraphBuilder::FfiPointerFromAddress(const Type& result_type) { // do not appear in the type arguments to a any Pointer classes in an FFI // signature. ASSERT(args.IsNull() || args.IsInstantiated()); - args = args.Canonicalize(); Fragment code; code += Constant(args); @@ -2451,6 +2450,14 @@ Fragment FlowGraphBuilder::FfiConvertArgumentToNative( const Representation native_representation) { Fragment body; + // Return 0 for void. + if (compiler::ffi::NativeTypeIsVoid(ffi_type)) { + body += Drop(); + body += IntConstant(0); + body += UnboxTruncate(kUnboxedFfiIntPtr); + return body; + } + // Check for 'null'. body += LoadLocal(MakeTemporary()); body <<= new (Z) CheckNullInstr(Pop(), String::ZoneHandle(Z, function.name()), @@ -2607,20 +2614,9 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFfiCallback(const Function& function) { /*needs_stacktrace=*/false, /*is_synthesized=*/true); // Return the "exceptional return" value given in 'fromFunction'. - // - // For pointer and void return types, the exceptional return is always null -- - // return 0 instead. - if (compiler::ffi::NativeTypeIsPointer(ffi_type) || - compiler::ffi::NativeTypeIsVoid(ffi_type)) { - ASSERT(function.FfiCallbackExceptionalReturn() == Object::null()); - catch_body += IntConstant(0); - catch_body += UnboxTruncate(kUnboxedFfiIntPtr); - } else { - catch_body += Constant( - Instance::ZoneHandle(Z, function.FfiCallbackExceptionalReturn())); - catch_body += FfiConvertArgumentToNative(function, ffi_type, result_rep); - } - + catch_body += Constant( + Instance::ZoneHandle(Z, function.FfiCallbackExceptionalReturn())); + catch_body += FfiConvertArgumentToNative(function, ffi_type, result_rep); catch_body += NativeReturn(result_rep); --catch_depth_; diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h index 3af03f5204d..9ecb99466bb 100644 --- a/runtime/vm/compiler/recognized_methods_list.h +++ b/runtime/vm/compiler/recognized_methods_list.h @@ -143,8 +143,6 @@ namespace dart { V(::, _classRangeCheck, ClassRangeCheck, 0xca52e30a) \ V(::, _asyncStackTraceHelper, AsyncStackTraceHelper, 0xaeaed5cb) \ V(::, _abi, FfiAbi, 0xf2e89620) \ - V(::, _asFunctionInternal, FfiAsFunctionInternal, 0x82525e9e) \ - V(::, _nativeCallbackFunction, FfiNativeCallbackFunction, 0x591fb33c) \ // List of intrinsics: // (class-name, function-name, intrinsification method, fingerprint). diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h index 05794184aef..fe9e2532023 100644 --- a/runtime/vm/compiler/runtime_api.h +++ b/runtime/vm/compiler/runtime_api.h @@ -21,7 +21,6 @@ #include "platform/globals.h" #include "vm/allocation.h" #include "vm/bitfield.h" -#include "vm/bss_relocs.h" #include "vm/class_id.h" #include "vm/code_entry_kind.h" #include "vm/constants.h" diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc index 63060295ed8..96f58463445 100644 --- a/runtime/vm/elf.cc +++ b/runtime/vm/elf.cc @@ -82,6 +82,8 @@ static const intptr_t kElfDynamicTableEntrySize = 16; static const intptr_t kElfSymbolHashTableEntrySize = 4; #endif +static const intptr_t kPageSize = 4096; + class Section : public ZoneAllocated { public: Section() {} @@ -113,34 +115,23 @@ class ProgramBits : public Section { public: ProgramBits(bool allocate, bool executable, - bool writable, const uint8_t* bytes, - intptr_t filesz, - intptr_t memsz = -1) { - if (memsz == -1) memsz = filesz; - + intptr_t size) { section_type = SHT_PROGBITS; if (allocate) { section_flags = SHF_ALLOC; if (executable) section_flags |= SHF_EXECINSTR; - if (writable) section_flags |= SHF_WRITE; segment_type = PT_LOAD; segment_flags = PF_R; if (executable) segment_flags |= PF_X; - if (writable) segment_flags |= PF_W; } bytes_ = bytes; - file_size = filesz; - memory_size = memsz; + file_size = memory_size = size; } - void Write(Elf* stream) { - if (bytes_ != nullptr) { - stream->WriteBytes(bytes_, file_size); - } - } + void Write(Elf* stream) { stream->WriteBytes(bytes_, memory_size); } const uint8_t* bytes_; }; @@ -380,7 +371,7 @@ static const intptr_t kNumInvalidSections = 1; // Elf::segments_. static const intptr_t kNumImplicitSegments = 3; -static const intptr_t kProgramTableSegmentSize = Elf::kPageSize; +static const intptr_t kProgramTableSegmentSize = kPageSize; Elf::Elf(Zone* zone, StreamingWriteStream* stream) : zone_(zone), stream_(stream), memory_offset_(0) { @@ -424,7 +415,7 @@ intptr_t Elf::NextMemoryOffset() { } intptr_t Elf::AddText(const char* name, const uint8_t* bytes, intptr_t size) { - ProgramBits* image = new (zone_) ProgramBits(true, true, false, bytes, size); + ProgramBits* image = new (zone_) ProgramBits(true, true, bytes, size); image->section_name = shstrtab_->AddString(".text"); AddSection(image); AddSegment(image); @@ -443,29 +434,8 @@ intptr_t Elf::AddText(const char* name, const uint8_t* bytes, intptr_t size) { return symbol->offset; } -intptr_t Elf::AddBSSData(const char* name, intptr_t size) { - ProgramBits* image = new (zone_) - ProgramBits(true, false, true, nullptr, /*filesz=*/0, /*memsz=*/size); - image->section_name = shstrtab_->AddString(".bss"); - AddSection(image); - AddSegment(image); - - Symbol* symbol = new (zone_) Symbol(); - symbol->cstr = name; - symbol->name = symstrtab_->AddString(name); - symbol->info = (STB_GLOBAL << 4) | STT_OBJECT; - symbol->section = image->section_index; - // For shared libraries, this is the offset from the DSO base. For static - // libraries, this is section relative. - symbol->offset = image->memory_offset; - symbol->size = size; - symtab_->AddSymbol(symbol); - - return symbol->offset; -} - intptr_t Elf::AddROData(const char* name, const uint8_t* bytes, intptr_t size) { - ProgramBits* image = new (zone_) ProgramBits(true, false, false, bytes, size); + ProgramBits* image = new (zone_) ProgramBits(true, false, bytes, size); image->section_name = shstrtab_->AddString(".rodata"); AddSection(image); AddSegment(image); @@ -485,8 +455,7 @@ intptr_t Elf::AddROData(const char* name, const uint8_t* bytes, intptr_t size) { } void Elf::AddDebug(const char* name, const uint8_t* bytes, intptr_t size) { - ProgramBits* image = - new (zone_) ProgramBits(false, false, false, bytes, size); + ProgramBits* image = new (zone_) ProgramBits(false, false, bytes, size); image->section_name = shstrtab_->AddString(name); AddSection(image); } diff --git a/runtime/vm/elf.h b/runtime/vm/elf.h index 882c9177b23..d6d63b717b8 100644 --- a/runtime/vm/elf.h +++ b/runtime/vm/elf.h @@ -23,12 +23,9 @@ class Elf : public ZoneAllocated { public: Elf(Zone* zone, StreamingWriteStream* stream); - static const intptr_t kPageSize = 4096; - intptr_t NextMemoryOffset(); intptr_t AddText(const char* name, const uint8_t* bytes, intptr_t size); intptr_t AddROData(const char* name, const uint8_t* bytes, intptr_t size); - intptr_t AddBSSData(const char* name, intptr_t size); void AddDebug(const char* name, const uint8_t* bytes, intptr_t size); void Finalize(); diff --git a/runtime/vm/ffi_callback_trampolines.cc b/runtime/vm/ffi_callback_trampolines.cc index af987dcc274..5516ddbf157 100644 --- a/runtime/vm/ffi_callback_trampolines.cc +++ b/runtime/vm/ffi_callback_trampolines.cc @@ -14,22 +14,7 @@ namespace dart { DECLARE_FLAG(bool, disassemble_stubs); #if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) -uword NativeCallbackTrampolines::TrampolineForId(int32_t callback_id) { -#if defined(DART_PRECOMPILER) - ASSERT(!Enabled()); - UNREACHABLE(); -#else - const intptr_t trampolines_per_page = NumCallbackTrampolinesPerPage(); - const intptr_t page_index = callback_id / trampolines_per_page; - const uword entry_point = trampoline_pages_[page_index]->start(); - - return entry_point + - (callback_id % trampolines_per_page) * - compiler::StubCodeCompiler::kNativeCallbackTrampolineSize; -#endif -} - -void NativeCallbackTrampolines::AllocateTrampoline() { +uword NativeCallbackTrampolines::AllocateTrampoline() { #if defined(DART_PRECOMPILER) ASSERT(!Enabled()); UNREACHABLE(); @@ -91,11 +76,16 @@ void NativeCallbackTrampolines::AllocateTrampoline() { } #endif + next_callback_trampoline_ = memory->start(); trampolines_left_on_page_ = NumCallbackTrampolinesPerPage(); } trampolines_left_on_page_--; next_callback_id_++; + const uword entrypoint = next_callback_trampoline_; + next_callback_trampoline_ += + compiler::StubCodeCompiler::kNativeCallbackTrampolineSize; + return entrypoint; #endif // defined(DART_PRECOMPILER) } #endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) diff --git a/runtime/vm/ffi_callback_trampolines.h b/runtime/vm/ffi_callback_trampolines.h index 77822d5a0fe..65c2a37ece6 100644 --- a/runtime/vm/ffi_callback_trampolines.h +++ b/runtime/vm/ffi_callback_trampolines.h @@ -57,13 +57,11 @@ class NativeCallbackTrampolines : public ValueObject { // Allocates a callback trampoline corresponding to the callback id // 'next_callback_id()'. Returns an entrypoint to the trampoline. - void AllocateTrampoline(); - - // Get the entrypoint for a previously allocated callback ID. - uword TrampolineForId(int32_t callback_id); + uword AllocateTrampoline(); private: MallocGrowableArray trampoline_pages_; + uword next_callback_trampoline_ = 0; intptr_t trampolines_left_on_page_ = 0; intptr_t next_callback_id_ = 0; diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc index c097744bf69..84c03163148 100644 --- a/runtime/vm/image_snapshot.cc +++ b/runtime/vm/image_snapshot.cc @@ -556,11 +556,6 @@ const char* NameOfStubIsolateSpecificStub(ObjectStore* object_store, void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { Zone* zone = Thread::Current()->zone(); -#if defined(DART_PRECOMPILER) - const char* bss_symbol = - vm ? "_kDartVmSnapshotBss" : "_kDartIsolateSnapshotBss"; -#endif - const char* instructions_symbol = vm ? "_kDartVmSnapshotInstructions" : "_kDartIsolateSnapshotInstructions"; assembly_stream_.Print(".text\n"); @@ -575,16 +570,8 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { // look like a HeapPage. intptr_t instructions_length = next_text_offset_; WriteWordLiteralText(instructions_length); - -#if defined(DART_PRECOMPILER) - assembly_stream_.Print("%s %s - %s\n", kLiteralPrefix, bss_symbol, - instructions_symbol); -#else - WriteWordLiteralText(0); // No relocations. -#endif - intptr_t header_words = Image::kHeaderSize / sizeof(compiler::target::uword); - for (intptr_t i = Image::kHeaderFields; i < header_words; i++) { + for (intptr_t i = 1; i < header_words; i++) { WriteWordLiteralText(0); } @@ -592,7 +579,6 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { Object& owner = Object::Handle(zone); String& str = String::Handle(zone); - PcDescriptors& descriptors = PcDescriptors::Handle(zone); ObjectStore* object_store = Isolate::Current()->object_store(); @@ -627,7 +613,6 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { const Instructions& insns = *data.insns_; const Code& code = *data.code_; - descriptors = data.code_->pc_descriptors(); if (profile_writer_ != nullptr) { const intptr_t offset = Image::kHeaderSize + text_offset; @@ -732,27 +717,7 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { ASSERT(Utils::IsAligned(entry, sizeof(uword))); ASSERT(Utils::IsAligned(end, sizeof(uword))); -#if defined(DART_PRECOMPILER) - PcDescriptors::Iterator iterator(descriptors, - RawPcDescriptors::kBSSRelocation); - uword next_reloc_offset = iterator.MoveNext() ? iterator.PcOffset() : -1; - - for (uword cursor = entry; cursor < end; - cursor += sizeof(compiler::target::uword*)) { - compiler::target::uword data = - *reinterpret_cast(cursor); - if ((cursor - entry) == next_reloc_offset) { - assembly_stream_.Print("%s %s - (.) + %" Pd "\n", kLiteralPrefix, - bss_symbol, /*addend=*/data); - next_reloc_offset = iterator.MoveNext() ? iterator.PcOffset() : -1; - } else { - WriteWordLiteralText(data); - } - } - text_offset += end - entry; -#else text_offset += WriteByteSequence(entry, end); -#endif } ASSERT((text_offset - instr_start) == insns.raw()->HeapSize()); @@ -760,16 +725,6 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { FrameUnwindEpilogue(); -#if defined(DART_PRECOMPILER) - assembly_stream_.Print(".bss\n"); - assembly_stream_.Print("%s:\n", bss_symbol); - - // Currently we only put one symbol in the data section, the address of - // DLRT_GetThreadForNativeCallback, which is populated when the snapshot is - // loaded. - WriteWordLiteralText(0); -#endif - #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \ defined(TARGET_OS_FUCHSIA) assembly_stream_.Print(".section .rodata\n"); @@ -905,42 +860,24 @@ intptr_t BlobImageWriter::WriteByteSequence(uword start, uword end) { } void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { - const intptr_t instructions_length = next_text_offset_; #ifdef DART_PRECOMPILER intptr_t segment_base = 0; if (elf_ != nullptr) { segment_base = elf_->NextMemoryOffset(); } - - // Calculate the start of the BSS section based on the known size of the - // text section and page alignment. - intptr_t bss_base = 0; - if (elf_ != nullptr) { - bss_base = - Utils::RoundUp(segment_base + instructions_length, Elf::kPageSize); - } #endif // This header provides the gap to make the instructions snapshot look like a // HeapPage. + intptr_t instructions_length = next_text_offset_; instructions_blob_stream_.WriteWord(instructions_length); -#if defined(DART_PRECOMPILER) - instructions_blob_stream_.WriteWord(elf_ != nullptr ? bss_base - segment_base - : 0); -#else - instructions_blob_stream_.WriteWord(0); // No relocations. -#endif intptr_t header_words = Image::kHeaderSize / sizeof(uword); - for (intptr_t i = Image::kHeaderFields; i < header_words; i++) { + for (intptr_t i = 1; i < header_words; i++) { instructions_blob_stream_.WriteWord(0); } intptr_t text_offset = 0; -#if defined(DART_PRECOMPILER) - PcDescriptors& descriptors = PcDescriptors::Handle(); -#endif - NoSafepointScope no_safepoint; for (intptr_t i = 0; i < instructions_.length(); i++) { auto& data = instructions_[i]; @@ -991,8 +928,6 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { marked_tags |= static_cast(insns.raw_ptr()->hash_) << 32; #endif - intptr_t payload_stream_start = 0; - #if defined(IS_SIMARM_X64) const intptr_t start_offset = instructions_blob_stream_.bytes_written(); const intptr_t size_in_bytes = InstructionsSizeInSnapshot(insns.Size()); @@ -1003,7 +938,6 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { instructions_blob_stream_.WriteFixed( insns.raw_ptr()->unchecked_entrypoint_pc_offset_); instructions_blob_stream_.Align(kSimarmX64InstructionsAlignment); - payload_stream_start = instructions_blob_stream_.Position(); instructions_blob_stream_.WriteBytes( reinterpret_cast(insns.PayloadStart()), insns.Size()); instructions_blob_stream_.Align(kSimarmX64InstructionsAlignment); @@ -1011,61 +945,16 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { text_offset += (end_offset - start_offset); USE(end); #else // defined(IS_SIMARM_X64) - payload_stream_start = instructions_blob_stream_.Position() + - (insns.PayloadStart() - beginning); - instructions_blob_stream_.WriteWord(marked_tags); text_offset += sizeof(uword); beginning += sizeof(uword); text_offset += WriteByteSequence(beginning, end); #endif // defined(IS_SIMARM_X64) -#if defined(DART_PRECOMPILER) - // Don't patch the relocation if we're not generating ELF. The regular blobs - // format does not yet support these relocations. Use - // Code::VerifyBSSRelocations to check whether the relocations are patched - // or not after loading. - if (elf_ != nullptr) { - const intptr_t current_stream_position = - instructions_blob_stream_.Position(); - - descriptors = data.code_->pc_descriptors(); - - PcDescriptors::Iterator iterator( - descriptors, /*kind_mask=*/RawPcDescriptors::kBSSRelocation); - - while (iterator.MoveNext()) { - const intptr_t reloc_offset = iterator.PcOffset(); - - // The instruction stream at the relocation position holds an offset - // into BSS corresponding to the symbol being resolved. This addend is - // factored into the relocation. - const auto addend = *reinterpret_cast( - insns.PayloadStart() + reloc_offset); - - // Overwrite the relocation position in the instruction stream with the - // (positive) offset of the start of the payload from the start of the - // BSS segment plus the addend in the relocation. - instructions_blob_stream_.SetPosition(payload_stream_start + - reloc_offset); - - const uword offset = - bss_base - (segment_base + payload_stream_start + reloc_offset) + - addend; - instructions_blob_stream_.WriteTargetWord(offset); - } - - // Restore stream position after the relocation was patched. - instructions_blob_stream_.SetPosition(current_stream_position); - } -#endif - ASSERT((text_offset - instr_start) == ImageWriter::SizeInSnapshot(insns.raw())); } - ASSERT(instructions_blob_stream_.bytes_written() == instructions_length); - #ifdef DART_PRECOMPILER if (elf_ != nullptr) { const char* instructions_symbol = vm ? "_kDartVmSnapshotInstructions" @@ -1074,9 +963,6 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { elf_->AddText(instructions_symbol, instructions_blob_stream_.buffer(), instructions_blob_stream_.bytes_written()); ASSERT(segment_base == segment_base2); - - const intptr_t real_bss_base = elf_->AddBSSData("_kDartVMBSSData", 8); - ASSERT(bss_base == real_bss_base); } #endif } diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h index deb94ef7942..5acb75d0504 100644 --- a/runtime/vm/image_snapshot.h +++ b/runtime/vm/image_snapshot.h @@ -48,11 +48,6 @@ class Image : ValueObject { return snapshot_size - kHeaderSize; } - uword bss_offset() const { - return *(reinterpret_cast(raw_memory_) + 1); - } - - static constexpr intptr_t kHeaderFields = 2; static const intptr_t kHeaderSize = OS::kMaxPreferredCodeAlignment; private: @@ -319,15 +314,8 @@ class AssemblyImageWriter : public ImageWriter { void FrameUnwindPrologue(); void FrameUnwindEpilogue(); intptr_t WriteByteSequence(uword start, uword end); - -#if defined(TARGET_ARCH_IS_64_BIT) - const char* kLiteralPrefix = ".quad"; -#else - const char* kLiteralPrefix = ".long"; -#endif - void WriteWordLiteralText(compiler::target::uword value) { - // Padding is helpful for comparing the .S with --disassemble. +// Padding is helpful for comparing the .S with --disassemble. #if defined(TARGET_ARCH_IS_64_BIT) assembly_stream_.Print(".quad 0x%0.16" Px "\n", value); #else diff --git a/runtime/vm/native_entry.h b/runtime/vm/native_entry.h index 6878c45a56e..a4a5ee5bed1 100644 --- a/runtime/vm/native_entry.h +++ b/runtime/vm/native_entry.h @@ -35,6 +35,15 @@ class String; #define NATIVE_ENTRY_FUNCTION(name) BootstrapNatives::DN_##name +#ifdef DEBUG +#define SET_NATIVE_RETVAL(args, value) \ + RawObject* retval = value; \ + ASSERT(retval->IsDartInstance()); \ + arguments->SetReturnUnsafe(retval); +#else +#define SET_NATIVE_RETVAL(arguments, value) arguments->SetReturnUnsafe(value); +#endif + #define DEFINE_NATIVE_ENTRY(name, type_argument_count, argument_count) \ static RawObject* DN_Helper##name(Isolate* isolate, Thread* thread, \ Zone* zone, NativeArguments* arguments); \ @@ -54,15 +63,9 @@ class String; Isolate* isolate = thread->isolate(); \ TransitionGeneratedToVM transition(thread); \ StackZone zone(thread); \ - /* Be careful holding return_value_unsafe without a handle here. */ \ - /* A return of Object::sentinel means the return value has already */ \ - /* been set. */ \ - RawObject* return_value_unsafe = \ - DN_Helper##name(isolate, thread, zone.GetZone(), arguments); \ - if (return_value_unsafe != Object::sentinel().raw()) { \ - ASSERT(return_value_unsafe->IsDartInstance()); \ - arguments->SetReturnUnsafe(return_value_unsafe); \ - } \ + SET_NATIVE_RETVAL( \ + arguments, \ + DN_Helper##name(isolate, thread, zone.GetZone(), arguments)); \ DEOPTIMIZE_ALOT; \ } \ VERIFY_ON_TRANSITION; \ diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index c541cd26e7d..2fbe4e57db6 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -12437,8 +12437,8 @@ RawInstructions* Instructions::New(intptr_t size, result ^= raw; result.SetSize(size); result.SetHasSingleEntryPoint(has_single_entry_point); - result.set_unchecked_entrypoint_pc_offset(unchecked_entrypoint_pc_offset); result.set_stats(nullptr); + result.set_unchecked_entrypoint_pc_offset(unchecked_entrypoint_pc_offset); } return result.raw(); } @@ -12641,8 +12641,6 @@ const char* PcDescriptors::KindAsStr(RawPcDescriptors::Kind kind) { return "osr-entry "; case RawPcDescriptors::kRewind: return "rewind "; - case RawPcDescriptors::kBSSRelocation: - return "bss reloc "; case RawPcDescriptors::kOther: return "other "; case RawPcDescriptors::kAnyKind: @@ -15168,25 +15166,6 @@ void Code::DumpSourcePositions() const { reader.DumpSourcePositions(PayloadStart()); } -bool Code::VerifyBSSRelocations() const { - const auto& descriptors = PcDescriptors::Handle(pc_descriptors()); - const auto& insns = Instructions::Handle(instructions()); - PcDescriptors::Iterator iterator(descriptors, - RawPcDescriptors::kBSSRelocation); - while (iterator.MoveNext()) { - const uword reloc = insns.PayloadStart() + iterator.PcOffset(); - const word target = *reinterpret_cast(reloc); - // The relocation is in its original unpatched form -- the addend - // representing the target symbol itself. - if (target >= 0 && - target < - BSS::RelocationIndex(BSS::Relocation::NumRelocations) * kWordSize) { - return false; - } - } - return true; -} - void Bytecode::Disassemble(DisassemblyFormatter* formatter) const { #if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER) #if !defined(DART_PRECOMPILED_RUNTIME) diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 37aba42c4fb..35ee3c86543 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -5409,9 +5409,6 @@ class Code : public Object { void Disassemble(DisassemblyFormatter* formatter = NULL) const; - // Returns true if all BSS relocations in the code have been patched. - bool VerifyBSSRelocations() const; - class Comments : public ZoneAllocated { public: static Comments& New(intptr_t count); diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 0c88bdc4900..17a637ca87f 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -1514,9 +1514,7 @@ class RawPcDescriptors : public RawObject { V(OsrEntry, kRuntimeCall << 1) \ /* Call rewind target address. */ \ V(Rewind, kOsrEntry << 1) \ - /* Target-word-size relocation. */ \ - V(BSSRelocation, kRewind << 1) \ - V(Other, kBSSRelocation << 1) \ + V(Other, kRewind << 1) \ V(AnyKind, -1) enum Kind { diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h index 31bb9e7abd8..2097eb60410 100644 --- a/runtime/vm/symbols.h +++ b/runtime/vm/symbols.h @@ -117,7 +117,6 @@ class ObjectPointerVisitor; V(ExternalTwoByteString, "_ExternalTwoByteString") \ V(FactoryResult, "factory result") \ V(FallThroughError, "FallThroughError") \ - V(FfiCallback, "_FfiCallback") \ V(FfiDouble, "Double") \ V(FfiDynamicLibrary, "DynamicLibrary") \ V(FfiFloat, "Float") \ diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc index 688e88624b1..476a1cbfd91 100644 --- a/runtime/vm/thread.cc +++ b/runtime/vm/thread.cc @@ -941,7 +941,7 @@ DisableThreadInterruptsScope::~DisableThreadInterruptsScope() { } const intptr_t kInitialCallbackIdsReserved = 1024; -int32_t Thread::AllocateFfiCallbackId() { +int32_t Thread::AllocateFfiCallbackId(uword* trampoline) { Zone* Z = isolate()->current_zone(); if (ffi_callback_code_ == GrowableObjectArray::null()) { ffi_callback_code_ = GrowableObjectArray::New(kInitialCallbackIdsReserved); @@ -955,7 +955,7 @@ int32_t Thread::AllocateFfiCallbackId() { if (NativeCallbackTrampolines::Enabled()) { auto* const tramps = isolate()->native_callback_trampolines(); ASSERT(tramps->next_callback_id() == id); - tramps->AllocateTrampoline(); + *trampoline = tramps->AllocateTrampoline(); } #endif @@ -964,25 +964,7 @@ int32_t Thread::AllocateFfiCallbackId() { void Thread::SetFfiCallbackCode(int32_t callback_id, const Code& code) { Zone* Z = isolate()->current_zone(); - - /// In AOT the callback ID might have been allocated during compilation but - /// 'ffi_callback_code_' is initialized to empty again when the program - /// starts. Therefore we may need to initialize or expand it to accomodate - /// the callback ID. - - if (ffi_callback_code_ == GrowableObjectArray::null()) { - ffi_callback_code_ = GrowableObjectArray::New(kInitialCallbackIdsReserved); - } - const auto& array = GrowableObjectArray::Handle(Z, ffi_callback_code_); - - if (callback_id >= array.Length()) { - if (callback_id >= array.Capacity()) { - array.Grow(callback_id + 1); - } - array.SetLength(callback_id + 1); - } - array.SetAt(callback_id, code); } diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h index b1fa522c4f9..894197a1bf1 100644 --- a/runtime/vm/thread.h +++ b/runtime/vm/thread.h @@ -14,7 +14,6 @@ #include "platform/atomic.h" #include "platform/safe_stack.h" #include "vm/bitfield.h" -#include "vm/compiler/runtime_api.h" #include "vm/constants.h" #include "vm/globals.h" #include "vm/handles.h" @@ -24,6 +23,7 @@ #include "vm/runtime_entry_list.h" #include "vm/thread_stack_resource.h" #include "vm/thread_state.h" + namespace dart { class AbstractType; @@ -786,11 +786,7 @@ class Thread : public ThreadState { } } - int32_t AllocateFfiCallbackId(); - - // Store 'code' for the native callback identified by 'callback_id'. - // - // Expands the callback code array as necessary to accomodate the callback ID. + int32_t AllocateFfiCallbackId(uword* trampoline); void SetFfiCallbackCode(int32_t callback_id, const Code& code); // Ensure that 'callback_id' refers to a valid callback in this isolate. diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni index b692ab45763..fcc057f39ac 100644 --- a/runtime/vm/vm_sources.gni +++ b/runtime/vm/vm_sources.gni @@ -19,8 +19,6 @@ vm_sources = [ "bootstrap.h", "bootstrap_natives.cc", "bootstrap_natives.h", - "bss_relocs.cc", - "bss_relocs.h", "class_finalizer.cc", "class_finalizer.h", "class_id.h", diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart index a975a138447..1a3c95c4849 100644 --- a/sdk/lib/ffi/ffi.dart +++ b/sdk/lib/ffi/ffi.dart @@ -58,8 +58,7 @@ class Pointer extends NativeType { /// Does not accept dynamic invocations -- where the type of the receiver is /// [dynamic]. external static Pointer> fromFunction( - @DartRepresentationOf("T") Function f, - [Object exceptionalReturn]); + @DartRepresentationOf("T") Function f, Object exceptionalReturn); /// Store a Dart value into this location. /// diff --git a/sdk_nnbd/lib/ffi/ffi.dart b/sdk_nnbd/lib/ffi/ffi.dart index a975a138447..1a3c95c4849 100644 --- a/sdk_nnbd/lib/ffi/ffi.dart +++ b/sdk_nnbd/lib/ffi/ffi.dart @@ -58,8 +58,7 @@ class Pointer extends NativeType { /// Does not accept dynamic invocations -- where the type of the receiver is /// [dynamic]. external static Pointer> fromFunction( - @DartRepresentationOf("T") Function f, - [Object exceptionalReturn]); + @DartRepresentationOf("T") Function f, Object exceptionalReturn); /// Store a Dart value into this location. /// diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status index 46f4755abde..96e41a3aa07 100644 --- a/tests/ffi/ffi.status +++ b/tests/ffi/ffi.status @@ -5,15 +5,6 @@ [ $arch == simdbc || $arch == simdbc64 ] *: Skip # SIMDBC will be deleted soon. -# Issue 37295, not yet supported in blobs snapshots at present. -[ $compiler == dartkp && $system == windows ] -function_callbacks_test: Skip -regress_37511_callbacks_test: Skip -stacktrace_regress_37910_test: Skip - -[ $compiler != dartkp || $system != windows ] -function_callbacks_unsupported_test: SkipByDesign # See above - [ $builder_tag == asan ] data_not_asan_test: SkipByDesign # This test tries to allocate too much memory on purpose. @@ -25,6 +16,11 @@ function_callbacks_test/01: Skip function_callbacks_test/02: Skip function_callbacks_test/03: Skip +[ $runtime == dart_precompiled ] +function_callbacks_test: Skip # Issue dartbug.com/37295 +regress_37511_callbacks_test: Skip # Issue dartbug.com/37295 +stacktrace_regress_37910_test: Skip # Issue dartbug.com/37295 + [ $arch == arm && $system != android ] *: Skip # "hardfp" calling convention is not yet supported (iOS is also supported but not tested): dartbug.com/36309 diff --git a/tests/ffi/function_callbacks_test.dart b/tests/ffi/function_callbacks_test.dart index 1c5eca5aaab..637c9245d03 100644 --- a/tests/ffi/function_callbacks_test.dart +++ b/tests/ffi/function_callbacks_test.dart @@ -192,26 +192,26 @@ final List testcases = [ Test("ManyInts", Pointer.fromFunction(manyInts, 0)), Test("ManyDoubles", Pointer.fromFunction(manyDoubles, 0.0)), Test("ManyArgs", Pointer.fromFunction(manyArgs, 0.0)), - Test("Store", Pointer.fromFunction(store)), - Test("NullPointers", Pointer.fromFunction(nullPointers)), + Test("Store", Pointer.fromFunction(store, null)), + Test("NullPointers", Pointer.fromFunction(nullPointers, null)), Test("ReturnNull", Pointer.fromFunction(returnNull, 42)), - Test("ReturnVoid", Pointer.fromFunction(returnVoid)), + Test("ReturnVoid", Pointer.fromFunction(returnVoid, null)), Test("ThrowExceptionDouble", Pointer.fromFunction(throwExceptionDouble, 42.0)), Test( "ThrowExceptionPointer", Pointer.fromFunction( - throwExceptionPointer)), + throwExceptionPointer, Pointer.fromAddress(42))), Test("ThrowException", Pointer.fromFunction(throwExceptionInt, 42)), - Test("GC", Pointer.fromFunction(testGC)), - Test("UnprotectCode", Pointer.fromFunction(waitForHelper)), + Test("GC", Pointer.fromFunction(testGC, null)), + Test("UnprotectCode", Pointer.fromFunction(waitForHelper, null)), ]; testCallbackWrongThread() => - Test("CallbackWrongThread", Pointer.fromFunction(returnVoid)).run(); + Test("CallbackWrongThread", Pointer.fromFunction(returnVoid, null)).run(); testCallbackOutsideIsolate() => - Test("CallbackOutsideIsolate", Pointer.fromFunction(returnVoid)) + Test("CallbackOutsideIsolate", Pointer.fromFunction(returnVoid, null)) .run(); isolateHelper(int callbackPointer) { @@ -223,25 +223,22 @@ isolateHelper(int callbackPointer) { } testCallbackWrongIsolate() async { - final int callbackPointer = Pointer.fromFunction(returnVoid).address; + final int callbackPointer = Pointer.fromFunction(returnVoid, null).address; final ReceivePort exitPort = ReceivePort(); await Isolate.spawn(isolateHelper, callbackPointer, errorsAreFatal: true, onExit: exitPort.sendPort); await exitPort.first; } -const double zeroPointZero = 0.0; - // Correct type of exceptionalReturn argument to Pointer.fromFunction. double testExceptionalReturn() { Pointer.fromFunction(testExceptionalReturn, 0.0); - Pointer.fromFunction(testExceptionalReturn, zeroPointZero); + Expect.throwsArgumentError(() => Pointer.fromFunction(returnVoid, 0)); + Pointer.fromFunction(returnVoid, null); + Expect.throwsArgumentError(() => Pointer.fromFunction(returnVoid, null)); - Pointer.fromFunction(returnVoid, null); //# 59: compile-time error - Pointer.fromFunction(returnVoid, 0); //# 60: compile-time error Pointer.fromFunction(testExceptionalReturn, "abc"); //# 61: compile-time error Pointer.fromFunction(testExceptionalReturn, 0); //# 62: compile-time error - Pointer.fromFunction(testExceptionalReturn); //# 63: compile-time error } void main() async { @@ -266,1012 +263,9 @@ void testManyCallbacks() { // trampolines. The use of distinct exceptional return values forces separate // trampolines. final List pointers = []; - - // All the parameters of 'fromFunction' are forced to be constant so that we - // only need to generate one trampoline per 'fromFunction' call-site. - // - // As a consequence, to force the creation of 1000 trampolines (and prevent - // any possible caching), we need literally 1000 call-sites. - pointers.add(Pointer.fromFunction(simpleAddition, 0)); - pointers.add(Pointer.fromFunction(simpleAddition, 1)); - pointers.add(Pointer.fromFunction(simpleAddition, 2)); - pointers.add(Pointer.fromFunction(simpleAddition, 3)); - pointers.add(Pointer.fromFunction(simpleAddition, 4)); - pointers.add(Pointer.fromFunction(simpleAddition, 5)); - pointers.add(Pointer.fromFunction(simpleAddition, 6)); - pointers.add(Pointer.fromFunction(simpleAddition, 7)); - pointers.add(Pointer.fromFunction(simpleAddition, 8)); - pointers.add(Pointer.fromFunction(simpleAddition, 9)); - pointers.add(Pointer.fromFunction(simpleAddition, 10)); - pointers.add(Pointer.fromFunction(simpleAddition, 11)); - pointers.add(Pointer.fromFunction(simpleAddition, 12)); - pointers.add(Pointer.fromFunction(simpleAddition, 13)); - pointers.add(Pointer.fromFunction(simpleAddition, 14)); - pointers.add(Pointer.fromFunction(simpleAddition, 15)); - pointers.add(Pointer.fromFunction(simpleAddition, 16)); - pointers.add(Pointer.fromFunction(simpleAddition, 17)); - pointers.add(Pointer.fromFunction(simpleAddition, 18)); - pointers.add(Pointer.fromFunction(simpleAddition, 19)); - pointers.add(Pointer.fromFunction(simpleAddition, 20)); - pointers.add(Pointer.fromFunction(simpleAddition, 21)); - pointers.add(Pointer.fromFunction(simpleAddition, 22)); - pointers.add(Pointer.fromFunction(simpleAddition, 23)); - pointers.add(Pointer.fromFunction(simpleAddition, 24)); - pointers.add(Pointer.fromFunction(simpleAddition, 25)); - pointers.add(Pointer.fromFunction(simpleAddition, 26)); - pointers.add(Pointer.fromFunction(simpleAddition, 27)); - pointers.add(Pointer.fromFunction(simpleAddition, 28)); - pointers.add(Pointer.fromFunction(simpleAddition, 29)); - pointers.add(Pointer.fromFunction(simpleAddition, 30)); - pointers.add(Pointer.fromFunction(simpleAddition, 31)); - pointers.add(Pointer.fromFunction(simpleAddition, 32)); - pointers.add(Pointer.fromFunction(simpleAddition, 33)); - pointers.add(Pointer.fromFunction(simpleAddition, 34)); - pointers.add(Pointer.fromFunction(simpleAddition, 35)); - pointers.add(Pointer.fromFunction(simpleAddition, 36)); - pointers.add(Pointer.fromFunction(simpleAddition, 37)); - pointers.add(Pointer.fromFunction(simpleAddition, 38)); - pointers.add(Pointer.fromFunction(simpleAddition, 39)); - pointers.add(Pointer.fromFunction(simpleAddition, 40)); - pointers.add(Pointer.fromFunction(simpleAddition, 41)); - pointers.add(Pointer.fromFunction(simpleAddition, 42)); - pointers.add(Pointer.fromFunction(simpleAddition, 43)); - pointers.add(Pointer.fromFunction(simpleAddition, 44)); - pointers.add(Pointer.fromFunction(simpleAddition, 45)); - pointers.add(Pointer.fromFunction(simpleAddition, 46)); - pointers.add(Pointer.fromFunction(simpleAddition, 47)); - pointers.add(Pointer.fromFunction(simpleAddition, 48)); - pointers.add(Pointer.fromFunction(simpleAddition, 49)); - pointers.add(Pointer.fromFunction(simpleAddition, 50)); - pointers.add(Pointer.fromFunction(simpleAddition, 51)); - pointers.add(Pointer.fromFunction(simpleAddition, 52)); - pointers.add(Pointer.fromFunction(simpleAddition, 53)); - pointers.add(Pointer.fromFunction(simpleAddition, 54)); - pointers.add(Pointer.fromFunction(simpleAddition, 55)); - pointers.add(Pointer.fromFunction(simpleAddition, 56)); - pointers.add(Pointer.fromFunction(simpleAddition, 57)); - pointers.add(Pointer.fromFunction(simpleAddition, 58)); - pointers.add(Pointer.fromFunction(simpleAddition, 59)); - pointers.add(Pointer.fromFunction(simpleAddition, 60)); - pointers.add(Pointer.fromFunction(simpleAddition, 61)); - pointers.add(Pointer.fromFunction(simpleAddition, 62)); - pointers.add(Pointer.fromFunction(simpleAddition, 63)); - pointers.add(Pointer.fromFunction(simpleAddition, 64)); - pointers.add(Pointer.fromFunction(simpleAddition, 65)); - pointers.add(Pointer.fromFunction(simpleAddition, 66)); - pointers.add(Pointer.fromFunction(simpleAddition, 67)); - pointers.add(Pointer.fromFunction(simpleAddition, 68)); - pointers.add(Pointer.fromFunction(simpleAddition, 69)); - pointers.add(Pointer.fromFunction(simpleAddition, 70)); - pointers.add(Pointer.fromFunction(simpleAddition, 71)); - pointers.add(Pointer.fromFunction(simpleAddition, 72)); - pointers.add(Pointer.fromFunction(simpleAddition, 73)); - pointers.add(Pointer.fromFunction(simpleAddition, 74)); - pointers.add(Pointer.fromFunction(simpleAddition, 75)); - pointers.add(Pointer.fromFunction(simpleAddition, 76)); - pointers.add(Pointer.fromFunction(simpleAddition, 77)); - pointers.add(Pointer.fromFunction(simpleAddition, 78)); - pointers.add(Pointer.fromFunction(simpleAddition, 79)); - pointers.add(Pointer.fromFunction(simpleAddition, 80)); - pointers.add(Pointer.fromFunction(simpleAddition, 81)); - pointers.add(Pointer.fromFunction(simpleAddition, 82)); - pointers.add(Pointer.fromFunction(simpleAddition, 83)); - pointers.add(Pointer.fromFunction(simpleAddition, 84)); - pointers.add(Pointer.fromFunction(simpleAddition, 85)); - pointers.add(Pointer.fromFunction(simpleAddition, 86)); - pointers.add(Pointer.fromFunction(simpleAddition, 87)); - pointers.add(Pointer.fromFunction(simpleAddition, 88)); - pointers.add(Pointer.fromFunction(simpleAddition, 89)); - pointers.add(Pointer.fromFunction(simpleAddition, 90)); - pointers.add(Pointer.fromFunction(simpleAddition, 91)); - pointers.add(Pointer.fromFunction(simpleAddition, 92)); - pointers.add(Pointer.fromFunction(simpleAddition, 93)); - pointers.add(Pointer.fromFunction(simpleAddition, 94)); - pointers.add(Pointer.fromFunction(simpleAddition, 95)); - pointers.add(Pointer.fromFunction(simpleAddition, 96)); - pointers.add(Pointer.fromFunction(simpleAddition, 97)); - pointers.add(Pointer.fromFunction(simpleAddition, 98)); - pointers.add(Pointer.fromFunction(simpleAddition, 99)); - pointers.add(Pointer.fromFunction(simpleAddition, 100)); - pointers.add(Pointer.fromFunction(simpleAddition, 101)); - pointers.add(Pointer.fromFunction(simpleAddition, 102)); - pointers.add(Pointer.fromFunction(simpleAddition, 103)); - pointers.add(Pointer.fromFunction(simpleAddition, 104)); - pointers.add(Pointer.fromFunction(simpleAddition, 105)); - pointers.add(Pointer.fromFunction(simpleAddition, 106)); - pointers.add(Pointer.fromFunction(simpleAddition, 107)); - pointers.add(Pointer.fromFunction(simpleAddition, 108)); - pointers.add(Pointer.fromFunction(simpleAddition, 109)); - pointers.add(Pointer.fromFunction(simpleAddition, 110)); - pointers.add(Pointer.fromFunction(simpleAddition, 111)); - pointers.add(Pointer.fromFunction(simpleAddition, 112)); - pointers.add(Pointer.fromFunction(simpleAddition, 113)); - pointers.add(Pointer.fromFunction(simpleAddition, 114)); - pointers.add(Pointer.fromFunction(simpleAddition, 115)); - pointers.add(Pointer.fromFunction(simpleAddition, 116)); - pointers.add(Pointer.fromFunction(simpleAddition, 117)); - pointers.add(Pointer.fromFunction(simpleAddition, 118)); - pointers.add(Pointer.fromFunction(simpleAddition, 119)); - pointers.add(Pointer.fromFunction(simpleAddition, 120)); - pointers.add(Pointer.fromFunction(simpleAddition, 121)); - pointers.add(Pointer.fromFunction(simpleAddition, 122)); - pointers.add(Pointer.fromFunction(simpleAddition, 123)); - pointers.add(Pointer.fromFunction(simpleAddition, 124)); - pointers.add(Pointer.fromFunction(simpleAddition, 125)); - pointers.add(Pointer.fromFunction(simpleAddition, 126)); - pointers.add(Pointer.fromFunction(simpleAddition, 127)); - pointers.add(Pointer.fromFunction(simpleAddition, 128)); - pointers.add(Pointer.fromFunction(simpleAddition, 129)); - pointers.add(Pointer.fromFunction(simpleAddition, 130)); - pointers.add(Pointer.fromFunction(simpleAddition, 131)); - pointers.add(Pointer.fromFunction(simpleAddition, 132)); - pointers.add(Pointer.fromFunction(simpleAddition, 133)); - pointers.add(Pointer.fromFunction(simpleAddition, 134)); - pointers.add(Pointer.fromFunction(simpleAddition, 135)); - pointers.add(Pointer.fromFunction(simpleAddition, 136)); - pointers.add(Pointer.fromFunction(simpleAddition, 137)); - pointers.add(Pointer.fromFunction(simpleAddition, 138)); - pointers.add(Pointer.fromFunction(simpleAddition, 139)); - pointers.add(Pointer.fromFunction(simpleAddition, 140)); - pointers.add(Pointer.fromFunction(simpleAddition, 141)); - pointers.add(Pointer.fromFunction(simpleAddition, 142)); - pointers.add(Pointer.fromFunction(simpleAddition, 143)); - pointers.add(Pointer.fromFunction(simpleAddition, 144)); - pointers.add(Pointer.fromFunction(simpleAddition, 145)); - pointers.add(Pointer.fromFunction(simpleAddition, 146)); - pointers.add(Pointer.fromFunction(simpleAddition, 147)); - pointers.add(Pointer.fromFunction(simpleAddition, 148)); - pointers.add(Pointer.fromFunction(simpleAddition, 149)); - pointers.add(Pointer.fromFunction(simpleAddition, 150)); - pointers.add(Pointer.fromFunction(simpleAddition, 151)); - pointers.add(Pointer.fromFunction(simpleAddition, 152)); - pointers.add(Pointer.fromFunction(simpleAddition, 153)); - pointers.add(Pointer.fromFunction(simpleAddition, 154)); - pointers.add(Pointer.fromFunction(simpleAddition, 155)); - pointers.add(Pointer.fromFunction(simpleAddition, 156)); - pointers.add(Pointer.fromFunction(simpleAddition, 157)); - pointers.add(Pointer.fromFunction(simpleAddition, 158)); - pointers.add(Pointer.fromFunction(simpleAddition, 159)); - pointers.add(Pointer.fromFunction(simpleAddition, 160)); - pointers.add(Pointer.fromFunction(simpleAddition, 161)); - pointers.add(Pointer.fromFunction(simpleAddition, 162)); - pointers.add(Pointer.fromFunction(simpleAddition, 163)); - pointers.add(Pointer.fromFunction(simpleAddition, 164)); - pointers.add(Pointer.fromFunction(simpleAddition, 165)); - pointers.add(Pointer.fromFunction(simpleAddition, 166)); - pointers.add(Pointer.fromFunction(simpleAddition, 167)); - pointers.add(Pointer.fromFunction(simpleAddition, 168)); - pointers.add(Pointer.fromFunction(simpleAddition, 169)); - pointers.add(Pointer.fromFunction(simpleAddition, 170)); - pointers.add(Pointer.fromFunction(simpleAddition, 171)); - pointers.add(Pointer.fromFunction(simpleAddition, 172)); - pointers.add(Pointer.fromFunction(simpleAddition, 173)); - pointers.add(Pointer.fromFunction(simpleAddition, 174)); - pointers.add(Pointer.fromFunction(simpleAddition, 175)); - pointers.add(Pointer.fromFunction(simpleAddition, 176)); - pointers.add(Pointer.fromFunction(simpleAddition, 177)); - pointers.add(Pointer.fromFunction(simpleAddition, 178)); - pointers.add(Pointer.fromFunction(simpleAddition, 179)); - pointers.add(Pointer.fromFunction(simpleAddition, 180)); - pointers.add(Pointer.fromFunction(simpleAddition, 181)); - pointers.add(Pointer.fromFunction(simpleAddition, 182)); - pointers.add(Pointer.fromFunction(simpleAddition, 183)); - pointers.add(Pointer.fromFunction(simpleAddition, 184)); - pointers.add(Pointer.fromFunction(simpleAddition, 185)); - pointers.add(Pointer.fromFunction(simpleAddition, 186)); - pointers.add(Pointer.fromFunction(simpleAddition, 187)); - pointers.add(Pointer.fromFunction(simpleAddition, 188)); - pointers.add(Pointer.fromFunction(simpleAddition, 189)); - pointers.add(Pointer.fromFunction(simpleAddition, 190)); - pointers.add(Pointer.fromFunction(simpleAddition, 191)); - pointers.add(Pointer.fromFunction(simpleAddition, 192)); - pointers.add(Pointer.fromFunction(simpleAddition, 193)); - pointers.add(Pointer.fromFunction(simpleAddition, 194)); - pointers.add(Pointer.fromFunction(simpleAddition, 195)); - pointers.add(Pointer.fromFunction(simpleAddition, 196)); - pointers.add(Pointer.fromFunction(simpleAddition, 197)); - pointers.add(Pointer.fromFunction(simpleAddition, 198)); - pointers.add(Pointer.fromFunction(simpleAddition, 199)); - pointers.add(Pointer.fromFunction(simpleAddition, 200)); - pointers.add(Pointer.fromFunction(simpleAddition, 201)); - pointers.add(Pointer.fromFunction(simpleAddition, 202)); - pointers.add(Pointer.fromFunction(simpleAddition, 203)); - pointers.add(Pointer.fromFunction(simpleAddition, 204)); - pointers.add(Pointer.fromFunction(simpleAddition, 205)); - pointers.add(Pointer.fromFunction(simpleAddition, 206)); - pointers.add(Pointer.fromFunction(simpleAddition, 207)); - pointers.add(Pointer.fromFunction(simpleAddition, 208)); - pointers.add(Pointer.fromFunction(simpleAddition, 209)); - pointers.add(Pointer.fromFunction(simpleAddition, 210)); - pointers.add(Pointer.fromFunction(simpleAddition, 211)); - pointers.add(Pointer.fromFunction(simpleAddition, 212)); - pointers.add(Pointer.fromFunction(simpleAddition, 213)); - pointers.add(Pointer.fromFunction(simpleAddition, 214)); - pointers.add(Pointer.fromFunction(simpleAddition, 215)); - pointers.add(Pointer.fromFunction(simpleAddition, 216)); - pointers.add(Pointer.fromFunction(simpleAddition, 217)); - pointers.add(Pointer.fromFunction(simpleAddition, 218)); - pointers.add(Pointer.fromFunction(simpleAddition, 219)); - pointers.add(Pointer.fromFunction(simpleAddition, 220)); - pointers.add(Pointer.fromFunction(simpleAddition, 221)); - pointers.add(Pointer.fromFunction(simpleAddition, 222)); - pointers.add(Pointer.fromFunction(simpleAddition, 223)); - pointers.add(Pointer.fromFunction(simpleAddition, 224)); - pointers.add(Pointer.fromFunction(simpleAddition, 225)); - pointers.add(Pointer.fromFunction(simpleAddition, 226)); - pointers.add(Pointer.fromFunction(simpleAddition, 227)); - pointers.add(Pointer.fromFunction(simpleAddition, 228)); - pointers.add(Pointer.fromFunction(simpleAddition, 229)); - pointers.add(Pointer.fromFunction(simpleAddition, 230)); - pointers.add(Pointer.fromFunction(simpleAddition, 231)); - pointers.add(Pointer.fromFunction(simpleAddition, 232)); - pointers.add(Pointer.fromFunction(simpleAddition, 233)); - pointers.add(Pointer.fromFunction(simpleAddition, 234)); - pointers.add(Pointer.fromFunction(simpleAddition, 235)); - pointers.add(Pointer.fromFunction(simpleAddition, 236)); - pointers.add(Pointer.fromFunction(simpleAddition, 237)); - pointers.add(Pointer.fromFunction(simpleAddition, 238)); - pointers.add(Pointer.fromFunction(simpleAddition, 239)); - pointers.add(Pointer.fromFunction(simpleAddition, 240)); - pointers.add(Pointer.fromFunction(simpleAddition, 241)); - pointers.add(Pointer.fromFunction(simpleAddition, 242)); - pointers.add(Pointer.fromFunction(simpleAddition, 243)); - pointers.add(Pointer.fromFunction(simpleAddition, 244)); - pointers.add(Pointer.fromFunction(simpleAddition, 245)); - pointers.add(Pointer.fromFunction(simpleAddition, 246)); - pointers.add(Pointer.fromFunction(simpleAddition, 247)); - pointers.add(Pointer.fromFunction(simpleAddition, 248)); - pointers.add(Pointer.fromFunction(simpleAddition, 249)); - pointers.add(Pointer.fromFunction(simpleAddition, 250)); - pointers.add(Pointer.fromFunction(simpleAddition, 251)); - pointers.add(Pointer.fromFunction(simpleAddition, 252)); - pointers.add(Pointer.fromFunction(simpleAddition, 253)); - pointers.add(Pointer.fromFunction(simpleAddition, 254)); - pointers.add(Pointer.fromFunction(simpleAddition, 255)); - pointers.add(Pointer.fromFunction(simpleAddition, 256)); - pointers.add(Pointer.fromFunction(simpleAddition, 257)); - pointers.add(Pointer.fromFunction(simpleAddition, 258)); - pointers.add(Pointer.fromFunction(simpleAddition, 259)); - pointers.add(Pointer.fromFunction(simpleAddition, 260)); - pointers.add(Pointer.fromFunction(simpleAddition, 261)); - pointers.add(Pointer.fromFunction(simpleAddition, 262)); - pointers.add(Pointer.fromFunction(simpleAddition, 263)); - pointers.add(Pointer.fromFunction(simpleAddition, 264)); - pointers.add(Pointer.fromFunction(simpleAddition, 265)); - pointers.add(Pointer.fromFunction(simpleAddition, 266)); - pointers.add(Pointer.fromFunction(simpleAddition, 267)); - pointers.add(Pointer.fromFunction(simpleAddition, 268)); - pointers.add(Pointer.fromFunction(simpleAddition, 269)); - pointers.add(Pointer.fromFunction(simpleAddition, 270)); - pointers.add(Pointer.fromFunction(simpleAddition, 271)); - pointers.add(Pointer.fromFunction(simpleAddition, 272)); - pointers.add(Pointer.fromFunction(simpleAddition, 273)); - pointers.add(Pointer.fromFunction(simpleAddition, 274)); - pointers.add(Pointer.fromFunction(simpleAddition, 275)); - pointers.add(Pointer.fromFunction(simpleAddition, 276)); - pointers.add(Pointer.fromFunction(simpleAddition, 277)); - pointers.add(Pointer.fromFunction(simpleAddition, 278)); - pointers.add(Pointer.fromFunction(simpleAddition, 279)); - pointers.add(Pointer.fromFunction(simpleAddition, 280)); - pointers.add(Pointer.fromFunction(simpleAddition, 281)); - pointers.add(Pointer.fromFunction(simpleAddition, 282)); - pointers.add(Pointer.fromFunction(simpleAddition, 283)); - pointers.add(Pointer.fromFunction(simpleAddition, 284)); - pointers.add(Pointer.fromFunction(simpleAddition, 285)); - pointers.add(Pointer.fromFunction(simpleAddition, 286)); - pointers.add(Pointer.fromFunction(simpleAddition, 287)); - pointers.add(Pointer.fromFunction(simpleAddition, 288)); - pointers.add(Pointer.fromFunction(simpleAddition, 289)); - pointers.add(Pointer.fromFunction(simpleAddition, 290)); - pointers.add(Pointer.fromFunction(simpleAddition, 291)); - pointers.add(Pointer.fromFunction(simpleAddition, 292)); - pointers.add(Pointer.fromFunction(simpleAddition, 293)); - pointers.add(Pointer.fromFunction(simpleAddition, 294)); - pointers.add(Pointer.fromFunction(simpleAddition, 295)); - pointers.add(Pointer.fromFunction(simpleAddition, 296)); - pointers.add(Pointer.fromFunction(simpleAddition, 297)); - pointers.add(Pointer.fromFunction(simpleAddition, 298)); - pointers.add(Pointer.fromFunction(simpleAddition, 299)); - pointers.add(Pointer.fromFunction(simpleAddition, 300)); - pointers.add(Pointer.fromFunction(simpleAddition, 301)); - pointers.add(Pointer.fromFunction(simpleAddition, 302)); - pointers.add(Pointer.fromFunction(simpleAddition, 303)); - pointers.add(Pointer.fromFunction(simpleAddition, 304)); - pointers.add(Pointer.fromFunction(simpleAddition, 305)); - pointers.add(Pointer.fromFunction(simpleAddition, 306)); - pointers.add(Pointer.fromFunction(simpleAddition, 307)); - pointers.add(Pointer.fromFunction(simpleAddition, 308)); - pointers.add(Pointer.fromFunction(simpleAddition, 309)); - pointers.add(Pointer.fromFunction(simpleAddition, 310)); - pointers.add(Pointer.fromFunction(simpleAddition, 311)); - pointers.add(Pointer.fromFunction(simpleAddition, 312)); - pointers.add(Pointer.fromFunction(simpleAddition, 313)); - pointers.add(Pointer.fromFunction(simpleAddition, 314)); - pointers.add(Pointer.fromFunction(simpleAddition, 315)); - pointers.add(Pointer.fromFunction(simpleAddition, 316)); - pointers.add(Pointer.fromFunction(simpleAddition, 317)); - pointers.add(Pointer.fromFunction(simpleAddition, 318)); - pointers.add(Pointer.fromFunction(simpleAddition, 319)); - pointers.add(Pointer.fromFunction(simpleAddition, 320)); - pointers.add(Pointer.fromFunction(simpleAddition, 321)); - pointers.add(Pointer.fromFunction(simpleAddition, 322)); - pointers.add(Pointer.fromFunction(simpleAddition, 323)); - pointers.add(Pointer.fromFunction(simpleAddition, 324)); - pointers.add(Pointer.fromFunction(simpleAddition, 325)); - pointers.add(Pointer.fromFunction(simpleAddition, 326)); - pointers.add(Pointer.fromFunction(simpleAddition, 327)); - pointers.add(Pointer.fromFunction(simpleAddition, 328)); - pointers.add(Pointer.fromFunction(simpleAddition, 329)); - pointers.add(Pointer.fromFunction(simpleAddition, 330)); - pointers.add(Pointer.fromFunction(simpleAddition, 331)); - pointers.add(Pointer.fromFunction(simpleAddition, 332)); - pointers.add(Pointer.fromFunction(simpleAddition, 333)); - pointers.add(Pointer.fromFunction(simpleAddition, 334)); - pointers.add(Pointer.fromFunction(simpleAddition, 335)); - pointers.add(Pointer.fromFunction(simpleAddition, 336)); - pointers.add(Pointer.fromFunction(simpleAddition, 337)); - pointers.add(Pointer.fromFunction(simpleAddition, 338)); - pointers.add(Pointer.fromFunction(simpleAddition, 339)); - pointers.add(Pointer.fromFunction(simpleAddition, 340)); - pointers.add(Pointer.fromFunction(simpleAddition, 341)); - pointers.add(Pointer.fromFunction(simpleAddition, 342)); - pointers.add(Pointer.fromFunction(simpleAddition, 343)); - pointers.add(Pointer.fromFunction(simpleAddition, 344)); - pointers.add(Pointer.fromFunction(simpleAddition, 345)); - pointers.add(Pointer.fromFunction(simpleAddition, 346)); - pointers.add(Pointer.fromFunction(simpleAddition, 347)); - pointers.add(Pointer.fromFunction(simpleAddition, 348)); - pointers.add(Pointer.fromFunction(simpleAddition, 349)); - pointers.add(Pointer.fromFunction(simpleAddition, 350)); - pointers.add(Pointer.fromFunction(simpleAddition, 351)); - pointers.add(Pointer.fromFunction(simpleAddition, 352)); - pointers.add(Pointer.fromFunction(simpleAddition, 353)); - pointers.add(Pointer.fromFunction(simpleAddition, 354)); - pointers.add(Pointer.fromFunction(simpleAddition, 355)); - pointers.add(Pointer.fromFunction(simpleAddition, 356)); - pointers.add(Pointer.fromFunction(simpleAddition, 357)); - pointers.add(Pointer.fromFunction(simpleAddition, 358)); - pointers.add(Pointer.fromFunction(simpleAddition, 359)); - pointers.add(Pointer.fromFunction(simpleAddition, 360)); - pointers.add(Pointer.fromFunction(simpleAddition, 361)); - pointers.add(Pointer.fromFunction(simpleAddition, 362)); - pointers.add(Pointer.fromFunction(simpleAddition, 363)); - pointers.add(Pointer.fromFunction(simpleAddition, 364)); - pointers.add(Pointer.fromFunction(simpleAddition, 365)); - pointers.add(Pointer.fromFunction(simpleAddition, 366)); - pointers.add(Pointer.fromFunction(simpleAddition, 367)); - pointers.add(Pointer.fromFunction(simpleAddition, 368)); - pointers.add(Pointer.fromFunction(simpleAddition, 369)); - pointers.add(Pointer.fromFunction(simpleAddition, 370)); - pointers.add(Pointer.fromFunction(simpleAddition, 371)); - pointers.add(Pointer.fromFunction(simpleAddition, 372)); - pointers.add(Pointer.fromFunction(simpleAddition, 373)); - pointers.add(Pointer.fromFunction(simpleAddition, 374)); - pointers.add(Pointer.fromFunction(simpleAddition, 375)); - pointers.add(Pointer.fromFunction(simpleAddition, 376)); - pointers.add(Pointer.fromFunction(simpleAddition, 377)); - pointers.add(Pointer.fromFunction(simpleAddition, 378)); - pointers.add(Pointer.fromFunction(simpleAddition, 379)); - pointers.add(Pointer.fromFunction(simpleAddition, 380)); - pointers.add(Pointer.fromFunction(simpleAddition, 381)); - pointers.add(Pointer.fromFunction(simpleAddition, 382)); - pointers.add(Pointer.fromFunction(simpleAddition, 383)); - pointers.add(Pointer.fromFunction(simpleAddition, 384)); - pointers.add(Pointer.fromFunction(simpleAddition, 385)); - pointers.add(Pointer.fromFunction(simpleAddition, 386)); - pointers.add(Pointer.fromFunction(simpleAddition, 387)); - pointers.add(Pointer.fromFunction(simpleAddition, 388)); - pointers.add(Pointer.fromFunction(simpleAddition, 389)); - pointers.add(Pointer.fromFunction(simpleAddition, 390)); - pointers.add(Pointer.fromFunction(simpleAddition, 391)); - pointers.add(Pointer.fromFunction(simpleAddition, 392)); - pointers.add(Pointer.fromFunction(simpleAddition, 393)); - pointers.add(Pointer.fromFunction(simpleAddition, 394)); - pointers.add(Pointer.fromFunction(simpleAddition, 395)); - pointers.add(Pointer.fromFunction(simpleAddition, 396)); - pointers.add(Pointer.fromFunction(simpleAddition, 397)); - pointers.add(Pointer.fromFunction(simpleAddition, 398)); - pointers.add(Pointer.fromFunction(simpleAddition, 399)); - pointers.add(Pointer.fromFunction(simpleAddition, 400)); - pointers.add(Pointer.fromFunction(simpleAddition, 401)); - pointers.add(Pointer.fromFunction(simpleAddition, 402)); - pointers.add(Pointer.fromFunction(simpleAddition, 403)); - pointers.add(Pointer.fromFunction(simpleAddition, 404)); - pointers.add(Pointer.fromFunction(simpleAddition, 405)); - pointers.add(Pointer.fromFunction(simpleAddition, 406)); - pointers.add(Pointer.fromFunction(simpleAddition, 407)); - pointers.add(Pointer.fromFunction(simpleAddition, 408)); - pointers.add(Pointer.fromFunction(simpleAddition, 409)); - pointers.add(Pointer.fromFunction(simpleAddition, 410)); - pointers.add(Pointer.fromFunction(simpleAddition, 411)); - pointers.add(Pointer.fromFunction(simpleAddition, 412)); - pointers.add(Pointer.fromFunction(simpleAddition, 413)); - pointers.add(Pointer.fromFunction(simpleAddition, 414)); - pointers.add(Pointer.fromFunction(simpleAddition, 415)); - pointers.add(Pointer.fromFunction(simpleAddition, 416)); - pointers.add(Pointer.fromFunction(simpleAddition, 417)); - pointers.add(Pointer.fromFunction(simpleAddition, 418)); - pointers.add(Pointer.fromFunction(simpleAddition, 419)); - pointers.add(Pointer.fromFunction(simpleAddition, 420)); - pointers.add(Pointer.fromFunction(simpleAddition, 421)); - pointers.add(Pointer.fromFunction(simpleAddition, 422)); - pointers.add(Pointer.fromFunction(simpleAddition, 423)); - pointers.add(Pointer.fromFunction(simpleAddition, 424)); - pointers.add(Pointer.fromFunction(simpleAddition, 425)); - pointers.add(Pointer.fromFunction(simpleAddition, 426)); - pointers.add(Pointer.fromFunction(simpleAddition, 427)); - pointers.add(Pointer.fromFunction(simpleAddition, 428)); - pointers.add(Pointer.fromFunction(simpleAddition, 429)); - pointers.add(Pointer.fromFunction(simpleAddition, 430)); - pointers.add(Pointer.fromFunction(simpleAddition, 431)); - pointers.add(Pointer.fromFunction(simpleAddition, 432)); - pointers.add(Pointer.fromFunction(simpleAddition, 433)); - pointers.add(Pointer.fromFunction(simpleAddition, 434)); - pointers.add(Pointer.fromFunction(simpleAddition, 435)); - pointers.add(Pointer.fromFunction(simpleAddition, 436)); - pointers.add(Pointer.fromFunction(simpleAddition, 437)); - pointers.add(Pointer.fromFunction(simpleAddition, 438)); - pointers.add(Pointer.fromFunction(simpleAddition, 439)); - pointers.add(Pointer.fromFunction(simpleAddition, 440)); - pointers.add(Pointer.fromFunction(simpleAddition, 441)); - pointers.add(Pointer.fromFunction(simpleAddition, 442)); - pointers.add(Pointer.fromFunction(simpleAddition, 443)); - pointers.add(Pointer.fromFunction(simpleAddition, 444)); - pointers.add(Pointer.fromFunction(simpleAddition, 445)); - pointers.add(Pointer.fromFunction(simpleAddition, 446)); - pointers.add(Pointer.fromFunction(simpleAddition, 447)); - pointers.add(Pointer.fromFunction(simpleAddition, 448)); - pointers.add(Pointer.fromFunction(simpleAddition, 449)); - pointers.add(Pointer.fromFunction(simpleAddition, 450)); - pointers.add(Pointer.fromFunction(simpleAddition, 451)); - pointers.add(Pointer.fromFunction(simpleAddition, 452)); - pointers.add(Pointer.fromFunction(simpleAddition, 453)); - pointers.add(Pointer.fromFunction(simpleAddition, 454)); - pointers.add(Pointer.fromFunction(simpleAddition, 455)); - pointers.add(Pointer.fromFunction(simpleAddition, 456)); - pointers.add(Pointer.fromFunction(simpleAddition, 457)); - pointers.add(Pointer.fromFunction(simpleAddition, 458)); - pointers.add(Pointer.fromFunction(simpleAddition, 459)); - pointers.add(Pointer.fromFunction(simpleAddition, 460)); - pointers.add(Pointer.fromFunction(simpleAddition, 461)); - pointers.add(Pointer.fromFunction(simpleAddition, 462)); - pointers.add(Pointer.fromFunction(simpleAddition, 463)); - pointers.add(Pointer.fromFunction(simpleAddition, 464)); - pointers.add(Pointer.fromFunction(simpleAddition, 465)); - pointers.add(Pointer.fromFunction(simpleAddition, 466)); - pointers.add(Pointer.fromFunction(simpleAddition, 467)); - pointers.add(Pointer.fromFunction(simpleAddition, 468)); - pointers.add(Pointer.fromFunction(simpleAddition, 469)); - pointers.add(Pointer.fromFunction(simpleAddition, 470)); - pointers.add(Pointer.fromFunction(simpleAddition, 471)); - pointers.add(Pointer.fromFunction(simpleAddition, 472)); - pointers.add(Pointer.fromFunction(simpleAddition, 473)); - pointers.add(Pointer.fromFunction(simpleAddition, 474)); - pointers.add(Pointer.fromFunction(simpleAddition, 475)); - pointers.add(Pointer.fromFunction(simpleAddition, 476)); - pointers.add(Pointer.fromFunction(simpleAddition, 477)); - pointers.add(Pointer.fromFunction(simpleAddition, 478)); - pointers.add(Pointer.fromFunction(simpleAddition, 479)); - pointers.add(Pointer.fromFunction(simpleAddition, 480)); - pointers.add(Pointer.fromFunction(simpleAddition, 481)); - pointers.add(Pointer.fromFunction(simpleAddition, 482)); - pointers.add(Pointer.fromFunction(simpleAddition, 483)); - pointers.add(Pointer.fromFunction(simpleAddition, 484)); - pointers.add(Pointer.fromFunction(simpleAddition, 485)); - pointers.add(Pointer.fromFunction(simpleAddition, 486)); - pointers.add(Pointer.fromFunction(simpleAddition, 487)); - pointers.add(Pointer.fromFunction(simpleAddition, 488)); - pointers.add(Pointer.fromFunction(simpleAddition, 489)); - pointers.add(Pointer.fromFunction(simpleAddition, 490)); - pointers.add(Pointer.fromFunction(simpleAddition, 491)); - pointers.add(Pointer.fromFunction(simpleAddition, 492)); - pointers.add(Pointer.fromFunction(simpleAddition, 493)); - pointers.add(Pointer.fromFunction(simpleAddition, 494)); - pointers.add(Pointer.fromFunction(simpleAddition, 495)); - pointers.add(Pointer.fromFunction(simpleAddition, 496)); - pointers.add(Pointer.fromFunction(simpleAddition, 497)); - pointers.add(Pointer.fromFunction(simpleAddition, 498)); - pointers.add(Pointer.fromFunction(simpleAddition, 499)); - pointers.add(Pointer.fromFunction(simpleAddition, 500)); - pointers.add(Pointer.fromFunction(simpleAddition, 501)); - pointers.add(Pointer.fromFunction(simpleAddition, 502)); - pointers.add(Pointer.fromFunction(simpleAddition, 503)); - pointers.add(Pointer.fromFunction(simpleAddition, 504)); - pointers.add(Pointer.fromFunction(simpleAddition, 505)); - pointers.add(Pointer.fromFunction(simpleAddition, 506)); - pointers.add(Pointer.fromFunction(simpleAddition, 507)); - pointers.add(Pointer.fromFunction(simpleAddition, 508)); - pointers.add(Pointer.fromFunction(simpleAddition, 509)); - pointers.add(Pointer.fromFunction(simpleAddition, 510)); - pointers.add(Pointer.fromFunction(simpleAddition, 511)); - pointers.add(Pointer.fromFunction(simpleAddition, 512)); - pointers.add(Pointer.fromFunction(simpleAddition, 513)); - pointers.add(Pointer.fromFunction(simpleAddition, 514)); - pointers.add(Pointer.fromFunction(simpleAddition, 515)); - pointers.add(Pointer.fromFunction(simpleAddition, 516)); - pointers.add(Pointer.fromFunction(simpleAddition, 517)); - pointers.add(Pointer.fromFunction(simpleAddition, 518)); - pointers.add(Pointer.fromFunction(simpleAddition, 519)); - pointers.add(Pointer.fromFunction(simpleAddition, 520)); - pointers.add(Pointer.fromFunction(simpleAddition, 521)); - pointers.add(Pointer.fromFunction(simpleAddition, 522)); - pointers.add(Pointer.fromFunction(simpleAddition, 523)); - pointers.add(Pointer.fromFunction(simpleAddition, 524)); - pointers.add(Pointer.fromFunction(simpleAddition, 525)); - pointers.add(Pointer.fromFunction(simpleAddition, 526)); - pointers.add(Pointer.fromFunction(simpleAddition, 527)); - pointers.add(Pointer.fromFunction(simpleAddition, 528)); - pointers.add(Pointer.fromFunction(simpleAddition, 529)); - pointers.add(Pointer.fromFunction(simpleAddition, 530)); - pointers.add(Pointer.fromFunction(simpleAddition, 531)); - pointers.add(Pointer.fromFunction(simpleAddition, 532)); - pointers.add(Pointer.fromFunction(simpleAddition, 533)); - pointers.add(Pointer.fromFunction(simpleAddition, 534)); - pointers.add(Pointer.fromFunction(simpleAddition, 535)); - pointers.add(Pointer.fromFunction(simpleAddition, 536)); - pointers.add(Pointer.fromFunction(simpleAddition, 537)); - pointers.add(Pointer.fromFunction(simpleAddition, 538)); - pointers.add(Pointer.fromFunction(simpleAddition, 539)); - pointers.add(Pointer.fromFunction(simpleAddition, 540)); - pointers.add(Pointer.fromFunction(simpleAddition, 541)); - pointers.add(Pointer.fromFunction(simpleAddition, 542)); - pointers.add(Pointer.fromFunction(simpleAddition, 543)); - pointers.add(Pointer.fromFunction(simpleAddition, 544)); - pointers.add(Pointer.fromFunction(simpleAddition, 545)); - pointers.add(Pointer.fromFunction(simpleAddition, 546)); - pointers.add(Pointer.fromFunction(simpleAddition, 547)); - pointers.add(Pointer.fromFunction(simpleAddition, 548)); - pointers.add(Pointer.fromFunction(simpleAddition, 549)); - pointers.add(Pointer.fromFunction(simpleAddition, 550)); - pointers.add(Pointer.fromFunction(simpleAddition, 551)); - pointers.add(Pointer.fromFunction(simpleAddition, 552)); - pointers.add(Pointer.fromFunction(simpleAddition, 553)); - pointers.add(Pointer.fromFunction(simpleAddition, 554)); - pointers.add(Pointer.fromFunction(simpleAddition, 555)); - pointers.add(Pointer.fromFunction(simpleAddition, 556)); - pointers.add(Pointer.fromFunction(simpleAddition, 557)); - pointers.add(Pointer.fromFunction(simpleAddition, 558)); - pointers.add(Pointer.fromFunction(simpleAddition, 559)); - pointers.add(Pointer.fromFunction(simpleAddition, 560)); - pointers.add(Pointer.fromFunction(simpleAddition, 561)); - pointers.add(Pointer.fromFunction(simpleAddition, 562)); - pointers.add(Pointer.fromFunction(simpleAddition, 563)); - pointers.add(Pointer.fromFunction(simpleAddition, 564)); - pointers.add(Pointer.fromFunction(simpleAddition, 565)); - pointers.add(Pointer.fromFunction(simpleAddition, 566)); - pointers.add(Pointer.fromFunction(simpleAddition, 567)); - pointers.add(Pointer.fromFunction(simpleAddition, 568)); - pointers.add(Pointer.fromFunction(simpleAddition, 569)); - pointers.add(Pointer.fromFunction(simpleAddition, 570)); - pointers.add(Pointer.fromFunction(simpleAddition, 571)); - pointers.add(Pointer.fromFunction(simpleAddition, 572)); - pointers.add(Pointer.fromFunction(simpleAddition, 573)); - pointers.add(Pointer.fromFunction(simpleAddition, 574)); - pointers.add(Pointer.fromFunction(simpleAddition, 575)); - pointers.add(Pointer.fromFunction(simpleAddition, 576)); - pointers.add(Pointer.fromFunction(simpleAddition, 577)); - pointers.add(Pointer.fromFunction(simpleAddition, 578)); - pointers.add(Pointer.fromFunction(simpleAddition, 579)); - pointers.add(Pointer.fromFunction(simpleAddition, 580)); - pointers.add(Pointer.fromFunction(simpleAddition, 581)); - pointers.add(Pointer.fromFunction(simpleAddition, 582)); - pointers.add(Pointer.fromFunction(simpleAddition, 583)); - pointers.add(Pointer.fromFunction(simpleAddition, 584)); - pointers.add(Pointer.fromFunction(simpleAddition, 585)); - pointers.add(Pointer.fromFunction(simpleAddition, 586)); - pointers.add(Pointer.fromFunction(simpleAddition, 587)); - pointers.add(Pointer.fromFunction(simpleAddition, 588)); - pointers.add(Pointer.fromFunction(simpleAddition, 589)); - pointers.add(Pointer.fromFunction(simpleAddition, 590)); - pointers.add(Pointer.fromFunction(simpleAddition, 591)); - pointers.add(Pointer.fromFunction(simpleAddition, 592)); - pointers.add(Pointer.fromFunction(simpleAddition, 593)); - pointers.add(Pointer.fromFunction(simpleAddition, 594)); - pointers.add(Pointer.fromFunction(simpleAddition, 595)); - pointers.add(Pointer.fromFunction(simpleAddition, 596)); - pointers.add(Pointer.fromFunction(simpleAddition, 597)); - pointers.add(Pointer.fromFunction(simpleAddition, 598)); - pointers.add(Pointer.fromFunction(simpleAddition, 599)); - pointers.add(Pointer.fromFunction(simpleAddition, 600)); - pointers.add(Pointer.fromFunction(simpleAddition, 601)); - pointers.add(Pointer.fromFunction(simpleAddition, 602)); - pointers.add(Pointer.fromFunction(simpleAddition, 603)); - pointers.add(Pointer.fromFunction(simpleAddition, 604)); - pointers.add(Pointer.fromFunction(simpleAddition, 605)); - pointers.add(Pointer.fromFunction(simpleAddition, 606)); - pointers.add(Pointer.fromFunction(simpleAddition, 607)); - pointers.add(Pointer.fromFunction(simpleAddition, 608)); - pointers.add(Pointer.fromFunction(simpleAddition, 609)); - pointers.add(Pointer.fromFunction(simpleAddition, 610)); - pointers.add(Pointer.fromFunction(simpleAddition, 611)); - pointers.add(Pointer.fromFunction(simpleAddition, 612)); - pointers.add(Pointer.fromFunction(simpleAddition, 613)); - pointers.add(Pointer.fromFunction(simpleAddition, 614)); - pointers.add(Pointer.fromFunction(simpleAddition, 615)); - pointers.add(Pointer.fromFunction(simpleAddition, 616)); - pointers.add(Pointer.fromFunction(simpleAddition, 617)); - pointers.add(Pointer.fromFunction(simpleAddition, 618)); - pointers.add(Pointer.fromFunction(simpleAddition, 619)); - pointers.add(Pointer.fromFunction(simpleAddition, 620)); - pointers.add(Pointer.fromFunction(simpleAddition, 621)); - pointers.add(Pointer.fromFunction(simpleAddition, 622)); - pointers.add(Pointer.fromFunction(simpleAddition, 623)); - pointers.add(Pointer.fromFunction(simpleAddition, 624)); - pointers.add(Pointer.fromFunction(simpleAddition, 625)); - pointers.add(Pointer.fromFunction(simpleAddition, 626)); - pointers.add(Pointer.fromFunction(simpleAddition, 627)); - pointers.add(Pointer.fromFunction(simpleAddition, 628)); - pointers.add(Pointer.fromFunction(simpleAddition, 629)); - pointers.add(Pointer.fromFunction(simpleAddition, 630)); - pointers.add(Pointer.fromFunction(simpleAddition, 631)); - pointers.add(Pointer.fromFunction(simpleAddition, 632)); - pointers.add(Pointer.fromFunction(simpleAddition, 633)); - pointers.add(Pointer.fromFunction(simpleAddition, 634)); - pointers.add(Pointer.fromFunction(simpleAddition, 635)); - pointers.add(Pointer.fromFunction(simpleAddition, 636)); - pointers.add(Pointer.fromFunction(simpleAddition, 637)); - pointers.add(Pointer.fromFunction(simpleAddition, 638)); - pointers.add(Pointer.fromFunction(simpleAddition, 639)); - pointers.add(Pointer.fromFunction(simpleAddition, 640)); - pointers.add(Pointer.fromFunction(simpleAddition, 641)); - pointers.add(Pointer.fromFunction(simpleAddition, 642)); - pointers.add(Pointer.fromFunction(simpleAddition, 643)); - pointers.add(Pointer.fromFunction(simpleAddition, 644)); - pointers.add(Pointer.fromFunction(simpleAddition, 645)); - pointers.add(Pointer.fromFunction(simpleAddition, 646)); - pointers.add(Pointer.fromFunction(simpleAddition, 647)); - pointers.add(Pointer.fromFunction(simpleAddition, 648)); - pointers.add(Pointer.fromFunction(simpleAddition, 649)); - pointers.add(Pointer.fromFunction(simpleAddition, 650)); - pointers.add(Pointer.fromFunction(simpleAddition, 651)); - pointers.add(Pointer.fromFunction(simpleAddition, 652)); - pointers.add(Pointer.fromFunction(simpleAddition, 653)); - pointers.add(Pointer.fromFunction(simpleAddition, 654)); - pointers.add(Pointer.fromFunction(simpleAddition, 655)); - pointers.add(Pointer.fromFunction(simpleAddition, 656)); - pointers.add(Pointer.fromFunction(simpleAddition, 657)); - pointers.add(Pointer.fromFunction(simpleAddition, 658)); - pointers.add(Pointer.fromFunction(simpleAddition, 659)); - pointers.add(Pointer.fromFunction(simpleAddition, 660)); - pointers.add(Pointer.fromFunction(simpleAddition, 661)); - pointers.add(Pointer.fromFunction(simpleAddition, 662)); - pointers.add(Pointer.fromFunction(simpleAddition, 663)); - pointers.add(Pointer.fromFunction(simpleAddition, 664)); - pointers.add(Pointer.fromFunction(simpleAddition, 665)); - pointers.add(Pointer.fromFunction(simpleAddition, 666)); - pointers.add(Pointer.fromFunction(simpleAddition, 667)); - pointers.add(Pointer.fromFunction(simpleAddition, 668)); - pointers.add(Pointer.fromFunction(simpleAddition, 669)); - pointers.add(Pointer.fromFunction(simpleAddition, 670)); - pointers.add(Pointer.fromFunction(simpleAddition, 671)); - pointers.add(Pointer.fromFunction(simpleAddition, 672)); - pointers.add(Pointer.fromFunction(simpleAddition, 673)); - pointers.add(Pointer.fromFunction(simpleAddition, 674)); - pointers.add(Pointer.fromFunction(simpleAddition, 675)); - pointers.add(Pointer.fromFunction(simpleAddition, 676)); - pointers.add(Pointer.fromFunction(simpleAddition, 677)); - pointers.add(Pointer.fromFunction(simpleAddition, 678)); - pointers.add(Pointer.fromFunction(simpleAddition, 679)); - pointers.add(Pointer.fromFunction(simpleAddition, 680)); - pointers.add(Pointer.fromFunction(simpleAddition, 681)); - pointers.add(Pointer.fromFunction(simpleAddition, 682)); - pointers.add(Pointer.fromFunction(simpleAddition, 683)); - pointers.add(Pointer.fromFunction(simpleAddition, 684)); - pointers.add(Pointer.fromFunction(simpleAddition, 685)); - pointers.add(Pointer.fromFunction(simpleAddition, 686)); - pointers.add(Pointer.fromFunction(simpleAddition, 687)); - pointers.add(Pointer.fromFunction(simpleAddition, 688)); - pointers.add(Pointer.fromFunction(simpleAddition, 689)); - pointers.add(Pointer.fromFunction(simpleAddition, 690)); - pointers.add(Pointer.fromFunction(simpleAddition, 691)); - pointers.add(Pointer.fromFunction(simpleAddition, 692)); - pointers.add(Pointer.fromFunction(simpleAddition, 693)); - pointers.add(Pointer.fromFunction(simpleAddition, 694)); - pointers.add(Pointer.fromFunction(simpleAddition, 695)); - pointers.add(Pointer.fromFunction(simpleAddition, 696)); - pointers.add(Pointer.fromFunction(simpleAddition, 697)); - pointers.add(Pointer.fromFunction(simpleAddition, 698)); - pointers.add(Pointer.fromFunction(simpleAddition, 699)); - pointers.add(Pointer.fromFunction(simpleAddition, 700)); - pointers.add(Pointer.fromFunction(simpleAddition, 701)); - pointers.add(Pointer.fromFunction(simpleAddition, 702)); - pointers.add(Pointer.fromFunction(simpleAddition, 703)); - pointers.add(Pointer.fromFunction(simpleAddition, 704)); - pointers.add(Pointer.fromFunction(simpleAddition, 705)); - pointers.add(Pointer.fromFunction(simpleAddition, 706)); - pointers.add(Pointer.fromFunction(simpleAddition, 707)); - pointers.add(Pointer.fromFunction(simpleAddition, 708)); - pointers.add(Pointer.fromFunction(simpleAddition, 709)); - pointers.add(Pointer.fromFunction(simpleAddition, 710)); - pointers.add(Pointer.fromFunction(simpleAddition, 711)); - pointers.add(Pointer.fromFunction(simpleAddition, 712)); - pointers.add(Pointer.fromFunction(simpleAddition, 713)); - pointers.add(Pointer.fromFunction(simpleAddition, 714)); - pointers.add(Pointer.fromFunction(simpleAddition, 715)); - pointers.add(Pointer.fromFunction(simpleAddition, 716)); - pointers.add(Pointer.fromFunction(simpleAddition, 717)); - pointers.add(Pointer.fromFunction(simpleAddition, 718)); - pointers.add(Pointer.fromFunction(simpleAddition, 719)); - pointers.add(Pointer.fromFunction(simpleAddition, 720)); - pointers.add(Pointer.fromFunction(simpleAddition, 721)); - pointers.add(Pointer.fromFunction(simpleAddition, 722)); - pointers.add(Pointer.fromFunction(simpleAddition, 723)); - pointers.add(Pointer.fromFunction(simpleAddition, 724)); - pointers.add(Pointer.fromFunction(simpleAddition, 725)); - pointers.add(Pointer.fromFunction(simpleAddition, 726)); - pointers.add(Pointer.fromFunction(simpleAddition, 727)); - pointers.add(Pointer.fromFunction(simpleAddition, 728)); - pointers.add(Pointer.fromFunction(simpleAddition, 729)); - pointers.add(Pointer.fromFunction(simpleAddition, 730)); - pointers.add(Pointer.fromFunction(simpleAddition, 731)); - pointers.add(Pointer.fromFunction(simpleAddition, 732)); - pointers.add(Pointer.fromFunction(simpleAddition, 733)); - pointers.add(Pointer.fromFunction(simpleAddition, 734)); - pointers.add(Pointer.fromFunction(simpleAddition, 735)); - pointers.add(Pointer.fromFunction(simpleAddition, 736)); - pointers.add(Pointer.fromFunction(simpleAddition, 737)); - pointers.add(Pointer.fromFunction(simpleAddition, 738)); - pointers.add(Pointer.fromFunction(simpleAddition, 739)); - pointers.add(Pointer.fromFunction(simpleAddition, 740)); - pointers.add(Pointer.fromFunction(simpleAddition, 741)); - pointers.add(Pointer.fromFunction(simpleAddition, 742)); - pointers.add(Pointer.fromFunction(simpleAddition, 743)); - pointers.add(Pointer.fromFunction(simpleAddition, 744)); - pointers.add(Pointer.fromFunction(simpleAddition, 745)); - pointers.add(Pointer.fromFunction(simpleAddition, 746)); - pointers.add(Pointer.fromFunction(simpleAddition, 747)); - pointers.add(Pointer.fromFunction(simpleAddition, 748)); - pointers.add(Pointer.fromFunction(simpleAddition, 749)); - pointers.add(Pointer.fromFunction(simpleAddition, 750)); - pointers.add(Pointer.fromFunction(simpleAddition, 751)); - pointers.add(Pointer.fromFunction(simpleAddition, 752)); - pointers.add(Pointer.fromFunction(simpleAddition, 753)); - pointers.add(Pointer.fromFunction(simpleAddition, 754)); - pointers.add(Pointer.fromFunction(simpleAddition, 755)); - pointers.add(Pointer.fromFunction(simpleAddition, 756)); - pointers.add(Pointer.fromFunction(simpleAddition, 757)); - pointers.add(Pointer.fromFunction(simpleAddition, 758)); - pointers.add(Pointer.fromFunction(simpleAddition, 759)); - pointers.add(Pointer.fromFunction(simpleAddition, 760)); - pointers.add(Pointer.fromFunction(simpleAddition, 761)); - pointers.add(Pointer.fromFunction(simpleAddition, 762)); - pointers.add(Pointer.fromFunction(simpleAddition, 763)); - pointers.add(Pointer.fromFunction(simpleAddition, 764)); - pointers.add(Pointer.fromFunction(simpleAddition, 765)); - pointers.add(Pointer.fromFunction(simpleAddition, 766)); - pointers.add(Pointer.fromFunction(simpleAddition, 767)); - pointers.add(Pointer.fromFunction(simpleAddition, 768)); - pointers.add(Pointer.fromFunction(simpleAddition, 769)); - pointers.add(Pointer.fromFunction(simpleAddition, 770)); - pointers.add(Pointer.fromFunction(simpleAddition, 771)); - pointers.add(Pointer.fromFunction(simpleAddition, 772)); - pointers.add(Pointer.fromFunction(simpleAddition, 773)); - pointers.add(Pointer.fromFunction(simpleAddition, 774)); - pointers.add(Pointer.fromFunction(simpleAddition, 775)); - pointers.add(Pointer.fromFunction(simpleAddition, 776)); - pointers.add(Pointer.fromFunction(simpleAddition, 777)); - pointers.add(Pointer.fromFunction(simpleAddition, 778)); - pointers.add(Pointer.fromFunction(simpleAddition, 779)); - pointers.add(Pointer.fromFunction(simpleAddition, 780)); - pointers.add(Pointer.fromFunction(simpleAddition, 781)); - pointers.add(Pointer.fromFunction(simpleAddition, 782)); - pointers.add(Pointer.fromFunction(simpleAddition, 783)); - pointers.add(Pointer.fromFunction(simpleAddition, 784)); - pointers.add(Pointer.fromFunction(simpleAddition, 785)); - pointers.add(Pointer.fromFunction(simpleAddition, 786)); - pointers.add(Pointer.fromFunction(simpleAddition, 787)); - pointers.add(Pointer.fromFunction(simpleAddition, 788)); - pointers.add(Pointer.fromFunction(simpleAddition, 789)); - pointers.add(Pointer.fromFunction(simpleAddition, 790)); - pointers.add(Pointer.fromFunction(simpleAddition, 791)); - pointers.add(Pointer.fromFunction(simpleAddition, 792)); - pointers.add(Pointer.fromFunction(simpleAddition, 793)); - pointers.add(Pointer.fromFunction(simpleAddition, 794)); - pointers.add(Pointer.fromFunction(simpleAddition, 795)); - pointers.add(Pointer.fromFunction(simpleAddition, 796)); - pointers.add(Pointer.fromFunction(simpleAddition, 797)); - pointers.add(Pointer.fromFunction(simpleAddition, 798)); - pointers.add(Pointer.fromFunction(simpleAddition, 799)); - pointers.add(Pointer.fromFunction(simpleAddition, 800)); - pointers.add(Pointer.fromFunction(simpleAddition, 801)); - pointers.add(Pointer.fromFunction(simpleAddition, 802)); - pointers.add(Pointer.fromFunction(simpleAddition, 803)); - pointers.add(Pointer.fromFunction(simpleAddition, 804)); - pointers.add(Pointer.fromFunction(simpleAddition, 805)); - pointers.add(Pointer.fromFunction(simpleAddition, 806)); - pointers.add(Pointer.fromFunction(simpleAddition, 807)); - pointers.add(Pointer.fromFunction(simpleAddition, 808)); - pointers.add(Pointer.fromFunction(simpleAddition, 809)); - pointers.add(Pointer.fromFunction(simpleAddition, 810)); - pointers.add(Pointer.fromFunction(simpleAddition, 811)); - pointers.add(Pointer.fromFunction(simpleAddition, 812)); - pointers.add(Pointer.fromFunction(simpleAddition, 813)); - pointers.add(Pointer.fromFunction(simpleAddition, 814)); - pointers.add(Pointer.fromFunction(simpleAddition, 815)); - pointers.add(Pointer.fromFunction(simpleAddition, 816)); - pointers.add(Pointer.fromFunction(simpleAddition, 817)); - pointers.add(Pointer.fromFunction(simpleAddition, 818)); - pointers.add(Pointer.fromFunction(simpleAddition, 819)); - pointers.add(Pointer.fromFunction(simpleAddition, 820)); - pointers.add(Pointer.fromFunction(simpleAddition, 821)); - pointers.add(Pointer.fromFunction(simpleAddition, 822)); - pointers.add(Pointer.fromFunction(simpleAddition, 823)); - pointers.add(Pointer.fromFunction(simpleAddition, 824)); - pointers.add(Pointer.fromFunction(simpleAddition, 825)); - pointers.add(Pointer.fromFunction(simpleAddition, 826)); - pointers.add(Pointer.fromFunction(simpleAddition, 827)); - pointers.add(Pointer.fromFunction(simpleAddition, 828)); - pointers.add(Pointer.fromFunction(simpleAddition, 829)); - pointers.add(Pointer.fromFunction(simpleAddition, 830)); - pointers.add(Pointer.fromFunction(simpleAddition, 831)); - pointers.add(Pointer.fromFunction(simpleAddition, 832)); - pointers.add(Pointer.fromFunction(simpleAddition, 833)); - pointers.add(Pointer.fromFunction(simpleAddition, 834)); - pointers.add(Pointer.fromFunction(simpleAddition, 835)); - pointers.add(Pointer.fromFunction(simpleAddition, 836)); - pointers.add(Pointer.fromFunction(simpleAddition, 837)); - pointers.add(Pointer.fromFunction(simpleAddition, 838)); - pointers.add(Pointer.fromFunction(simpleAddition, 839)); - pointers.add(Pointer.fromFunction(simpleAddition, 840)); - pointers.add(Pointer.fromFunction(simpleAddition, 841)); - pointers.add(Pointer.fromFunction(simpleAddition, 842)); - pointers.add(Pointer.fromFunction(simpleAddition, 843)); - pointers.add(Pointer.fromFunction(simpleAddition, 844)); - pointers.add(Pointer.fromFunction(simpleAddition, 845)); - pointers.add(Pointer.fromFunction(simpleAddition, 846)); - pointers.add(Pointer.fromFunction(simpleAddition, 847)); - pointers.add(Pointer.fromFunction(simpleAddition, 848)); - pointers.add(Pointer.fromFunction(simpleAddition, 849)); - pointers.add(Pointer.fromFunction(simpleAddition, 850)); - pointers.add(Pointer.fromFunction(simpleAddition, 851)); - pointers.add(Pointer.fromFunction(simpleAddition, 852)); - pointers.add(Pointer.fromFunction(simpleAddition, 853)); - pointers.add(Pointer.fromFunction(simpleAddition, 854)); - pointers.add(Pointer.fromFunction(simpleAddition, 855)); - pointers.add(Pointer.fromFunction(simpleAddition, 856)); - pointers.add(Pointer.fromFunction(simpleAddition, 857)); - pointers.add(Pointer.fromFunction(simpleAddition, 858)); - pointers.add(Pointer.fromFunction(simpleAddition, 859)); - pointers.add(Pointer.fromFunction(simpleAddition, 860)); - pointers.add(Pointer.fromFunction(simpleAddition, 861)); - pointers.add(Pointer.fromFunction(simpleAddition, 862)); - pointers.add(Pointer.fromFunction(simpleAddition, 863)); - pointers.add(Pointer.fromFunction(simpleAddition, 864)); - pointers.add(Pointer.fromFunction(simpleAddition, 865)); - pointers.add(Pointer.fromFunction(simpleAddition, 866)); - pointers.add(Pointer.fromFunction(simpleAddition, 867)); - pointers.add(Pointer.fromFunction(simpleAddition, 868)); - pointers.add(Pointer.fromFunction(simpleAddition, 869)); - pointers.add(Pointer.fromFunction(simpleAddition, 870)); - pointers.add(Pointer.fromFunction(simpleAddition, 871)); - pointers.add(Pointer.fromFunction(simpleAddition, 872)); - pointers.add(Pointer.fromFunction(simpleAddition, 873)); - pointers.add(Pointer.fromFunction(simpleAddition, 874)); - pointers.add(Pointer.fromFunction(simpleAddition, 875)); - pointers.add(Pointer.fromFunction(simpleAddition, 876)); - pointers.add(Pointer.fromFunction(simpleAddition, 877)); - pointers.add(Pointer.fromFunction(simpleAddition, 878)); - pointers.add(Pointer.fromFunction(simpleAddition, 879)); - pointers.add(Pointer.fromFunction(simpleAddition, 880)); - pointers.add(Pointer.fromFunction(simpleAddition, 881)); - pointers.add(Pointer.fromFunction(simpleAddition, 882)); - pointers.add(Pointer.fromFunction(simpleAddition, 883)); - pointers.add(Pointer.fromFunction(simpleAddition, 884)); - pointers.add(Pointer.fromFunction(simpleAddition, 885)); - pointers.add(Pointer.fromFunction(simpleAddition, 886)); - pointers.add(Pointer.fromFunction(simpleAddition, 887)); - pointers.add(Pointer.fromFunction(simpleAddition, 888)); - pointers.add(Pointer.fromFunction(simpleAddition, 889)); - pointers.add(Pointer.fromFunction(simpleAddition, 890)); - pointers.add(Pointer.fromFunction(simpleAddition, 891)); - pointers.add(Pointer.fromFunction(simpleAddition, 892)); - pointers.add(Pointer.fromFunction(simpleAddition, 893)); - pointers.add(Pointer.fromFunction(simpleAddition, 894)); - pointers.add(Pointer.fromFunction(simpleAddition, 895)); - pointers.add(Pointer.fromFunction(simpleAddition, 896)); - pointers.add(Pointer.fromFunction(simpleAddition, 897)); - pointers.add(Pointer.fromFunction(simpleAddition, 898)); - pointers.add(Pointer.fromFunction(simpleAddition, 899)); - pointers.add(Pointer.fromFunction(simpleAddition, 900)); - pointers.add(Pointer.fromFunction(simpleAddition, 901)); - pointers.add(Pointer.fromFunction(simpleAddition, 902)); - pointers.add(Pointer.fromFunction(simpleAddition, 903)); - pointers.add(Pointer.fromFunction(simpleAddition, 904)); - pointers.add(Pointer.fromFunction(simpleAddition, 905)); - pointers.add(Pointer.fromFunction(simpleAddition, 906)); - pointers.add(Pointer.fromFunction(simpleAddition, 907)); - pointers.add(Pointer.fromFunction(simpleAddition, 908)); - pointers.add(Pointer.fromFunction(simpleAddition, 909)); - pointers.add(Pointer.fromFunction(simpleAddition, 910)); - pointers.add(Pointer.fromFunction(simpleAddition, 911)); - pointers.add(Pointer.fromFunction(simpleAddition, 912)); - pointers.add(Pointer.fromFunction(simpleAddition, 913)); - pointers.add(Pointer.fromFunction(simpleAddition, 914)); - pointers.add(Pointer.fromFunction(simpleAddition, 915)); - pointers.add(Pointer.fromFunction(simpleAddition, 916)); - pointers.add(Pointer.fromFunction(simpleAddition, 917)); - pointers.add(Pointer.fromFunction(simpleAddition, 918)); - pointers.add(Pointer.fromFunction(simpleAddition, 919)); - pointers.add(Pointer.fromFunction(simpleAddition, 920)); - pointers.add(Pointer.fromFunction(simpleAddition, 921)); - pointers.add(Pointer.fromFunction(simpleAddition, 922)); - pointers.add(Pointer.fromFunction(simpleAddition, 923)); - pointers.add(Pointer.fromFunction(simpleAddition, 924)); - pointers.add(Pointer.fromFunction(simpleAddition, 925)); - pointers.add(Pointer.fromFunction(simpleAddition, 926)); - pointers.add(Pointer.fromFunction(simpleAddition, 927)); - pointers.add(Pointer.fromFunction(simpleAddition, 928)); - pointers.add(Pointer.fromFunction(simpleAddition, 929)); - pointers.add(Pointer.fromFunction(simpleAddition, 930)); - pointers.add(Pointer.fromFunction(simpleAddition, 931)); - pointers.add(Pointer.fromFunction(simpleAddition, 932)); - pointers.add(Pointer.fromFunction(simpleAddition, 933)); - pointers.add(Pointer.fromFunction(simpleAddition, 934)); - pointers.add(Pointer.fromFunction(simpleAddition, 935)); - pointers.add(Pointer.fromFunction(simpleAddition, 936)); - pointers.add(Pointer.fromFunction(simpleAddition, 937)); - pointers.add(Pointer.fromFunction(simpleAddition, 938)); - pointers.add(Pointer.fromFunction(simpleAddition, 939)); - pointers.add(Pointer.fromFunction(simpleAddition, 940)); - pointers.add(Pointer.fromFunction(simpleAddition, 941)); - pointers.add(Pointer.fromFunction(simpleAddition, 942)); - pointers.add(Pointer.fromFunction(simpleAddition, 943)); - pointers.add(Pointer.fromFunction(simpleAddition, 944)); - pointers.add(Pointer.fromFunction(simpleAddition, 945)); - pointers.add(Pointer.fromFunction(simpleAddition, 946)); - pointers.add(Pointer.fromFunction(simpleAddition, 947)); - pointers.add(Pointer.fromFunction(simpleAddition, 948)); - pointers.add(Pointer.fromFunction(simpleAddition, 949)); - pointers.add(Pointer.fromFunction(simpleAddition, 950)); - pointers.add(Pointer.fromFunction(simpleAddition, 951)); - pointers.add(Pointer.fromFunction(simpleAddition, 952)); - pointers.add(Pointer.fromFunction(simpleAddition, 953)); - pointers.add(Pointer.fromFunction(simpleAddition, 954)); - pointers.add(Pointer.fromFunction(simpleAddition, 955)); - pointers.add(Pointer.fromFunction(simpleAddition, 956)); - pointers.add(Pointer.fromFunction(simpleAddition, 957)); - pointers.add(Pointer.fromFunction(simpleAddition, 958)); - pointers.add(Pointer.fromFunction(simpleAddition, 959)); - pointers.add(Pointer.fromFunction(simpleAddition, 960)); - pointers.add(Pointer.fromFunction(simpleAddition, 961)); - pointers.add(Pointer.fromFunction(simpleAddition, 962)); - pointers.add(Pointer.fromFunction(simpleAddition, 963)); - pointers.add(Pointer.fromFunction(simpleAddition, 964)); - pointers.add(Pointer.fromFunction(simpleAddition, 965)); - pointers.add(Pointer.fromFunction(simpleAddition, 966)); - pointers.add(Pointer.fromFunction(simpleAddition, 967)); - pointers.add(Pointer.fromFunction(simpleAddition, 968)); - pointers.add(Pointer.fromFunction(simpleAddition, 969)); - pointers.add(Pointer.fromFunction(simpleAddition, 970)); - pointers.add(Pointer.fromFunction(simpleAddition, 971)); - pointers.add(Pointer.fromFunction(simpleAddition, 972)); - pointers.add(Pointer.fromFunction(simpleAddition, 973)); - pointers.add(Pointer.fromFunction(simpleAddition, 974)); - pointers.add(Pointer.fromFunction(simpleAddition, 975)); - pointers.add(Pointer.fromFunction(simpleAddition, 976)); - pointers.add(Pointer.fromFunction(simpleAddition, 977)); - pointers.add(Pointer.fromFunction(simpleAddition, 978)); - pointers.add(Pointer.fromFunction(simpleAddition, 979)); - pointers.add(Pointer.fromFunction(simpleAddition, 980)); - pointers.add(Pointer.fromFunction(simpleAddition, 981)); - pointers.add(Pointer.fromFunction(simpleAddition, 982)); - pointers.add(Pointer.fromFunction(simpleAddition, 983)); - pointers.add(Pointer.fromFunction(simpleAddition, 984)); - pointers.add(Pointer.fromFunction(simpleAddition, 985)); - pointers.add(Pointer.fromFunction(simpleAddition, 986)); - pointers.add(Pointer.fromFunction(simpleAddition, 987)); - pointers.add(Pointer.fromFunction(simpleAddition, 988)); - pointers.add(Pointer.fromFunction(simpleAddition, 989)); - pointers.add(Pointer.fromFunction(simpleAddition, 990)); - pointers.add(Pointer.fromFunction(simpleAddition, 991)); - pointers.add(Pointer.fromFunction(simpleAddition, 992)); - pointers.add(Pointer.fromFunction(simpleAddition, 993)); - pointers.add(Pointer.fromFunction(simpleAddition, 994)); - pointers.add(Pointer.fromFunction(simpleAddition, 995)); - pointers.add(Pointer.fromFunction(simpleAddition, 996)); - pointers.add(Pointer.fromFunction(simpleAddition, 997)); - pointers.add(Pointer.fromFunction(simpleAddition, 998)); - pointers.add(Pointer.fromFunction(simpleAddition, 999)); + for (int i = 0; i < 1000; ++i) { + pointers.add(Pointer.fromFunction(simpleAddition, i)); + } for (final pointer in pointers) { Test("SimpleAddition", pointer).run(); diff --git a/tests/ffi/function_callbacks_unsupported_test.dart b/tests/ffi/function_callbacks_unsupported_test.dart deleted file mode 100644 index 5ac1b5d93ed..00000000000 --- a/tests/ffi/function_callbacks_unsupported_test.dart +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2019, 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. -// -// Dart test program for testing that FFI callbacks report an appropriate -// runtime error for unsupported snapshot formats. - -import 'dart:ffi'; - -import 'package:expect/expect.dart'; - -bool checkError(UnsupportedError err) { - return "$err".contains("callbacks are not yet supported in blobs"); -} - -void main() { - Expect.throws( - () => Pointer.fromFunction(main), checkError); -} diff --git a/tests/ffi/static_checks_test.dart b/tests/ffi/static_checks_test.dart index 22d52567890..0a24b6d935d 100644 --- a/tests/ffi/static_checks_test.dart +++ b/tests/ffi/static_checks_test.dart @@ -36,7 +36,6 @@ void main() { testFromFunctionTypeMismatch(); testFromFunctionClosure(); testFromFunctionTearOff(); - testFromFunctionAbstract(); testLookupFunctionGeneric(); testLookupFunctionGeneric2(); testLookupFunctionWrongNativeFunctionSignature(); @@ -249,10 +248,6 @@ void testFromFunctionTearOff() { p = ffi.fromFunction(fld); //# 75: compile-time error } -void testFromFunctionAbstract() { - ffi.Pointer.fromFunction(testFromFunctionAbstract); //# 76: compile-time error -} - void testLookupFunctionGeneric() { Function generic() { ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library"); diff --git a/tools/VERSION b/tools/VERSION index 618fa3d5b20..f1a4b101723 100644 --- a/tools/VERSION +++ b/tools/VERSION @@ -35,5 +35,5 @@ MINOR 6 PATCH 0 PRERELEASE 0 PRERELEASE_PATCH 0 -ABI_VERSION 14 -OLDEST_SUPPORTED_ABI_VERSION 13 +ABI_VERSION 15 +OLDEST_SUPPORTED_ABI_VERSION 15