IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
RuntimeByteCodePropertyJavaField.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2014 Jeroen Frijters
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24using System;
25
27
28#if IMPORTER || EXPORTER
29using IKVM.Reflection;
31
32using Type = IKVM.Reflection.Type;
33
34#else
35using System.Reflection;
36using System.Reflection.Emit;
37#endif
38
39#if IMPORTER
41#endif
42
43namespace IKVM.Runtime
44{
45
46#if EXPORTER == false
47
52 {
53
54 readonly RuntimeJavaMethod getter;
55 readonly RuntimeJavaMethod setter;
56 PropertyBuilder pb;
57
58 RuntimeJavaMethod GetMethod(string name, string sig, bool isstatic)
59 {
60 if (name != null)
61 {
62 var mw = DeclaringType.GetMethod(name, sig, false);
63 if (mw != null && mw.IsStatic == isstatic)
64 {
65 mw.IsPropertyAccessor = true;
66 return mw;
67 }
68
69 DeclaringType.ClassLoader.Diagnostics.GenericCompilerError($"Property '{Name}' accessor '{name}' not found in class '{DeclaringType.Name}'");
70 }
71
72 return null;
73 }
74
80 internal RuntimeByteCodePropertyJavaField(RuntimeJavaType declaringType, ClassFile.Field fld) :
81 base(declaringType, null, fld.Name, fld.Signature, new ExModifiers(fld.Modifiers, fld.IsInternal), null)
82 {
83 getter = GetMethod(fld.PropertyGetter, "()" + fld.Signature, fld.IsStatic);
84 setter = GetMethod(fld.PropertySetter, "(" + fld.Signature + ")V", fld.IsStatic);
85 }
86
87#if !IMPORTER && !FIRST_PASS
88
89 internal override void ResolveField()
90 {
91 getter?.ResolveMethod();
92 setter?.ResolveMethod();
93 }
94
95#endif
96
97 internal PropertyBuilder GetPropertyBuilder()
98 {
99 AssertLinked();
100 return pb;
101 }
102
103 internal void DoLink(TypeBuilder tb)
104 {
105 if (getter != null)
106 {
107 getter.Link();
108 }
109 if (setter != null)
110 {
111 setter.Link();
112 }
113 pb = tb.DefineProperty(this.Name, PropertyAttributes.None, this.FieldTypeWrapper.TypeAsSignatureType, Type.EmptyTypes);
114 if (getter != null)
115 {
116 pb.SetGetMethod((MethodBuilder)getter.GetMethod());
117 }
118 if (setter != null)
119 {
120 pb.SetSetMethod((MethodBuilder)setter.GetMethod());
121 }
122#if IMPORTER
123 DeclaringType.Context.AttributeHelper.SetModifiers(pb, this.Modifiers, this.IsInternal);
124#endif
125 }
126
127#if EMITTERS
128 protected override void EmitGetImpl(CodeEmitter ilgen)
129 {
130 if (getter == null)
131 {
132 EmitThrowNoSuchMethodErrorForGetter(ilgen, this.FieldTypeWrapper, this);
133 }
134 else if (getter.IsStatic)
135 {
136 getter.EmitCall(ilgen);
137 }
138 else
139 {
140 getter.EmitCallvirt(ilgen);
141 }
142 }
143
144 internal static void EmitThrowNoSuchMethodErrorForGetter(CodeEmitter ilgen, RuntimeJavaType type, RuntimeJavaMember member)
145 {
146#if IMPORTER
147 type.ClassLoader.Diagnostics.EmittedNoSuchMethodError("<unknown>", member.DeclaringType.Name + "." + member.Name + member.Signature);
148#endif
149 // HACK the branch around the throw is to keep the verifier happy
150 CodeEmitterLabel label = ilgen.DefineLabel();
151 ilgen.Emit(OpCodes.Ldc_I4_0);
152 ilgen.EmitBrtrue(label);
153 ilgen.EmitThrow("java.lang.NoSuchMethodError");
154 ilgen.MarkLabel(label);
155 if (!member.IsStatic)
156 {
157 ilgen.Emit(OpCodes.Pop);
158 }
159 ilgen.Emit(OpCodes.Ldloc, ilgen.DeclareLocal(type.TypeAsLocalOrStackType));
160 }
161
162 protected override void EmitSetImpl(CodeEmitter ilgen)
163 {
164 if (setter == null)
165 {
166 if (this.IsFinal)
167 {
168 ilgen.Emit(OpCodes.Pop);
169 if (!this.IsStatic)
170 {
171 ilgen.Emit(OpCodes.Pop);
172 }
173 }
174 else
175 {
176 EmitThrowNoSuchMethodErrorForSetter(ilgen, this);
177 }
178 }
179 else if (setter.IsStatic)
180 {
181 setter.EmitCall(ilgen);
182 }
183 else
184 {
185 setter.EmitCallvirt(ilgen);
186 }
187 }
188
189 internal static void EmitThrowNoSuchMethodErrorForSetter(CodeEmitter ilgen, RuntimeJavaMember member)
190 {
191#if IMPORTER
192 member.DeclaringType.ClassLoader.Diagnostics.EmittedNoSuchMethodError("<unknown>", member.DeclaringType.Name + "." + member.Name + member.Signature);
193#endif
194 // HACK the branch around the throw is to keep the verifier happy
195 CodeEmitterLabel label = ilgen.DefineLabel();
196 ilgen.Emit(OpCodes.Ldc_I4_0);
197 ilgen.EmitBrtrue(label);
198 ilgen.EmitThrow("java.lang.NoSuchMethodError");
199 ilgen.MarkLabel(label);
200 ilgen.Emit(OpCodes.Pop);
201 if (!member.IsStatic)
202 {
203 ilgen.Emit(OpCodes.Pop);
204 }
205 }
206#endif
207
208#if !IMPORTER && !FIRST_PASS
209 internal override object GetValue(object obj)
210 {
211 if (getter == null)
212 {
213 throw new java.lang.NoSuchMethodError();
214 }
215 return getter.Invoke(obj, new object[0]);
216 }
217
218 internal override void SetValue(object obj, object value)
219 {
220 if (setter == null)
221 {
222 throw new java.lang.NoSuchMethodError();
223 }
224 setter.Invoke(obj, new object[] { value });
225 }
226#endif
227
228 }
229
230#endif
231
232}
IKVM.Reflection.Type Type
global::java.lang.invoke.LambdaForm.Name Name
Represents a .NET property defined in Java with the ikvm.lang.Property annotation.
virtual IDiagnosticHandler Diagnostics
Gets the IDiagnosticHandler events originated by this class loader should be sent to.
AttributeHelper AttributeHelper
Gets the AttributeHelper associated with this instance of the runtime.
void EmittedNoSuchMethodError(string arg0, string arg1)
The 'EmittedNoSuchMethodError' diagnostic.
void GenericCompilerError(string arg0)
The 'GenericCompilerError' diagnostic.