Skip to content

Commit 29f4095

Browse files
committed
[generator] Cache static final field values.
1 parent 51b784a commit 29f4095

File tree

4 files changed

+42
-10
lines changed

4 files changed

+42
-10
lines changed

src/Xamarin.SourceWriter/Models/TypeReferenceWriter.cs

+9-4
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,17 @@ public TypeReferenceWriter (string ns, string name)
4040

4141
public virtual void WriteTypeReference (CodeWriter writer)
4242
{
43-
if (Namespace.HasValue ())
44-
writer.Write ($"{Namespace}.{Name}{NullableOperator} ");
45-
else
46-
writer.Write ($"{Name}{NullableOperator} ");
43+
writer.Write ($"{ToString ()} ");
4744
}
4845

4946
string NullableOperator => Nullable ? "?" : string.Empty;
47+
48+
public override string ToString ()
49+
{
50+
if (Namespace.HasValue ())
51+
return $"{Namespace}.{Name}{NullableOperator}";
52+
53+
return $"{Name}{NullableOperator}";
54+
}
5055
}
5156
}

tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public class Field : ApiVersionsSupport.IApiAvailability, ISourceLineInfo
4242

4343
public bool NeedsProperty => !IsStatic || !IsFinal || string.IsNullOrEmpty (Value) || Symbol.IsArray || !primitive_types.Contains (Symbol.JavaName);
4444

45+
public string CachedMemberName => $"_{Name}_cache";
46+
4547
public bool Validate (CodeGenerationOptions opt, GenericParameterDefinitionList type_params, CodeGeneratorContext context)
4648
{
4749
Symbol = opt.SymbolTable.Lookup (TypeName, type_params);

tools/generator/SourceWriters/BoundFieldAsProperty.cs

+30-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class BoundFieldAsProperty : PropertyWriter
1616
{
1717
readonly Field field;
1818
readonly CodeGenerationOptions opt;
19+
readonly FieldWriter? cached_field;
1920

2021
public BoundFieldAsProperty (GenBase type, Field field, CodeGenerationOptions opt)
2122
{
@@ -59,10 +60,23 @@ public BoundFieldAsProperty (GenBase type, Field field, CodeGenerationOptions op
5960

6061
if (!field.IsConst)
6162
HasSet = true;
63+
64+
// This is considerably harder to support if we don't have NRT, due to the
65+
// differences in handling nullable value and reference types.
66+
if (field.IsConst && opt.SupportNullableReferenceTypes)
67+
cached_field = new FieldWriter {
68+
Name = field.CachedMemberName,
69+
Type = new TypeReferenceWriter (fieldType.TrimEnd ('?')) { Nullable = true },
70+
IsStatic = true,
71+
IsPrivate = true,
72+
UseExplicitPrivateKeyword = type is InterfaceGen,
73+
};
6274
}
6375

6476
public override void Write (CodeWriter writer)
6577
{
78+
cached_field?.Write (writer);
79+
6680
// This is just a temporary hack to write the [GeneratedEnum] attribute before the // Metadata.xml
6781
// comment so that we are 100% equal to pre-refactor.
6882
var generated_attr = Attributes.OfType<GeneratedEnumAttr> ().FirstOrDefault ();
@@ -82,6 +96,13 @@ public override void WriteAttributes (CodeWriter writer)
8296

8397
protected override void WriteGetterBody (CodeWriter writer)
8498
{
99+
var cached_field_type = cached_field is not null ? new TypeReferenceWriter (cached_field.Type.Namespace, cached_field.Type.Name) : null;
100+
101+
if (cached_field is not null) {
102+
writer.WriteLine ($"if ({field.CachedMemberName} != null) return ({cached_field_type}){field.CachedMemberName};");
103+
writer.WriteLine ();
104+
}
105+
85106
writer.WriteLine ($"const string __id = \"{field.JavaName}.{field.Symbol.JniName}\";");
86107
writer.WriteLine ();
87108

@@ -93,24 +114,27 @@ protected override void WriteGetterBody (CodeWriter writer)
93114

94115
writer.WriteLine ($"var __v = {field.Symbol.ReturnCast}_members.{indirect}.{invoke} (__id{(field.IsStatic ? "" : ", this")});");
95116

117+
var cache_setter = cached_field is not null ? $"({PropertyType})({field.CachedMemberName} = " : "";
118+
var cache_setter_end = cached_field is not null ? ")" : "";
119+
96120
if (opt.CodeGenerationTarget == CodeGenerationTarget.JavaInterop1) {
97121
if (field.Symbol.NativeType == field.Symbol.FullName) {
98-
writer.WriteLine ("return __v;");
122+
writer.WriteLine ($"return {cache_setter}__v{cache_setter_end};");
99123
return;
100124
}
101-
writer.Write ("return global::Java.Interop.JniEnvironment.Runtime.ValueManager.GetValue<");
125+
writer.Write ($"return {cache_setter}global::Java.Interop.JniEnvironment.Runtime.ValueManager.GetValue<");
102126
PropertyType.WriteTypeReference (writer);
103127
writer.Write (">(ref __v, JniObjectReferenceOptions.Copy)");
104-
writer.WriteLine (";");
128+
writer.WriteLine ($"{cache_setter_end};");
105129
return;
106130
}
107131

108132
if (field.Symbol.IsArray) {
109-
writer.WriteLine ($"return global::Android.Runtime.JavaArray<{opt.GetOutputName (field.Symbol.ElementType)}>.FromJniHandle (__v.Handle, JniHandleOwnership.TransferLocalRef);");
133+
writer.WriteLine ($"return {cache_setter}global::Android.Runtime.JavaArray<{opt.GetOutputName (field.Symbol.ElementType)}>.FromJniHandle (__v.Handle, JniHandleOwnership.TransferLocalRef){cache_setter_end};");
110134
} else if (field.Symbol.NativeType != field.Symbol.FullName) {
111-
writer.WriteLine ($"return {field.Symbol.ReturnCast}{(field.Symbol.FromNative (opt, invokeType != "Object" ? "__v" : "__v.Handle", true) + opt.GetNullForgiveness (field))};");
135+
writer.WriteLine ($"return {cache_setter}{field.Symbol.ReturnCast}{(field.Symbol.FromNative (opt, invokeType != "Object" ? "__v" : "__v.Handle", true) + opt.GetNullForgiveness (field))}{cache_setter_end};");
112136
} else {
113-
writer.WriteLine ("return __v;");
137+
writer.WriteLine ($"return {cache_setter}__v{cache_setter_end};");
114138
}
115139
}
116140

tools/generator/generator.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<TargetFramework>$(DotNetTargetFramework)</TargetFramework>
55
<OutputType>Exe</OutputType>
66
<DefineConstants>$(DefineConstants);GENERATOR;HAVE_CECIL;JCW_ONLY_TYPE_NAMES</DefineConstants>
7+
<Nullable>annotations</Nullable>
78
</PropertyGroup>
89

910
<Import Project="..\..\TargetFrameworkDependentValues.props" />

0 commit comments

Comments
 (0)