From 495a9e9a7c0873feb942a5d48e3275a7e9f5e985 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Thu, 11 Apr 2024 15:03:35 +0200 Subject: [PATCH 1/9] Towards 0.5.1 --- docs/conf.py | 2 +- nir/src/main/scala/scala/scalanative/nir/Versions.scala | 2 +- project/Settings.scala | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index ffe96d92b2..bdc2ad90c0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -71,7 +71,7 @@ def generateScalaNativeCurrentYear(): # The short X.Y version. version = u'0.5' # The full version, including alpha/beta/rc tags. -release = u'0.5.0' +release = u'0.5.1-SNAPSHOT' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/nir/src/main/scala/scala/scalanative/nir/Versions.scala b/nir/src/main/scala/scala/scalanative/nir/Versions.scala index 456ca47205..82f1d46b13 100644 --- a/nir/src/main/scala/scala/scalanative/nir/Versions.scala +++ b/nir/src/main/scala/scala/scalanative/nir/Versions.scala @@ -25,7 +25,7 @@ object Versions { final val revision: Int = 10 // a.k.a. MINOR version /* Current public release version of Scala Native. */ - final val current: String = "0.5.0" + final val current: String = "0.5.1-SNAPSHOT" final val currentBinaryVersion: String = binaryVersion(current) private object FullVersion { diff --git a/project/Settings.scala b/project/Settings.scala index db3111f582..e17bdb2594 100644 --- a/project/Settings.scala +++ b/project/Settings.scala @@ -206,7 +206,7 @@ object Settings { ), mimaPreviousArtifacts ++= { // The previous releases of Scala Native with which this version is binary compatible. - val binCompatVersions = Set.empty + val binCompatVersions = Set("0.5.0") binCompatVersions .map { version => ModuleID(organization.value, moduleName.value, version) From 2d257b462d0be35b582c4f9dd48916c97422a268 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Fri, 12 Apr 2024 01:03:15 +0200 Subject: [PATCH 2/9] Disable MiMa check in modules that do not emit bytecode (#3870) --- project/BinaryIncompatibilities.scala | 5 ----- project/Build.scala | 3 ++- project/Settings.scala | 8 ++++---- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/project/BinaryIncompatibilities.scala b/project/BinaryIncompatibilities.scala index 357d1cfaa0..dbd0746eb5 100644 --- a/project/BinaryIncompatibilities.scala +++ b/project/BinaryIncompatibilities.scala @@ -48,7 +48,6 @@ object BinaryIncompatibilities { final val PosixLib: Filters = Seq.empty final val WindowsLib: Filters = Nil - final val AuxLib, JavaLib, ScalaLib, Scala3Lib: Filters = Nil final val TestRunner: Filters = Nil final val TestInterface: Filters = Nil final val TestInterfaceSbtDefs: Filters = Nil @@ -63,10 +62,6 @@ object BinaryIncompatibilities { "posixlib" -> PosixLib, "windowslib" -> WindowsLib, "nativelib" -> NativeLib, - "auxlib" -> AuxLib, - "javalib" -> JavaLib, - "scalalib" -> ScalaLib, - "scala3lib" -> Scala3Lib, "test-runner" -> TestRunner, "test-interface" -> TestInterface, "test-interface-sbt-defs" -> TestInterfaceSbtDefs, diff --git a/project/Build.scala b/project/Build.scala index 26be043c2f..23219782b7 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -529,7 +529,8 @@ object Build { .settings( publishSettings(Some(VersionScheme.BreakOnMajor)), disabledDocsSettings, - scalacOptions --= ignoredScalaDeprecations(scalaVersion.value) + scalacOptions --= ignoredScalaDeprecations(scalaVersion.value), + NIROnlySettings ) .withNativeCompilerPlugin .mapBinaryVersions { diff --git a/project/Settings.scala b/project/Settings.scala index e17bdb2594..29c5c075fa 100644 --- a/project/Settings.scala +++ b/project/Settings.scala @@ -201,9 +201,8 @@ object Settings { // MiMa lazy val mimaSettings = Seq( mimaFailOnNoPrevious := false, - mimaBinaryIssueFilters ++= BinaryIncompatibilities.moduleFilters( - name.value - ), + mimaBinaryIssueFilters ++= BinaryIncompatibilities.moduleFilters + .getOrElse(name.value, Nil), mimaPreviousArtifacts ++= { // The previous releases of Scala Native with which this version is binary compatible. val binCompatVersions = Set("0.5.0") @@ -674,7 +673,8 @@ object Settings { case (_, path) => !ignoredExtensions.exists(path.endsWith(_)) } }, - exportJars := true + exportJars := true, + mimaPreviousArtifacts := Set.empty // No bytecode, so no point to check MiMa ) lazy val commonJavalibSettings = Def.settings( recompileAllOrNothingSettings, From 9d924ab73540ea9a40ac703388635a767df4c0d0 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Fri, 12 Apr 2024 12:58:11 +0200 Subject: [PATCH 3/9] fix: Make sure SCALANATIVE_DELIMCC_DEBUG works (#3868) --- .../src/main/resources/scala-native/delimcc.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/nativelib/src/main/resources/scala-native/delimcc.c b/nativelib/src/main/resources/scala-native/delimcc.c index 0645bfcf2f..bd00eb6aa9 100644 --- a/nativelib/src/main/resources/scala-native/delimcc.c +++ b/nativelib/src/main/resources/scala-native/delimcc.c @@ -32,8 +32,8 @@ #error "Unsupported platform" #endif -#ifdef DELIMCC_DEBUG -#define debug_printf(...) debug_printf(__VA_ARGS__) +#ifdef SCALANATIVE_DELIMCC_DEBUG +#define debug_printf(...) printf(__VA_ARGS__) #else #define debug_printf(...) (void)0 #endif @@ -207,7 +207,7 @@ __continuation_boundary_impl(void **btm, ContinuationBody *body, void *arg) { .stack_btm = btm, .result = &result, }; - // debug_printf("Setting up result slot at %p\n", &result); + debug_printf("Setting up result slot at %p, header = %p\n", &result, &h); ContinuationBoundaryLabel l = h.id; handler_push(&h); @@ -269,13 +269,13 @@ void *scalanative_continuation_suspend(ContinuationBoundaryLabel b, volatile void *ret_val = NULL; continuation->return_slot = &ret_val; - debug_printf("Putting result %p to slot %p\n", *last_handler->h->result, - last_handler->h->result); - // we will be back... if (_lh_setjmp(continuation->buf) == 0) { // assign it to the handler's return value *last_handler->h->result = f(continuation, arg); + debug_printf("Putting result %p to slot %p, header = %p\n", + *last_handler->h->result, last_handler->h->result, + last_handler); return _lh_longjmp(last_handler->h->buf, 1); } else { // We're back, ret_val should be populated. @@ -318,8 +318,9 @@ void __continuation_resume_impl(void *tail, Continuation *continuation, debug_printf( "diff is %td, stack (size = %td) goes %p~%p -> %p~%p | original " "cont = %p [%p]\n", - diff, cont->size, cont->stack_top, cont->stack_top + cont->size, target, - tail, cont, cont->stack); + diff, continuation->size, continuation->stack_top, + continuation->stack_top + continuation->size, target, tail, + continuation, continuation->stack); // clone the handler chain, with fixes. to_install = nw = handler_clone_fix(continuation->handlers, diff); #define fixed_addr(X) (void *)(X) + diff From cb745e49a551c871c494331dd93723b1f94c6936 Mon Sep 17 00:00:00 2001 From: Claudio Bley Date: Sun, 14 Apr 2024 23:51:47 +0200 Subject: [PATCH 4/9] Support mingw compiler (#3869) * Add OS compat targeting windows gnu In contrast to UnixCompat, this generates code with dso_local. Depending on whether the target OS is 32 bit or 64 bit, the `__gxx_personality_v0` and `__gxx_personality_seh0` personality is used, respectively. * Make registry functions available when using mingw Currently, mingw is only missing the `SE_REGISTRY_WOW64_64KEY`. * Use standard complex types with mingw * Use `%S` instead of `%ws` format specifier The `w` argument size modifier prefix is a Microsoft extension and does not work with mingw-msvcrt (but when using ucrt). However, `%S` is equivalent to `%ws` for (sn)printf. --- .../src/main/resources/scala-native/complex.c | 2 +- .../scala-native/platform/windows/unwind.c | 2 +- .../codegen/llvm/AbstractCodeGen.scala | 11 ++- .../llvm/compat/os/WindowsGnuCompat.scala | 98 +++++++++++++++++++ .../windows/accCtrl/securityObjectType.c | 6 +- 5 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 tools/src/main/scala/scala/scalanative/codegen/llvm/compat/os/WindowsGnuCompat.scala diff --git a/clib/src/main/resources/scala-native/complex.c b/clib/src/main/resources/scala-native/complex.c index d06b0d97a2..f08a50cd1f 100644 --- a/clib/src/main/resources/scala-native/complex.c +++ b/clib/src/main/resources/scala-native/complex.c @@ -1,7 +1,7 @@ #if defined(SCALANATIVE_COMPILE_ALWAYS) || defined(__SCALANATIVE_C_COMPLEX) #include -#if defined(_WIN32) +#if defined(_WIN32) && !defined(__MINGW32__) typedef _Fcomplex FloatComplex; typedef _Dcomplex DoubleComplex; #else diff --git a/nativelib/src/main/resources/scala-native/platform/windows/unwind.c b/nativelib/src/main/resources/scala-native/platform/windows/unwind.c index afa4851c59..a0f9170ce7 100644 --- a/nativelib/src/main/resources/scala-native/platform/windows/unwind.c +++ b/nativelib/src/main/resources/scala-native/platform/windows/unwind.c @@ -59,7 +59,7 @@ int scalanative_unwind_get_proc_name(void *cursor, char *buffer, size_t length, void *address = ucontext->stack[ucontext->cursor]; PSYMBOL_INFOW symbol = &ucontext->symbol.info; SymFromAddrW(ucontext->process, (DWORD64)address, 0, symbol); - snprintf(buffer, length, "%ws", symbol->Name); + snprintf(buffer, length, "%S", symbol->Name); memcpy(offset, &(symbol->Address), sizeof(void *)); if (SymGetLineFromAddr(ucontext->process, (DWORD64)address, &displacement, &line)) { diff --git a/tools/src/main/scala/scala/scalanative/codegen/llvm/AbstractCodeGen.scala b/tools/src/main/scala/scala/scalanative/codegen/llvm/AbstractCodeGen.scala index fb04def868..4d36b01d46 100644 --- a/tools/src/main/scala/scala/scalanative/codegen/llvm/AbstractCodeGen.scala +++ b/tools/src/main/scala/scala/scalanative/codegen/llvm/AbstractCodeGen.scala @@ -38,9 +38,18 @@ private[codegen] abstract class AbstractCodeGen( private val generated = mutable.Set.empty[String] private val externSigMembers = mutable.Map.empty[nir.Sig, nir.Global.Member] + private def isGnu: Boolean = { + meta.buildConfig.compilerConfig.configuredOrDetectedTriple.env + .startsWith("gnu") + } + final val os: OsCompat = { import scala.scalanative.codegen.llvm.compat.os._ - if (meta.platform.targetsWindows) new WindowsCompat(this) + if (meta.platform.targetsWindows) + if (isGnu) + new WindowsGnuCompat(this) + else + new WindowsCompat(this) else new UnixCompat(this) } diff --git a/tools/src/main/scala/scala/scalanative/codegen/llvm/compat/os/WindowsGnuCompat.scala b/tools/src/main/scala/scala/scalanative/codegen/llvm/compat/os/WindowsGnuCompat.scala new file mode 100644 index 0000000000..84b92e860a --- /dev/null +++ b/tools/src/main/scala/scala/scalanative/codegen/llvm/compat/os/WindowsGnuCompat.scala @@ -0,0 +1,98 @@ +package scala.scalanative +package codegen.llvm +package compat.os + +import scala.scalanative.codegen.llvm.AbstractCodeGen +import scala.scalanative.nir.Defn.Define.DebugInfo +import scala.scalanative.util.ShowBuilder + +private[codegen] class WindowsGnuCompat(codegen: AbstractCodeGen) + extends OsCompat(codegen) { + + import codegen.{pointerType => ptrT} + + val ehWrapperTy = "@_ZTIN11scalanative16ExceptionWrapperE" + val excRecTy = s"{ $ptrT, i32 }" + val beginCatch = "@__cxa_begin_catch" + val endCatch = "@__cxa_end_catch" + val catchSig = + if (useOpaquePointers) s"$ptrT $ehWrapperTy" + else s"i8* bitcast ({ i8*, i8*, i8* }* $ehWrapperTy to i8*)" + val landingpad = + s"landingpad $excRecTy catch $catchSig" + val typeid = + s"call i32 @llvm.eh.typeid.for($catchSig)" + + protected val osPersonalityType: String = + if (codegen.meta.buildConfig.compilerConfig.is32BitPlatform) + "@__gxx_personality_v0" + else + "@__gxx_personality_seh0" + + override def genBlockAlloca(block: nir.ControlFlow.Block)(implicit + sb: ShowBuilder + ): Unit = + () + + def genLandingPad( + unwind: nir.Next.Unwind + )(implicit + fresh: nir.Fresh, + pos: nir.SourcePosition, + sb: ShowBuilder + ): Unit = { + import sb._ + val nir.Next.Unwind(nir.Val.Local(excname, _), next) = unwind + + val excpad = "_" + excname.id + ".landingpad" + val excsucc = excpad + ".succ" + val excfail = excpad + ".fail" + + val exc = "%_" + excname.id + val rec, r0, r1, id, cmp = "%_" + fresh().id + val w0, w1, w2 = "%_" + fresh().id + + def line(s: String) = { newline(); str(s) } + + line(s"$excpad:") + indent() + line(s"$rec = $landingpad") + line(s"$r0 = extractvalue $excRecTy $rec, 0") + line(s"$r1 = extractvalue $excRecTy $rec, 1") + line(s"$id = $typeid") + line(s"$cmp = icmp eq i32 $r1, $id") + line(s"br i1 $cmp, label %$excsucc, label %$excfail") + unindent() + + line(s"$excsucc:") + indent() + line(s"$w0 = call $ptrT $beginCatch($ptrT $r0)") + if (useOpaquePointers) { + line(s"$w2 = getelementptr ptr, ptr $w0, i32 1") + line(s"$exc = load ptr, ptr $w2") + } else { + line(s"$w1 = bitcast i8* $w0 to i8**") + line(s"$w2 = getelementptr i8*, i8** $w1, i32 1") + line(s"$exc = load i8*, i8** $w2") + } + line(s"call void $endCatch()") + str("br ") + codegen.genNext(next) + unindent() + + line(s"$excfail:") + indent() + line(s"resume $excRecTy $rec") + unindent() + } + + def genPrelude()(implicit builder: ShowBuilder): Unit = { + import builder._ + line(s"declare i32 @llvm.eh.typeid.for($ptrT)") + line(s"declare dso_local i32 $osPersonalityType(...)") + line(s"declare dso_local $ptrT $beginCatch($ptrT)") + line(s"declare dso_local void $endCatch()") + line(s"$ehWrapperTy = external constant { $ptrT, $ptrT, $ptrT }") + } + +} diff --git a/windowslib/src/main/resources/scala-native/windows/accCtrl/securityObjectType.c b/windowslib/src/main/resources/scala-native/windows/accCtrl/securityObjectType.c index 466d26783c..104b356376 100644 --- a/windowslib/src/main/resources/scala-native/windows/accCtrl/securityObjectType.c +++ b/windowslib/src/main/resources/scala-native/windows/accCtrl/securityObjectType.c @@ -1,4 +1,4 @@ -#if (defined(_WIN32) || defined(WIN32)) && !defined(__MINGW64__) +#if (defined(_WIN32) || defined(WIN32)) #define WIN32_LEAN_AND_MEAN #include @@ -17,6 +17,8 @@ int scalanative_se_provider_defined_object() { } int scalanative_se_wmiguid_object() { return SE_WMIGUID_OBJECT; } int scalanative_se_registry_wow64_32key() { return SE_REGISTRY_WOW64_32KEY; } +#ifndef __MINGW32__ +// missing in mingw 3.11 / mingw-64 12.0.0 int scalanative_se_registry_wow64_64key() { return SE_REGISTRY_WOW64_64KEY; } - +#endif #endif // defined(_WIN32) From d83e5fa6d4d871157cb60d234845bb94d771413b Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Mon, 15 Apr 2024 05:31:35 +0200 Subject: [PATCH 5/9] docs: Fix typos and links in 0.5.x release notes (#3873) --- docs/changelog/0.5.x/0.5.0-RC1.md | 10 +++++----- docs/changelog/0.5.x/0.5.0.md | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/changelog/0.5.x/0.5.0-RC1.md b/docs/changelog/0.5.x/0.5.0-RC1.md index ab734b343a..b9bf6ddf0f 100644 --- a/docs/changelog/0.5.x/0.5.0-RC1.md +++ b/docs/changelog/0.5.x/0.5.0-RC1.md @@ -45,7 +45,7 @@ Check out the documentation at Scala Native now allows to use system threads based on `java.lang.Thread` implementation, along with all the necessary primitives to work with concurrency: * `synchronized` blocks are now using object monitors following partially JVM semantics - these might be less performant when compared to JVM, but are going to achive improvements in the followup patch releases. * JVM compliant support for `@volatile` annotations - * Configurable mostly JVM-compliant support for final fields semantics, see [multithreading guide](../user/lang.rst#Multithreading) + * Configurable mostly JVM-compliant support for final fields semantics, see [multithreading guide](../../user/lang.md/#multithreading) * Thread safe implementation of most `java.util.concurrent` types and methods, including atomics, thread pools, etc. See list of currently implemented primitives in our [meta-issue on GitHub](https://github.com/scala-native/scala-native/issues/3165). Be aware that our Java Standard Library implementation might still contain thread-unsafe implementations of types not listed in the tracker. * Support for most of `scala.concurrent` and `scala.collection.concurrent` types. * Multithreading-aware implemenation of all garbage collections. @@ -65,7 +65,7 @@ Be aware that both Scala Native optimizer and LLVM optimizers can remove some of .withMode(scalanative.build.Mode.debug) // compile using LLVM without optimizations } ``` -See our [debugging guide](../user/testing.md#source-level-debugging) for more informations. +See our [debugging guide](../../user/testing.md#source-level-debugging) for more informations. ### SIP-51 support: Drop forward binary compatibility of the Scala 2.13 standard library We're chaning how the Scala standard library artifacts are published. Previously each Scala Native version shipped with 1 artifact for Scala standard library based on latest version of Scala. However this approach was insufficient to fully cover changes in Scala 3 standard library and it's 2 lines of releases: Scala LTS and Scala Next. @@ -78,7 +78,7 @@ Now when referring to not implemented Java standard library method, or a type fr ### JVM service providers supports We're introducing a user configured support for Java Service Providers. Similarry to it's JVM variant these would allow you to introduce implementations of Service Provider Interfaces however due to Ahead-of-time compilation constraint and to limit ammount of introduced dependencies only explicitly enabled implementations would be linked in the final binary. -For more details refer to [our guide](../lib/javalib.rst#Support-for-discovering-service-providers) +For more details refer to [our guide](../../lib/javalib.md#Support-for-discovering-service-providers) ### User build settings You can now specify the `basename` of your executable or library.. Typically it will default to the project's module name. @@ -100,7 +100,7 @@ Scala Native 0.5.0 breaks backward binary compatibility with previous releases o Libraries published using version 0.4.x or older must be republished for Scala Native 0.5.x. ### Scala Native Runtime -* `scala.scalanative.unsafe.Zone.apply` by default uses a context function argument. For Scala 2 cross-compilation see [Memory managment section](../user/interop.rst#Memory-management) +* `scala.scalanative.unsafe.Zone.apply` by default uses a context function argument. For Scala 2 cross-compilation see [Memory managment section](../../user/interop.md#memory-management) * The idiomatic alternative for C `void*` is now `Ptr[?]`(Scala 3) / `Ptr[_]` (Scala 2). Use `unsafe.CVoidPtr` for alias when defining bindings. ### Java Standard Library @@ -226,7 +226,7 @@ are used on all GCs. The last one works on Boehm and Commix. * GC_MAXIMUM_HEAP_SIZE (was SCALANATIVE_MAX_HEAP_SIZE) * GC_NPROCS (was SCALANATIVE_GC_THREADS) * GC_TIME_RATIO (was SCALANATIVE_TIME_RATIO) - * GC_FREE_RATION (was SCALANATIVE_FREE_RATIO) + * GC_FREE_RATIO (was SCALANATIVE_FREE_RATIO) * GC_STATS_FILE (was SCALANATIVE_STATS_FILE) diff --git a/docs/changelog/0.5.x/0.5.0.md b/docs/changelog/0.5.x/0.5.0.md index 6bfd35d17d..da463286d3 100644 --- a/docs/changelog/0.5.x/0.5.0.md +++ b/docs/changelog/0.5.x/0.5.0.md @@ -45,7 +45,7 @@ Check out the documentation at Scala Native now allows to use system threads based on `java.lang.Thread` implementation, along with all the necessary primitives to work with concurrency: * `synchronized` blocks are now using object monitors following partially JVM semantics - these might be less performant when compared to JVM, but are going to achive improvements in the followup patch releases. * JVM compliant support for `@volatile` annotations - * Configurable mostly JVM-compliant support for final fields semantics, see [multithreading guide](../user/lang.rst#Multithreading) + * Configurable mostly JVM-compliant support for final fields semantics, see [multithreading guide](../../user/lang.md/#multithreading) * Thread safe implementation of most `java.util.concurrent` types and methods, including atomics, thread pools, etc. See list of currently implemented primitives in our [meta-issue on GitHub](https://github.com/scala-native/scala-native/issues/3165). Be aware that our Java Standard Library implementation might still contain thread-unsafe implementations of types not listed in the tracker. * Support for most of `scala.concurrent` and `scala.collection.concurrent` types. * Multithreading-aware implemenation of all garbage collections. @@ -65,7 +65,7 @@ Be aware that both Scala Native optimizer and LLVM optimizers can remove some of .withMode(scalanative.build.Mode.debug) // compile using LLVM without optimizations } ``` -See our [debugging guide](../user/testing.md#source-level-debugging) for more informations. +See our [debugging guide](../../user/testing.md#source-level-debugging) for more informations. ### SIP-51 support: Drop forward binary compatibility of the Scala 2.13 standard library We're chaning how the Scala standard library artifacts are published. Previously each Scala Native version shipped with 1 artifact for Scala standard library based on latest version of Scala. However this approach was insufficient to fully cover changes in Scala 3 standard library and it's 2 lines of releases: Scala LTS and Scala Next. @@ -78,7 +78,7 @@ Now when referring to not implemented Java standard library method, or a type fr ### JVM service providers supports We're introducing a user configured support for Java Service Providers. Similarry to it's JVM variant these would allow you to introduce implementations of Service Provider Interfaces however due to Ahead-of-time compilation constraint and to limit ammount of introduced dependencies only explicitly enabled implementations would be linked in the final binary. -For more details refer to [our guide](../lib/javalib.rst#Support-for-discovering-service-providers) +For more details refer to [our guide](../../lib/javalib.md#Support-for-discovering-service-providers) ### User build settings You can now specify the `basename` of your executable or library.. Typically it will default to the project's module name. @@ -100,7 +100,7 @@ Scala Native 0.5.0 breaks backward binary compatibility with previous releases o Libraries published using version 0.4.x or older must be republished for Scala Native 0.5.x. ### Scala Native Runtime -* `scala.scalanative.unsafe.Zone.apply` by default uses a context function argument. For Scala 2 cross-compilation see [Memory managment section](../user/interop.rst#Memory-management) +* `scala.scalanative.unsafe.Zone.apply` by default uses a context function argument. For Scala 2 cross-compilation see [Memory managment section](../../user/interop.md#memory-management) * The idiomatic alternative for C `void*` is now `Ptr[?]`(Scala 3) / `Ptr[_]` (Scala 2). Use `unsafe.CVoidPtr` for alias when defining bindings. ### Java Standard Library @@ -226,7 +226,7 @@ are used on all GCs. The last one works on Boehm and Commix. * GC_MAXIMUM_HEAP_SIZE (was SCALANATIVE_MAX_HEAP_SIZE) * GC_NPROCS (was SCALANATIVE_GC_THREADS) * GC_TIME_RATIO (was SCALANATIVE_TIME_RATIO) - * GC_FREE_RATION (was SCALANATIVE_FREE_RATIO) + * GC_FREE_RATIO (was SCALANATIVE_FREE_RATIO) * GC_STATS_FILE (was SCALANATIVE_STATS_FILE) From 74f06ece14e99d51cfb5b84f0955d0650c91a734 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Mon, 15 Apr 2024 05:31:49 +0200 Subject: [PATCH 6/9] fix: Handle exceptions when reporting warnings in Scala 3 compiler plugin (#3872) * Handle exceptions when reporting warnings in ScalaNativePlugin when using incomplete Context * Disable fatal warning when testing deprecated plugin settings --- .../scala/scalanative/nscplugin/ScalaNativePlugin.scala | 4 ++-- project/Build.scala | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/ScalaNativePlugin.scala b/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/ScalaNativePlugin.scala index 9880fb939b..8dc7ac8189 100644 --- a/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/ScalaNativePlugin.scala +++ b/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/ScalaNativePlugin.scala @@ -2,7 +2,7 @@ package scala.scalanative.nscplugin import dotty.tools.dotc.plugins._ import dotty.tools.dotc.report -import dotty.tools.dotc.core.Contexts.NoContext +import dotty.tools.dotc.core.Contexts.ContextBase import java.net.URI import java.net.URISyntaxException import dotty.tools.dotc.core.Contexts.Context @@ -45,7 +45,7 @@ class ScalaNativePlugin extends StandardPlugin: .filter(_.isAbsolute())).distinct.sortBy(-_.getNameCount()) ) case (config, s"mapSourceURI:${mapping}") => - given Context = NoContext + given Context = ContextBase().initialCtx report.warning("'mapSourceURI' is deprecated, it's ignored.") config case (config, _) => config diff --git a/project/Build.scala b/project/Build.scala index 23219782b7..e033a40879 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -642,6 +642,9 @@ object Build { .enablePlugins(MyScalaNativePlugin) .settings(noPublishSettings) .settings( + // Setting only used to ensure that compiler does not crash when reporting deprecated options + scalacOptions += "-P:scalanative:mapSourceURI:path->unused", + scalacOptions -= "-Xfatal-warnings", nativeConfig ~= { _.withLinkStubs(true) }, From 14f96d61be20aaaba9fbf89b7546a602b5186175 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Mon, 15 Apr 2024 17:33:43 +0200 Subject: [PATCH 7/9] fix: Enable skipped concurrent tests and fix implemenation of failing tests (#3875) --- .../scala/java/util/AbstractCollection.scala | 7 +- .../concurrent/ConcurrentLinkedQueue.scala | 208 +++++++++--------- .../util/concurrent/atomic/LongAdder.scala | 29 +-- .../util/concurrent/atomic/Striped64.scala | 96 ++++---- .../testsuite/javalib/lang/ThreadTest.scala | 28 ++- .../ConcurrentLinkedQueueTest.scala | 89 ++++---- .../util/concurrent/RecursiveActionTest.scala | 102 ++++----- .../util/concurrent/RecursiveTaskTest.scala | 2 +- .../util/concurrent/SemaphoreTest.scala | 2 +- .../concurrent/atomic/LongAdderTest.scala | 22 +- 10 files changed, 296 insertions(+), 289 deletions(-) diff --git a/javalib/src/main/scala/java/util/AbstractCollection.scala b/javalib/src/main/scala/java/util/AbstractCollection.scala index 39bfea56da..0922e7db91 100644 --- a/javalib/src/main/scala/java/util/AbstractCollection.scala +++ b/javalib/src/main/scala/java/util/AbstractCollection.scala @@ -56,8 +56,11 @@ abstract class AbstractCollection[E] protected () extends Collection[E] { findAndRemove(iterator()) } - def containsAll(c: Collection[_]): Boolean = - c.scalaOps.forall(this.contains(_)) + def containsAll(c: Collection[_]): Boolean = { + var it = c.iterator() + while (it.hasNext()) if (!contains(it.next())) return false + true + } def addAll(c: Collection[_ <: E]): Boolean = c.scalaOps.foldLeft(false)((prev, elem) => add(elem) || prev) diff --git a/javalib/src/main/scala/java/util/concurrent/ConcurrentLinkedQueue.scala b/javalib/src/main/scala/java/util/concurrent/ConcurrentLinkedQueue.scala index 0841fcc0ee..7f19e5a95b 100644 --- a/javalib/src/main/scala/java/util/concurrent/ConcurrentLinkedQueue.scala +++ b/javalib/src/main/scala/java/util/concurrent/ConcurrentLinkedQueue.scala @@ -27,7 +27,6 @@ import scala.scalanative.libc.stdatomic.memory_order.memory_order_relaxed @SerialVersionUID(196745693267521676L) object ConcurrentLinkedQueue { - // import _ final private[concurrent] class Node[E <: AnyRef] private[concurrent] /** Constructs a dead dummy node. */ @@ -83,7 +82,21 @@ class ConcurrentLinkedQueue[E <: AnyRef] @alwaysinline private def TAIL: AtomicRef[Node[E]] = fromRawPtr[Node[E]](classFieldRawPtr(this, "tail")).atomic - // def this(c: Collection[_ <: E]) + def this(c: Collection[_ <: E]) = { + this() + var h, t: Node[E] = head + c.forEach { e => + val newNode = new Node[E](Objects.requireNonNull(e)) + t.appendRelaxed(newNode) + t = newNode + } + if (h == null) { + h = new Node[E](); + t = h + } + head = h; + tail = t; + } override def add(e: E): Boolean = offer(e) @@ -93,10 +106,11 @@ class ConcurrentLinkedQueue[E <: AnyRef] h.NEXT.store(h, memory_order_release) } - final private[concurrent] def succ(_p: Node[E]) = { - val p = _p.next - if (_p eq p) p - else head + final private[concurrent] def succ(p: Node[E]) = { + p.next match { + case `p` => head + case next => next + } } private def tryCasSuccessor( @@ -149,10 +163,8 @@ class ConcurrentLinkedQueue[E <: AnyRef] // for e to become an element of this queue, // and for newNode to become "live". if (p ne t) - this.TAIL.compareExchangeWeak( - t, - newNode - ) // hop two nodes at a time; failure is OK + // hop two nodes at a time; failure is OK + this.TAIL.compareExchangeWeak(t, newNode) return true } } else if (p eq q) // We have fallen off list. If tail is unchanged, it @@ -220,7 +232,7 @@ class ConcurrentLinkedQueue[E <: AnyRef] null.asInstanceOf[E] } - private[concurrent] def first: Node[E] = { + private[concurrent] def first(): Node[E] = { while (true) { val h = head var p = h @@ -240,12 +252,12 @@ class ConcurrentLinkedQueue[E <: AnyRef] null } - override def isEmpty(): Boolean = first == null + override def isEmpty(): Boolean = first() == null override def size(): Int = { while (true) { var count = 0 - var p = first + var p = first() var restart = false while (p != null && !restart) { if (p.item != null) { @@ -262,39 +274,30 @@ class ConcurrentLinkedQueue[E <: AnyRef] } override def contains(_o: Any): Boolean = { - if (_o == null || !_o.isInstanceOf[AnyRef]) return false + if (_o == null) return false val o = _o.asInstanceOf[AnyRef] - while (true) { - var p = head - var pred: Node[E] = null - var restart = false - while (p != null && !restart) { - var q = p.next - val item: E = p.item - var skip = false - if (item != null) { - if (o eq item) return true - pred = p - p = q - skip = true - } - if (!skip) { - val c = p - var break = false - while (!break && !restart) { - if (q == null || q.item != null) { - pred = skipDeadNodes(pred, c, p, q) - p = q - break = true - } - if (p eq { p = q; p }) restart = true - else q = p.next + var p = head + var pred: Node[E] = null + while (p != null) { + var q = p.next + val item: E = p.item + if (item != null) { + if (o.equals(item)) return true + pred = p + p = q + } else { + var c = p + var break = false + while (!break) { + if (q == null || q.item != null) { + pred = skipDeadNodes(pred, c, p, q) + p = q + break = true } + if (!break && (p eq { p = q; q })) break = true } } - if (!restart) return false } - // unreachable false } @@ -302,40 +305,38 @@ class ConcurrentLinkedQueue[E <: AnyRef] if (_o == null || !_o.isInstanceOf[AnyRef]) return false val o = _o.asInstanceOf[AnyRef] - while (true) { + var restartFromHead = true + while (restartFromHead) { + restartFromHead = false var p = head var pred: Node[E] = null - var restart = false - while (p != null && !restart) { + while (p != null && !restartFromHead) { var q = p.next val item: E = p.item - var continue = false if (item != null) { - if (o == item && p.casItem(item, null.asInstanceOf[E])) { + if (o.equals(item) && p.casItem(item, null.asInstanceOf[E])) { skipDeadNodes(pred, p, p, q) return true } pred = p p = q - continue = true - } - if (!continue) { - val c = p + } else { + var c = p var break = false - while (!break && !restart) { + while (!break) { if (q == null || q.item != null) { pred = skipDeadNodes(pred, c, p, q) p = q break = true } - if (p eq { p = q; p }) restart = true - else q = p.next + if (!break && { p eq { p = q; q } }) { + break = true + restartFromHead = true + } } } } - if (!restart) return false } - // unrachable false } @@ -393,7 +394,7 @@ class ConcurrentLinkedQueue[E <: AnyRef] while (true) { var charLength = 0 var size = 0 - var p = first + var p = first() var restart = false while (p != null && !restart) { val item: E = p.item @@ -418,11 +419,12 @@ class ConcurrentLinkedQueue[E <: AnyRef] private def toArrayInternal(a: Array[AnyRef]): Array[AnyRef] = { var x = a + var restartFromHead = true while (true) { var size = 0 - var p = first - var restart = false - while (p != null && !restart) { + var p = first() + restartFromHead = false + while (p != null && !restartFromHead) { val item: E = p.item if (item != null) { if (x == null) x = new Array[AnyRef](4) @@ -430,9 +432,9 @@ class ConcurrentLinkedQueue[E <: AnyRef] x(size) = item size += 1 } - if (p eq { p = p.next; p }) restart = true + if (p eq { p = p.next; p }) restartFromHead = true } - if (!restart) { + if (!restartFromHead) { if (x == null) return new Array[AnyRef](0) else if (a != null && size <= a.length) { if (a ne x) System.arraycopy(x, 0, a, 0, size) @@ -443,8 +445,7 @@ class ConcurrentLinkedQueue[E <: AnyRef] else Arrays.copyOf(x, size) } } - // unreachalbe - a + a // unreachable } override def toArray(): Array[AnyRef] = toArrayInternal(null) @@ -461,50 +462,56 @@ class ConcurrentLinkedQueue[E <: AnyRef] private var nextItem: E = _ private var lastRet: Node[E] = _ - locally { - var done = false - while (!done) { + private def _init(): Unit = { + var restartFromHead = true + while (restartFromHead) { + restartFromHead = false var h: Node[E] = head var p: Node[E] = h var q: Node[E] = null var break = false - var restart = false - while (!break && !restart) { + while (!break) { val item: E = p.item if (item != null) { nextNode = p nextItem = item break = true - } else if ({ q = p.next; q } == null) break = true - else if (p eq q) restart = true - else p = q + } else if ({ q = p.next; q == null }) { + break = true + } else if (p eq q) { + restartFromHead = true + break = true + } + if (!break) p = q } - if (!restart) { + if (!restartFromHead) { updateHead(h, p) - done = true + return } } } + _init() override def hasNext(): Boolean = nextItem != null override def next(): E = { val pred = nextNode - if (pred == null) throw new NoSuchElementException - // assert nextItem != null; + if (pred == null) throw new NoSuchElementException() lastRet = pred var item: E = null.asInstanceOf[E] + var p = succ(pred) var q: Node[E] = null while (true) { - if (p == null || { item = p.item; item } != null) { + if (p == null || { item = p.item; item != null }) { nextNode = p val x = nextItem nextItem = item return x } // unlink deleted nodes - if ({ q = succ(p); q } != null) pred.NEXT.compareExchangeStrong(p, q) + if ({ q = succ(p); q != null }) + pred.NEXT.compareExchangeStrong(p, q) p = q } // unreachable @@ -514,7 +521,7 @@ class ConcurrentLinkedQueue[E <: AnyRef] // Default implementation of forEachRemaining is "good enough". override def remove(): Unit = { val l = lastRet - if (l == null) throw new IllegalStateException + if (l == null) throw new IllegalStateException() // rely on a future traversal to relink. l.item = null.asInstanceOf[E] lastRet = null @@ -526,7 +533,7 @@ class ConcurrentLinkedQueue[E <: AnyRef] // Write out any hidden stuff s.defaultWriteObject() // Write out all elements in the proper order. - var p = first + var p = first() while (p != null) { val item: E = p.item if (item != null) s.writeObject(item) @@ -579,7 +586,7 @@ class ConcurrentLinkedQueue[E <: AnyRef] a(i) = e i += 1 } - if (p eq { p = q; p }) p = first + if (p eq { p = q; p }) p = first() p != null && { q = p.next; q } != null && i < n }) () setCurrent(p) @@ -610,7 +617,7 @@ class ConcurrentLinkedQueue[E <: AnyRef] var e: E = null.asInstanceOf[E] while ({ e = p.item - if (p eq { p = p.next; p }) p = first + if (p eq { p = p.next; p }) p = first() e == null && p != null }) () setCurrent(p) @@ -628,7 +635,7 @@ class ConcurrentLinkedQueue[E <: AnyRef] private def getCurrent() = { var p: Node[E] = current - if (p == null && !exhausted) setCurrent({ p = first; p }) + if (p == null && !exhausted) setCurrent({ p = first(); p }) p } @@ -661,41 +668,40 @@ class ConcurrentLinkedQueue[E <: AnyRef] private def bulkRemove(filter: Predicate[_ >: E]): Boolean = { var removed = false - - while (true) { + var restartFromHead = true + while (restartFromHead) { + restartFromHead = false var hops = MAX_HOPS + var p, c: Node[E] = head + var pred, q: Node[E] = null // c will be CASed to collapse intervening dead nodes between // pred (or head if null) and p. - var p = head - var c = p - var pred: Node[E] = null - var q: Node[E] = null - var restart = false - while (p != null && !restart) { + while (p != null && !restartFromHead) { q = p.next - val item: E = p.item + val item = p.item var pAlive = item != null - if (pAlive) if (filter.test(item)) { - if (p.casItem(item, null.asInstanceOf[E])) removed = true - pAlive = false + if (pAlive) { + if (filter.test(item)) { + if (p.casItem(item, null.asInstanceOf[E])) removed = true + // Set pAlive to false to signify that the node is no longer alive + pAlive = false + } } - if (pAlive || q == null || { hops -= 1; hops } == 0) { + if (pAlive || q == null || { hops -= 1; hops == 0 }) { // p might already be self-linked here, but if so: // - CASing head will surely fail // - CASing pred's next will be useless but harmless. - if (((c ne p) && !tryCasSuccessor(pred, c, { c = p; c })) || pAlive) { + if (((c ne p) && !tryCasSuccessor(pred, c, { c = p; p })) || pAlive) { // if CAS failed or alive, abandon old pred hops = MAX_HOPS pred = p c = q } - } else if (p eq q) restart = true - else p = q + } else if (p eq q) restartFromHead = true + p = q } - if (!restart) return removed } - // unreachable - false + return removed } /** Runs action on each element found during a traversal starting at p. If p diff --git a/javalib/src/main/scala/java/util/concurrent/atomic/LongAdder.scala b/javalib/src/main/scala/java/util/concurrent/atomic/LongAdder.scala index 3bdbd5710f..30addf1df4 100644 --- a/javalib/src/main/scala/java/util/concurrent/atomic/LongAdder.scala +++ b/javalib/src/main/scala/java/util/concurrent/atomic/LongAdder.scala @@ -28,24 +28,25 @@ object LongAdder { @SerialVersionUID(7249069246863182397L) class LongAdder() extends Striped64 with Serializable { + import Striped64.{Cell, getProbe} def add(x: Long): Unit = { - var cs: Array[Striped64.Cell] = null.asInstanceOf[Array[Striped64.Cell]] - var b = 0L - var v = 0L - var m = 0 - var c: Striped64.Cell = null - if ({ cs = cells; cs != null || !casBase({ b = base; b }, b + x) }) { - val index = Striped64.getProbe() + var cs: Array[Cell] = null + var b: Long = 0 + var v: Long = 0 + var m: Int = 0 + var c: Cell = null + + if ({ cs = cells; cs != null } || !casBase({ b = base; b }, b + x)) { + val index = getProbe() var uncontended = true - if ({ - m = cs.length; - c = cs(index & m); - v = c.value; - uncontended = c.cas(v, v + x); - cs == null || m < 0 || c == null || !uncontended - }) + if (cs == null || { m = cells.length - 1; m < 0 } || { + c = cells(index & m); c == null + } || { + uncontended = c.cas({ v = c.value; v }, v + x); !uncontended + }) { longAccumulate(x, null, uncontended, index) + } } } diff --git a/javalib/src/main/scala/java/util/concurrent/atomic/Striped64.scala b/javalib/src/main/scala/java/util/concurrent/atomic/Striped64.scala index 04ccdeca1a..500d92c681 100644 --- a/javalib/src/main/scala/java/util/concurrent/atomic/Striped64.scala +++ b/javalib/src/main/scala/java/util/concurrent/atomic/Striped64.scala @@ -61,7 +61,7 @@ private[atomic] object Striped64 { ) private[atomic] def getProbe(): Int = - threadProbeAtomic().load().asInstanceOf[Int] + threadProbeAtomic().load() private[atomic] def advanceProbe(probe: Int) = { var _probe = probe @@ -84,8 +84,9 @@ private[atomic] object Striped64 { @SuppressWarnings(Array("serial")) private[atomic] abstract class Striped64 private[atomic] () extends Number { + import Striped64._ - @transient @volatile private[atomic] var cells: Array[Striped64.Cell] = null + @transient @volatile private[atomic] var cells: Array[Striped64.Cell] = _ @transient @volatile private[atomic] var base: Long = 0L @@ -123,56 +124,48 @@ private[atomic] abstract class Striped64 private[atomic] () extends Number { if (index == 0) { ThreadLocalRandom.current() // force initialization - - index = Striped64.getProbe() + index = getProbe() wasUncontended = true } - - var continue1 = true - var continue2 = true var collide = false - while (continue1) { // True if last slot nonempty - continue2 = true - var cs: Array[Striped64.Cell] = null - var c: Striped64.Cell = null - var n = 0 - var v = 0L - if ({ cs = cells; n = cs.length; cs != null && n > 0 }) { - if ({ c = cs((n - 1) & index); c == null }) { - if (cellsBusy == 0) { // Try to attach new Cell - val r = new Striped64.Cell(x) // Optimistically create + while (true) { + var cs: Array[Cell] = null + var c: Cell = null + var n: Int = 0 + var v: Long = 0 + + if (cells != null && { n = cells.length; n > 0 }) { + c = cells((n - 1) & index) + if (c == null) { + var continue = false + if (cellsBusy == 0) { + val r = new Cell(x) if (cellsBusy == 0 && casCellsBusy()) { - try { // Recheck under lock - var rs: Array[Striped64.Cell] = null - var m = 0 - var j = 0 - if ({ - rs = cells; m = rs.length; j = (m - 1) & index; - rs != null && m > 0 && rs(j) == null - }) { + try { + var rs: Array[Cell] = null + var m: Int = 0 + var j: Int = 0 + rs = cells + if (rs != null && { m = rs.length; m > 0 } && + rs({ j = (m - 1) & index; j }) == null) { rs(j) = r - continue1 = false - continue2 = false - + return } } finally { cellsBusy = 0 } - continue2 = false + continue = true } } - if (continue2 == true) - collide = false + if (!continue) collide = false } else if (!wasUncontended) { // CAS already known to fail wasUncontended = true // Continue after rehash } else if (c.cas( { v = c.value; v }, - if (fn == null) v + x - else fn.applyAsLong(v, x) + if (fn == null) v + x else fn.applyAsLong(v, x) )) { - continue1 = false - continue2 = false - } else if (n >= Striped64.NCPU || (cells != cs)) + return + } else if (n >= NCPU || cells != cs) collide = false // At max size or stale else if (!collide) collide = true else if (cellsBusy == 0 && casCellsBusy()) { @@ -184,29 +177,22 @@ private[atomic] abstract class Striped64 private[atomic] () extends Number { cellsBusy = 0 } collide = false - continue2 = false - // Retry with expanded table + return } - if (continue2 == true) - index = Striped64.advanceProbe(index) - } else if (cellsBusy == 0 && (cells == cs) && casCellsBusy()) - try // Initialize table + index = advanceProbe(index) + } else if (cellsBusy == 0 && cells == cs && casCellsBusy()) { + try { // Initialize table if (cells == cs) { - val rs = new Array[Striped64.Cell](2) - rs(index & 1) = new Striped64.Cell(x) + val rs = new Array[Cell](2) + rs(index & 1) = new Cell(x) cells = rs - continue1 = false + return } - finally cellsBusy = 0 - else { // Fall back on using base - if (casBase( - { v = base; v }, - if (fn == null) v + x - else fn.applyAsLong(v, x) - )) { - continue1 = false - } - } + } finally cellsBusy = 0 + } else if (casBase( // Fall back on using base + { v = base; v }, + if (fn == null) v + x else fn.applyAsLong(v, x) + )) return } } diff --git a/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/lang/ThreadTest.scala b/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/lang/ThreadTest.scala index e491ad3c87..4d8ef57193 100644 --- a/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/lang/ThreadTest.scala +++ b/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/lang/ThreadTest.scala @@ -89,23 +89,31 @@ class ThreadTest { /** getUncaughtExceptionHandler returns ThreadGroup unless set, otherwise * returning value of last setUncaughtExceptionHandler. */ - def testGetAndSetUncaughtExceptionHandler(): Unit = { + @Test def testGetAndSetUncaughtExceptionHandler(): Unit = { // these must be done all at once to avoid state // dependencies across tests val current = Thread.currentThread() - val tg = current.getThreadGroup() val eh = new MyHandler() - assertSame(tg, current.getUncaughtExceptionHandler()) - current.setUncaughtExceptionHandler(eh) - try assertSame(eh, current.getUncaughtExceptionHandler()) - finally current.setUncaughtExceptionHandler(null) - assertSame(tg, current.getUncaughtExceptionHandler()) + val prevEh = current.getUncaughtExceptionHandler() + // Scala Native test are running in ExecutionContext that sets up custom uncought exception handler + val tg = current.getThreadGroup() + // assertSame(tg, current.getUncaughtExceptionHandler()) + try { + current.setUncaughtExceptionHandler(eh) + try assertSame(eh, current.getUncaughtExceptionHandler()) + finally current.setUncaughtExceptionHandler(null) + assertSame(tg, current.getUncaughtExceptionHandler()) + } finally { + current.setUncaughtExceptionHandler(prevEh) + assertSame(prevEh, current.getUncaughtExceptionHandler()) + } } /** getDefaultUncaughtExceptionHandler returns value of last * setDefaultUncaughtExceptionHandler. */ - @deprecated def testGetAndSetDefaultUncaughtExceptionHandler(): Unit = { + @deprecated + @Test def testGetAndSetDefaultUncaughtExceptionHandler(): Unit = { assertNull(Thread.getDefaultUncaughtExceptionHandler()) // failure due to SecurityException is OK. // Would be nice to explicitly test both ways, but cannot yet. @@ -113,11 +121,11 @@ class ThreadTest { val eh = new MyHandler() try { Thread.setDefaultUncaughtExceptionHandler(eh) - try assertSame(eh, Thread.getDefaultUncaughtExceptionHandler()) + try assertSame("1", eh, Thread.getDefaultUncaughtExceptionHandler()) finally Thread.setDefaultUncaughtExceptionHandler(defaultHandler) } catch { case ok: SecurityException => - assertNotNull(System.getSecurityManager()) + // assertNotNull(System.getSecurityManager()) } assertSame(defaultHandler, Thread.getDefaultUncaughtExceptionHandler()) } diff --git a/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/ConcurrentLinkedQueueTest.scala b/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/ConcurrentLinkedQueueTest.scala index a543933682..b0fb59f13d 100644 --- a/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/ConcurrentLinkedQueueTest.scala +++ b/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/ConcurrentLinkedQueueTest.scala @@ -12,6 +12,7 @@ import java.util.{Arrays, Collection, NoSuchElementException, Queue} import java.util.concurrent.ConcurrentLinkedQueue import org.junit.Assert._ +import org.junit._ object ConcurrentLinkedQueueTest { import JSR166Test._ @@ -37,13 +38,13 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** new queue is empty */ - def testConstructor1(): Unit = { + @Test def testConstructor1(): Unit = { mustEqual(0, new ConcurrentLinkedQueue[Item]().size) } /** Initializing from null Collection throws NPE */ - def testConstructor3(): Unit = { + @Test def testConstructor3(): Unit = { try { new ConcurrentLinkedQueue[Item](null.asInstanceOf[Collection[Item]]) shouldThrow() @@ -54,7 +55,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** Initializing from Collection of null elements throws NPE */ - def testConstructor4(): Unit = { + @Test def testConstructor4(): Unit = { try { new ConcurrentLinkedQueue[Item](Arrays.asList(new Array[Item](SIZE): _*)) shouldThrow() @@ -66,7 +67,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** Initializing from Collection with some null elements throws NPE */ - def testConstructor5(): Unit = { + @Test def testConstructor5(): Unit = { val items: Array[Item] = new Array[Item](2) items(0) = zero try { @@ -80,7 +81,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** Queue contains all elements of collection used to initialize */ - def testConstructor6(): Unit = { + @Test def testConstructor6(): Unit = { val items: Array[Item] = defaultItems val q: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue( Arrays.asList(items: _*) @@ -94,7 +95,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** isEmpty is true before add, false after */ - def testEmpty(): Unit = { + @Test def testEmpty(): Unit = { val q: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue[Item] assertTrue(q.isEmpty) q.add(one) @@ -107,7 +108,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** size changes when elements added and removed */ - def testSize(): Unit = { + @Test def testSize(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) var i: Int = 0 @@ -128,7 +129,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** offer(null) throws NPE */ - def testOfferNull(): Unit = { + @Test def testOfferNull(): Unit = { val q: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue[Item] try { q.offer(null) @@ -141,7 +142,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** add(null) throws NPE */ - def testAddNull(): Unit = { + @Test def testAddNull(): Unit = { val q: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue[Item] try { q.add(null) @@ -154,7 +155,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** Offer returns true */ - def testOffer(): Unit = { + @Test def testOffer(): Unit = { val q: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue[Item] assertTrue(q.offer(zero)) assertTrue(q.offer(one)) @@ -162,7 +163,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** add returns true */ - def testAdd(): Unit = { + @Test def testAdd(): Unit = { val q: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue[Item] var i: Int = 0 while (i < SIZE) { @@ -175,7 +176,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** addAll(null) throws NullPointerException */ - def testAddAll1(): Unit = { + @Test def testAddAll1(): Unit = { val q: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue[Item] try { q.addAll(null) @@ -188,7 +189,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** addAll(this) throws IllegalArgumentException */ - def testAddAllSelf(): Unit = { + @Test def testAddAllSelf(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) try { @@ -202,7 +203,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** addAll of a collection with null elements throws NullPointerException */ - def testAddAll2(): Unit = { + @Test def testAddAll2(): Unit = { val q: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue[Item] try { q.addAll(Arrays.asList(new Array[Item](SIZE): _*)) @@ -216,7 +217,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** addAll of a collection with any null elements throws NPE after possibly * adding some elements */ - def testAddAll3(): Unit = { + @Test def testAddAll3(): Unit = { val q: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue[Item] val items: Array[Item] = new Array[Item](2) items(0) = zero @@ -231,7 +232,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** Queue contains all elements, in traversal order, of successful addAll */ - def testAddAll5(): Unit = { + @Test def testAddAll5(): Unit = { val empty: Array[Item] = new Array[Item](0) val items: Array[Item] = defaultItems val q: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue[Item] @@ -246,7 +247,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** poll succeeds unless empty */ - def testPoll(): Unit = { + @Test def testPoll(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) var i: Int = 0 @@ -260,7 +261,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** peek returns next element, or null if empty */ - def testPeek(): Unit = { + @Test def testPeek(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) var i: Int = 0 @@ -276,7 +277,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** element returns next element, or throws NSEE if empty */ - def testElement(): Unit = { + @Test def testElement(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) var i: Int = 0 @@ -297,7 +298,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** remove removes next element, or throws NSEE if empty */ - def testRemove(): Unit = { + @Test def testRemove(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) var i: Int = 0 @@ -317,7 +318,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** remove(x) removes x and returns true if present */ - def testRemoveElement(): Unit = { + @Test def testRemoveElement(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) var i: Int = 1 @@ -344,7 +345,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** contains(x) reports true when elements added but not yet removed */ - def testContains(): Unit = { + @Test def testContains(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) var i: Int = 0 @@ -359,7 +360,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** clear removes all elements */ - def testClear(): Unit = { + @Test def testClear(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) q.clear() @@ -373,7 +374,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** containsAll(c) is true when c contains a subset of elements */ - def testContainsAll(): Unit = { + @Test def testContainsAll(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) val p: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue[Item] @@ -390,7 +391,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** retainAll(c) retains only those elements of c and reports true if change */ - def testRetainAll(): Unit = { + @Test def testRetainAll(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) val p: ConcurrentLinkedQueue[Item] = @@ -413,7 +414,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** removeAll(c) removes only those elements of c and reports true if changed */ - def testRemoveAll(): Unit = { + @Test def testRemoveAll(): Unit = { var i: Int = 1 while (i < SIZE) { val q: ConcurrentLinkedQueue[Item] = @@ -433,7 +434,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** toArray contains all elements in FIFO order */ - def testToArray(): Unit = { + @Test def testToArray(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) val a: Array[AnyRef] = q.toArray @@ -446,7 +447,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** toArray(a) contains all elements in FIFO order */ - def testToArray2(): Unit = { + @Test def testToArray2(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) val items: Array[Item] = new Array[Item](SIZE) @@ -460,7 +461,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** toArray(null) throws NullPointerException */ - def testToArray_NullArg(): Unit = { + @Test def testToArray_NullArg(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) try { @@ -474,9 +475,8 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** toArray(incompatible array type) throws ArrayStoreException */ - @SuppressWarnings( - Array("CollectionToArraySafeParameter") - ) def testToArray_incompatibleArrayType(): Unit = { + @Ignore("No array object exact element type information in SN runtime") + @Test def testToArray_incompatibleArrayType(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) try { @@ -484,13 +484,12 @@ class ConcurrentLinkedQueueTest extends JSR166Test { shouldThrow() } catch { case success: ArrayStoreException => - } } /** iterator iterates through all elements */ - def testIterator(): Unit = { + @Test def testIterator(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) val it: java.util.Iterator[_ <: Item] = q.iterator() @@ -506,13 +505,13 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** iterator of empty collection has no elements */ - def testEmptyIterator(): Unit = { + @Test def testEmptyIterator(): Unit = { assertIteratorExhausted(new ConcurrentLinkedQueue[AnyRef]().iterator) } /** iterator ordering is FIFO */ - def testIteratorOrdering(): Unit = { + @Test def testIteratorOrdering(): Unit = { val q: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue[Item] q.add(one) q.add(two) @@ -532,7 +531,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** Modifications do not cause iterators to fail */ - def testWeaklyConsistentIteration(): Unit = { + @Test def testWeaklyConsistentIteration(): Unit = { val q: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue[Item] q.add(one) q.add(two) @@ -547,23 +546,23 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** iterator.remove removes current element */ - def testIteratorRemove(): Unit = { + @Test def testIteratorRemove(): Unit = { val q: ConcurrentLinkedQueue[Item] = new ConcurrentLinkedQueue[Item] - q.add(one) - q.add(two) - q.add(three) + q.add(itemFor(one)) + q.add(itemFor(two)) + q.add(itemFor(three)) var it: java.util.Iterator[_ <: Item] = q.iterator it.next it.remove() it = q.iterator - assertSame(it.next, two) - assertSame(it.next, three) + assertSame(it.next, itemFor(two)) + assertSame(it.next, itemFor(three)) assertFalse(it.hasNext) } /** toString contains toStrings of elements */ - def testToString(): Unit = { + @Test def testToString(): Unit = { val q: ConcurrentLinkedQueue[Item] = ConcurrentLinkedQueueTest.populatedQueue(SIZE) val s: String = q.toString @@ -596,7 +595,7 @@ class ConcurrentLinkedQueueTest extends JSR166Test { /** remove(null), contains(null) always return false */ - def testNeverContainsNull(): Unit = { + @Test def testNeverContainsNull(): Unit = { val qs: Array[Collection[_]] = Array( new ConcurrentLinkedQueue[AnyRef], ConcurrentLinkedQueueTest.populatedQueue(2) diff --git a/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/RecursiveActionTest.scala b/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/RecursiveActionTest.scala index 8d500195fe..73ba3d60ba 100644 --- a/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/RecursiveActionTest.scala +++ b/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/RecursiveActionTest.scala @@ -239,7 +239,7 @@ class RecursiveActionTest extends JSR166Test { * isCancelled return false for normally completed tasks. getRawResult of a * RecursiveAction returns null; */ - def testInvoke(): Unit = { + @Test def testInvoke(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -255,7 +255,7 @@ class RecursiveActionTest extends JSR166Test { * isCompletedAbnormally and isCancelled return false for normally completed * tasks */ - def testQuietlyInvoke(): Unit = { + @Test def testQuietlyInvoke(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -269,7 +269,7 @@ class RecursiveActionTest extends JSR166Test { /** join of a forked task returns when task completes */ - def testForkJoin(): Unit = { + @Test def testForkJoin(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -284,7 +284,7 @@ class RecursiveActionTest extends JSR166Test { /** join/quietlyJoin of a forked task succeeds in the presence of interrupts */ - def testJoinIgnoresInterrupts(): Unit = { + @Test def testJoinIgnoresInterrupts(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { var f = new FibAction(8) @@ -352,7 +352,7 @@ class RecursiveActionTest extends JSR166Test { /** join/quietlyJoin of a forked task when not in ForkJoinPool succeeds in the * presence of interrupts */ - def testJoinIgnoresInterruptsOutsideForkJoinPool(): Unit = { + @Test def testJoinIgnoresInterruptsOutsideForkJoinPool(): Unit = { val sq = new SynchronousQueue[Array[FibAction]] val a = new CheckedRecursiveAction() { @throws[InterruptedException] @@ -436,7 +436,7 @@ class RecursiveActionTest extends JSR166Test { /** get of a forked task returns when task completes */ - def testForkGet(): Unit = { + @Test def testForkGet(): Unit = { val a = new CheckedRecursiveAction() { @throws[Exception] protected def realCompute(): Unit = { @@ -452,7 +452,7 @@ class RecursiveActionTest extends JSR166Test { /** timed get of a forked task returns when task completes */ - def testForkTimedGet(): Unit = { + @Test def testForkTimedGet(): Unit = { val a = new CheckedRecursiveAction() { @throws[Exception] protected def realCompute(): Unit = { @@ -468,7 +468,7 @@ class RecursiveActionTest extends JSR166Test { /** timed get with null time unit throws NPE */ - def testForkTimedGetNPE(): Unit = { + @Test def testForkTimedGetNPE(): Unit = { val a = new CheckedRecursiveAction() { @throws[Exception] protected def realCompute(): Unit = { @@ -488,7 +488,7 @@ class RecursiveActionTest extends JSR166Test { /** quietlyJoin of a forked task returns when task completes */ - def testForkQuietlyJoin(): Unit = { + @Test def testForkQuietlyJoin(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -504,7 +504,7 @@ class RecursiveActionTest extends JSR166Test { /** helpQuiesce returns when tasks are complete. getQueuedTaskCount returns 0 * when quiescent */ - def testForkHelpQuiesce(): Unit = { + @Test def testForkHelpQuiesce(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -522,7 +522,7 @@ class RecursiveActionTest extends JSR166Test { /** invoke task throws exception when task completes abnormally */ - def testAbnormalInvoke(): Unit = { + @Test def testAbnormalInvoke(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new RecursiveActionTest.FailingFibAction(8) @@ -540,7 +540,7 @@ class RecursiveActionTest extends JSR166Test { /** quietlyInvoke task returns when task completes abnormally */ - def testAbnormalQuietlyInvoke(): Unit = { + @Test def testAbnormalQuietlyInvoke(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new RecursiveActionTest.FailingFibAction(8) @@ -554,7 +554,7 @@ class RecursiveActionTest extends JSR166Test { /** join of a forked task throws exception when task completes abnormally */ - def testAbnormalForkJoin(): Unit = { + @Test def testAbnormalForkJoin(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new RecursiveActionTest.FailingFibAction(8) @@ -573,7 +573,7 @@ class RecursiveActionTest extends JSR166Test { /** get of a forked task throws exception when task completes abnormally */ - def testAbnormalForkGet(): Unit = { + @Test def testAbnormalForkGet(): Unit = { val a = new CheckedRecursiveAction() { @throws[Exception] protected def realCompute(): Unit = { @@ -595,7 +595,7 @@ class RecursiveActionTest extends JSR166Test { /** timed get of a forked task throws exception when task completes abnormally */ - def testAbnormalForkTimedGet(): Unit = { + @Test def testAbnormalForkTimedGet(): Unit = { val a = new CheckedRecursiveAction() { @throws[Exception] protected def realCompute(): Unit = { @@ -617,7 +617,7 @@ class RecursiveActionTest extends JSR166Test { /** quietlyJoin of a forked task returns when task completes abnormally */ - def testAbnormalForkQuietlyJoin(): Unit = { + @Test def testAbnormalForkQuietlyJoin(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new RecursiveActionTest.FailingFibAction(8) @@ -632,7 +632,7 @@ class RecursiveActionTest extends JSR166Test { /** invoke task throws exception when task cancelled */ - def testCancelledInvoke(): Unit = { + @Test def testCancelledInvoke(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -651,7 +651,7 @@ class RecursiveActionTest extends JSR166Test { /** join of a forked task throws exception when task cancelled */ - def testCancelledForkJoin(): Unit = { + @Test def testCancelledForkJoin(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -671,7 +671,7 @@ class RecursiveActionTest extends JSR166Test { /** get of a forked task throws exception when task cancelled */ - def testCancelledForkGet(): Unit = { + @Test def testCancelledForkGet(): Unit = { val a = new CheckedRecursiveAction() { @throws[Exception] protected def realCompute(): Unit = { @@ -692,7 +692,7 @@ class RecursiveActionTest extends JSR166Test { /** timed get of a forked task throws exception when task cancelled */ - def testCancelledForkTimedGet(): Unit = { + @Test def testCancelledForkTimedGet(): Unit = { val a = new CheckedRecursiveAction() { @throws[Exception] protected def realCompute(): Unit = { @@ -713,7 +713,7 @@ class RecursiveActionTest extends JSR166Test { /** quietlyJoin of a forked task returns when task cancelled */ - def testCancelledForkQuietlyJoin(): Unit = { + @Test def testCancelledForkQuietlyJoin(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -728,7 +728,7 @@ class RecursiveActionTest extends JSR166Test { /** getPool of executing task returns its pool */ - def testGetPool(): Unit = { + @Test def testGetPool(): Unit = { val mainPool = RecursiveActionTest.mainPool val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { assertSame(mainPool, getPool) } @@ -738,7 +738,8 @@ class RecursiveActionTest extends JSR166Test { /** getPool of non-FJ task returns null */ - def testGetPool2(): Unit = { + @Ignore("All Scala Native tests are exuected in the pool") + @Test def testGetPool2(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { assertNull(getPool) } } @@ -747,7 +748,7 @@ class RecursiveActionTest extends JSR166Test { /** inForkJoinPool of executing task returns true */ - def testInForkJoinPool(): Unit = { + @Test def testInForkJoinPool(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { assertTrue(inForkJoinPool) } } @@ -756,7 +757,8 @@ class RecursiveActionTest extends JSR166Test { /** inForkJoinPool of non-FJ task returns false */ - def testInForkJoinPool2(): Unit = { + @Ignore("All Scala Native etests are exuected in the pool") + @Test def testInForkJoinPool2(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { assertFalse(inForkJoinPool) } } @@ -765,7 +767,7 @@ class RecursiveActionTest extends JSR166Test { /** getPool of current thread in pool returns its pool */ - def testWorkerGetPool(): Unit = { + @Test def testWorkerGetPool(): Unit = { val mainPool = RecursiveActionTest.mainPool val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { @@ -778,7 +780,7 @@ class RecursiveActionTest extends JSR166Test { /** getPoolIndex of current thread in pool returns 0 <= value < poolSize */ - def testWorkerGetPoolIndex(): Unit = { + @Test def testWorkerGetPoolIndex(): Unit = { val mainPool = RecursiveActionTest.mainPool val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { @@ -793,7 +795,7 @@ class RecursiveActionTest extends JSR166Test { /** setRawResult(null) succeeds */ - def testSetRawResult(): Unit = { + @Test def testSetRawResult(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { setRawResult(null) @@ -805,7 +807,7 @@ class RecursiveActionTest extends JSR166Test { /** A reinitialized normally completed task may be re-invoked */ - def testReinitialize(): Unit = { + @Test def testReinitialize(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -824,7 +826,7 @@ class RecursiveActionTest extends JSR166Test { /** A reinitialized abnormally completed task may be re-invoked */ - def testReinitializeAbnormal(): Unit = { + @Test def testReinitializeAbnormal(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new RecursiveActionTest.FailingFibAction(8) @@ -847,7 +849,7 @@ class RecursiveActionTest extends JSR166Test { /** invoke task throws exception after invoking completeExceptionally */ - def testCompleteExceptionally(): Unit = { + @Test def testCompleteExceptionally(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -866,7 +868,7 @@ class RecursiveActionTest extends JSR166Test { /** invoke task suppresses execution invoking complete */ - def testComplete(): Unit = { + @Test def testComplete(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -881,7 +883,7 @@ class RecursiveActionTest extends JSR166Test { /** invokeAll(t1, t2) invokes all task arguments */ - def testInvokeAll2(): Unit = { + @Test def testInvokeAll2(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -898,7 +900,7 @@ class RecursiveActionTest extends JSR166Test { /** invokeAll(tasks) with 1 argument invokes task */ - def testInvokeAll1(): Unit = { + @Test def testInvokeAll1(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -912,7 +914,7 @@ class RecursiveActionTest extends JSR166Test { /** invokeAll(tasks) with > 2 argument invokes tasks */ - def testInvokeAll3(): Unit = { + @Test def testInvokeAll3(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -935,7 +937,7 @@ class RecursiveActionTest extends JSR166Test { /** invokeAll(collection) invokes all tasks in the collection */ - def testInvokeAllCollection(): Unit = { + @Test def testInvokeAllCollection(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -962,7 +964,7 @@ class RecursiveActionTest extends JSR166Test { /** invokeAll(tasks) with any null task throws NPE */ - def testInvokeAllNPE(): Unit = { + @Test def testInvokeAllNPE(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -982,7 +984,7 @@ class RecursiveActionTest extends JSR166Test { /** invokeAll(t1, t2) throw exception if any task does */ - def testAbnormalInvokeAll2(): Unit = { + @Test def testAbnormalInvokeAll2(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -1001,7 +1003,7 @@ class RecursiveActionTest extends JSR166Test { /** invokeAll(tasks) with 1 argument throws exception if task does */ - def testAbnormalInvokeAll1(): Unit = { + @Test def testAbnormalInvokeAll1(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val g = new RecursiveActionTest.FailingFibAction(9) @@ -1019,7 +1021,7 @@ class RecursiveActionTest extends JSR166Test { /** invokeAll(tasks) with > 2 argument throws exception if any task does */ - def testAbnormalInvokeAll3(): Unit = { + @Test def testAbnormalInvokeAll3(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new FibAction(8) @@ -1039,7 +1041,7 @@ class RecursiveActionTest extends JSR166Test { /** invokeAll(collection) throws exception if any task does */ - def testAbnormalInvokeAllCollection(): Unit = { + @Test def testAbnormalInvokeAllCollection(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val f = new RecursiveActionTest.FailingFibAction(8) @@ -1064,7 +1066,7 @@ class RecursiveActionTest extends JSR166Test { /** tryUnfork returns true for most recent unexecuted task, and suppresses * execution */ - def testTryUnfork(): Unit = { + @Test def testTryUnfork(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val g = new FibAction(9) @@ -1083,7 +1085,7 @@ class RecursiveActionTest extends JSR166Test { /** getSurplusQueuedTaskCount returns > 0 when there are more tasks than * threads */ - def testGetSurplusQueuedTaskCount(): Unit = { + @Test def testGetSurplusQueuedTaskCount(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val h = new FibAction(7) @@ -1105,7 +1107,7 @@ class RecursiveActionTest extends JSR166Test { /** peekNextLocalTask returns most recent unexecuted task. */ - def testPeekNextLocalTask(): Unit = { + @Test def testPeekNextLocalTask(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val g = new FibAction(9) @@ -1125,7 +1127,7 @@ class RecursiveActionTest extends JSR166Test { /** pollNextLocalTask returns most recent unexecuted task without executing it */ - def testPollNextLocalTask(): Unit = { + @Test def testPollNextLocalTask(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val g = new FibAction(9) @@ -1143,7 +1145,7 @@ class RecursiveActionTest extends JSR166Test { /** pollTask returns an unexecuted task without executing it */ - def testPollTask(): Unit = { + @Test def testPollTask(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val g = new FibAction(9) @@ -1161,7 +1163,7 @@ class RecursiveActionTest extends JSR166Test { /** peekNextLocalTask returns least recent unexecuted task in async mode */ - def testPeekNextLocalTaskAsync(): Unit = { + @Test def testPeekNextLocalTaskAsync(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val g = new FibAction(9) @@ -1181,7 +1183,7 @@ class RecursiveActionTest extends JSR166Test { /** pollNextLocalTask returns least recent unexecuted task without executing * it, in async mode */ - def testPollNextLocalTaskAsync(): Unit = { + @Test def testPollNextLocalTaskAsync(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val g = new FibAction(9) @@ -1199,7 +1201,7 @@ class RecursiveActionTest extends JSR166Test { /** pollTask returns an unexecuted task without executing it, in async mode */ - def testPollTaskAsync(): Unit = { + @Test def testPollTaskAsync(): Unit = { val a = new CheckedRecursiveAction() { protected def realCompute(): Unit = { val g = new FibAction(9) @@ -1217,7 +1219,7 @@ class RecursiveActionTest extends JSR166Test { /** SortTask demo works as advertised */ - def testSortTaskDemo(): Unit = { + @Test def testSortTaskDemo(): Unit = { val rnd = ThreadLocalRandom.current val array = new Array[Long](1007) for (i <- 0 until array.length) { array(i) = rnd.nextLong } diff --git a/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/RecursiveTaskTest.scala b/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/RecursiveTaskTest.scala index 96e20767b1..9361151d5e 100644 --- a/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/RecursiveTaskTest.scala +++ b/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/RecursiveTaskTest.scala @@ -260,7 +260,7 @@ class RecursiveTaskTest extends JSR166Test { /** get of a forked task returns when task completes */ - def testForkGet(): Unit = { + @Test def testForkGet(): Unit = { val a = new CheckedRecursiveTask[Integer] { protected def realCompute(): Integer = { val f = new FibTask(8) diff --git a/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/SemaphoreTest.scala b/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/SemaphoreTest.scala index 539f908070..e092b3a62d 100644 --- a/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/SemaphoreTest.scala +++ b/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/SemaphoreTest.scala @@ -635,7 +635,7 @@ class SemaphoreTest extends JSR166Test { AcquireMethod.acquireUninterruptibly ) } - def testReleaseAcquireDifferentThreads_acquireUninterruptiblyN_fair() + @Test def testReleaseAcquireDifferentThreads_acquireUninterruptiblyN_fair() : Unit = { testReleaseAcquireDifferentThreads( true, diff --git a/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/atomic/LongAdderTest.scala b/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/atomic/LongAdderTest.scala index a178eac92e..384f9eba5f 100644 --- a/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/atomic/LongAdderTest.scala +++ b/unit-tests/shared/src/test/scala/org/scalanative/testsuite/javalib/util/concurrent/atomic/LongAdderTest.scala @@ -122,20 +122,22 @@ class LongAdderTest extends JSR166Test { /** adds by multiple threads produce correct sum */ @throws[Throwable] - def testAddAndSumMT(): Unit = { + @Test def testAddAndSumMT(): Unit = { val incs = 1000000 val nthreads = 4 val pool = Executors.newCachedThreadPool() - val a = new LongAdder - val barrier = new CyclicBarrier(nthreads + 1) - for (i <- 0 until nthreads) { - pool.execute(new AdderTask(a, barrier, incs)) + usingPoolCleaner(pool) { _ => + val a = new LongAdder + val barrier = new CyclicBarrier(nthreads + 1) + for (i <- 0 until nthreads) { + pool.execute(new AdderTask(a, barrier, incs)) + } + barrier.await + barrier.await + val total = nthreads.toLong * incs + val sum = a.sum + assertEquals(sum, total) } - barrier.await - barrier.await - val total = nthreads.toLong * incs - val sum = a.sum - assertEquals(sum, total) pool.shutdown() } final class AdderTask( From 71f409ac5aa2d6bd3b56d7defa5aebe5df95de20 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Tue, 16 Apr 2024 16:06:56 +0200 Subject: [PATCH 8/9] docs: Format dates without using time information --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index bdc2ad90c0..8066df02fa 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -89,7 +89,7 @@ def generateScalaNativeCurrentYear(): # # today_fmt = '%B %d, %Y' -today_fmt = '%Y-%m-%d %H:%M:%S' # Scala Native change. Use ISO format. +today_fmt = '%Y-%m-%d' # Scala Native change. Use ISO format. # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -181,7 +181,7 @@ def generateScalaNativeCurrentYear(): # bottom, using the given strftime format. # The empty string is equivalent to '%b %d, %Y'. # -html_last_updated_fmt = '%Y-%m-%d %H:%M:%S' +html_last_updated_fmt = '%Y-%m-%d' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. From 57afc449111c96af6c02718d000484caf6045e50 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Tue, 16 Apr 2024 16:07:11 +0200 Subject: [PATCH 9/9] Set version to 0.5.1 and generate changelog --- docs/changelog/0.5.x/0.5.1.md | 70 +++++++++++++++++++ docs/changelog/0.5.x/index.rst | 1 + docs/conf.py | 2 +- .../scala/scalanative/nir/Versions.scala | 2 +- 4 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 docs/changelog/0.5.x/0.5.1.md diff --git a/docs/changelog/0.5.x/0.5.1.md b/docs/changelog/0.5.x/0.5.1.md new file mode 100644 index 0000000000..3e1591ad09 --- /dev/null +++ b/docs/changelog/0.5.x/0.5.1.md @@ -0,0 +1,70 @@ + +# 0.5.1 (2024-04-16) + +We're happy to announce the release of Scala Native v0.5.1. + +This patch release is focued on elimination of compiler plugin crashes and bugfixes to Java concurrent collections. +It does also fix some of the issues when using MinGW compiler. + +## Supported Scala versions + +| Scala Binary Version | Supported Scala Versions | +| -------------------- | ------------------------ | +| 2.12 | 2.12.14 ... 2.12.19 | +| 2.13 | 2.13.8 ... 2.13.13 | +| 3 | 3.1.2 ... 3.1.3
3.2.0 ... 3.2.2
3.3.0 ... 3.3.3
3.4.0 ... 3.4.1 | + + +> Upon release of new Scala version (stable, or Scala 3 RC) version dependent artifacts would be published without a new release. + +
+ + + + + + + + + + + + + + + +
Commits since last release7
Merged PRs6
Contributors3
+ +## Contributors + +Big thanks to everybody who contributed to this release or reported an issue! + +``` +$ git shortlog -sn --no-merges v0.5.0..v0.5.1 + 5 Wojciech Mazur + 1 Claudio Bley + 1 Natsu Kagami +``` + +## Highlighted merged PRs + +## [v0.5.1](https://github.com/scala-native/scala-native/tree/v0.5.1) (2024-04-16) + +[Full Changelog](https://github.com/scala-native/scala-native/compare/v0.5.0...v0.5.1) + +**Merged pull requests:** + +### Toolchain +- Support mingw compiler + [\#3869](https://github.com/scala-native/scala-native/pull/3869) + ([avdv](https://github.com/avdv)) + +### Scala compiler plugin +- fix: Handle exceptions when reporting warnings in Scala 3 compiler plugin + [\#3872](https://github.com/scala-native/scala-native/pull/3872) + ([WojciechMazur](https://github.com/WojciechMazur)) + +### Java Standard Library +- fix: Enable skipped concurrent tests and fix underlying hidden bugs + [\#3875](https://github.com/scala-native/scala-native/pull/3875) + ([WojciechMazur](https://github.com/WojciechMazur)) diff --git a/docs/changelog/0.5.x/index.rst b/docs/changelog/0.5.x/index.rst index ed1ad905e5..5eab1308bf 100644 --- a/docs/changelog/0.5.x/index.rst +++ b/docs/changelog/0.5.x/index.rst @@ -6,6 +6,7 @@ .. toctree:: :maxdepth: 1 + 0.5.1 0.5.0 0.5.0-RC3 0.5.0-RC2 diff --git a/docs/conf.py b/docs/conf.py index 8066df02fa..06c351fc09 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -71,7 +71,7 @@ def generateScalaNativeCurrentYear(): # The short X.Y version. version = u'0.5' # The full version, including alpha/beta/rc tags. -release = u'0.5.1-SNAPSHOT' +release = u'0.5.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/nir/src/main/scala/scala/scalanative/nir/Versions.scala b/nir/src/main/scala/scala/scalanative/nir/Versions.scala index 82f1d46b13..7eb35453e9 100644 --- a/nir/src/main/scala/scala/scalanative/nir/Versions.scala +++ b/nir/src/main/scala/scala/scalanative/nir/Versions.scala @@ -25,7 +25,7 @@ object Versions { final val revision: Int = 10 // a.k.a. MINOR version /* Current public release version of Scala Native. */ - final val current: String = "0.5.1-SNAPSHOT" + final val current: String = "0.5.1" final val currentBinaryVersion: String = binaryVersion(current) private object FullVersion {