mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8372696: Allow boot classes to explicitly opt-in for final field trusting
Reviewed-by: jvernee, jrose, alanb
This commit is contained in:
parent
b42861a2aa
commit
3220c4cb43
@ -216,6 +216,10 @@ ciField::ciField(fieldDescriptor *fd) :
|
|||||||
static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
|
static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
|
||||||
if (holder == nullptr)
|
if (holder == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
if (holder->trust_final_fields()) {
|
||||||
|
// Explicit opt-in from system classes
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// Even if general trusting is disabled, trust system-built closures in these packages.
|
// Even if general trusting is disabled, trust system-built closures in these packages.
|
||||||
if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke") ||
|
if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke") ||
|
||||||
holder->is_in_package("java/lang/reflect") || holder->is_in_package("jdk/internal/reflect") ||
|
holder->is_in_package("java/lang/reflect") || holder->is_in_package("jdk/internal/reflect") ||
|
||||||
@ -230,14 +234,6 @@ static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
|
|||||||
// Trust final fields in records
|
// Trust final fields in records
|
||||||
if (holder->is_record())
|
if (holder->is_record())
|
||||||
return true;
|
return true;
|
||||||
// Trust Atomic*FieldUpdaters: they are very important for performance, and make up one
|
|
||||||
// more reason not to use Unsafe, if their final fields are trusted. See more in JDK-8140483.
|
|
||||||
if (holder->name() == ciSymbols::java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl() ||
|
|
||||||
holder->name() == ciSymbols::java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater() ||
|
|
||||||
holder->name() == ciSymbols::java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater() ||
|
|
||||||
holder->name() == ciSymbols::java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return TrustFinalNonStaticFields;
|
return TrustFinalNonStaticFields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -65,6 +65,7 @@ ciInstanceKlass::ciInstanceKlass(Klass* k) :
|
|||||||
_has_nonstatic_concrete_methods = ik->has_nonstatic_concrete_methods();
|
_has_nonstatic_concrete_methods = ik->has_nonstatic_concrete_methods();
|
||||||
_is_hidden = ik->is_hidden();
|
_is_hidden = ik->is_hidden();
|
||||||
_is_record = ik->is_record();
|
_is_record = ik->is_record();
|
||||||
|
_trust_final_fields = ik->trust_final_fields();
|
||||||
_nonstatic_fields = nullptr; // initialized lazily by compute_nonstatic_fields:
|
_nonstatic_fields = nullptr; // initialized lazily by compute_nonstatic_fields:
|
||||||
_has_injected_fields = -1;
|
_has_injected_fields = -1;
|
||||||
_implementor = nullptr; // we will fill these lazily
|
_implementor = nullptr; // we will fill these lazily
|
||||||
|
|||||||
@ -59,6 +59,7 @@ private:
|
|||||||
bool _has_nonstatic_concrete_methods;
|
bool _has_nonstatic_concrete_methods;
|
||||||
bool _is_hidden;
|
bool _is_hidden;
|
||||||
bool _is_record;
|
bool _is_record;
|
||||||
|
bool _trust_final_fields;
|
||||||
bool _has_trusted_loader;
|
bool _has_trusted_loader;
|
||||||
|
|
||||||
ciFlags _flags;
|
ciFlags _flags;
|
||||||
@ -207,6 +208,10 @@ public:
|
|||||||
return _is_record;
|
return _is_record;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool trust_final_fields() const {
|
||||||
|
return _trust_final_fields;
|
||||||
|
}
|
||||||
|
|
||||||
ciInstanceKlass* get_canonical_holder(int offset);
|
ciInstanceKlass* get_canonical_holder(int offset);
|
||||||
ciField* get_field_by_offset(int field_offset, bool is_static);
|
ciField* get_field_by_offset(int field_offset, bool is_static);
|
||||||
ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static);
|
ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static);
|
||||||
|
|||||||
@ -943,6 +943,7 @@ public:
|
|||||||
_java_lang_Deprecated_for_removal,
|
_java_lang_Deprecated_for_removal,
|
||||||
_jdk_internal_vm_annotation_AOTSafeClassInitializer,
|
_jdk_internal_vm_annotation_AOTSafeClassInitializer,
|
||||||
_method_AOTRuntimeSetup,
|
_method_AOTRuntimeSetup,
|
||||||
|
_jdk_internal_vm_annotation_TrustFinalFields,
|
||||||
_annotation_LIMIT
|
_annotation_LIMIT
|
||||||
};
|
};
|
||||||
const Location _location;
|
const Location _location;
|
||||||
@ -1878,6 +1879,11 @@ AnnotationCollector::annotation_index(const ClassLoaderData* loader_data,
|
|||||||
if (!privileged) break; // only allow in privileged code
|
if (!privileged) break; // only allow in privileged code
|
||||||
return _field_Stable;
|
return _field_Stable;
|
||||||
}
|
}
|
||||||
|
case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_TrustFinalFields_signature): {
|
||||||
|
if (_location != _in_class) break; // only allow for classes
|
||||||
|
if (!privileged) break; // only allow in privileged code
|
||||||
|
return _jdk_internal_vm_annotation_TrustFinalFields;
|
||||||
|
}
|
||||||
case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_Contended_signature): {
|
case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_Contended_signature): {
|
||||||
if (_location != _in_field && _location != _in_class) {
|
if (_location != _in_field && _location != _in_class) {
|
||||||
break; // only allow for fields and classes
|
break; // only allow for fields and classes
|
||||||
@ -1992,6 +1998,9 @@ void ClassFileParser::ClassAnnotationCollector::apply_to(InstanceKlass* ik) {
|
|||||||
if (has_annotation(_jdk_internal_vm_annotation_AOTSafeClassInitializer)) {
|
if (has_annotation(_jdk_internal_vm_annotation_AOTSafeClassInitializer)) {
|
||||||
ik->set_has_aot_safe_initializer();
|
ik->set_has_aot_safe_initializer();
|
||||||
}
|
}
|
||||||
|
if (has_annotation(_jdk_internal_vm_annotation_TrustFinalFields)) {
|
||||||
|
ik->set_trust_final_fields(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_ARGS_SIZE 255
|
#define MAX_ARGS_SIZE 255
|
||||||
|
|||||||
@ -245,10 +245,6 @@ class SerializeClosure;
|
|||||||
\
|
\
|
||||||
/* Concurrency support */ \
|
/* Concurrency support */ \
|
||||||
template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \
|
template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \
|
||||||
template(java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl, "java/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl") \
|
|
||||||
template(java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater") \
|
|
||||||
template(java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater") \
|
|
||||||
template(java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl, "java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl") \
|
|
||||||
template(jdk_internal_vm_annotation_Contended_signature, "Ljdk/internal/vm/annotation/Contended;") \
|
template(jdk_internal_vm_annotation_Contended_signature, "Ljdk/internal/vm/annotation/Contended;") \
|
||||||
template(jdk_internal_vm_annotation_ReservedStackAccess_signature, "Ljdk/internal/vm/annotation/ReservedStackAccess;") \
|
template(jdk_internal_vm_annotation_ReservedStackAccess_signature, "Ljdk/internal/vm/annotation/ReservedStackAccess;") \
|
||||||
template(jdk_internal_ValueBased_signature, "Ljdk/internal/ValueBased;") \
|
template(jdk_internal_ValueBased_signature, "Ljdk/internal/ValueBased;") \
|
||||||
@ -302,6 +298,7 @@ class SerializeClosure;
|
|||||||
template(jdk_internal_misc_Scoped_signature, "Ljdk/internal/misc/ScopedMemoryAccess$Scoped;") \
|
template(jdk_internal_misc_Scoped_signature, "Ljdk/internal/misc/ScopedMemoryAccess$Scoped;") \
|
||||||
template(jdk_internal_vm_annotation_IntrinsicCandidate_signature, "Ljdk/internal/vm/annotation/IntrinsicCandidate;") \
|
template(jdk_internal_vm_annotation_IntrinsicCandidate_signature, "Ljdk/internal/vm/annotation/IntrinsicCandidate;") \
|
||||||
template(jdk_internal_vm_annotation_Stable_signature, "Ljdk/internal/vm/annotation/Stable;") \
|
template(jdk_internal_vm_annotation_Stable_signature, "Ljdk/internal/vm/annotation/Stable;") \
|
||||||
|
template(jdk_internal_vm_annotation_TrustFinalFields_signature, "Ljdk/internal/vm/annotation/TrustFinalFields;") \
|
||||||
\
|
\
|
||||||
template(jdk_internal_vm_annotation_ChangesCurrentThread_signature, "Ljdk/internal/vm/annotation/ChangesCurrentThread;") \
|
template(jdk_internal_vm_annotation_ChangesCurrentThread_signature, "Ljdk/internal/vm/annotation/ChangesCurrentThread;") \
|
||||||
template(jdk_internal_vm_annotation_JvmtiHideEvents_signature, "Ljdk/internal/vm/annotation/JvmtiHideEvents;") \
|
template(jdk_internal_vm_annotation_JvmtiHideEvents_signature, "Ljdk/internal/vm/annotation/JvmtiHideEvents;") \
|
||||||
|
|||||||
@ -353,6 +353,9 @@ class InstanceKlass: public Klass {
|
|||||||
int static_oop_field_count() const { return (int)_static_oop_field_count; }
|
int static_oop_field_count() const { return (int)_static_oop_field_count; }
|
||||||
void set_static_oop_field_count(u2 size) { _static_oop_field_count = size; }
|
void set_static_oop_field_count(u2 size) { _static_oop_field_count = size; }
|
||||||
|
|
||||||
|
bool trust_final_fields() { return _misc_flags.trust_final_fields(); }
|
||||||
|
void set_trust_final_fields(bool value) { _misc_flags.set_trust_final_fields(value); }
|
||||||
|
|
||||||
// Java itable
|
// Java itable
|
||||||
int itable_length() const { return _itable_len; }
|
int itable_length() const { return _itable_len; }
|
||||||
void set_itable_length(int len) { _itable_len = len; }
|
void set_itable_length(int len) { _itable_len = len; }
|
||||||
|
|||||||
@ -54,6 +54,7 @@ class InstanceKlassFlags {
|
|||||||
flag(has_localvariable_table , 1 << 11) /* has localvariable information */ \
|
flag(has_localvariable_table , 1 << 11) /* has localvariable information */ \
|
||||||
flag(has_miranda_methods , 1 << 12) /* True if this class has miranda methods in it's vtable */ \
|
flag(has_miranda_methods , 1 << 12) /* True if this class has miranda methods in it's vtable */ \
|
||||||
flag(has_final_method , 1 << 13) /* True if klass has final method */ \
|
flag(has_final_method , 1 << 13) /* True if klass has final method */ \
|
||||||
|
flag(trust_final_fields , 1 << 14) /* All instance final fields in this class should be trusted */ \
|
||||||
/* end of list */
|
/* end of list */
|
||||||
|
|
||||||
#define IK_FLAGS_ENUM_NAME(name, value) _misc_##name = value,
|
#define IK_FLAGS_ENUM_NAME(name, value) _misc_##name = value,
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
package java.util;
|
package java.util;
|
||||||
|
|
||||||
import jdk.internal.vm.annotation.Stable;
|
import jdk.internal.vm.annotation.TrustFinalFields;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -62,6 +62,7 @@ import java.util.stream.Stream;
|
|||||||
* @since 1.8
|
* @since 1.8
|
||||||
*/
|
*/
|
||||||
@jdk.internal.ValueBased
|
@jdk.internal.ValueBased
|
||||||
|
@TrustFinalFields
|
||||||
public final class Optional<T> {
|
public final class Optional<T> {
|
||||||
/**
|
/**
|
||||||
* Common instance for {@code empty()}.
|
* Common instance for {@code empty()}.
|
||||||
@ -71,7 +72,6 @@ public final class Optional<T> {
|
|||||||
/**
|
/**
|
||||||
* If non-null, the value; if null, indicates no value is present
|
* If non-null, the value; if null, indicates no value is present
|
||||||
*/
|
*/
|
||||||
@Stable
|
|
||||||
private final T value;
|
private final T value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -42,6 +42,8 @@ import java.util.function.IntUnaryOperator;
|
|||||||
import jdk.internal.misc.Unsafe;
|
import jdk.internal.misc.Unsafe;
|
||||||
import jdk.internal.reflect.CallerSensitive;
|
import jdk.internal.reflect.CallerSensitive;
|
||||||
import jdk.internal.reflect.Reflection;
|
import jdk.internal.reflect.Reflection;
|
||||||
|
import jdk.internal.vm.annotation.TrustFinalFields;
|
||||||
|
|
||||||
import java.lang.invoke.VarHandle;
|
import java.lang.invoke.VarHandle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -371,6 +373,7 @@ public abstract class AtomicIntegerFieldUpdater<T> {
|
|||||||
/**
|
/**
|
||||||
* Standard hotspot implementation using intrinsics.
|
* Standard hotspot implementation using intrinsics.
|
||||||
*/
|
*/
|
||||||
|
@TrustFinalFields
|
||||||
private static final class AtomicIntegerFieldUpdaterImpl<T>
|
private static final class AtomicIntegerFieldUpdaterImpl<T>
|
||||||
extends AtomicIntegerFieldUpdater<T> {
|
extends AtomicIntegerFieldUpdater<T> {
|
||||||
private static final Unsafe U = Unsafe.getUnsafe();
|
private static final Unsafe U = Unsafe.getUnsafe();
|
||||||
|
|||||||
@ -42,6 +42,8 @@ import java.util.function.LongUnaryOperator;
|
|||||||
import jdk.internal.misc.Unsafe;
|
import jdk.internal.misc.Unsafe;
|
||||||
import jdk.internal.reflect.CallerSensitive;
|
import jdk.internal.reflect.CallerSensitive;
|
||||||
import jdk.internal.reflect.Reflection;
|
import jdk.internal.reflect.Reflection;
|
||||||
|
import jdk.internal.vm.annotation.TrustFinalFields;
|
||||||
|
|
||||||
import java.lang.invoke.VarHandle;
|
import java.lang.invoke.VarHandle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -368,6 +370,7 @@ public abstract class AtomicLongFieldUpdater<T> {
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TrustFinalFields
|
||||||
private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
|
private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
|
||||||
private static final Unsafe U = Unsafe.getUnsafe();
|
private static final Unsafe U = Unsafe.getUnsafe();
|
||||||
private final long offset;
|
private final long offset;
|
||||||
|
|||||||
@ -42,6 +42,8 @@ import java.util.function.UnaryOperator;
|
|||||||
import jdk.internal.misc.Unsafe;
|
import jdk.internal.misc.Unsafe;
|
||||||
import jdk.internal.reflect.CallerSensitive;
|
import jdk.internal.reflect.CallerSensitive;
|
||||||
import jdk.internal.reflect.Reflection;
|
import jdk.internal.reflect.Reflection;
|
||||||
|
import jdk.internal.vm.annotation.TrustFinalFields;
|
||||||
|
|
||||||
import java.lang.invoke.VarHandle;
|
import java.lang.invoke.VarHandle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -312,6 +314,7 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TrustFinalFields
|
||||||
private static final class AtomicReferenceFieldUpdaterImpl<T,V>
|
private static final class AtomicReferenceFieldUpdaterImpl<T,V>
|
||||||
extends AtomicReferenceFieldUpdater<T,V> {
|
extends AtomicReferenceFieldUpdater<T,V> {
|
||||||
private static final Unsafe U = Unsafe.getUnsafe();
|
private static final Unsafe U = Unsafe.getUnsafe();
|
||||||
|
|||||||
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jdk.internal.vm.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/// Indicates all instance final fields declared in the annotated class should
|
||||||
|
/// be trusted as constants by compilers in `ciField::is_constant`.
|
||||||
|
///
|
||||||
|
/// The compiler already treats static final fields and instance final fields in
|
||||||
|
/// record classes and hidden classes as constant. All classes in select
|
||||||
|
/// packages (Defined in `trust_final_non_static_fields` in `ciField.cpp`) in
|
||||||
|
/// the boot class loader also have their instance final fields trusted. This
|
||||||
|
/// annotation is not necessary in these cases.
|
||||||
|
///
|
||||||
|
/// The [Stable] annotation treats fields as constants once they are not the
|
||||||
|
/// zero or null value. In comparison, a non-stable final instance field
|
||||||
|
/// trusted by this annotation can treat zero and null values as constants.
|
||||||
|
///
|
||||||
|
/// This annotation is suitable when constant treatment of final fields is
|
||||||
|
/// performance sensitive, yet package-wide final field constant treatment may
|
||||||
|
/// be at risk from final field modifications such as serialization.
|
||||||
|
///
|
||||||
|
/// This annotation is only recognized on classes from the boot and platform
|
||||||
|
/// class loaders and is ignored elsewhere.
|
||||||
|
///
|
||||||
|
/// @since 26
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
public @interface TrustFinalFields {
|
||||||
|
}
|
||||||
63
test/hotspot/jtreg/compiler/corelibs/OptionalFold.java
Normal file
63
test/hotspot/jtreg/compiler/corelibs/OptionalFold.java
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package compiler.corelibs;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import compiler.lib.ir_framework.Check;
|
||||||
|
import compiler.lib.ir_framework.IR;
|
||||||
|
import compiler.lib.ir_framework.IRNode;
|
||||||
|
import compiler.lib.ir_framework.Test;
|
||||||
|
import compiler.lib.ir_framework.TestFramework;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8372696
|
||||||
|
* @summary Verify constant folding for Optional, both present and absent
|
||||||
|
* @library /test/lib /
|
||||||
|
* @run driver ${test.main.class}
|
||||||
|
*/
|
||||||
|
public class OptionalFold {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
TestFramework.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure both present and empty values can fold
|
||||||
|
static final Optional<Integer> ONE = Optional.of(5), TWO = Optional.empty();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.ADD_I})
|
||||||
|
public int testSum() {
|
||||||
|
return ONE.orElse(7) + TWO.orElse(12);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Check(test = "testSum")
|
||||||
|
public void checkTestSum(int res) {
|
||||||
|
if (res != 5 + 12) {
|
||||||
|
throw new RuntimeException("incorrect result: " + res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user