1 /*
  2  * Copyright (c) 2016, 2018, 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 
 25 #include "precompiled.hpp"
 26 #include "code/dependencyContext.hpp"
 27 #include "unittest.hpp"
 28 
 29 class TestDependencyContext {
 30  public:
 31   nmethod* _nmethods[3];
 32 
 33   intptr_t _dependency_context;
 34 
 35   DependencyContext dependencies() {
 36     DependencyContext depContext(&_dependency_context);
 37     return depContext;
 38   }
 39 
 40   TestDependencyContext() : _dependency_context(DependencyContext::EMPTY) {
 41     CodeCache_lock->lock_without_safepoint_check();
 42 
 43     _nmethods[0] = reinterpret_cast<nmethod*>(0x8 * 0);
 44     _nmethods[1] = reinterpret_cast<nmethod*>(0x8 * 1);
 45     _nmethods[2] = reinterpret_cast<nmethod*>(0x8 * 2);
 46 
 47     dependencies().add_dependent_nmethod(_nmethods[2]);
 48     dependencies().add_dependent_nmethod(_nmethods[1]);
 49     dependencies().add_dependent_nmethod(_nmethods[0]);
 50   }
 51 
 52   ~TestDependencyContext() {
 53     wipe();
 54     CodeCache_lock->unlock();
 55   }
 56 
 57   static bool has_stale_entries(DependencyContext ctx) {
 58     return ctx.has_stale_entries();
 59   }
 60 
 61 #ifndef PRODUCT
 62   static bool find_stale_entries(DependencyContext ctx) {
 63     return ctx.find_stale_entries();
 64   }
 65 #endif
 66 
 67   void wipe() {
 68     DependencyContext ctx(&_dependency_context);
 69     nmethodBucket* b = ctx.dependencies();
 70     ctx.set_dependencies(NULL);
 71     ctx.set_has_stale_entries(false);
 72     while (b != NULL) {
 73       nmethodBucket* next = b->next();
 74       delete b;
 75       b = next;
 76     }
 77   }
 78 };
 79 
 80 static void test_remove_dependent_nmethod(int id, bool delete_immediately) {
 81   TestDependencyContext c;
 82   DependencyContext depContext = c.dependencies();
 83   NOT_PRODUCT(ASSERT_FALSE(TestDependencyContext::find_stale_entries(depContext)));
 84   ASSERT_FALSE(TestDependencyContext::has_stale_entries(depContext));
 85 
 86   nmethod* nm = c._nmethods[id];
 87   depContext.remove_dependent_nmethod(nm, delete_immediately);
 88 
 89   if (!delete_immediately) {
 90     NOT_PRODUCT(ASSERT_TRUE(TestDependencyContext::find_stale_entries(depContext)));
 91     ASSERT_TRUE(TestDependencyContext::has_stale_entries(depContext));
 92     NOT_PRODUCT(ASSERT_TRUE(depContext.is_dependent_nmethod(nm)));
 93     depContext.expunge_stale_entries();
 94   }
 95 
 96   NOT_PRODUCT(ASSERT_FALSE(TestDependencyContext::find_stale_entries(depContext)));
 97   ASSERT_FALSE(TestDependencyContext::has_stale_entries(depContext));
 98   NOT_PRODUCT(ASSERT_FALSE(depContext.is_dependent_nmethod(nm)));
 99 }
100 
101 TEST_VM(code, dependency_context) {
102   test_remove_dependent_nmethod(0, false);
103   test_remove_dependent_nmethod(1, false);
104   test_remove_dependent_nmethod(2, false);
105 
106   test_remove_dependent_nmethod(0, true);
107   test_remove_dependent_nmethod(1, true);
108   test_remove_dependent_nmethod(2, true);
109 }