21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import sun.invoke.util.Wrapper;
29
30 import java.lang.ref.SoftReference;
31 import java.util.Arrays;
32 import java.util.Comparator;
33 import java.util.TreeMap;
34 import java.util.concurrent.ConcurrentHashMap;
35
36 import static java.lang.invoke.LambdaForm.*;
37 import static java.lang.invoke.LambdaForm.BasicType.*;
38 import static java.lang.invoke.MethodHandleImpl.Intrinsic;
39 import static java.lang.invoke.MethodHandleImpl.NF_loop;
40 import static java.lang.invoke.MethodHandleImpl.makeIntrinsic;
41
42 /** Transforms on LFs.
43 * A lambda-form editor can derive new LFs from its base LF.
44 * The editor can cache derived LFs, which simplifies the reuse of their underlying bytecodes.
45 * To support this caching, a LF has an optional pointer to its editor.
46 */
47 class LambdaFormEditor {
48 final LambdaForm lambdaForm;
49
50 private LambdaFormEditor(LambdaForm lambdaForm) {
51 this.lambdaForm = lambdaForm;
52 }
53
54 // Factory method.
55 static LambdaFormEditor lambdaFormEditor(LambdaForm lambdaForm) {
56 // TO DO: Consider placing intern logic here, to cut down on duplication.
57 // lambdaForm = findPreexistingEquivalent(lambdaForm)
58
59 // Always use uncustomized version for editing.
60 // It helps caching and customized LambdaForms reuse transformCache field to keep a link to uncustomized version.
72 FILTER_RETURN = 6,
73 COLLECT_ARGS = 7,
74 COLLECT_ARGS_TO_VOID = 8,
75 REPEAT_FILTER_ARGS = 9,
76 FOLD_ARGS = 10,
77 FOLD_ARGS_TO_VOID = 11,
78 PERMUTE_ARGS = 12,
79 LOCAL_TYPES = 13,
80 FILTER_SELECT_ARGS = 14,
81 FOLD_SELECT_ARGS = 15;
82
83 /**
84 * A description of a cached transform, possibly associated with the result of the transform.
85 * The logical content is a sequence of byte values, starting with a kind value.
86 * The sequence is unterminated, ending with an indefinite number of zero bytes.
87 * Sequences that are simple (short enough and with small enough values) pack into a 64-bit long.
88 *
89 * Tightly coupled with the TransformKey class, which is used to lookup existing
90 * Transforms.
91 */
92 private static final class Transform extends SoftReference<LambdaForm> {
93 final long packedBytes;
94 final byte[] fullBytes;
95
96 private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) {
97 super(result);
98 this.packedBytes = packedBytes;
99 this.fullBytes = fullBytes;
100 }
101
102 @Override
103 public boolean equals(Object obj) {
104 if (obj instanceof TransformKey key) {
105 return equals(key);
106 }
107 return obj instanceof Transform transform && equals(transform);
108 }
109
110 private boolean equals(TransformKey that) {
111 return this.packedBytes == that.packedBytes && Arrays.equals(this.fullBytes, that.fullBytes);
112 }
113
114 private boolean equals(Transform that) {
115 return this.packedBytes == that.packedBytes && Arrays.equals(this.fullBytes, that.fullBytes);
116 }
117
118 @Override
119 public int hashCode() {
120 if (packedBytes != 0) {
121 assert(fullBytes == null);
122 return Long.hashCode(packedBytes);
123 }
124 return Arrays.hashCode(fullBytes);
125 }
126
127 @Override
128 public String toString() {
129 StringBuilder buf = new StringBuilder();
130 buf.append(new TransformKey(packedBytes, fullBytes).toString());
131 LambdaForm result = get();
132 if (result != null) {
133 buf.append(" result=");
134 buf.append(result);
135 }
136 return buf.toString();
137 }
138 }
139
140 /**
141 * Used as a lookup key to find existing Transforms
142 */
143 private static final class TransformKey {
144 final long packedBytes;
145 final byte[] fullBytes;
146
147 private TransformKey(long packedBytes) {
148 this.packedBytes = packedBytes;
149 this.fullBytes = null;
150 }
151
152 private TransformKey(byte[] fullBytes) {
153 assert(packedBytes(fullBytes) == 0);
154 this.fullBytes = fullBytes;
155 this.packedBytes = 0;
156 }
157
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import sun.invoke.util.Wrapper;
29
30 import java.lang.ref.SoftReference;
31 import java.util.Arrays;
32 import java.util.Comparator;
33 import java.util.TreeMap;
34 import java.util.concurrent.ConcurrentHashMap;
35
36 import static java.lang.invoke.LambdaForm.*;
37 import static java.lang.invoke.LambdaForm.BasicType.*;
38 import static java.lang.invoke.MethodHandleImpl.Intrinsic;
39 import static java.lang.invoke.MethodHandleImpl.NF_loop;
40 import static java.lang.invoke.MethodHandleImpl.makeIntrinsic;
41 import static java.lang.invoke.MethodHandleStatics.NO_SOFT_CACHE;
42
43 /** Transforms on LFs.
44 * A lambda-form editor can derive new LFs from its base LF.
45 * The editor can cache derived LFs, which simplifies the reuse of their underlying bytecodes.
46 * To support this caching, a LF has an optional pointer to its editor.
47 */
48 class LambdaFormEditor {
49 final LambdaForm lambdaForm;
50
51 private LambdaFormEditor(LambdaForm lambdaForm) {
52 this.lambdaForm = lambdaForm;
53 }
54
55 // Factory method.
56 static LambdaFormEditor lambdaFormEditor(LambdaForm lambdaForm) {
57 // TO DO: Consider placing intern logic here, to cut down on duplication.
58 // lambdaForm = findPreexistingEquivalent(lambdaForm)
59
60 // Always use uncustomized version for editing.
61 // It helps caching and customized LambdaForms reuse transformCache field to keep a link to uncustomized version.
73 FILTER_RETURN = 6,
74 COLLECT_ARGS = 7,
75 COLLECT_ARGS_TO_VOID = 8,
76 REPEAT_FILTER_ARGS = 9,
77 FOLD_ARGS = 10,
78 FOLD_ARGS_TO_VOID = 11,
79 PERMUTE_ARGS = 12,
80 LOCAL_TYPES = 13,
81 FILTER_SELECT_ARGS = 14,
82 FOLD_SELECT_ARGS = 15;
83
84 /**
85 * A description of a cached transform, possibly associated with the result of the transform.
86 * The logical content is a sequence of byte values, starting with a kind value.
87 * The sequence is unterminated, ending with an indefinite number of zero bytes.
88 * Sequences that are simple (short enough and with small enough values) pack into a 64-bit long.
89 *
90 * Tightly coupled with the TransformKey class, which is used to lookup existing
91 * Transforms.
92 */
93 private static final class Transform {
94 final Object cache;
95 final long packedBytes;
96 final byte[] fullBytes;
97
98 private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) {
99 if (NO_SOFT_CACHE) {
100 cache = result;
101 } else {
102 cache = new SoftReference<LambdaForm>(result);
103 }
104 this.packedBytes = packedBytes;
105 this.fullBytes = fullBytes;
106 }
107
108 @Override
109 public boolean equals(Object obj) {
110 if (obj instanceof TransformKey key) {
111 return equals(key);
112 }
113 return obj instanceof Transform transform && equals(transform);
114 }
115
116 private boolean equals(TransformKey that) {
117 return this.packedBytes == that.packedBytes && Arrays.equals(this.fullBytes, that.fullBytes);
118 }
119
120 private boolean equals(Transform that) {
121 return this.packedBytes == that.packedBytes && Arrays.equals(this.fullBytes, that.fullBytes);
122 }
123
124 @Override
125 public int hashCode() {
126 if (packedBytes != 0) {
127 assert(fullBytes == null);
128 return Long.hashCode(packedBytes);
129 }
130 return Arrays.hashCode(fullBytes);
131 }
132
133 @Override
134 public String toString() {
135 StringBuilder buf = new StringBuilder();
136 buf.append(new TransformKey(packedBytes, fullBytes).toString());
137 LambdaForm result = get();
138 if (result != null) {
139 buf.append(" result=");
140 buf.append(result);
141 }
142 return buf.toString();
143 }
144
145 @SuppressWarnings({"rawtypes", "unchecked"})
146 public LambdaForm get() {
147 if (cache instanceof LambdaForm) {
148 return (LambdaForm)cache;
149 } else {
150 return ((SoftReference<LambdaForm>)cache).get();
151 }
152 }
153 }
154
155 /**
156 * Used as a lookup key to find existing Transforms
157 */
158 private static final class TransformKey {
159 final long packedBytes;
160 final byte[] fullBytes;
161
162 private TransformKey(long packedBytes) {
163 this.packedBytes = packedBytes;
164 this.fullBytes = null;
165 }
166
167 private TransformKey(byte[] fullBytes) {
168 assert(packedBytes(fullBytes) == 0);
169 this.fullBytes = fullBytes;
170 this.packedBytes = 0;
171 }
172
|