/
scopedMemoryAccess.cpp
164 lines (133 loc) · 4.61 KB
/
scopedMemoryAccess.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include "precompiled.hpp"
#include "jni.h"
#include "jvm.h"
#include "classfile/vmSymbols.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/vframe.inline.hpp"
#include "runtime/deoptimization.hpp"
#include "prims/stackwalk.hpp"
class CloseScopedMemoryFindOopClosure : public OopClosure {
oop _deopt;
bool _found;
public:
CloseScopedMemoryFindOopClosure(jobject deopt) :
_deopt(JNIHandles::resolve(deopt)),
_found(false) {}
template <typename T>
void do_oop_work(T* p) {
if (_found) {
return;
}
if (RawAccess<>::oop_load(p) == _deopt) {
_found = true;
}
}
virtual void do_oop(oop* p) {
do_oop_work(p);
}
virtual void do_oop(narrowOop* p) {
do_oop_work(p);
}
bool found() {
return _found;
}
};
class CloseScopedMemoryClosure : public HandshakeClosure {
jobject _deopt;
jobject _exception;
public:
CloseScopedMemoryClosure(jobject deopt, jobject exception)
: HandshakeClosure("CloseScopedMemory")
, _deopt(deopt)
, _exception(exception) {}
void do_thread(Thread* thread) {
JavaThread* jt = (JavaThread*)thread;
if (!jt->has_last_Java_frame()) {
return;
}
frame last_frame = jt->last_frame();
RegisterMap register_map(jt, true);
if (last_frame.is_safepoint_blob_frame()) {
last_frame = last_frame.sender(®ister_map);
}
ResourceMark rm;
if (_deopt != NULL && last_frame.is_compiled_frame() && last_frame.can_be_deoptimized()) {
CloseScopedMemoryFindOopClosure cl(_deopt);
CompiledMethod* cm = last_frame.cb()->as_compiled_method();
//FIXME: this doesn't work if reachability fences are violated by C2
// last_frame.oops_do(&cl, NULL, ®ister_map);
// if (cl.found()) {
// // Found the deopt oop in a compiled method; deoptimize.
// Deoptimization::deoptimize(jt, last_frame);
// }
// so... we unconditionally deoptimize, for now
Deoptimization::deoptimize(jt, last_frame);
}
const int max_critical_stack_depth = 5;
int depth = 0;
vframeStream stream(jt);
for (; !stream.at_end(); stream.next()) {
Method* m = stream.method();
if (m->is_scoped()) {
StackValueCollection* locals = stream.asJavaVFrame()->locals();
for (int i = 0; i < locals->size(); i++) {
StackValue* var = locals->at(i);
if (var->type() == T_OBJECT) {
if (var->get_obj() == JNIHandles::resolve(_deopt)) {
assert(depth < max_critical_stack_depth, "can't have more than %d critical frames", max_critical_stack_depth);
if (!jt->is_exception_handling()) {
jt->install_async_exception(JNIHandles::resolve(_exception));
}
return;
}
}
}
break;
}
depth++;
#ifndef ASSERT
if (depth >= max_critical_stack_depth) {
break;
}
#endif
}
}
};
/*
* This function issues a global handshake operation with all
* Java threads. This is useful for implementing asymmetric
* dekker synchronization schemes, where expensive synchronization
* in performance sensitive common paths, may be shifted to
* a less common slow path instead.
* Top frames containg obj will be deoptimized.
*/
JVM_ENTRY(void, ScopedMemoryAccess_closeScope(JNIEnv *env, jobject receiver, jobject deopt, jobject exception)) {
CloseScopedMemoryClosure cl(deopt, exception);
Handshake::execute(&cl);
} JVM_END
/// JVM_RegisterUnsafeMethods
#define LANG "Ljdk/internal/misc/"
#define MEMACCESS "ScopedMemoryAccess"
#define SCOPE LANG MEMACCESS "$Scope;"
#define SCOPED_ERR LANG MEMACCESS "$Scope$ScopedAccessError;"
#define CC (char*) /*cast a literal from (const char*)*/
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
static JNINativeMethod jdk_internal_misc_ScopedMemoryAccess_methods[] = {
{CC "closeScope0", CC "(" SCOPE SCOPED_ERR ")V", FN_PTR(ScopedMemoryAccess_closeScope)},
};
#undef CC
#undef FN_PTR
#undef LANG
#undef MEMACCESS
#undef SCOPE
#undef SCOPED_EXC
// This function is exported, used by NativeLookup.
JVM_ENTRY(void, JVM_RegisterJDKInternalMiscScopedMemoryAccessMethods(JNIEnv *env, jclass scopedMemoryAccessClass)) {
ThreadToNativeFromVM ttnfv(thread);
int ok = env->RegisterNatives(scopedMemoryAccessClass, jdk_internal_misc_ScopedMemoryAccess_methods, sizeof(jdk_internal_misc_ScopedMemoryAccess_methods)/sizeof(JNINativeMethod));
guarantee(ok == 0, "register jdk.internal.misc.ScopedMemoryAccess natives");
} JVM_END