29 #include "memory/allocation.hpp" |
29 #include "memory/allocation.hpp" |
30 #include "oops/array.hpp" |
30 #include "oops/array.hpp" |
31 #include "oops/oopHandle.hpp" |
31 #include "oops/oopHandle.hpp" |
32 #include "runtime/orderAccess.hpp" |
32 #include "runtime/orderAccess.hpp" |
33 #include "utilities/align.hpp" |
33 #include "utilities/align.hpp" |
|
34 #include "utilities/constantTag.hpp" |
34 |
35 |
35 class PSPromotionManager; |
36 class PSPromotionManager; |
36 |
37 |
37 // The ConstantPoolCache is not a cache! It is the resolution table that the |
38 // The ConstantPoolCache is not a cache! It is the resolution table that the |
38 // interpreter uses to avoid going into the runtime and a way to access resolved |
39 // interpreter uses to avoid going into the runtime and a way to access resolved |
48 // -------------------------------- |
49 // -------------------------------- |
49 // _indices [ b2 | b1 | index ] index = constant_pool_index |
50 // _indices [ b2 | b1 | index ] index = constant_pool_index |
50 // _f1 [ entry specific ] metadata ptr (method or klass) |
51 // _f1 [ entry specific ] metadata ptr (method or klass) |
51 // _f2 [ entry specific ] vtable or res_ref index, or vfinal method ptr |
52 // _f2 [ entry specific ] vtable or res_ref index, or vfinal method ptr |
52 // _flags [tos|0|F=1|0|0|0|f|v|0 |0000|field_index] (for field entries) |
53 // _flags [tos|0|F=1|0|0|0|f|v|0 |0000|field_index] (for field entries) |
53 // bit length [ 4 |1| 1 |1|1|1|1|1|1 |-4--|----16-----] |
54 // bit length [ 4 |1| 1 |1|1|1|1|1|1 |1 |-3-|----16-----] |
54 // _flags [tos|0|F=0|M|A|I|f|0|vf|0000|00000|psize] (for method entries) |
55 // _flags [tos|0|F=0|M|A|I|f|0|vf|indy_rf|000|00000|psize] (for method entries) |
55 // bit length [ 4 |1| 1 |1|1|1|1|1|1 |-4--|--8--|--8--] |
56 // bit length [ 4 |1| 1 |1|1|1|1|1|1 |-4--|--8--|--8--] |
56 |
57 |
57 // -------------------------------- |
58 // -------------------------------- |
58 // |
59 // |
59 // with: |
60 // with: |
69 // A = call site has an appendix argument (loaded from resolved references) |
70 // A = call site has an appendix argument (loaded from resolved references) |
70 // I = interface call is forced virtual (must use a vtable index or vfinal) |
71 // I = interface call is forced virtual (must use a vtable index or vfinal) |
71 // f = field or method is final |
72 // f = field or method is final |
72 // v = field is volatile |
73 // v = field is volatile |
73 // vf = virtual but final (method entries only: is_vfinal()) |
74 // vf = virtual but final (method entries only: is_vfinal()) |
|
75 // indy_rf = call site specifier method resolution failed |
74 // |
76 // |
75 // The flags after TosState have the following interpretation: |
77 // The flags after TosState have the following interpretation: |
76 // bit 27: 0 for fields, 1 for methods |
78 // bit 27: 0 for fields, 1 for methods |
77 // f flag true if field is marked final |
79 // f flag true if field is marked final |
78 // v flag true if field is volatile (only for fields) |
80 // v flag true if field is volatile (only for fields) |
183 has_appendix_shift = 24, // (A) does the call site have an appendix argument? |
185 has_appendix_shift = 24, // (A) does the call site have an appendix argument? |
184 is_forced_virtual_shift = 23, // (I) is the interface reference forced to virtual mode? |
186 is_forced_virtual_shift = 23, // (I) is the interface reference forced to virtual mode? |
185 is_final_shift = 22, // (f) is the field or method final? |
187 is_final_shift = 22, // (f) is the field or method final? |
186 is_volatile_shift = 21, // (v) is the field volatile? |
188 is_volatile_shift = 21, // (v) is the field volatile? |
187 is_vfinal_shift = 20, // (vf) did the call resolve to a final method? |
189 is_vfinal_shift = 20, // (vf) did the call resolve to a final method? |
|
190 indy_resolution_failed_shift= 19, // (indy_rf) did call site specifier resolution fail ? |
188 // low order bits give field index (for FieldInfo) or method parameter size: |
191 // low order bits give field index (for FieldInfo) or method parameter size: |
189 field_index_bits = 16, |
192 field_index_bits = 16, |
190 field_index_mask = right_n_bits(field_index_bits), |
193 field_index_mask = right_n_bits(field_index_bits), |
191 parameter_size_bits = 8, // subset of field_index_mask, range is 0..255 |
194 parameter_size_bits = 8, // subset of field_index_mask, range is 0..255 |
192 parameter_size_mask = right_n_bits(parameter_size_bits), |
195 parameter_size_mask = right_n_bits(parameter_size_bits), |
279 const constantPoolHandle& cpool, // holding constant pool (required for locking) |
282 const constantPoolHandle& cpool, // holding constant pool (required for locking) |
280 Bytecodes::Code invoke_code, // _invokehandle or _invokedynamic |
283 Bytecodes::Code invoke_code, // _invokehandle or _invokedynamic |
281 const CallInfo &call_info // Call link information |
284 const CallInfo &call_info // Call link information |
282 ); |
285 ); |
283 |
286 |
|
287 // Return TRUE if resolution failed and this thread got to record the failure |
|
288 // status. Return FALSE if another thread succeeded or failed in resolving |
|
289 // the method and recorded the success or failure before this thread had a |
|
290 // chance to record its failure. |
|
291 bool save_and_throw_indy_exc(const constantPoolHandle& cpool, int cpool_index, |
|
292 int index, constantTag tag, TRAPS); |
|
293 |
284 // invokedynamic and invokehandle call sites have two entries in the |
294 // invokedynamic and invokehandle call sites have two entries in the |
285 // resolved references array: |
295 // resolved references array: |
286 // appendix (at index+0) |
296 // appendix (at index+0) |
287 // MethodType (at index+1) |
297 // MethodType (at index+1) |
288 enum { |
298 enum { |
340 // of _f1 must be ordered with the loads performed by |
350 // of _f1 must be ordered with the loads performed by |
341 // cache->main_entry_index(). |
351 // cache->main_entry_index(). |
342 bool is_f1_null() const { Metadata* f1 = f1_ord(); return f1 == NULL; } // classifies a CPC entry as unbound |
352 bool is_f1_null() const { Metadata* f1 = f1_ord(); return f1 == NULL; } // classifies a CPC entry as unbound |
343 int f2_as_index() const { assert(!is_vfinal(), ""); return (int) _f2; } |
353 int f2_as_index() const { assert(!is_vfinal(), ""); return (int) _f2; } |
344 Method* f2_as_vfinal_method() const { assert(is_vfinal(), ""); return (Method*)_f2; } |
354 Method* f2_as_vfinal_method() const { assert(is_vfinal(), ""); return (Method*)_f2; } |
|
355 intx flags_ord() const { return (intx)OrderAccess::load_acquire(&_flags); } |
345 int field_index() const { assert(is_field_entry(), ""); return (_flags & field_index_mask); } |
356 int field_index() const { assert(is_field_entry(), ""); return (_flags & field_index_mask); } |
346 int parameter_size() const { assert(is_method_entry(), ""); return (_flags & parameter_size_mask); } |
357 int parameter_size() const { assert(is_method_entry(), ""); return (_flags & parameter_size_mask); } |
347 bool is_volatile() const { return (_flags & (1 << is_volatile_shift)) != 0; } |
358 bool is_volatile() const { return (_flags & (1 << is_volatile_shift)) != 0; } |
348 bool is_final() const { return (_flags & (1 << is_final_shift)) != 0; } |
359 bool is_final() const { return (_flags & (1 << is_final_shift)) != 0; } |
349 bool is_forced_virtual() const { return (_flags & (1 << is_forced_virtual_shift)) != 0; } |
360 bool is_forced_virtual() const { return (_flags & (1 << is_forced_virtual_shift)) != 0; } |
350 bool is_vfinal() const { return (_flags & (1 << is_vfinal_shift)) != 0; } |
361 bool is_vfinal() const { return (_flags & (1 << is_vfinal_shift)) != 0; } |
|
362 bool indy_resolution_failed() const { intx flags = flags_ord(); return (flags & (1 << indy_resolution_failed_shift)) != 0; } |
351 bool has_appendix() const { return (!is_f1_null()) && (_flags & (1 << has_appendix_shift)) != 0; } |
363 bool has_appendix() const { return (!is_f1_null()) && (_flags & (1 << has_appendix_shift)) != 0; } |
352 bool has_method_type() const { return (!is_f1_null()) && (_flags & (1 << has_method_type_shift)) != 0; } |
364 bool has_method_type() const { return (!is_f1_null()) && (_flags & (1 << has_method_type_shift)) != 0; } |
353 bool is_method_entry() const { return (_flags & (1 << is_field_entry_shift)) == 0; } |
365 bool is_method_entry() const { return (_flags & (1 << is_field_entry_shift)) == 0; } |
354 bool is_field_entry() const { return (_flags & (1 << is_field_entry_shift)) != 0; } |
366 bool is_field_entry() const { return (_flags & (1 << is_field_entry_shift)) != 0; } |
355 bool is_long() const { return flag_state() == ltos; } |
367 bool is_long() const { return flag_state() == ltos; } |
356 bool is_double() const { return flag_state() == dtos; } |
368 bool is_double() const { return flag_state() == dtos; } |
357 TosState flag_state() const { assert((uint)number_of_states <= (uint)tos_state_mask+1, ""); |
369 TosState flag_state() const { assert((uint)number_of_states <= (uint)tos_state_mask+1, ""); |
358 return (TosState)((_flags >> tos_state_shift) & tos_state_mask); } |
370 return (TosState)((_flags >> tos_state_shift) & tos_state_mask); } |
|
371 void set_indy_resolution_failed(); |
359 |
372 |
360 // Code generation support |
373 // Code generation support |
361 static WordSize size() { |
374 static WordSize size() { |
362 return in_WordSize(align_up((int)sizeof(ConstantPoolCacheEntry), wordSize) / wordSize); |
375 return in_WordSize(align_up((int)sizeof(ConstantPoolCacheEntry), wordSize) / wordSize); |
363 } |
376 } |