interfaceSupport.cpp revision 6646:b596a1063e90
1251881Speter/*
2251881Speter * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3251881Speter * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4251881Speter *
5251881Speter * This code is free software; you can redistribute it and/or modify it
6251881Speter * under the terms of the GNU General Public License version 2 only, as
7251881Speter * published by the Free Software Foundation.
8251881Speter *
9251881Speter * This code is distributed in the hope that it will be useful, but WITHOUT
10251881Speter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11251881Speter * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12251881Speter * version 2 for more details (a copy is included in the LICENSE file that
13251881Speter * accompanied this code).
14251881Speter *
15251881Speter * You should have received a copy of the GNU General Public License version
16251881Speter * 2 along with this work; if not, write to the Free Software Foundation,
17251881Speter * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18251881Speter *
19251881Speter * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20251881Speter * or visit www.oracle.com if you need additional information or have any
21251881Speter * questions.
22251881Speter *
23251881Speter */
24251881Speter
25251881Speter#include "precompiled.hpp"
26251881Speter#include "gc_implementation/shared/markSweep.hpp"
27251881Speter#include "gc_interface/collectedHeap.hpp"
28251881Speter#include "gc_interface/collectedHeap.inline.hpp"
29251881Speter#include "memory/genCollectedHeap.hpp"
30251881Speter#include "memory/resourceArea.hpp"
31251881Speter#include "runtime/atomic.inline.hpp"
32251881Speter#include "runtime/init.hpp"
33251881Speter#include "runtime/interfaceSupport.hpp"
34251881Speter#include "runtime/orderAccess.inline.hpp"
35251881Speter#include "runtime/threadLocalStorage.hpp"
36251881Speter#include "runtime/vframe.hpp"
37251881Speter#include "utilities/preserveException.hpp"
38251881Speter
39251881SpeterPRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
40251881Speter
41251881Speter// Implementation of InterfaceSupport
42251881Speter
43251881Speter#ifdef ASSERT
44251881Speter
45251881Speterlong InterfaceSupport::_number_of_calls       = 0;
46251881Speterlong InterfaceSupport::_scavenge_alot_counter = 1;
47251881Speterlong InterfaceSupport::_fullgc_alot_counter   = 1;
48251881Speterlong InterfaceSupport::_fullgc_alot_invocation = 0;
49251881Speter
50251881SpeterHistogram* RuntimeHistogram;
51251881Speter
52251881SpeterRuntimeHistogramElement::RuntimeHistogramElement(const char* elementName) {
53251881Speter  static volatile jint RuntimeHistogram_lock = 0;
54251881Speter  _name = elementName;
55251881Speter  uintx count = 0;
56251881Speter
57251881Speter  while (Atomic::cmpxchg(1, &RuntimeHistogram_lock, 0) != 0) {
58251881Speter    while (OrderAccess::load_acquire(&RuntimeHistogram_lock) != 0) {
59251881Speter      count +=1;
60251881Speter      if ( (WarnOnStalledSpinLock > 0)
61251881Speter        && (count % WarnOnStalledSpinLock == 0)) {
62251881Speter        warning("RuntimeHistogram_lock seems to be stalled");
63251881Speter      }
64251881Speter    }
65251881Speter  }
66251881Speter
67251881Speter  if (RuntimeHistogram == NULL) {
68251881Speter    RuntimeHistogram = new Histogram("VM Runtime Call Counts",200);
69251881Speter  }
70251881Speter
71251881Speter  RuntimeHistogram->add_element(this);
72251881Speter  Atomic::dec(&RuntimeHistogram_lock);
73251881Speter}
74251881Speter
75251881Spetervoid InterfaceSupport::trace(const char* result_type, const char* header) {
76251881Speter  tty->print_cr("%6d  %s", _number_of_calls, header);
77251881Speter}
78251881Speter
79251881Spetervoid InterfaceSupport::gc_alot() {
80251881Speter  Thread *thread = Thread::current();
81251881Speter  if (!thread->is_Java_thread()) return; // Avoid concurrent calls
82251881Speter  // Check for new, not quite initialized thread. A thread in new mode cannot initiate a GC.
83251881Speter  JavaThread *current_thread = (JavaThread *)thread;
84251881Speter  if (current_thread->active_handles() == NULL) return;
85251881Speter
86251881Speter  // Short-circuit any possible re-entrant gc-a-lot attempt
87251881Speter  if (thread->skip_gcalot()) return;
88251881Speter
89251881Speter  if (is_init_completed()) {
90251881Speter
91251881Speter    if (++_fullgc_alot_invocation < FullGCALotStart) {
92251881Speter      return;
93251881Speter    }
94251881Speter
95251881Speter    // Use this line if you want to block at a specific point,
96251881Speter    // e.g. one number_of_calls/scavenge/gc before you got into problems
97251881Speter    if (FullGCALot) _fullgc_alot_counter--;
98251881Speter
99251881Speter    // Check if we should force a full gc
100251881Speter    if (_fullgc_alot_counter == 0) {
101251881Speter      // Release dummy so objects are forced to move
102251881Speter      if (!Universe::release_fullgc_alot_dummy()) {
103251881Speter        warning("FullGCALot: Unable to release more dummies at bottom of heap");
104251881Speter      }
105251881Speter      HandleMark hm(thread);
106251881Speter      Universe::heap()->collect(GCCause::_full_gc_alot);
107251881Speter      unsigned int invocations = Universe::heap()->total_full_collections();
108251881Speter      // Compute new interval
109251881Speter      if (FullGCALotInterval > 1) {
110251881Speter        _fullgc_alot_counter = 1+(long)((double)FullGCALotInterval*os::random()/(max_jint+1.0));
111251881Speter        if (PrintGCDetails && Verbose) {
112251881Speter          tty->print_cr("Full gc no: %u\tInterval: %d", invocations,
113251881Speter                        _fullgc_alot_counter);
114251881Speter        }
115251881Speter      } else {
116251881Speter        _fullgc_alot_counter = 1;
117251881Speter      }
118251881Speter      // Print progress message
119251881Speter      if (invocations % 100 == 0) {
120251881Speter        if (PrintGCDetails && Verbose) tty->print_cr("Full gc no: %u", invocations);
121251881Speter      }
122251881Speter    } else {
123251881Speter      if (ScavengeALot) _scavenge_alot_counter--;
124251881Speter      // Check if we should force a scavenge
125251881Speter      if (_scavenge_alot_counter == 0) {
126251881Speter        HandleMark hm(thread);
127251881Speter        Universe::heap()->collect(GCCause::_scavenge_alot);
128251881Speter        unsigned int invocations = Universe::heap()->total_collections() - Universe::heap()->total_full_collections();
129251881Speter        // Compute new interval
130251881Speter        if (ScavengeALotInterval > 1) {
131251881Speter          _scavenge_alot_counter = 1+(long)((double)ScavengeALotInterval*os::random()/(max_jint+1.0));
132251881Speter          if (PrintGCDetails && Verbose) {
133251881Speter            tty->print_cr("Scavenge no: %u\tInterval: %d", invocations,
134251881Speter                          _scavenge_alot_counter);
135251881Speter          }
136251881Speter        } else {
137251881Speter          _scavenge_alot_counter = 1;
138251881Speter        }
139251881Speter        // Print progress message
140251881Speter        if (invocations % 1000 == 0) {
141251881Speter          if (PrintGCDetails && Verbose) tty->print_cr("Scavenge no: %u", invocations);
142251881Speter        }
143251881Speter      }
144251881Speter    }
145251881Speter  }
146251881Speter}
147251881Speter
148251881Speter
149251881Spetervframe* vframe_array[50];
150251881Speterint walk_stack_counter = 0;
151251881Speter
152251881Spetervoid InterfaceSupport::walk_stack_from(vframe* start_vf) {
153251881Speter  // walk
154251881Speter  int i = 0;
155251881Speter  for (vframe* f = start_vf; f; f = f->sender() ) {
156251881Speter    if (i < 50) vframe_array[i++] = f;
157251881Speter  }
158251881Speter}
159251881Speter
160251881Speter
161251881Spetervoid InterfaceSupport::walk_stack() {
162251881Speter  JavaThread* thread = JavaThread::current();
163251881Speter  walk_stack_counter++;
164251881Speter  if (!thread->has_last_Java_frame()) return;
165251881Speter  ResourceMark rm(thread);
166251881Speter  RegisterMap reg_map(thread);
167251881Speter  walk_stack_from(thread->last_java_vframe(&reg_map));
168251881Speter}
169251881Speter
170251881Speter
171251881Speter# ifdef ENABLE_ZAP_DEAD_LOCALS
172251881Speter
173251881Speterstatic int zap_traversals = 0;
174251881Speter
175251881Spetervoid InterfaceSupport::zap_dead_locals_old() {
176251881Speter  JavaThread* thread = JavaThread::current();
177251881Speter  if (zap_traversals == -1) // edit constant for debugging
178251881Speter    warning("I am here");
179251881Speter  int zap_frame_count = 0; // count frames to help debugging
180251881Speter  for (StackFrameStream sfs(thread); !sfs.is_done(); sfs.next()) {
181251881Speter    sfs.current()->zap_dead_locals(thread, sfs.register_map());
182251881Speter    ++zap_frame_count;
183251881Speter  }
184251881Speter  ++zap_traversals;
185251881Speter}
186251881Speter
187251881Speter# endif
188251881Speter
189251881Speter
190251881Speterint deoptimizeAllCounter = 0;
191251881Speterint zombieAllCounter = 0;
192251881Speter
193251881Speter
194251881Spetervoid InterfaceSupport::zombieAll() {
195251881Speter  if (is_init_completed() && zombieAllCounter > ZombieALotInterval) {
196251881Speter    zombieAllCounter = 0;
197251881Speter    VM_ZombieAll op;
198251881Speter    VMThread::execute(&op);
199251881Speter  } else {
200251881Speter    zombieAllCounter++;
201251881Speter  }
202251881Speter}
203251881Speter
204251881Spetervoid InterfaceSupport::unlinkSymbols() {
205251881Speter  VM_UnlinkSymbols op;
206251881Speter  VMThread::execute(&op);
207251881Speter}
208251881Speter
209251881Spetervoid InterfaceSupport::deoptimizeAll() {
210251881Speter  if (is_init_completed() ) {
211251881Speter    if (DeoptimizeALot && deoptimizeAllCounter > DeoptimizeALotInterval) {
212251881Speter      deoptimizeAllCounter = 0;
213251881Speter      VM_DeoptimizeAll op;
214251881Speter      VMThread::execute(&op);
215251881Speter    } else if (DeoptimizeRandom && (deoptimizeAllCounter & 0x1f) == (os::random() & 0x1f)) {
216251881Speter      VM_DeoptimizeAll op;
217251881Speter      VMThread::execute(&op);
218251881Speter    }
219251881Speter  }
220251881Speter  deoptimizeAllCounter++;
221251881Speter}
222251881Speter
223251881Speter
224251881Spetervoid InterfaceSupport::stress_derived_pointers() {
225251881Speter#ifdef COMPILER2
226251881Speter  JavaThread *thread = JavaThread::current();
227251881Speter  if (!is_init_completed()) return;
228251881Speter  ResourceMark rm(thread);
229251881Speter  bool found = false;
230251881Speter  for (StackFrameStream sfs(thread); !sfs.is_done() && !found; sfs.next()) {
231251881Speter    CodeBlob* cb = sfs.current()->cb();
232251881Speter    if (cb != NULL && cb->oop_maps() ) {
233251881Speter      // Find oopmap for current method
234251881Speter      OopMap* map = cb->oop_map_for_return_address(sfs.current()->pc());
235251881Speter      assert(map != NULL, "no oopmap found for pc");
236251881Speter      found = map->has_derived_pointer();
237251881Speter    }
238251881Speter  }
239251881Speter  if (found) {
240251881Speter    // $$$ Not sure what to do here.
241251881Speter    /*
242251881Speter    Scavenge::invoke(0);
243251881Speter    */
244251881Speter  }
245251881Speter#endif
246251881Speter}
247251881Speter
248251881Speter
249251881Spetervoid InterfaceSupport::verify_stack() {
250251881Speter  JavaThread* thread = JavaThread::current();
251251881Speter  ResourceMark rm(thread);
252251881Speter  // disabled because it throws warnings that oop maps should only be accessed
253251881Speter  // in VM thread or during debugging
254251881Speter
255251881Speter  if (!thread->has_pending_exception()) {
256251881Speter    // verification does not work if there are pending exceptions
257251881Speter    StackFrameStream sfs(thread);
258251881Speter    CodeBlob* cb = sfs.current()->cb();
259251881Speter      // In case of exceptions we might not have a runtime_stub on
260251881Speter      // top of stack, hence, all callee-saved registers are not going
261251881Speter      // to be setup correctly, hence, we cannot do stack verify
262251881Speter    if (cb != NULL && !(cb->is_runtime_stub() || cb->is_uncommon_trap_stub())) return;
263251881Speter
264251881Speter    for (; !sfs.is_done(); sfs.next()) {
265251881Speter      sfs.current()->verify(sfs.register_map());
266251881Speter    }
267251881Speter  }
268251881Speter}
269251881Speter
270251881Speter
271251881Spetervoid InterfaceSupport::verify_last_frame() {
272251881Speter  JavaThread* thread = JavaThread::current();
273251881Speter  ResourceMark rm(thread);
274251881Speter  RegisterMap reg_map(thread);
275251881Speter  frame fr = thread->last_frame();
276251881Speter  fr.verify(&reg_map);
277251881Speter}
278251881Speter
279251881Speter
280251881Speter#endif // ASSERT
281251881Speter
282251881Speter
283251881Spetervoid InterfaceSupport_init() {
284251881Speter#ifdef ASSERT
285251881Speter  if (ScavengeALot || FullGCALot) {
286251881Speter    srand(ScavengeALotInterval * FullGCALotInterval);
287251881Speter  }
288251881Speter#endif
289251881Speter}
290251881Speter