33 #include "oops/oop.inline.hpp"
34 #include "runtime/atomic.hpp"
35 #include "utilities/debug.hpp"
36
37 class ZNMethodWithImmediateOops {
38 private:
39 nmethod* const _nm;
40 const size_t _nimmediate_oops;
41
42 static size_t header_size();
43
44 ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops);
45
46 public:
47 static ZNMethodWithImmediateOops* create(nmethod* nm, const GrowableArray<oop*>& immediate_oops);
48 static void destroy(ZNMethodWithImmediateOops* nmi);
49
50 nmethod* method() const;
51 size_t immediate_oops_count() const;
52 oop** immediate_oops_begin() const;
53 oop** immediate_oops_begin_safe() const;
54 oop** immediate_oops_end() const;
55 };
56
57 size_t ZNMethodWithImmediateOops::header_size() {
58 const size_t size = sizeof(ZNMethodWithImmediateOops);
59 assert(is_aligned(size, sizeof(oop*)), "Header misaligned");
60 return size;
61 }
62
63 ZNMethodWithImmediateOops::ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops) :
64 _nm(nm),
65 _nimmediate_oops(immediate_oops.length()) {
66 // Save all immediate oops
67 for (size_t i = 0; i < _nimmediate_oops; i++) {
68 immediate_oops_begin()[i] = immediate_oops.at(i);
69 }
70 }
71
72 ZNMethodWithImmediateOops* ZNMethodWithImmediateOops::create(nmethod* nm, const GrowableArray<oop*>& immediate_oops) {
|
33 #include "oops/oop.inline.hpp"
34 #include "runtime/atomic.hpp"
35 #include "utilities/debug.hpp"
36
37 class ZNMethodWithImmediateOops {
38 private:
39 nmethod* const _nm;
40 const size_t _nimmediate_oops;
41
42 static size_t header_size();
43
44 ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops);
45
46 public:
47 static ZNMethodWithImmediateOops* create(nmethod* nm, const GrowableArray<oop*>& immediate_oops);
48 static void destroy(ZNMethodWithImmediateOops* nmi);
49
50 nmethod* method() const;
51 size_t immediate_oops_count() const;
52 oop** immediate_oops_begin() const;
53 oop** immediate_oops_end() const;
54 };
55
56 size_t ZNMethodWithImmediateOops::header_size() {
57 const size_t size = sizeof(ZNMethodWithImmediateOops);
58 assert(is_aligned(size, sizeof(oop*)), "Header misaligned");
59 return size;
60 }
61
62 ZNMethodWithImmediateOops::ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops) :
63 _nm(nm),
64 _nimmediate_oops(immediate_oops.length()) {
65 // Save all immediate oops
66 for (size_t i = 0; i < _nimmediate_oops; i++) {
67 immediate_oops_begin()[i] = immediate_oops.at(i);
68 }
69 }
70
71 ZNMethodWithImmediateOops* ZNMethodWithImmediateOops::create(nmethod* nm, const GrowableArray<oop*>& immediate_oops) {
|
77 return ::new (method_with_immediate_oops) ZNMethodWithImmediateOops(nm, immediate_oops);
78 }
79
80 void ZNMethodWithImmediateOops::destroy(ZNMethodWithImmediateOops* nmi) {
81 FREE_C_HEAP_ARRAY(uint8_t, nmi);
82 }
83
84 nmethod* ZNMethodWithImmediateOops::method() const {
85 return _nm;
86 }
87
88 size_t ZNMethodWithImmediateOops::immediate_oops_count() const {
89 return _nimmediate_oops;
90 }
91
92 oop** ZNMethodWithImmediateOops::immediate_oops_begin() const {
93 // The immediate oop* array starts immediately after this object
94 return (oop**)((uintptr_t)this + header_size());
95 }
96
97 oop** ZNMethodWithImmediateOops::immediate_oops_begin_safe() const {
98 // Non-entrant nmethods have a jump instruction patched into the beginning
99 // of the verified entry point, which could have overwritten an immediate
100 // oop. If so, make sure we skip over that oop.
101 if (_nm->is_not_entrant()) {
102 oop* const first_immediate_oop = *immediate_oops_begin();
103 oop* const safe_begin = (oop*)(_nm->verified_entry_point() + NativeJump::instruction_size);
104 if (first_immediate_oop < safe_begin) {
105 // First immediate oop overwritten, skip it
106 return immediate_oops_begin() + 1;
107 }
108 }
109
110 // First immediate oop not overwritten
111 return immediate_oops_begin();
112 }
113
114
115 oop** ZNMethodWithImmediateOops::immediate_oops_end() const {
116 return immediate_oops_begin() + immediate_oops_count();
117 }
118
119 ZNMethodTableEntry* ZNMethodTable::_table = NULL;
120 size_t ZNMethodTable::_size = 0;
121 size_t ZNMethodTable::_nregistered = 0;
122 size_t ZNMethodTable::_nunregistered = 0;
123 volatile size_t ZNMethodTable::_claimed = 0;
124
125 ZNMethodTableEntry ZNMethodTable::create_entry(nmethod* nm) {
126 GrowableArray<oop*> immediate_oops;
127 bool non_immediate_oops = false;
128
129 // Find all oops relocations
130 RelocIterator iter(nm);
131 while (iter.next()) {
132 if (iter.type() != relocInfo::oop_type) {
133 // Not an oop
|
76 return ::new (method_with_immediate_oops) ZNMethodWithImmediateOops(nm, immediate_oops);
77 }
78
79 void ZNMethodWithImmediateOops::destroy(ZNMethodWithImmediateOops* nmi) {
80 FREE_C_HEAP_ARRAY(uint8_t, nmi);
81 }
82
83 nmethod* ZNMethodWithImmediateOops::method() const {
84 return _nm;
85 }
86
87 size_t ZNMethodWithImmediateOops::immediate_oops_count() const {
88 return _nimmediate_oops;
89 }
90
91 oop** ZNMethodWithImmediateOops::immediate_oops_begin() const {
92 // The immediate oop* array starts immediately after this object
93 return (oop**)((uintptr_t)this + header_size());
94 }
95
96 oop** ZNMethodWithImmediateOops::immediate_oops_end() const {
97 return immediate_oops_begin() + immediate_oops_count();
98 }
99
100 ZNMethodTableEntry* ZNMethodTable::_table = NULL;
101 size_t ZNMethodTable::_size = 0;
102 size_t ZNMethodTable::_nregistered = 0;
103 size_t ZNMethodTable::_nunregistered = 0;
104 volatile size_t ZNMethodTable::_claimed = 0;
105
106 ZNMethodTableEntry ZNMethodTable::create_entry(nmethod* nm) {
107 GrowableArray<oop*> immediate_oops;
108 bool non_immediate_oops = false;
109
110 // Find all oops relocations
111 RelocIterator iter(nm);
112 while (iter.next()) {
113 if (iter.type() != relocInfo::oop_type) {
114 // Not an oop
|
411
412 void ZNMethodTable::entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl) {
413 nmethod* const nm = method(entry);
414 if (!nm->is_alive()) {
415 // No need to visit oops
416 return;
417 }
418
419 // Process oops table
420 oop* const begin = nm->oops_begin();
421 oop* const end = nm->oops_end();
422 for (oop* p = begin; p < end; p++) {
423 if (*p != Universe::non_oop_word()) {
424 cl->do_oop(p);
425 }
426 }
427
428 if (entry.immediate_oops()) {
429 // Process immediate oops
430 const ZNMethodWithImmediateOops* const nmi = entry.method_with_immediate_oops();
431 oop** const begin = nmi->immediate_oops_begin_safe();
432 oop** const end = nmi->immediate_oops_end();
433 for (oop** p = begin; p < end; p++) {
434 cl->do_oop(*p);
435 }
436 }
437
438 if (entry.non_immediate_oops()) {
439 // Process non-immediate oops
440 nm->fix_oop_relocations();
441 }
442 }
443
444 void ZNMethodTable::oops_do(OopClosure* cl) {
445 for (;;) {
446 // Claim table partition. Each partition is currently sized to span
447 // two cache lines. This number is just a guess, but seems to work well.
448 const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry);
449 const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _size);
450 const size_t partition_end = MIN2(partition_start + partition_size, _size);
|
392
393 void ZNMethodTable::entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl) {
394 nmethod* const nm = method(entry);
395 if (!nm->is_alive()) {
396 // No need to visit oops
397 return;
398 }
399
400 // Process oops table
401 oop* const begin = nm->oops_begin();
402 oop* const end = nm->oops_end();
403 for (oop* p = begin; p < end; p++) {
404 if (*p != Universe::non_oop_word()) {
405 cl->do_oop(p);
406 }
407 }
408
409 if (entry.immediate_oops()) {
410 // Process immediate oops
411 const ZNMethodWithImmediateOops* const nmi = entry.method_with_immediate_oops();
412 oop** const begin = nmi->immediate_oops_begin();
413 oop** const end = nmi->immediate_oops_end();
414 for (oop** p = begin; p < end; p++) {
415 cl->do_oop(*p);
416 }
417 }
418
419 if (entry.non_immediate_oops()) {
420 // Process non-immediate oops
421 nm->fix_oop_relocations();
422 }
423 }
424
425 void ZNMethodTable::oops_do(OopClosure* cl) {
426 for (;;) {
427 // Claim table partition. Each partition is currently sized to span
428 // two cache lines. This number is just a guess, but seems to work well.
429 const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry);
430 const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _size);
431 const size_t partition_end = MIN2(partition_start + partition_size, _size);
|