5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package jdk.vm.ci.meta;
24
25 import java.util.*;
26
27 /**
28 * Represents the type of values in the LIR. It is composed of a {@link PlatformKind} that gives the
29 * low level representation of the value, and a {@link #referenceMask} that describes the location
30 * of object references in the value, and optionally a {@link #derivedReferenceBase}.
31 *
32 * <h2>Constructing {@link LIRKind} instances</h2>
33 *
34 * During LIR generation, every new {@link Value} should get a {@link LIRKind} of the correct
35 * {@link PlatformKind} that also contains the correct reference information. {@linkplain LIRKind
36 * LIRKinds} should be created as follows:
37 *
38 * <p>
39 * If the result value is created from one or more input values, the {@link LIRKind} should be
40 * created with {@link LIRKind#combine}(inputs). If the result has a different {@link PlatformKind}
41 * than the inputs, {@link LIRKind#combine}(inputs).{@link #changeType}(resultKind) should be used.
42 * <p>
43 * If the result is an exact copy of one of the inputs, {@link Value#getLIRKind()} can be used. Note
44 * that this is only correct for move-like operations, like conditional move or compare-and-swap.
45 * For convert operations, {@link LIRKind#combine} should be used.
46 * <p>
47 * If it is known that the result will be a reference (e.g. pointer arithmetic where the end result
48 * is a valid oop), {@link LIRKind#reference} should be used.
49 * <p>
50 * If it is known that the result will neither be a reference nor be derived from a reference,
51 * {@link LIRKind#value} can be used. If the operation producing this value has inputs, this is very
52 * likely wrong, and {@link LIRKind#combine} should be used instead.
53 * <p>
54 * If it is known that the result is derived from a reference in a way that the garbage collector
55 * can not track, {@link LIRKind#unknownReference} can be used. In most cases,
56 * {@link LIRKind#combine} should be used instead, since it is able to detect this automatically.
57 */
58 public final class LIRKind {
59
60 /**
61 * The non-type. This uses {@link #unknownReference}, so it can never be part of an oop map.
62 */
63 public static final LIRKind Illegal = unknownReference(JavaKind.Illegal);
64
65 private final PlatformKind platformKind;
66 private final int referenceMask;
67
68 private AllocatableValue derivedReferenceBase;
69
70 private static final int UNKNOWN_REFERENCE = -1;
71
72 private LIRKind(PlatformKind platformKind, int referenceMask, AllocatableValue derivedReferenceBase) {
73 assert platformKind != JavaKind.Object : "Kind.Object shouldn't be used in the backend";
74 this.platformKind = platformKind;
75 this.referenceMask = referenceMask;
76 this.derivedReferenceBase = derivedReferenceBase;
77
78 assert derivedReferenceBase == null || !derivedReferenceBase.getLIRKind().isDerivedReference() : "derived reference can't have another derived reference as base";
79 }
80
81 /**
82 * Create a {@link LIRKind} of type {@code platformKind} that contains a primitive value. Should
83 * be only used when it's guaranteed that the value is not even indirectly derived from a
84 * reference. Otherwise, {@link #combine(Value...)} should be used instead.
85 */
86 public static LIRKind value(PlatformKind platformKind) {
87 return new LIRKind(platformKind, 0, null);
88 }
89
90 /**
91 * Create a {@link LIRKind} of type {@code platformKind} that contains a single tracked oop
92 * reference.
93 */
414 return result;
415 }
416
417 @Override
418 public boolean equals(Object obj) {
419 if (this == obj) {
420 return true;
421 }
422 if (!(obj instanceof LIRKind)) {
423 return false;
424 }
425
426 LIRKind other = (LIRKind) obj;
427 return platformKind == other.platformKind && referenceMask == other.referenceMask;
428 }
429
430 public static boolean verifyMoveKinds(LIRKind dst, LIRKind src) {
431 if (src.equals(dst)) {
432 return true;
433 }
434 /*
435 * TODO(je,rs) What we actually want is toStackKind(src.getPlatformKind()).equals(
436 * dst.getPlatformKind()) but due to the handling of sub-integer at the current point
437 * (phi-)moves from e.g. integer to short can happen. Therefore we compare stack kinds.
438 */
439 if (toStackKind(src.getPlatformKind()).equals(toStackKind(dst.getPlatformKind()))) {
440 return !src.isUnknownReference() || dst.isUnknownReference();
441 }
442 return false;
443 }
444
445 private static PlatformKind toStackKind(PlatformKind platformKind) {
446 if (platformKind instanceof JavaKind) {
447 return ((JavaKind) platformKind).getStackKind();
448 }
449 return platformKind;
450 }
451 }
|
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package jdk.vm.ci.meta;
24
25 import java.util.ArrayList;
26
27 /**
28 * Represents the type of values in the LIR. It is composed of a {@link PlatformKind} that gives the
29 * low level representation of the value, and a {@link #referenceMask} that describes the location
30 * of object references in the value, and optionally a {@link #derivedReferenceBase}.
31 *
32 * <h2>Constructing {@link LIRKind} instances</h2>
33 *
34 * During LIR generation, every new {@link Value} should get a {@link LIRKind} of the correct
35 * {@link PlatformKind} that also contains the correct reference information. {@linkplain LIRKind
36 * LIRKinds} should be created as follows:
37 *
38 * <p>
39 * If the result value is created from one or more input values, the {@link LIRKind} should be
40 * created with {@link LIRKind#combine}(inputs). If the result has a different {@link PlatformKind}
41 * than the inputs, {@link LIRKind#combine}(inputs).{@link #changeType}(resultKind) should be used.
42 * <p>
43 * If the result is an exact copy of one of the inputs, {@link Value#getLIRKind()} can be used. Note
44 * that this is only correct for move-like operations, like conditional move or compare-and-swap.
45 * For convert operations, {@link LIRKind#combine} should be used.
46 * <p>
47 * If it is known that the result will be a reference (e.g. pointer arithmetic where the end result
48 * is a valid oop), {@link LIRKind#reference} should be used.
49 * <p>
50 * If it is known that the result will neither be a reference nor be derived from a reference,
51 * {@link LIRKind#value} can be used. If the operation producing this value has inputs, this is very
52 * likely wrong, and {@link LIRKind#combine} should be used instead.
53 * <p>
54 * If it is known that the result is derived from a reference in a way that the garbage collector
55 * can not track, {@link LIRKind#unknownReference} can be used. In most cases,
56 * {@link LIRKind#combine} should be used instead, since it is able to detect this automatically.
57 */
58 public final class LIRKind {
59
60 private static enum IllegalKind implements PlatformKind {
61 ILLEGAL;
62
63 private final EnumKey<IllegalKind> key = new EnumKey<>(this);
64
65 public Key getKey() {
66 return key;
67 }
68
69 public int getSizeInBytes() {
70 return 0;
71 }
72
73 public int getVectorLength() {
74 return 0;
75 }
76
77 public char getTypeChar() {
78 return '-';
79 }
80 }
81
82 /**
83 * The non-type. This uses {@link #unknownReference}, so it can never be part of an oop map.
84 */
85 public static final LIRKind Illegal = unknownReference(IllegalKind.ILLEGAL);
86
87 private final PlatformKind platformKind;
88 private final int referenceMask;
89
90 private AllocatableValue derivedReferenceBase;
91
92 private static final int UNKNOWN_REFERENCE = -1;
93
94 private LIRKind(PlatformKind platformKind, int referenceMask, AllocatableValue derivedReferenceBase) {
95 this.platformKind = platformKind;
96 this.referenceMask = referenceMask;
97 this.derivedReferenceBase = derivedReferenceBase;
98
99 assert derivedReferenceBase == null || !derivedReferenceBase.getLIRKind().isDerivedReference() : "derived reference can't have another derived reference as base";
100 }
101
102 /**
103 * Create a {@link LIRKind} of type {@code platformKind} that contains a primitive value. Should
104 * be only used when it's guaranteed that the value is not even indirectly derived from a
105 * reference. Otherwise, {@link #combine(Value...)} should be used instead.
106 */
107 public static LIRKind value(PlatformKind platformKind) {
108 return new LIRKind(platformKind, 0, null);
109 }
110
111 /**
112 * Create a {@link LIRKind} of type {@code platformKind} that contains a single tracked oop
113 * reference.
114 */
435 return result;
436 }
437
438 @Override
439 public boolean equals(Object obj) {
440 if (this == obj) {
441 return true;
442 }
443 if (!(obj instanceof LIRKind)) {
444 return false;
445 }
446
447 LIRKind other = (LIRKind) obj;
448 return platformKind == other.platformKind && referenceMask == other.referenceMask;
449 }
450
451 public static boolean verifyMoveKinds(LIRKind dst, LIRKind src) {
452 if (src.equals(dst)) {
453 return true;
454 }
455 if (src.getPlatformKind().equals(dst.getPlatformKind())) {
456 return !src.isUnknownReference() || dst.isUnknownReference();
457 }
458 return false;
459 }
460 }
|