Tue, 18 Jun 2013 12:31:07 -0700
8015237: Parallelize string table scanning during strong root processing
Summary: Parallelize the scanning of the intern string table by having each GC worker claim a given number of buckets. Changes were also reviewed by Per Liden <per.liden@oracle.com>.
Reviewed-by: tschatzl, stefank, twisti
1 /*
2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
3 * Copyright 2009 Red Hat, Inc.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
26 #include "precompiled.hpp"
27 #include "ci/ciMethod.hpp"
28 #include "shark/llvmHeaders.hpp"
29 #include "shark/sharkIntrinsics.hpp"
30 #include "shark/sharkState.hpp"
31 #include "shark/sharkValue.hpp"
32 #include "shark/shark_globals.hpp"
34 using namespace llvm;
36 bool SharkIntrinsics::is_intrinsic(ciMethod *target) {
37 switch (target->intrinsic_id()) {
38 case vmIntrinsics::_none:
39 return false;
41 // java.lang.Math
42 case vmIntrinsics::_min:
43 case vmIntrinsics::_max:
44 case vmIntrinsics::_dabs:
45 case vmIntrinsics::_dsin:
46 case vmIntrinsics::_dcos:
47 case vmIntrinsics::_dtan:
48 case vmIntrinsics::_datan2:
49 case vmIntrinsics::_dsqrt:
50 case vmIntrinsics::_dlog:
51 case vmIntrinsics::_dlog10:
52 case vmIntrinsics::_dpow:
53 case vmIntrinsics::_dexp:
54 return true;
56 // java.lang.Object
57 case vmIntrinsics::_getClass:
58 return true;
60 // java.lang.System
61 case vmIntrinsics::_currentTimeMillis:
62 return true;
64 // java.lang.Thread
65 case vmIntrinsics::_currentThread:
66 return true;
68 // sun.misc.Unsafe
69 case vmIntrinsics::_compareAndSwapInt:
70 return true;
72 default:
73 if (SharkPerformanceWarnings) {
74 warning(
75 "unhandled intrinsic vmIntrinsic::%s",
76 vmIntrinsics::name_at(target->intrinsic_id()));
77 }
78 }
79 return false;
80 }
82 void SharkIntrinsics::inline_intrinsic(ciMethod *target, SharkState *state) {
83 SharkIntrinsics intrinsic(state, target);
84 intrinsic.do_intrinsic();
85 }
87 void SharkIntrinsics::do_intrinsic() {
88 switch (target()->intrinsic_id()) {
89 // java.lang.Math
90 case vmIntrinsics::_min:
91 do_Math_minmax(llvm::ICmpInst::ICMP_SLE);
92 break;
93 case vmIntrinsics::_max:
94 do_Math_minmax(llvm::ICmpInst::ICMP_SGE);
95 break;
96 case vmIntrinsics::_dabs:
97 do_Math_1to1(builder()->fabs());
98 break;
99 case vmIntrinsics::_dsin:
100 do_Math_1to1(builder()->sin());
101 break;
102 case vmIntrinsics::_dcos:
103 do_Math_1to1(builder()->cos());
104 break;
105 case vmIntrinsics::_dtan:
106 do_Math_1to1(builder()->tan());
107 break;
108 case vmIntrinsics::_datan2:
109 do_Math_2to1(builder()->atan2());
110 break;
111 case vmIntrinsics::_dsqrt:
112 do_Math_1to1(builder()->sqrt());
113 break;
114 case vmIntrinsics::_dlog:
115 do_Math_1to1(builder()->log());
116 break;
117 case vmIntrinsics::_dlog10:
118 do_Math_1to1(builder()->log10());
119 break;
120 case vmIntrinsics::_dpow:
121 do_Math_2to1(builder()->pow());
122 break;
123 case vmIntrinsics::_dexp:
124 do_Math_1to1(builder()->exp());
125 break;
127 // java.lang.Object
128 case vmIntrinsics::_getClass:
129 do_Object_getClass();
130 break;
132 // java.lang.System
133 case vmIntrinsics::_currentTimeMillis:
134 do_System_currentTimeMillis();
135 break;
137 // java.lang.Thread
138 case vmIntrinsics::_currentThread:
139 do_Thread_currentThread();
140 break;
142 // sun.misc.Unsafe
143 case vmIntrinsics::_compareAndSwapInt:
144 do_Unsafe_compareAndSwapInt();
145 break;
147 default:
148 ShouldNotReachHere();
149 }
150 }
152 void SharkIntrinsics::do_Math_minmax(ICmpInst::Predicate p) {
153 // Pop the arguments
154 SharkValue *sb = state()->pop();
155 SharkValue *sa = state()->pop();
156 Value *a = sa->jint_value();
157 Value *b = sb->jint_value();
159 // Perform the test
160 BasicBlock *ip = builder()->GetBlockInsertionPoint();
161 BasicBlock *return_a = builder()->CreateBlock(ip, "return_a");
162 BasicBlock *return_b = builder()->CreateBlock(ip, "return_b");
163 BasicBlock *done = builder()->CreateBlock(ip, "done");
165 builder()->CreateCondBr(builder()->CreateICmp(p, a, b), return_a, return_b);
167 builder()->SetInsertPoint(return_a);
168 builder()->CreateBr(done);
170 builder()->SetInsertPoint(return_b);
171 builder()->CreateBr(done);
173 builder()->SetInsertPoint(done);
174 PHINode *phi = builder()->CreatePHI(a->getType(), 0, "result");
175 phi->addIncoming(a, return_a);
176 phi->addIncoming(b, return_b);
178 // Push the result
179 state()->push(
180 SharkValue::create_jint(
181 phi,
182 sa->zero_checked() && sb->zero_checked()));
183 }
185 void SharkIntrinsics::do_Math_1to1(Value *function) {
186 SharkValue *empty = state()->pop();
187 assert(empty == NULL, "should be");
188 state()->push(
189 SharkValue::create_jdouble(
190 builder()->CreateCall(
191 function, state()->pop()->jdouble_value())));
192 state()->push(NULL);
193 }
195 void SharkIntrinsics::do_Math_2to1(Value *function) {
196 SharkValue *empty = state()->pop();
197 assert(empty == NULL, "should be");
198 Value *y = state()->pop()->jdouble_value();
199 empty = state()->pop();
200 assert(empty == NULL, "should be");
201 Value *x = state()->pop()->jdouble_value();
203 state()->push(
204 SharkValue::create_jdouble(
205 builder()->CreateCall2(function, x, y)));
206 state()->push(NULL);
207 }
209 void SharkIntrinsics::do_Object_getClass() {
210 Value *klass = builder()->CreateValueOfStructEntry(
211 state()->pop()->jobject_value(),
212 in_ByteSize(oopDesc::klass_offset_in_bytes()),
213 SharkType::klass_type(),
214 "klass");
216 state()->push(
217 SharkValue::create_jobject(
218 builder()->CreateValueOfStructEntry(
219 klass,
220 Klass::java_mirror_offset(),
221 SharkType::oop_type(),
222 "java_mirror"),
223 true));
224 }
226 void SharkIntrinsics::do_System_currentTimeMillis() {
227 state()->push(
228 SharkValue::create_jlong(
229 builder()->CreateCall(builder()->current_time_millis()),
230 false));
231 state()->push(NULL);
232 }
234 void SharkIntrinsics::do_Thread_currentThread() {
235 state()->push(
236 SharkValue::create_jobject(
237 builder()->CreateValueOfStructEntry(
238 thread(), JavaThread::threadObj_offset(),
239 SharkType::oop_type(),
240 "threadObj"),
241 true));
242 }
244 void SharkIntrinsics::do_Unsafe_compareAndSwapInt() {
245 // Pop the arguments
246 Value *x = state()->pop()->jint_value();
247 Value *e = state()->pop()->jint_value();
248 SharkValue *empty = state()->pop();
249 assert(empty == NULL, "should be");
250 Value *offset = state()->pop()->jlong_value();
251 Value *object = state()->pop()->jobject_value();
252 Value *unsafe = state()->pop()->jobject_value();
254 // Convert the offset
255 offset = builder()->CreateCall(
256 builder()->unsafe_field_offset_to_byte_offset(),
257 offset);
259 // Locate the field
260 Value *addr = builder()->CreateIntToPtr(
261 builder()->CreateAdd(
262 builder()->CreatePtrToInt(object, SharkType::intptr_type()),
263 builder()->CreateIntCast(offset, SharkType::intptr_type(), true)),
264 PointerType::getUnqual(SharkType::jint_type()),
265 "addr");
267 // Perform the operation
268 Value *result = builder()->CreateAtomicCmpXchg(addr, e, x, llvm::SequentiallyConsistent);
269 // Push the result
270 state()->push(
271 SharkValue::create_jint(
272 builder()->CreateIntCast(
273 builder()->CreateICmpEQ(result, e), SharkType::jint_type(), true),
274 false));
275 }