53 // When CHECK_UNHANDLED_OOPS is defined, an "oop" is a class with a |
53 // When CHECK_UNHANDLED_OOPS is defined, an "oop" is a class with a |
54 // carefully chosen set of constructors and conversion operators to go |
54 // carefully chosen set of constructors and conversion operators to go |
55 // to and from the underlying oopDesc pointer type. |
55 // to and from the underlying oopDesc pointer type. |
56 // |
56 // |
57 // Because oop and its subclasses <type>Oop are class types, arbitrary |
57 // Because oop and its subclasses <type>Oop are class types, arbitrary |
58 // conversions are not accepted by the compiler, and you may get a message |
58 // conversions are not accepted by the compiler. Applying a cast to |
59 // about overloading ambiguity (between long and int is common when converting |
59 // an oop will cause the best matched conversion operator to be |
60 // from a constant in 64 bit mode), or unable to convert from type to 'oop'. |
60 // invoked returning the underlying oopDesc* type if appropriate. |
61 // Applying a cast to one of these conversion operators first will get to the |
61 // No copy constructors, explicit user conversions or operators of |
62 // underlying oopDesc* type if appropriate. |
62 // numerical type should be defined within the oop class. Most C++ |
|
63 // compilers will issue a compile time error concerning the overloading |
|
64 // ambiguity between operators of numerical and pointer types. If |
|
65 // a conversion to or from an oop to a numerical type is needed, |
|
66 // use the inline template methods, cast_*_oop, defined below. |
|
67 // |
63 // Converting NULL to oop to Handle implicit is no longer accepted by the |
68 // Converting NULL to oop to Handle implicit is no longer accepted by the |
64 // compiler because there are too many steps in the conversion. Use Handle() |
69 // compiler because there are too many steps in the conversion. Use Handle() |
65 // instead, which generates less code anyway. |
70 // instead, which generates less code anyway. |
66 |
71 |
67 class Thread; |
72 class Thread; |
81 if (CheckUnhandledOops) register_oop(); |
86 if (CheckUnhandledOops) register_oop(); |
82 } |
87 } |
83 void raw_set_obj(const void* p) { _o = (oopDesc*)p; } |
88 void raw_set_obj(const void* p) { _o = (oopDesc*)p; } |
84 |
89 |
85 oop() { set_obj(NULL); } |
90 oop() { set_obj(NULL); } |
|
91 oop(const oop& o) { set_obj(o.obj()); } |
86 oop(const volatile oop& o) { set_obj(o.obj()); } |
92 oop(const volatile oop& o) { set_obj(o.obj()); } |
87 oop(const void* p) { set_obj(p); } |
93 oop(const void* p) { set_obj(p); } |
88 oop(intptr_t i) { set_obj((void *)i); } |
|
89 #ifdef _LP64 |
|
90 oop(int i) { set_obj((void *)i); } |
|
91 #endif |
|
92 ~oop() { |
94 ~oop() { |
93 if (CheckUnhandledOops) unregister_oop(); |
95 if (CheckUnhandledOops) unregister_oop(); |
94 } |
96 } |
95 |
97 |
96 oopDesc* obj() const volatile { return _o; } |
98 oopDesc* obj() const volatile { return _o; } |
99 oopDesc* operator->() const { return obj(); } |
101 oopDesc* operator->() const { return obj(); } |
100 bool operator==(const oop o) const { return obj() == o.obj(); } |
102 bool operator==(const oop o) const { return obj() == o.obj(); } |
101 bool operator==(void *p) const { return obj() == p; } |
103 bool operator==(void *p) const { return obj() == p; } |
102 bool operator!=(const volatile oop o) const { return obj() != o.obj(); } |
104 bool operator!=(const volatile oop o) const { return obj() != o.obj(); } |
103 bool operator!=(void *p) const { return obj() != p; } |
105 bool operator!=(void *p) const { return obj() != p; } |
104 bool operator==(intptr_t p) const { return obj() == (oopDesc*)p; } |
|
105 bool operator!=(intptr_t p) const { return obj() != (oopDesc*)p; } |
|
106 |
106 |
107 bool operator<(oop o) const { return obj() < o.obj(); } |
107 bool operator<(oop o) const { return obj() < o.obj(); } |
108 bool operator>(oop o) const { return obj() > o.obj(); } |
108 bool operator>(oop o) const { return obj() > o.obj(); } |
109 bool operator<=(oop o) const { return obj() <= o.obj(); } |
109 bool operator<=(oop o) const { return obj() <= o.obj(); } |
110 bool operator>=(oop o) const { return obj() >= o.obj(); } |
110 bool operator>=(oop o) const { return obj() >= o.obj(); } |
111 bool operator!() const { return !obj(); } |
111 bool operator!() const { return !obj(); } |
112 |
112 |
113 // Cast |
113 // Assignment |
|
114 oop& operator=(const oop& o) { _o = o.obj(); return *this; } |
|
115 #ifndef SOLARIS |
|
116 volatile oop& operator=(const oop& o) volatile { _o = o.obj(); return *this; } |
|
117 #endif |
|
118 volatile oop& operator=(const volatile oop& o) volatile { _o = o.obj(); return *this; } |
|
119 |
|
120 // Explict user conversions |
114 operator void* () const { return (void *)obj(); } |
121 operator void* () const { return (void *)obj(); } |
|
122 #ifndef SOLARIS |
|
123 operator void* () const volatile { return (void *)obj(); } |
|
124 #endif |
115 operator HeapWord* () const { return (HeapWord*)obj(); } |
125 operator HeapWord* () const { return (HeapWord*)obj(); } |
116 operator oopDesc* () const { return obj(); } |
126 operator oopDesc* () const { return obj(); } |
117 operator intptr_t* () const { return (intptr_t*)obj(); } |
127 operator intptr_t* () const { return (intptr_t*)obj(); } |
118 operator PromotedObject* () const { return (PromotedObject*)obj(); } |
128 operator PromotedObject* () const { return (PromotedObject*)obj(); } |
119 operator markOop () const { return markOop(obj()); } |
129 operator markOop () const { return markOop(obj()); } |
120 |
130 |
121 operator address () const { return (address)obj(); } |
131 operator address () const { return (address)obj(); } |
122 operator intptr_t () const volatile { return (intptr_t)obj(); } |
|
123 |
132 |
124 // from javaCalls.cpp |
133 // from javaCalls.cpp |
125 operator jobject () const { return (jobject)obj(); } |
134 operator jobject () const { return (jobject)obj(); } |
126 // from javaClasses.cpp |
135 // from javaClasses.cpp |
127 operator JavaThread* () const { return (JavaThread*)obj(); } |
136 operator JavaThread* () const { return (JavaThread*)obj(); } |
139 #define DEF_OOP(type) \ |
148 #define DEF_OOP(type) \ |
140 class type##OopDesc; \ |
149 class type##OopDesc; \ |
141 class type##Oop : public oop { \ |
150 class type##Oop : public oop { \ |
142 public: \ |
151 public: \ |
143 type##Oop() : oop() {} \ |
152 type##Oop() : oop() {} \ |
|
153 type##Oop(const oop& o) : oop(o) {} \ |
144 type##Oop(const volatile oop& o) : oop(o) {} \ |
154 type##Oop(const volatile oop& o) : oop(o) {} \ |
145 type##Oop(const void* p) : oop(p) {} \ |
155 type##Oop(const void* p) : oop(p) {} \ |
146 operator type##OopDesc* () const { return (type##OopDesc*)obj(); } \ |
156 operator type##OopDesc* () const { return (type##OopDesc*)obj(); } \ |
147 type##OopDesc* operator->() const { \ |
157 type##OopDesc* operator->() const { \ |
148 return (type##OopDesc*)obj(); \ |
158 return (type##OopDesc*)obj(); \ |
149 } \ |
159 } \ |
|
160 type##Oop& operator=(const type##Oop& o) { \ |
|
161 oop::operator=(o); \ |
|
162 return *this; \ |
|
163 } \ |
|
164 NOT_SOLARIS( \ |
|
165 volatile type##Oop& operator=(const type##Oop& o) volatile { \ |
|
166 (void)const_cast<oop&>(oop::operator=(o)); \ |
|
167 return *this; \ |
|
168 }) \ |
|
169 volatile type##Oop& operator=(const volatile type##Oop& o) volatile {\ |
|
170 (void)const_cast<oop&>(oop::operator=(o)); \ |
|
171 return *this; \ |
|
172 } \ |
150 }; |
173 }; |
151 |
174 |
152 DEF_OOP(instance); |
175 DEF_OOP(instance); |
153 DEF_OOP(array); |
176 DEF_OOP(array); |
154 DEF_OOP(objArray); |
177 DEF_OOP(objArray); |
155 DEF_OOP(typeArray); |
178 DEF_OOP(typeArray); |
156 |
179 |
157 #endif // CHECK_UNHANDLED_OOPS |
180 #endif // CHECK_UNHANDLED_OOPS |
|
181 |
|
182 // For CHECK_UNHANDLED_OOPS, it is ambiguous C++ behavior to have the oop |
|
183 // structure contain explicit user defined conversions of both numerical |
|
184 // and pointer type. Define inline methods to provide the numerical conversions. |
|
185 template <class T> inline oop cast_to_oop(T value) { |
|
186 return (oop)(CHECK_UNHANDLED_OOPS_ONLY((void *))(value)); |
|
187 } |
|
188 template <class T> inline T cast_from_oop(oop o) { |
|
189 return (T)(CHECK_UNHANDLED_OOPS_ONLY((void*))o); |
|
190 } |
158 |
191 |
159 // The metadata hierarchy is separate from the oop hierarchy |
192 // The metadata hierarchy is separate from the oop hierarchy |
160 |
193 |
161 // class MetaspaceObj |
194 // class MetaspaceObj |
162 class ConstMethod; |
195 class ConstMethod; |