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