1/*
2 * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
24#include "precompiled.hpp"
25#include "gc/z/zNMethodTableEntry.hpp"
26#include "gc/z/zNMethodTableIteration.hpp"
27#include "memory/iterator.hpp"
28#include "runtime/atomic.hpp"
29#include "utilities/debug.hpp"
30#include "utilities/globalDefinitions.hpp"
31
32ZNMethodTableIteration::ZNMethodTableIteration() :
33 _table(NULL),
34 _size(0),
35 _claimed(0) {}
36
37bool ZNMethodTableIteration::in_progress() const {
38 return _table != NULL;
39}
40
41void ZNMethodTableIteration::nmethods_do_begin(ZNMethodTableEntry* table, size_t size) {
42 assert(!in_progress(), "precondition");
43
44 _table = table;
45 _size = size;
46 _claimed = 0;
47}
48
49void ZNMethodTableIteration::nmethods_do_end() {
50 assert(_claimed >= _size, "Failed to claim all table entries");
51
52 // Finish iteration
53 _table = NULL;
54}
55
56void ZNMethodTableIteration::nmethods_do(NMethodClosure* cl) {
57 for (;;) {
58 // Claim table partition. Each partition is currently sized to span
59 // two cache lines. This number is just a guess, but seems to work well.
60 const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry);
61 const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _size);
62 const size_t partition_end = MIN2(partition_start + partition_size, _size);
63 if (partition_start == partition_end) {
64 // End of table
65 break;
66 }
67
68 // Process table partition
69 for (size_t i = partition_start; i < partition_end; i++) {
70 const ZNMethodTableEntry entry = _table[i];
71 if (entry.registered()) {
72 cl->do_nmethod(entry.method());
73 }
74 }
75 }
76}
77