IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
ConstantTable.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2009-2012 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;
25using System.Collections.Generic;
26using System.Diagnostics;
27using System.Reflection.Metadata;
28using System.Reflection.Metadata.Ecma335;
29
31
33{
34
35 sealed class ConstantTable : SortedTable<ConstantTable.Record>
36 {
37
38 internal struct Record : IRecord
39 {
40
41 internal short Type;
42 internal int Parent;
43 internal BlobHandle Offset;
44 internal object Value;
45
46 readonly int IRecord.FilterKey => Parent;
47
48 public readonly int CompareTo(Record other) => Comparer<int>.Default.Compare(EncodeHasConstant(Parent), EncodeHasConstant(other.Parent));
49
50 }
51
52 internal const int Index = 0x0B;
53
54 internal override void Read(IKVM.Reflection.Reader.MetadataReader mr)
55 {
56 for (int i = 0; i < records.Length; i++)
57 {
58 records[i].Type = mr.ReadInt16();
59 records[i].Parent = mr.ReadHasConstant();
60 records[i].Offset = MetadataTokens.BlobHandle(mr.ReadBlobIndex());
61 }
62 }
63
64 internal override void Write(ModuleBuilder module)
65 {
66 for (int i = 0; i < rowCount; i++)
67 {
68 // check that blob handle ends up the same
69 var b = module.Metadata.GetOrAddConstantBlob(records[i].Value);
70 Debug.Assert(b == records[i].Offset);
71
72 // insert constant, and allow reencoding; should use same blob
73 var h = module.Metadata.AddConstant(MetadataTokens.EntityHandle(records[i].Parent), records[i].Value);
74 Debug.Assert(h == MetadataTokens.ConstantHandle(i + 1));
75 }
76 }
77
78 internal void Fixup(ModuleBuilder module)
79 {
80 for (int i = 0; i < rowCount; i++)
81 module.FixupPseudoToken(ref records[i].Parent);
82
83 Sort();
84 }
85
86 internal static int EncodeHasConstant(int token) => (token >> 24) switch
87 {
88 FieldTable.Index => (token & 0xFFFFFF) << 2 | 0,
89 ParamTable.Index => (token & 0xFFFFFF) << 2 | 1,
90 PropertyTable.Index => (token & 0xFFFFFF) << 2 | 2,
91 _ => throw new InvalidOperationException(),
92 };
93
94 internal object GetRawConstantValue(Module module, int parent)
95 {
96 foreach (var i in Filter(parent))
97 {
98 var br = module.GetBlobReader(module.ConstantTable.records[i].Offset);
99
100 switch (module.ConstantTable.records[i].Type)
101 {
102 // see ModuleBuilder.AddConstant for the encodings
103 case Signature.ELEMENT_TYPE_BOOLEAN:
104 return br.ReadByte() != 0;
105 case Signature.ELEMENT_TYPE_I1:
106 return br.ReadSByte();
107 case Signature.ELEMENT_TYPE_I2:
108 return br.ReadInt16();
109 case Signature.ELEMENT_TYPE_I4:
110 return br.ReadInt32();
111 case Signature.ELEMENT_TYPE_I8:
112 return br.ReadInt64();
113 case Signature.ELEMENT_TYPE_U1:
114 return br.ReadByte();
115 case Signature.ELEMENT_TYPE_U2:
116 return br.ReadUInt16();
117 case Signature.ELEMENT_TYPE_U4:
118 return br.ReadUInt32();
119 case Signature.ELEMENT_TYPE_U8:
120 return br.ReadUInt64();
121 case Signature.ELEMENT_TYPE_R4:
122 return br.ReadSingle();
123 case Signature.ELEMENT_TYPE_R8:
124 return br.ReadDouble();
125 case Signature.ELEMENT_TYPE_CHAR:
126 return br.ReadChar();
127 case Signature.ELEMENT_TYPE_STRING:
128 {
129 var chars = new char[br.Length / 2];
130 for (int j = 0; j < chars.Length; j++)
131 chars[j] = br.ReadChar();
132
133 return new string(chars);
134 }
135 case Signature.ELEMENT_TYPE_CLASS:
136 if (br.ReadInt32() != 0)
137 throw new BadImageFormatException();
138
139 return null;
140 default:
141 throw new BadImageFormatException();
142 }
143 }
144
145 throw new InvalidOperationException();
146 }
147
148 }
149
150}