Mercurial > hg > truffle
annotate src/share/vm/opto/library_call.cpp @ 4710:41406797186b
7113012: G1: rename not-fully-young GCs as "mixed"
Summary: Renamed partially-young GCs as mixed and fully-young GCs as young. Change all external output that includes those terms (GC log and GC ergo log) as well as any comments, fields, methods, etc. The changeset also includes very minor code tidying up (added some curly brackets).
Reviewed-by: johnc, brutisso
author | tonyp |
---|---|
date | Fri, 16 Dec 2011 02:14:27 -0500 |
parents | a92cdbac8b9e |
children | 52b5d32fbfaf 069ab3f976d3 |
rev | line source |
---|---|
0 | 1 /* |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1513
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1513
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1513
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/systemDictionary.hpp" | |
27 #include "classfile/vmSymbols.hpp" | |
2405
3d58a4983660
7022998: JSR 292 recursive method handle calls inline themselves infinitely
twisti
parents:
2385
diff
changeset
|
28 #include "compiler/compileBroker.hpp" |
1972 | 29 #include "compiler/compileLog.hpp" |
30 #include "oops/objArrayKlass.hpp" | |
31 #include "opto/addnode.hpp" | |
32 #include "opto/callGenerator.hpp" | |
33 #include "opto/cfgnode.hpp" | |
34 #include "opto/idealKit.hpp" | |
35 #include "opto/mulnode.hpp" | |
36 #include "opto/parse.hpp" | |
37 #include "opto/runtime.hpp" | |
38 #include "opto/subnode.hpp" | |
39 #include "prims/nativeLookup.hpp" | |
40 #include "runtime/sharedRuntime.hpp" | |
0 | 41 |
42 class LibraryIntrinsic : public InlineCallGenerator { | |
43 // Extend the set of intrinsics known to the runtime: | |
44 public: | |
45 private: | |
46 bool _is_virtual; | |
47 vmIntrinsics::ID _intrinsic_id; | |
48 | |
49 public: | |
50 LibraryIntrinsic(ciMethod* m, bool is_virtual, vmIntrinsics::ID id) | |
51 : InlineCallGenerator(m), | |
52 _is_virtual(is_virtual), | |
53 _intrinsic_id(id) | |
54 { | |
55 } | |
56 virtual bool is_intrinsic() const { return true; } | |
57 virtual bool is_virtual() const { return _is_virtual; } | |
58 virtual JVMState* generate(JVMState* jvms); | |
59 vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; } | |
60 }; | |
61 | |
62 | |
63 // Local helper class for LibraryIntrinsic: | |
64 class LibraryCallKit : public GraphKit { | |
65 private: | |
66 LibraryIntrinsic* _intrinsic; // the library intrinsic being called | |
67 | |
68 public: | |
69 LibraryCallKit(JVMState* caller, LibraryIntrinsic* intrinsic) | |
70 : GraphKit(caller), | |
71 _intrinsic(intrinsic) | |
72 { | |
73 } | |
74 | |
75 ciMethod* caller() const { return jvms()->method(); } | |
76 int bci() const { return jvms()->bci(); } | |
77 LibraryIntrinsic* intrinsic() const { return _intrinsic; } | |
78 vmIntrinsics::ID intrinsic_id() const { return _intrinsic->intrinsic_id(); } | |
79 ciMethod* callee() const { return _intrinsic->method(); } | |
80 ciSignature* signature() const { return callee()->signature(); } | |
81 int arg_size() const { return callee()->arg_size(); } | |
82 | |
83 bool try_to_inline(); | |
84 | |
85 // Helper functions to inline natives | |
86 void push_result(RegionNode* region, PhiNode* value); | |
87 Node* generate_guard(Node* test, RegionNode* region, float true_prob); | |
88 Node* generate_slow_guard(Node* test, RegionNode* region); | |
89 Node* generate_fair_guard(Node* test, RegionNode* region); | |
90 Node* generate_negative_guard(Node* index, RegionNode* region, | |
91 // resulting CastII of index: | |
92 Node* *pos_index = NULL); | |
93 Node* generate_nonpositive_guard(Node* index, bool never_negative, | |
94 // resulting CastII of index: | |
95 Node* *pos_index = NULL); | |
96 Node* generate_limit_guard(Node* offset, Node* subseq_length, | |
97 Node* array_length, | |
98 RegionNode* region); | |
99 Node* generate_current_thread(Node* &tls_output); | |
100 address basictype2arraycopy(BasicType t, Node *src_offset, Node *dest_offset, | |
2324 | 101 bool disjoint_bases, const char* &name, bool dest_uninitialized); |
0 | 102 Node* load_mirror_from_klass(Node* klass); |
103 Node* load_klass_from_mirror_common(Node* mirror, bool never_see_null, | |
104 int nargs, | |
105 RegionNode* region, int null_path, | |
106 int offset); | |
107 Node* load_klass_from_mirror(Node* mirror, bool never_see_null, int nargs, | |
108 RegionNode* region, int null_path) { | |
109 int offset = java_lang_Class::klass_offset_in_bytes(); | |
110 return load_klass_from_mirror_common(mirror, never_see_null, nargs, | |
111 region, null_path, | |
112 offset); | |
113 } | |
114 Node* load_array_klass_from_mirror(Node* mirror, bool never_see_null, | |
115 int nargs, | |
116 RegionNode* region, int null_path) { | |
117 int offset = java_lang_Class::array_klass_offset_in_bytes(); | |
118 return load_klass_from_mirror_common(mirror, never_see_null, nargs, | |
119 region, null_path, | |
120 offset); | |
121 } | |
122 Node* generate_access_flags_guard(Node* kls, | |
123 int modifier_mask, int modifier_bits, | |
124 RegionNode* region); | |
125 Node* generate_interface_guard(Node* kls, RegionNode* region); | |
126 Node* generate_array_guard(Node* kls, RegionNode* region) { | |
127 return generate_array_guard_common(kls, region, false, false); | |
128 } | |
129 Node* generate_non_array_guard(Node* kls, RegionNode* region) { | |
130 return generate_array_guard_common(kls, region, false, true); | |
131 } | |
132 Node* generate_objArray_guard(Node* kls, RegionNode* region) { | |
133 return generate_array_guard_common(kls, region, true, false); | |
134 } | |
135 Node* generate_non_objArray_guard(Node* kls, RegionNode* region) { | |
136 return generate_array_guard_common(kls, region, true, true); | |
137 } | |
138 Node* generate_array_guard_common(Node* kls, RegionNode* region, | |
139 bool obj_array, bool not_array); | |
140 Node* generate_virtual_guard(Node* obj_klass, RegionNode* slow_region); | |
141 CallJavaNode* generate_method_call(vmIntrinsics::ID method_id, | |
142 bool is_virtual = false, bool is_static = false); | |
143 CallJavaNode* generate_method_call_static(vmIntrinsics::ID method_id) { | |
144 return generate_method_call(method_id, false, true); | |
145 } | |
146 CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) { | |
147 return generate_method_call(method_id, true, false); | |
148 } | |
149 | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
150 Node* make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2); |
0 | 151 bool inline_string_compareTo(); |
152 bool inline_string_indexOf(); | |
153 Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i); | |
681 | 154 bool inline_string_equals(); |
0 | 155 Node* pop_math_arg(); |
156 bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName); | |
157 bool inline_math_native(vmIntrinsics::ID id); | |
158 bool inline_trig(vmIntrinsics::ID id); | |
159 bool inline_trans(vmIntrinsics::ID id); | |
160 bool inline_abs(vmIntrinsics::ID id); | |
161 bool inline_sqrt(vmIntrinsics::ID id); | |
162 bool inline_pow(vmIntrinsics::ID id); | |
163 bool inline_exp(vmIntrinsics::ID id); | |
164 bool inline_min_max(vmIntrinsics::ID id); | |
165 Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y); | |
166 // This returns Type::AnyPtr, RawPtr, or OopPtr. | |
167 int classify_unsafe_addr(Node* &base, Node* &offset); | |
168 Node* make_unsafe_address(Node* base, Node* offset); | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
169 // Helper for inline_unsafe_access. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
170 // Generates the guards that check whether the result of |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
171 // Unsafe.getObject should be recorded in an SATB log buffer. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
172 void insert_g1_pre_barrier(Node* base_oop, Node* offset, Node* pre_val); |
0 | 173 bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile); |
174 bool inline_unsafe_prefetch(bool is_native_ptr, bool is_store, bool is_static); | |
175 bool inline_unsafe_allocate(); | |
176 bool inline_unsafe_copyMemory(); | |
177 bool inline_native_currentThread(); | |
178 bool inline_native_time_funcs(bool isNano); | |
179 bool inline_native_isInterrupted(); | |
180 bool inline_native_Class_query(vmIntrinsics::ID id); | |
181 bool inline_native_subtype_check(); | |
182 | |
183 bool inline_native_newArray(); | |
184 bool inline_native_getLength(); | |
185 bool inline_array_copyOf(bool is_copyOfRange); | |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
186 bool inline_array_equals(); |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
187 void copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array, bool card_mark); |
0 | 188 bool inline_native_clone(bool is_virtual); |
189 bool inline_native_Reflection_getCallerClass(); | |
190 bool inline_native_AtomicLong_get(); | |
191 bool inline_native_AtomicLong_attemptUpdate(); | |
192 bool is_method_invoke_or_aux_frame(JVMState* jvms); | |
193 // Helper function for inlining native object hash method | |
194 bool inline_native_hashcode(bool is_virtual, bool is_static); | |
195 bool inline_native_getClass(); | |
196 | |
197 // Helper functions for inlining arraycopy | |
198 bool inline_arraycopy(); | |
199 void generate_arraycopy(const TypePtr* adr_type, | |
200 BasicType basic_elem_type, | |
201 Node* src, Node* src_offset, | |
202 Node* dest, Node* dest_offset, | |
203 Node* copy_length, | |
204 bool disjoint_bases = false, | |
205 bool length_never_negative = false, | |
206 RegionNode* slow_region = NULL); | |
207 AllocateArrayNode* tightly_coupled_allocation(Node* ptr, | |
208 RegionNode* slow_region); | |
209 void generate_clear_array(const TypePtr* adr_type, | |
210 Node* dest, | |
211 BasicType basic_elem_type, | |
212 Node* slice_off, | |
213 Node* slice_len, | |
214 Node* slice_end); | |
215 bool generate_block_arraycopy(const TypePtr* adr_type, | |
216 BasicType basic_elem_type, | |
217 AllocateNode* alloc, | |
218 Node* src, Node* src_offset, | |
219 Node* dest, Node* dest_offset, | |
2324 | 220 Node* dest_size, bool dest_uninitialized); |
0 | 221 void generate_slow_arraycopy(const TypePtr* adr_type, |
222 Node* src, Node* src_offset, | |
223 Node* dest, Node* dest_offset, | |
2324 | 224 Node* copy_length, bool dest_uninitialized); |
0 | 225 Node* generate_checkcast_arraycopy(const TypePtr* adr_type, |
226 Node* dest_elem_klass, | |
227 Node* src, Node* src_offset, | |
228 Node* dest, Node* dest_offset, | |
2324 | 229 Node* copy_length, bool dest_uninitialized); |
0 | 230 Node* generate_generic_arraycopy(const TypePtr* adr_type, |
231 Node* src, Node* src_offset, | |
232 Node* dest, Node* dest_offset, | |
2324 | 233 Node* copy_length, bool dest_uninitialized); |
0 | 234 void generate_unchecked_arraycopy(const TypePtr* adr_type, |
235 BasicType basic_elem_type, | |
236 bool disjoint_bases, | |
237 Node* src, Node* src_offset, | |
238 Node* dest, Node* dest_offset, | |
2324 | 239 Node* copy_length, bool dest_uninitialized); |
0 | 240 bool inline_unsafe_CAS(BasicType type); |
241 bool inline_unsafe_ordered_store(BasicType type); | |
242 bool inline_fp_conversions(vmIntrinsics::ID id); | |
775
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
243 bool inline_numberOfLeadingZeros(vmIntrinsics::ID id); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
244 bool inline_numberOfTrailingZeros(vmIntrinsics::ID id); |
643
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
245 bool inline_bitCount(vmIntrinsics::ID id); |
0 | 246 bool inline_reverseBytes(vmIntrinsics::ID id); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
247 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
248 bool inline_reference_get(); |
0 | 249 }; |
250 | |
251 | |
252 //---------------------------make_vm_intrinsic---------------------------- | |
253 CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { | |
254 vmIntrinsics::ID id = m->intrinsic_id(); | |
255 assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); | |
256 | |
257 if (DisableIntrinsic[0] != '\0' | |
258 && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) { | |
259 // disabled by a user request on the command line: | |
260 // example: -XX:DisableIntrinsic=_hashCode,_getClass | |
261 return NULL; | |
262 } | |
263 | |
264 if (!m->is_loaded()) { | |
265 // do not attempt to inline unloaded methods | |
266 return NULL; | |
267 } | |
268 | |
269 // Only a few intrinsics implement a virtual dispatch. | |
270 // They are expensive calls which are also frequently overridden. | |
271 if (is_virtual) { | |
272 switch (id) { | |
273 case vmIntrinsics::_hashCode: | |
274 case vmIntrinsics::_clone: | |
275 // OK, Object.hashCode and Object.clone intrinsics come in both flavors | |
276 break; | |
277 default: | |
278 return NULL; | |
279 } | |
280 } | |
281 | |
282 // -XX:-InlineNatives disables nearly all intrinsics: | |
283 if (!InlineNatives) { | |
284 switch (id) { | |
285 case vmIntrinsics::_indexOf: | |
286 case vmIntrinsics::_compareTo: | |
681 | 287 case vmIntrinsics::_equals: |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
288 case vmIntrinsics::_equalsC: |
0 | 289 break; // InlineNatives does not control String.compareTo |
290 default: | |
291 return NULL; | |
292 } | |
293 } | |
294 | |
295 switch (id) { | |
296 case vmIntrinsics::_compareTo: | |
297 if (!SpecialStringCompareTo) return NULL; | |
298 break; | |
299 case vmIntrinsics::_indexOf: | |
300 if (!SpecialStringIndexOf) return NULL; | |
301 break; | |
681 | 302 case vmIntrinsics::_equals: |
303 if (!SpecialStringEquals) return NULL; | |
304 break; | |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
305 case vmIntrinsics::_equalsC: |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
306 if (!SpecialArraysEquals) return NULL; |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
307 break; |
0 | 308 case vmIntrinsics::_arraycopy: |
309 if (!InlineArrayCopy) return NULL; | |
310 break; | |
311 case vmIntrinsics::_copyMemory: | |
312 if (StubRoutines::unsafe_arraycopy() == NULL) return NULL; | |
313 if (!InlineArrayCopy) return NULL; | |
314 break; | |
315 case vmIntrinsics::_hashCode: | |
316 if (!InlineObjectHash) return NULL; | |
317 break; | |
318 case vmIntrinsics::_clone: | |
319 case vmIntrinsics::_copyOf: | |
320 case vmIntrinsics::_copyOfRange: | |
321 if (!InlineObjectCopy) return NULL; | |
322 // These also use the arraycopy intrinsic mechanism: | |
323 if (!InlineArrayCopy) return NULL; | |
324 break; | |
325 case vmIntrinsics::_checkIndex: | |
326 // We do not intrinsify this. The optimizer does fine with it. | |
327 return NULL; | |
328 | |
329 case vmIntrinsics::_get_AtomicLong: | |
330 case vmIntrinsics::_attemptUpdate: | |
331 if (!InlineAtomicLong) return NULL; | |
332 break; | |
333 | |
334 case vmIntrinsics::_getCallerClass: | |
335 if (!UseNewReflection) return NULL; | |
336 if (!InlineReflectionGetCallerClass) return NULL; | |
337 if (!JDK_Version::is_gte_jdk14x_version()) return NULL; | |
338 break; | |
339 | |
643
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
340 case vmIntrinsics::_bitCount_i: |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
341 case vmIntrinsics::_bitCount_l: |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
342 if (!UsePopCountInstruction) return NULL; |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
343 break; |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
344 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
345 case vmIntrinsics::_Reference_get: |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
346 // It is only when G1 is enabled that we absolutely |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
347 // need to use the intrinsic version of Reference.get() |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
348 // so that the value in the referent field, if necessary, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
349 // can be registered by the pre-barrier code. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
350 if (!UseG1GC) return NULL; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
351 break; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
352 |
0 | 353 default: |
856
75596850f863
6862576: vmIntrinsics needs cleanup in order to support JSR 292 intrinsics
jrose
parents:
851
diff
changeset
|
354 assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility"); |
75596850f863
6862576: vmIntrinsics needs cleanup in order to support JSR 292 intrinsics
jrose
parents:
851
diff
changeset
|
355 assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?"); |
0 | 356 break; |
357 } | |
358 | |
359 // -XX:-InlineClassNatives disables natives from the Class class. | |
360 // The flag applies to all reflective calls, notably Array.newArray | |
361 // (visible to Java programmers as Array.newInstance). | |
362 if (m->holder()->name() == ciSymbol::java_lang_Class() || | |
363 m->holder()->name() == ciSymbol::java_lang_reflect_Array()) { | |
364 if (!InlineClassNatives) return NULL; | |
365 } | |
366 | |
367 // -XX:-InlineThreadNatives disables natives from the Thread class. | |
368 if (m->holder()->name() == ciSymbol::java_lang_Thread()) { | |
369 if (!InlineThreadNatives) return NULL; | |
370 } | |
371 | |
372 // -XX:-InlineMathNatives disables natives from the Math,Float and Double classes. | |
373 if (m->holder()->name() == ciSymbol::java_lang_Math() || | |
374 m->holder()->name() == ciSymbol::java_lang_Float() || | |
375 m->holder()->name() == ciSymbol::java_lang_Double()) { | |
376 if (!InlineMathNatives) return NULL; | |
377 } | |
378 | |
379 // -XX:-InlineUnsafeOps disables natives from the Unsafe class. | |
380 if (m->holder()->name() == ciSymbol::sun_misc_Unsafe()) { | |
381 if (!InlineUnsafeOps) return NULL; | |
382 } | |
383 | |
384 return new LibraryIntrinsic(m, is_virtual, (vmIntrinsics::ID) id); | |
385 } | |
386 | |
387 //----------------------register_library_intrinsics----------------------- | |
388 // Initialize this file's data structures, for each Compile instance. | |
389 void Compile::register_library_intrinsics() { | |
390 // Nothing to do here. | |
391 } | |
392 | |
393 JVMState* LibraryIntrinsic::generate(JVMState* jvms) { | |
394 LibraryCallKit kit(jvms, this); | |
395 Compile* C = kit.C; | |
396 int nodes = C->unique(); | |
397 #ifndef PRODUCT | |
398 if ((PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) && Verbose) { | |
399 char buf[1000]; | |
400 const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf)); | |
401 tty->print_cr("Intrinsic %s", str); | |
402 } | |
403 #endif | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
404 |
0 | 405 if (kit.try_to_inline()) { |
406 if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) { | |
2405
3d58a4983660
7022998: JSR 292 recursive method handle calls inline themselves infinitely
twisti
parents:
2385
diff
changeset
|
407 CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, kit.bci(), is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); |
0 | 408 } |
409 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); | |
410 if (C->log()) { | |
411 C->log()->elem("intrinsic id='%s'%s nodes='%d'", | |
412 vmIntrinsics::name_at(intrinsic_id()), | |
413 (is_virtual() ? " virtual='1'" : ""), | |
414 C->unique() - nodes); | |
415 } | |
416 return kit.transfer_exceptions_into_jvms(); | |
417 } | |
418 | |
419 if (PrintIntrinsics) { | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
420 if (jvms->has_method()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
421 // Not a root compile. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
422 tty->print("Did not inline intrinsic %s%s at bci:%d in", |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
423 vmIntrinsics::name_at(intrinsic_id()), |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
424 (is_virtual() ? " (virtual)" : ""), kit.bci()); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
425 kit.caller()->print_short_name(tty); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
426 tty->print_cr(" (%d bytes)", kit.caller()->code_size()); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
427 } else { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
428 // Root compile |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
429 tty->print("Did not generate intrinsic %s%s at bci:%d in", |
856
75596850f863
6862576: vmIntrinsics needs cleanup in order to support JSR 292 intrinsics
jrose
parents:
851
diff
changeset
|
430 vmIntrinsics::name_at(intrinsic_id()), |
75596850f863
6862576: vmIntrinsics needs cleanup in order to support JSR 292 intrinsics
jrose
parents:
851
diff
changeset
|
431 (is_virtual() ? " (virtual)" : ""), kit.bci()); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
432 } |
0 | 433 } |
434 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); | |
435 return NULL; | |
436 } | |
437 | |
438 bool LibraryCallKit::try_to_inline() { | |
439 // Handle symbolic names for otherwise undistinguished boolean switches: | |
440 const bool is_store = true; | |
441 const bool is_native_ptr = true; | |
442 const bool is_static = true; | |
443 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
444 if (!jvms()->has_method()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
445 // Root JVMState has a null method. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
446 assert(map()->memory()->Opcode() == Op_Parm, ""); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
447 // Insert the memory aliasing node |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
448 set_all_memory(reset_memory()); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
449 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
450 assert(merged_memory(), ""); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
451 |
0 | 452 switch (intrinsic_id()) { |
453 case vmIntrinsics::_hashCode: | |
454 return inline_native_hashcode(intrinsic()->is_virtual(), !is_static); | |
455 case vmIntrinsics::_identityHashCode: | |
456 return inline_native_hashcode(/*!virtual*/ false, is_static); | |
457 case vmIntrinsics::_getClass: | |
458 return inline_native_getClass(); | |
459 | |
460 case vmIntrinsics::_dsin: | |
461 case vmIntrinsics::_dcos: | |
462 case vmIntrinsics::_dtan: | |
463 case vmIntrinsics::_dabs: | |
464 case vmIntrinsics::_datan2: | |
465 case vmIntrinsics::_dsqrt: | |
466 case vmIntrinsics::_dexp: | |
467 case vmIntrinsics::_dlog: | |
468 case vmIntrinsics::_dlog10: | |
469 case vmIntrinsics::_dpow: | |
470 return inline_math_native(intrinsic_id()); | |
471 | |
472 case vmIntrinsics::_min: | |
473 case vmIntrinsics::_max: | |
474 return inline_min_max(intrinsic_id()); | |
475 | |
476 case vmIntrinsics::_arraycopy: | |
477 return inline_arraycopy(); | |
478 | |
479 case vmIntrinsics::_compareTo: | |
480 return inline_string_compareTo(); | |
481 case vmIntrinsics::_indexOf: | |
482 return inline_string_indexOf(); | |
681 | 483 case vmIntrinsics::_equals: |
484 return inline_string_equals(); | |
0 | 485 |
486 case vmIntrinsics::_getObject: | |
487 return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, false); | |
488 case vmIntrinsics::_getBoolean: | |
489 return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, false); | |
490 case vmIntrinsics::_getByte: | |
491 return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, false); | |
492 case vmIntrinsics::_getShort: | |
493 return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, false); | |
494 case vmIntrinsics::_getChar: | |
495 return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, false); | |
496 case vmIntrinsics::_getInt: | |
497 return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, false); | |
498 case vmIntrinsics::_getLong: | |
499 return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, false); | |
500 case vmIntrinsics::_getFloat: | |
501 return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, false); | |
502 case vmIntrinsics::_getDouble: | |
503 return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, false); | |
504 | |
505 case vmIntrinsics::_putObject: | |
506 return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, false); | |
507 case vmIntrinsics::_putBoolean: | |
508 return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, false); | |
509 case vmIntrinsics::_putByte: | |
510 return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, false); | |
511 case vmIntrinsics::_putShort: | |
512 return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, false); | |
513 case vmIntrinsics::_putChar: | |
514 return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, false); | |
515 case vmIntrinsics::_putInt: | |
516 return inline_unsafe_access(!is_native_ptr, is_store, T_INT, false); | |
517 case vmIntrinsics::_putLong: | |
518 return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, false); | |
519 case vmIntrinsics::_putFloat: | |
520 return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, false); | |
521 case vmIntrinsics::_putDouble: | |
522 return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, false); | |
523 | |
524 case vmIntrinsics::_getByte_raw: | |
525 return inline_unsafe_access(is_native_ptr, !is_store, T_BYTE, false); | |
526 case vmIntrinsics::_getShort_raw: | |
527 return inline_unsafe_access(is_native_ptr, !is_store, T_SHORT, false); | |
528 case vmIntrinsics::_getChar_raw: | |
529 return inline_unsafe_access(is_native_ptr, !is_store, T_CHAR, false); | |
530 case vmIntrinsics::_getInt_raw: | |
531 return inline_unsafe_access(is_native_ptr, !is_store, T_INT, false); | |
532 case vmIntrinsics::_getLong_raw: | |
533 return inline_unsafe_access(is_native_ptr, !is_store, T_LONG, false); | |
534 case vmIntrinsics::_getFloat_raw: | |
535 return inline_unsafe_access(is_native_ptr, !is_store, T_FLOAT, false); | |
536 case vmIntrinsics::_getDouble_raw: | |
537 return inline_unsafe_access(is_native_ptr, !is_store, T_DOUBLE, false); | |
538 case vmIntrinsics::_getAddress_raw: | |
539 return inline_unsafe_access(is_native_ptr, !is_store, T_ADDRESS, false); | |
540 | |
541 case vmIntrinsics::_putByte_raw: | |
542 return inline_unsafe_access(is_native_ptr, is_store, T_BYTE, false); | |
543 case vmIntrinsics::_putShort_raw: | |
544 return inline_unsafe_access(is_native_ptr, is_store, T_SHORT, false); | |
545 case vmIntrinsics::_putChar_raw: | |
546 return inline_unsafe_access(is_native_ptr, is_store, T_CHAR, false); | |
547 case vmIntrinsics::_putInt_raw: | |
548 return inline_unsafe_access(is_native_ptr, is_store, T_INT, false); | |
549 case vmIntrinsics::_putLong_raw: | |
550 return inline_unsafe_access(is_native_ptr, is_store, T_LONG, false); | |
551 case vmIntrinsics::_putFloat_raw: | |
552 return inline_unsafe_access(is_native_ptr, is_store, T_FLOAT, false); | |
553 case vmIntrinsics::_putDouble_raw: | |
554 return inline_unsafe_access(is_native_ptr, is_store, T_DOUBLE, false); | |
555 case vmIntrinsics::_putAddress_raw: | |
556 return inline_unsafe_access(is_native_ptr, is_store, T_ADDRESS, false); | |
557 | |
558 case vmIntrinsics::_getObjectVolatile: | |
559 return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, true); | |
560 case vmIntrinsics::_getBooleanVolatile: | |
561 return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, true); | |
562 case vmIntrinsics::_getByteVolatile: | |
563 return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, true); | |
564 case vmIntrinsics::_getShortVolatile: | |
565 return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, true); | |
566 case vmIntrinsics::_getCharVolatile: | |
567 return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, true); | |
568 case vmIntrinsics::_getIntVolatile: | |
569 return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, true); | |
570 case vmIntrinsics::_getLongVolatile: | |
571 return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, true); | |
572 case vmIntrinsics::_getFloatVolatile: | |
573 return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, true); | |
574 case vmIntrinsics::_getDoubleVolatile: | |
575 return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, true); | |
576 | |
577 case vmIntrinsics::_putObjectVolatile: | |
578 return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, true); | |
579 case vmIntrinsics::_putBooleanVolatile: | |
580 return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, true); | |
581 case vmIntrinsics::_putByteVolatile: | |
582 return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, true); | |
583 case vmIntrinsics::_putShortVolatile: | |
584 return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, true); | |
585 case vmIntrinsics::_putCharVolatile: | |
586 return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, true); | |
587 case vmIntrinsics::_putIntVolatile: | |
588 return inline_unsafe_access(!is_native_ptr, is_store, T_INT, true); | |
589 case vmIntrinsics::_putLongVolatile: | |
590 return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, true); | |
591 case vmIntrinsics::_putFloatVolatile: | |
592 return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, true); | |
593 case vmIntrinsics::_putDoubleVolatile: | |
594 return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, true); | |
595 | |
596 case vmIntrinsics::_prefetchRead: | |
597 return inline_unsafe_prefetch(!is_native_ptr, !is_store, !is_static); | |
598 case vmIntrinsics::_prefetchWrite: | |
599 return inline_unsafe_prefetch(!is_native_ptr, is_store, !is_static); | |
600 case vmIntrinsics::_prefetchReadStatic: | |
601 return inline_unsafe_prefetch(!is_native_ptr, !is_store, is_static); | |
602 case vmIntrinsics::_prefetchWriteStatic: | |
603 return inline_unsafe_prefetch(!is_native_ptr, is_store, is_static); | |
604 | |
605 case vmIntrinsics::_compareAndSwapObject: | |
606 return inline_unsafe_CAS(T_OBJECT); | |
607 case vmIntrinsics::_compareAndSwapInt: | |
608 return inline_unsafe_CAS(T_INT); | |
609 case vmIntrinsics::_compareAndSwapLong: | |
610 return inline_unsafe_CAS(T_LONG); | |
611 | |
612 case vmIntrinsics::_putOrderedObject: | |
613 return inline_unsafe_ordered_store(T_OBJECT); | |
614 case vmIntrinsics::_putOrderedInt: | |
615 return inline_unsafe_ordered_store(T_INT); | |
616 case vmIntrinsics::_putOrderedLong: | |
617 return inline_unsafe_ordered_store(T_LONG); | |
618 | |
619 case vmIntrinsics::_currentThread: | |
620 return inline_native_currentThread(); | |
621 case vmIntrinsics::_isInterrupted: | |
622 return inline_native_isInterrupted(); | |
623 | |
624 case vmIntrinsics::_currentTimeMillis: | |
625 return inline_native_time_funcs(false); | |
626 case vmIntrinsics::_nanoTime: | |
627 return inline_native_time_funcs(true); | |
628 case vmIntrinsics::_allocateInstance: | |
629 return inline_unsafe_allocate(); | |
630 case vmIntrinsics::_copyMemory: | |
631 return inline_unsafe_copyMemory(); | |
632 case vmIntrinsics::_newArray: | |
633 return inline_native_newArray(); | |
634 case vmIntrinsics::_getLength: | |
635 return inline_native_getLength(); | |
636 case vmIntrinsics::_copyOf: | |
637 return inline_array_copyOf(false); | |
638 case vmIntrinsics::_copyOfRange: | |
639 return inline_array_copyOf(true); | |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
640 case vmIntrinsics::_equalsC: |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
641 return inline_array_equals(); |
0 | 642 case vmIntrinsics::_clone: |
643 return inline_native_clone(intrinsic()->is_virtual()); | |
644 | |
645 case vmIntrinsics::_isAssignableFrom: | |
646 return inline_native_subtype_check(); | |
647 | |
648 case vmIntrinsics::_isInstance: | |
649 case vmIntrinsics::_getModifiers: | |
650 case vmIntrinsics::_isInterface: | |
651 case vmIntrinsics::_isArray: | |
652 case vmIntrinsics::_isPrimitive: | |
653 case vmIntrinsics::_getSuperclass: | |
654 case vmIntrinsics::_getComponentType: | |
655 case vmIntrinsics::_getClassAccessFlags: | |
656 return inline_native_Class_query(intrinsic_id()); | |
657 | |
658 case vmIntrinsics::_floatToRawIntBits: | |
659 case vmIntrinsics::_floatToIntBits: | |
660 case vmIntrinsics::_intBitsToFloat: | |
661 case vmIntrinsics::_doubleToRawLongBits: | |
662 case vmIntrinsics::_doubleToLongBits: | |
663 case vmIntrinsics::_longBitsToDouble: | |
664 return inline_fp_conversions(intrinsic_id()); | |
665 | |
775
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
666 case vmIntrinsics::_numberOfLeadingZeros_i: |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
667 case vmIntrinsics::_numberOfLeadingZeros_l: |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
668 return inline_numberOfLeadingZeros(intrinsic_id()); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
669 |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
670 case vmIntrinsics::_numberOfTrailingZeros_i: |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
671 case vmIntrinsics::_numberOfTrailingZeros_l: |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
672 return inline_numberOfTrailingZeros(intrinsic_id()); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
673 |
643
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
674 case vmIntrinsics::_bitCount_i: |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
675 case vmIntrinsics::_bitCount_l: |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
676 return inline_bitCount(intrinsic_id()); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
677 |
0 | 678 case vmIntrinsics::_reverseBytes_i: |
679 case vmIntrinsics::_reverseBytes_l: | |
1396
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
680 case vmIntrinsics::_reverseBytes_s: |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
681 case vmIntrinsics::_reverseBytes_c: |
0 | 682 return inline_reverseBytes((vmIntrinsics::ID) intrinsic_id()); |
683 | |
684 case vmIntrinsics::_get_AtomicLong: | |
685 return inline_native_AtomicLong_get(); | |
686 case vmIntrinsics::_attemptUpdate: | |
687 return inline_native_AtomicLong_attemptUpdate(); | |
688 | |
689 case vmIntrinsics::_getCallerClass: | |
690 return inline_native_Reflection_getCallerClass(); | |
691 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
692 case vmIntrinsics::_Reference_get: |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
693 return inline_reference_get(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
694 |
0 | 695 default: |
696 // If you get here, it may be that someone has added a new intrinsic | |
697 // to the list in vmSymbols.hpp without implementing it here. | |
698 #ifndef PRODUCT | |
699 if ((PrintMiscellaneous && (Verbose || WizardMode)) || PrintOpto) { | |
700 tty->print_cr("*** Warning: Unimplemented intrinsic %s(%d)", | |
701 vmIntrinsics::name_at(intrinsic_id()), intrinsic_id()); | |
702 } | |
703 #endif | |
704 return false; | |
705 } | |
706 } | |
707 | |
708 //------------------------------push_result------------------------------ | |
709 // Helper function for finishing intrinsics. | |
710 void LibraryCallKit::push_result(RegionNode* region, PhiNode* value) { | |
711 record_for_igvn(region); | |
712 set_control(_gvn.transform(region)); | |
713 BasicType value_type = value->type()->basic_type(); | |
714 push_node(value_type, _gvn.transform(value)); | |
715 } | |
716 | |
717 //------------------------------generate_guard--------------------------- | |
718 // Helper function for generating guarded fast-slow graph structures. | |
719 // The given 'test', if true, guards a slow path. If the test fails | |
720 // then a fast path can be taken. (We generally hope it fails.) | |
721 // In all cases, GraphKit::control() is updated to the fast path. | |
722 // The returned value represents the control for the slow path. | |
723 // The return value is never 'top'; it is either a valid control | |
724 // or NULL if it is obvious that the slow path can never be taken. | |
725 // Also, if region and the slow control are not NULL, the slow edge | |
726 // is appended to the region. | |
727 Node* LibraryCallKit::generate_guard(Node* test, RegionNode* region, float true_prob) { | |
728 if (stopped()) { | |
729 // Already short circuited. | |
730 return NULL; | |
731 } | |
732 | |
733 // Build an if node and its projections. | |
734 // If test is true we take the slow path, which we assume is uncommon. | |
735 if (_gvn.type(test) == TypeInt::ZERO) { | |
736 // The slow branch is never taken. No need to build this guard. | |
737 return NULL; | |
738 } | |
739 | |
740 IfNode* iff = create_and_map_if(control(), test, true_prob, COUNT_UNKNOWN); | |
741 | |
742 Node* if_slow = _gvn.transform( new (C, 1) IfTrueNode(iff) ); | |
743 if (if_slow == top()) { | |
744 // The slow branch is never taken. No need to build this guard. | |
745 return NULL; | |
746 } | |
747 | |
748 if (region != NULL) | |
749 region->add_req(if_slow); | |
750 | |
751 Node* if_fast = _gvn.transform( new (C, 1) IfFalseNode(iff) ); | |
752 set_control(if_fast); | |
753 | |
754 return if_slow; | |
755 } | |
756 | |
757 inline Node* LibraryCallKit::generate_slow_guard(Node* test, RegionNode* region) { | |
758 return generate_guard(test, region, PROB_UNLIKELY_MAG(3)); | |
759 } | |
760 inline Node* LibraryCallKit::generate_fair_guard(Node* test, RegionNode* region) { | |
761 return generate_guard(test, region, PROB_FAIR); | |
762 } | |
763 | |
764 inline Node* LibraryCallKit::generate_negative_guard(Node* index, RegionNode* region, | |
765 Node* *pos_index) { | |
766 if (stopped()) | |
767 return NULL; // already stopped | |
768 if (_gvn.type(index)->higher_equal(TypeInt::POS)) // [0,maxint] | |
769 return NULL; // index is already adequately typed | |
770 Node* cmp_lt = _gvn.transform( new (C, 3) CmpINode(index, intcon(0)) ); | |
771 Node* bol_lt = _gvn.transform( new (C, 2) BoolNode(cmp_lt, BoolTest::lt) ); | |
772 Node* is_neg = generate_guard(bol_lt, region, PROB_MIN); | |
773 if (is_neg != NULL && pos_index != NULL) { | |
774 // Emulate effect of Parse::adjust_map_after_if. | |
775 Node* ccast = new (C, 2) CastIINode(index, TypeInt::POS); | |
776 ccast->set_req(0, control()); | |
777 (*pos_index) = _gvn.transform(ccast); | |
778 } | |
779 return is_neg; | |
780 } | |
781 | |
782 inline Node* LibraryCallKit::generate_nonpositive_guard(Node* index, bool never_negative, | |
783 Node* *pos_index) { | |
784 if (stopped()) | |
785 return NULL; // already stopped | |
786 if (_gvn.type(index)->higher_equal(TypeInt::POS1)) // [1,maxint] | |
787 return NULL; // index is already adequately typed | |
788 Node* cmp_le = _gvn.transform( new (C, 3) CmpINode(index, intcon(0)) ); | |
789 BoolTest::mask le_or_eq = (never_negative ? BoolTest::eq : BoolTest::le); | |
790 Node* bol_le = _gvn.transform( new (C, 2) BoolNode(cmp_le, le_or_eq) ); | |
791 Node* is_notp = generate_guard(bol_le, NULL, PROB_MIN); | |
792 if (is_notp != NULL && pos_index != NULL) { | |
793 // Emulate effect of Parse::adjust_map_after_if. | |
794 Node* ccast = new (C, 2) CastIINode(index, TypeInt::POS1); | |
795 ccast->set_req(0, control()); | |
796 (*pos_index) = _gvn.transform(ccast); | |
797 } | |
798 return is_notp; | |
799 } | |
800 | |
801 // Make sure that 'position' is a valid limit index, in [0..length]. | |
802 // There are two equivalent plans for checking this: | |
803 // A. (offset + copyLength) unsigned<= arrayLength | |
804 // B. offset <= (arrayLength - copyLength) | |
805 // We require that all of the values above, except for the sum and | |
806 // difference, are already known to be non-negative. | |
807 // Plan A is robust in the face of overflow, if offset and copyLength | |
808 // are both hugely positive. | |
809 // | |
810 // Plan B is less direct and intuitive, but it does not overflow at | |
811 // all, since the difference of two non-negatives is always | |
812 // representable. Whenever Java methods must perform the equivalent | |
813 // check they generally use Plan B instead of Plan A. | |
814 // For the moment we use Plan A. | |
815 inline Node* LibraryCallKit::generate_limit_guard(Node* offset, | |
816 Node* subseq_length, | |
817 Node* array_length, | |
818 RegionNode* region) { | |
819 if (stopped()) | |
820 return NULL; // already stopped | |
821 bool zero_offset = _gvn.type(offset) == TypeInt::ZERO; | |
822 if (zero_offset && _gvn.eqv_uncast(subseq_length, array_length)) | |
823 return NULL; // common case of whole-array copy | |
824 Node* last = subseq_length; | |
825 if (!zero_offset) // last += offset | |
826 last = _gvn.transform( new (C, 3) AddINode(last, offset)); | |
827 Node* cmp_lt = _gvn.transform( new (C, 3) CmpUNode(array_length, last) ); | |
828 Node* bol_lt = _gvn.transform( new (C, 2) BoolNode(cmp_lt, BoolTest::lt) ); | |
829 Node* is_over = generate_guard(bol_lt, region, PROB_MIN); | |
830 return is_over; | |
831 } | |
832 | |
833 | |
834 //--------------------------generate_current_thread-------------------- | |
835 Node* LibraryCallKit::generate_current_thread(Node* &tls_output) { | |
836 ciKlass* thread_klass = env()->Thread_klass(); | |
837 const Type* thread_type = TypeOopPtr::make_from_klass(thread_klass)->cast_to_ptr_type(TypePtr::NotNull); | |
838 Node* thread = _gvn.transform(new (C, 1) ThreadLocalNode()); | |
839 Node* p = basic_plus_adr(top()/*!oop*/, thread, in_bytes(JavaThread::threadObj_offset())); | |
840 Node* threadObj = make_load(NULL, p, thread_type, T_OBJECT); | |
841 tls_output = thread; | |
842 return threadObj; | |
843 } | |
844 | |
845 | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
846 //------------------------------make_string_method_node------------------------ |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
847 // Helper method for String intrinsic finctions. |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
848 Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
849 const int value_offset = java_lang_String::value_offset_in_bytes(); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
850 const int count_offset = java_lang_String::count_offset_in_bytes(); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
851 const int offset_offset = java_lang_String::offset_offset_in_bytes(); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
852 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
853 Node* no_ctrl = NULL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
854 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
855 ciInstanceKlass* klass = env()->String_klass(); |
1496
e8e83be27dd7
6951190: assert(!klass_is_exact(),"only non-exact klass") while building JDK
never
parents:
1396
diff
changeset
|
856 const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
857 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
858 const TypeAryPtr* value_type = |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
859 TypeAryPtr::make(TypePtr::NotNull, |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
860 TypeAry::make(TypeInt::CHAR,TypeInt::POS), |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
861 ciTypeArrayKlass::make(T_CHAR), true, 0); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
862 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
863 // Get start addr of string and substring |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
864 Node* str1_valuea = basic_plus_adr(str1, str1, value_offset); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
865 Node* str1_value = make_load(no_ctrl, str1_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
866 Node* str1_offseta = basic_plus_adr(str1, str1, offset_offset); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
867 Node* str1_offset = make_load(no_ctrl, str1_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
868 Node* str1_start = array_element_address(str1_value, str1_offset, T_CHAR); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
869 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
870 Node* str2_valuea = basic_plus_adr(str2, str2, value_offset); |
3337
e6d7eed3330c
7041100: The load in String.equals intrinsic executed before null check
kvn
parents:
3284
diff
changeset
|
871 Node* str2_value = make_load(no_ctrl, str2_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset)); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
872 Node* str2_offseta = basic_plus_adr(str2, str2, offset_offset); |
3337
e6d7eed3330c
7041100: The load in String.equals intrinsic executed before null check
kvn
parents:
3284
diff
changeset
|
873 Node* str2_offset = make_load(no_ctrl, str2_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset)); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
874 Node* str2_start = array_element_address(str2_value, str2_offset, T_CHAR); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
875 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
876 Node* result = NULL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
877 switch (opcode) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
878 case Op_StrIndexOf: |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
879 result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS), |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
880 str1_start, cnt1, str2_start, cnt2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
881 break; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
882 case Op_StrComp: |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
883 result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS), |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
884 str1_start, cnt1, str2_start, cnt2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
885 break; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
886 case Op_StrEquals: |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
887 result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS), |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
888 str1_start, str2_start, cnt1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
889 break; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
890 default: |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
891 ShouldNotReachHere(); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
892 return NULL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
893 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
894 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
895 // All these intrinsics have checks. |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
896 C->set_has_split_ifs(true); // Has chance for split-if optimization |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
897 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
898 return _gvn.transform(result); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
899 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
900 |
0 | 901 //------------------------------inline_string_compareTo------------------------ |
902 bool LibraryCallKit::inline_string_compareTo() { | |
903 | |
681 | 904 if (!Matcher::has_match_rule(Op_StrComp)) return false; |
905 | |
0 | 906 const int value_offset = java_lang_String::value_offset_in_bytes(); |
907 const int count_offset = java_lang_String::count_offset_in_bytes(); | |
908 const int offset_offset = java_lang_String::offset_offset_in_bytes(); | |
909 | |
910 _sp += 2; | |
911 Node *argument = pop(); // pop non-receiver first: it was pushed second | |
912 Node *receiver = pop(); | |
913 | |
914 // Null check on self without removing any arguments. The argument | |
915 // null check technically happens in the wrong place, which can lead to | |
916 // invalid stack traces when string compare is inlined into a method | |
917 // which handles NullPointerExceptions. | |
918 _sp += 2; | |
919 receiver = do_null_check(receiver, T_OBJECT); | |
920 argument = do_null_check(argument, T_OBJECT); | |
921 _sp -= 2; | |
922 if (stopped()) { | |
923 return true; | |
924 } | |
925 | |
926 ciInstanceKlass* klass = env()->String_klass(); | |
1496
e8e83be27dd7
6951190: assert(!klass_is_exact(),"only non-exact klass") while building JDK
never
parents:
1396
diff
changeset
|
927 const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
928 Node* no_ctrl = NULL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
929 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
930 // Get counts for string and argument |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
931 Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
932 Node* receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
933 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
934 Node* argument_cnta = basic_plus_adr(argument, argument, count_offset); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
935 Node* argument_cnt = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
936 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
937 Node* compare = make_string_method_node(Op_StrComp, receiver, receiver_cnt, argument, argument_cnt); |
0 | 938 push(compare); |
939 return true; | |
940 } | |
941 | |
681 | 942 //------------------------------inline_string_equals------------------------ |
943 bool LibraryCallKit::inline_string_equals() { | |
944 | |
945 if (!Matcher::has_match_rule(Op_StrEquals)) return false; | |
946 | |
947 const int value_offset = java_lang_String::value_offset_in_bytes(); | |
948 const int count_offset = java_lang_String::count_offset_in_bytes(); | |
949 const int offset_offset = java_lang_String::offset_offset_in_bytes(); | |
950 | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
951 int nargs = 2; |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
952 _sp += nargs; |
681 | 953 Node* argument = pop(); // pop non-receiver first: it was pushed second |
954 Node* receiver = pop(); | |
955 | |
956 // Null check on self without removing any arguments. The argument | |
957 // null check technically happens in the wrong place, which can lead to | |
958 // invalid stack traces when string compare is inlined into a method | |
959 // which handles NullPointerExceptions. | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
960 _sp += nargs; |
681 | 961 receiver = do_null_check(receiver, T_OBJECT); |
962 //should not do null check for argument for String.equals(), because spec | |
963 //allows to specify NULL as argument. | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
964 _sp -= nargs; |
681 | 965 |
966 if (stopped()) { | |
967 return true; | |
968 } | |
969 | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
970 // paths (plus control) merge |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
971 RegionNode* region = new (C, 5) RegionNode(5); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
972 Node* phi = new (C, 5) PhiNode(region, TypeInt::BOOL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
973 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
974 // does source == target string? |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
975 Node* cmp = _gvn.transform(new (C, 3) CmpPNode(receiver, argument)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
976 Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
977 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
978 Node* if_eq = generate_slow_guard(bol, NULL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
979 if (if_eq != NULL) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
980 // receiver == argument |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
981 phi->init_req(2, intcon(1)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
982 region->init_req(2, if_eq); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
983 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
984 |
681 | 985 // get String klass for instanceOf |
986 ciInstanceKlass* klass = env()->String_klass(); | |
987 | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
988 if (!stopped()) { |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
989 _sp += nargs; // gen_instanceof might do an uncommon trap |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
990 Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass))); |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
991 _sp -= nargs; |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
992 Node* cmp = _gvn.transform(new (C, 3) CmpINode(inst, intcon(1))); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
993 Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::ne)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
994 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
995 Node* inst_false = generate_guard(bol, NULL, PROB_MIN); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
996 //instanceOf == true, fallthrough |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
997 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
998 if (inst_false != NULL) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
999 phi->init_req(3, intcon(0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1000 region->init_req(3, inst_false); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1001 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1002 } |
681 | 1003 |
1496
e8e83be27dd7
6951190: assert(!klass_is_exact(),"only non-exact klass") while building JDK
never
parents:
1396
diff
changeset
|
1004 const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass); |
681 | 1005 |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1006 Node* no_ctrl = NULL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1007 Node* receiver_cnt; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1008 Node* argument_cnt; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1009 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1010 if (!stopped()) { |
1496
e8e83be27dd7
6951190: assert(!klass_is_exact(),"only non-exact klass") while building JDK
never
parents:
1396
diff
changeset
|
1011 // Properly cast the argument to String |
e8e83be27dd7
6951190: assert(!klass_is_exact(),"only non-exact klass") while building JDK
never
parents:
1396
diff
changeset
|
1012 argument = _gvn.transform(new (C, 2) CheckCastPPNode(control(), argument, string_type)); |
3337
e6d7eed3330c
7041100: The load in String.equals intrinsic executed before null check
kvn
parents:
3284
diff
changeset
|
1013 // This path is taken only when argument's type is String:NotNull. |
e6d7eed3330c
7041100: The load in String.equals intrinsic executed before null check
kvn
parents:
3284
diff
changeset
|
1014 argument = cast_not_null(argument, false); |
1496
e8e83be27dd7
6951190: assert(!klass_is_exact(),"only non-exact klass") while building JDK
never
parents:
1396
diff
changeset
|
1015 |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1016 // Get counts for string and argument |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1017 Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1018 receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1019 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1020 Node* argument_cnta = basic_plus_adr(argument, argument, count_offset); |
3337
e6d7eed3330c
7041100: The load in String.equals intrinsic executed before null check
kvn
parents:
3284
diff
changeset
|
1021 argument_cnt = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1022 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1023 // Check for receiver count != argument count |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1024 Node* cmp = _gvn.transform( new(C, 3) CmpINode(receiver_cnt, argument_cnt) ); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1025 Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::ne) ); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1026 Node* if_ne = generate_slow_guard(bol, NULL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1027 if (if_ne != NULL) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1028 phi->init_req(4, intcon(0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1029 region->init_req(4, if_ne); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1030 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1031 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1032 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1033 // Check for count == 0 is done by mach node StrEquals. |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1034 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1035 if (!stopped()) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1036 Node* equals = make_string_method_node(Op_StrEquals, receiver, receiver_cnt, argument, argument_cnt); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1037 phi->init_req(1, equals); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1038 region->init_req(1, control()); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1039 } |
681 | 1040 |
1041 // post merge | |
1042 set_control(_gvn.transform(region)); | |
1043 record_for_igvn(region); | |
1044 | |
1045 push(_gvn.transform(phi)); | |
1046 | |
1047 return true; | |
1048 } | |
1049 | |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1050 //------------------------------inline_array_equals---------------------------- |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1051 bool LibraryCallKit::inline_array_equals() { |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1052 |
174
510f98a80563
6709972: runThese failed with assert(false,"bad AD file")
rasbold
parents:
169
diff
changeset
|
1053 if (!Matcher::has_match_rule(Op_AryEq)) return false; |
510f98a80563
6709972: runThese failed with assert(false,"bad AD file")
rasbold
parents:
169
diff
changeset
|
1054 |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1055 _sp += 2; |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1056 Node *argument2 = pop(); |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1057 Node *argument1 = pop(); |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1058 |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1059 Node* equals = |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1060 _gvn.transform(new (C, 4) AryEqNode(control(), memory(TypeAryPtr::CHARS), |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1061 argument1, argument2) ); |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1062 push(equals); |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1063 return true; |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1064 } |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1065 |
0 | 1066 // Java version of String.indexOf(constant string) |
1067 // class StringDecl { | |
1068 // StringDecl(char[] ca) { | |
1069 // offset = 0; | |
1070 // count = ca.length; | |
1071 // value = ca; | |
1072 // } | |
1073 // int offset; | |
1074 // int count; | |
1075 // char[] value; | |
1076 // } | |
1077 // | |
1078 // static int string_indexOf_J(StringDecl string_object, char[] target_object, | |
1079 // int targetOffset, int cache_i, int md2) { | |
1080 // int cache = cache_i; | |
1081 // int sourceOffset = string_object.offset; | |
1082 // int sourceCount = string_object.count; | |
1083 // int targetCount = target_object.length; | |
1084 // | |
1085 // int targetCountLess1 = targetCount - 1; | |
1086 // int sourceEnd = sourceOffset + sourceCount - targetCountLess1; | |
1087 // | |
1088 // char[] source = string_object.value; | |
1089 // char[] target = target_object; | |
1090 // int lastChar = target[targetCountLess1]; | |
1091 // | |
1092 // outer_loop: | |
1093 // for (int i = sourceOffset; i < sourceEnd; ) { | |
1094 // int src = source[i + targetCountLess1]; | |
1095 // if (src == lastChar) { | |
1096 // // With random strings and a 4-character alphabet, | |
1097 // // reverse matching at this point sets up 0.8% fewer | |
1098 // // frames, but (paradoxically) makes 0.3% more probes. | |
1099 // // Since those probes are nearer the lastChar probe, | |
1100 // // there is may be a net D$ win with reverse matching. | |
1101 // // But, reversing loop inhibits unroll of inner loop | |
1102 // // for unknown reason. So, does running outer loop from | |
1103 // // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount) | |
1104 // for (int j = 0; j < targetCountLess1; j++) { | |
1105 // if (target[targetOffset + j] != source[i+j]) { | |
1106 // if ((cache & (1 << source[i+j])) == 0) { | |
1107 // if (md2 < j+1) { | |
1108 // i += j+1; | |
1109 // continue outer_loop; | |
1110 // } | |
1111 // } | |
1112 // i += md2; | |
1113 // continue outer_loop; | |
1114 // } | |
1115 // } | |
1116 // return i - sourceOffset; | |
1117 // } | |
1118 // if ((cache & (1 << src)) == 0) { | |
1119 // i += targetCountLess1; | |
1120 // } // using "i += targetCount;" and an "else i++;" causes a jump to jump. | |
1121 // i++; | |
1122 // } | |
1123 // return -1; | |
1124 // } | |
1125 | |
1126 //------------------------------string_indexOf------------------------ | |
1127 Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_array, jint targetOffset_i, | |
1128 jint cache_i, jint md2_i) { | |
1129 | |
1130 Node* no_ctrl = NULL; | |
1131 float likely = PROB_LIKELY(0.9); | |
1132 float unlikely = PROB_UNLIKELY(0.9); | |
1133 | |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2324
diff
changeset
|
1134 const int nargs = 2; // number of arguments to push back for uncommon trap in predicate |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2324
diff
changeset
|
1135 |
0 | 1136 const int value_offset = java_lang_String::value_offset_in_bytes(); |
1137 const int count_offset = java_lang_String::count_offset_in_bytes(); | |
1138 const int offset_offset = java_lang_String::offset_offset_in_bytes(); | |
1139 | |
1140 ciInstanceKlass* klass = env()->String_klass(); | |
1496
e8e83be27dd7
6951190: assert(!klass_is_exact(),"only non-exact klass") while building JDK
never
parents:
1396
diff
changeset
|
1141 const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass); |
0 | 1142 const TypeAryPtr* source_type = TypeAryPtr::make(TypePtr::NotNull, TypeAry::make(TypeInt::CHAR,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR), true, 0); |
1143 | |
1144 Node* sourceOffseta = basic_plus_adr(string_object, string_object, offset_offset); | |
1145 Node* sourceOffset = make_load(no_ctrl, sourceOffseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset)); | |
1146 Node* sourceCounta = basic_plus_adr(string_object, string_object, count_offset); | |
1147 Node* sourceCount = make_load(no_ctrl, sourceCounta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); | |
1148 Node* sourcea = basic_plus_adr(string_object, string_object, value_offset); | |
1149 Node* source = make_load(no_ctrl, sourcea, source_type, T_OBJECT, string_type->add_offset(value_offset)); | |
1150 | |
2379
b099aaf51bf8
6962931: move interned strings out of the perm gen
jcoomes
parents:
2324
diff
changeset
|
1151 Node* target = _gvn.transform( makecon(TypeOopPtr::make_from_constant(target_array, true)) ); |
0 | 1152 jint target_length = target_array->length(); |
1153 const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin)); | |
1154 const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot); | |
1155 | |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
1156 IdealKit kit(this, false, true); |
0 | 1157 #define __ kit. |
1158 Node* zero = __ ConI(0); | |
1159 Node* one = __ ConI(1); | |
1160 Node* cache = __ ConI(cache_i); | |
1161 Node* md2 = __ ConI(md2_i); | |
1162 Node* lastChar = __ ConI(target_array->char_at(target_length - 1)); | |
1163 Node* targetCount = __ ConI(target_length); | |
1164 Node* targetCountLess1 = __ ConI(target_length - 1); | |
1165 Node* targetOffset = __ ConI(targetOffset_i); | |
1166 Node* sourceEnd = __ SubI(__ AddI(sourceOffset, sourceCount), targetCountLess1); | |
1167 | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
1168 IdealVariable rtn(kit), i(kit), j(kit); __ declarations_done(); |
0 | 1169 Node* outer_loop = __ make_label(2 /* goto */); |
1170 Node* return_ = __ make_label(1); | |
1171 | |
1172 __ set(rtn,__ ConI(-1)); | |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2324
diff
changeset
|
1173 __ loop(this, nargs, i, sourceOffset, BoolTest::lt, sourceEnd); { |
0 | 1174 Node* i2 = __ AddI(__ value(i), targetCountLess1); |
1175 // pin to prohibit loading of "next iteration" value which may SEGV (rare) | |
1176 Node* src = load_array_element(__ ctrl(), source, i2, TypeAryPtr::CHARS); | |
1177 __ if_then(src, BoolTest::eq, lastChar, unlikely); { | |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2324
diff
changeset
|
1178 __ loop(this, nargs, j, zero, BoolTest::lt, targetCountLess1); { |
0 | 1179 Node* tpj = __ AddI(targetOffset, __ value(j)); |
1180 Node* targ = load_array_element(no_ctrl, target, tpj, target_type); | |
1181 Node* ipj = __ AddI(__ value(i), __ value(j)); | |
1182 Node* src2 = load_array_element(no_ctrl, source, ipj, TypeAryPtr::CHARS); | |
1183 __ if_then(targ, BoolTest::ne, src2); { | |
1184 __ if_then(__ AndI(cache, __ LShiftI(one, src2)), BoolTest::eq, zero); { | |
1185 __ if_then(md2, BoolTest::lt, __ AddI(__ value(j), one)); { | |
1186 __ increment(i, __ AddI(__ value(j), one)); | |
1187 __ goto_(outer_loop); | |
1188 } __ end_if(); __ dead(j); | |
1189 }__ end_if(); __ dead(j); | |
1190 __ increment(i, md2); | |
1191 __ goto_(outer_loop); | |
1192 }__ end_if(); | |
1193 __ increment(j, one); | |
1194 }__ end_loop(); __ dead(j); | |
1195 __ set(rtn, __ SubI(__ value(i), sourceOffset)); __ dead(i); | |
1196 __ goto_(return_); | |
1197 }__ end_if(); | |
1198 __ if_then(__ AndI(cache, __ LShiftI(one, src)), BoolTest::eq, zero, likely); { | |
1199 __ increment(i, targetCountLess1); | |
1200 }__ end_if(); | |
1201 __ increment(i, one); | |
1202 __ bind(outer_loop); | |
1203 }__ end_loop(); __ dead(i); | |
1204 __ bind(return_); | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
1205 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
1206 // Final sync IdealKit and GraphKit. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
1207 final_sync(kit); |
0 | 1208 Node* result = __ value(rtn); |
1209 #undef __ | |
1210 C->set_has_loops(true); | |
1211 return result; | |
1212 } | |
1213 | |
1214 //------------------------------inline_string_indexOf------------------------ | |
1215 bool LibraryCallKit::inline_string_indexOf() { | |
1216 | |
1217 const int value_offset = java_lang_String::value_offset_in_bytes(); | |
1218 const int count_offset = java_lang_String::count_offset_in_bytes(); | |
1219 const int offset_offset = java_lang_String::offset_offset_in_bytes(); | |
1220 | |
1221 _sp += 2; | |
681 | 1222 Node *argument = pop(); // pop non-receiver first: it was pushed second |
1223 Node *receiver = pop(); | |
1224 | |
1225 Node* result; | |
1504
ae8f909e5fc7
6948602: Disable use of SSE4.2 in String.indexOf intrinsic until 6942326 is fixed
iveresov
parents:
1396
diff
changeset
|
1226 // Disable the use of pcmpestri until it can be guaranteed that |
ae8f909e5fc7
6948602: Disable use of SSE4.2 in String.indexOf intrinsic until 6942326 is fixed
iveresov
parents:
1396
diff
changeset
|
1227 // the load doesn't cross into the uncommited space. |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1228 if (Matcher::has_match_rule(Op_StrIndexOf) && |
681 | 1229 UseSSE42Intrinsics) { |
1230 // Generate SSE4.2 version of indexOf | |
1231 // We currently only have match rules that use SSE4.2 | |
1232 | |
1233 // Null check on self without removing any arguments. The argument | |
1234 // null check technically happens in the wrong place, which can lead to | |
1235 // invalid stack traces when string compare is inlined into a method | |
1236 // which handles NullPointerExceptions. | |
1237 _sp += 2; | |
1238 receiver = do_null_check(receiver, T_OBJECT); | |
1239 argument = do_null_check(argument, T_OBJECT); | |
1240 _sp -= 2; | |
1241 | |
1242 if (stopped()) { | |
1243 return true; | |
1244 } | |
1245 | |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1246 ciInstanceKlass* str_klass = env()->String_klass(); |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1247 const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(str_klass); |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1248 |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1249 // Make the merge point |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1250 RegionNode* result_rgn = new (C, 4) RegionNode(4); |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1251 Node* result_phi = new (C, 4) PhiNode(result_rgn, TypeInt::INT); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1252 Node* no_ctrl = NULL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1253 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1254 // Get counts for string and substr |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1255 Node* source_cnta = basic_plus_adr(receiver, receiver, count_offset); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1256 Node* source_cnt = make_load(no_ctrl, source_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1257 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1258 Node* substr_cnta = basic_plus_adr(argument, argument, count_offset); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1259 Node* substr_cnt = make_load(no_ctrl, substr_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1260 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1261 // Check for substr count > string count |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1262 Node* cmp = _gvn.transform( new(C, 3) CmpINode(substr_cnt, source_cnt) ); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1263 Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::gt) ); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1264 Node* if_gt = generate_slow_guard(bol, NULL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1265 if (if_gt != NULL) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1266 result_phi->init_req(2, intcon(-1)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1267 result_rgn->init_req(2, if_gt); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1268 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1269 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1270 if (!stopped()) { |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1271 // Check for substr count == 0 |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1272 cmp = _gvn.transform( new(C, 3) CmpINode(substr_cnt, intcon(0)) ); |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1273 bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::eq) ); |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1274 Node* if_zero = generate_slow_guard(bol, NULL); |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1275 if (if_zero != NULL) { |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1276 result_phi->init_req(3, intcon(0)); |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1277 result_rgn->init_req(3, if_zero); |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1278 } |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1279 } |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1280 |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1281 if (!stopped()) { |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1282 result = make_string_method_node(Op_StrIndexOf, receiver, source_cnt, argument, substr_cnt); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1283 result_phi->init_req(1, result); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1284 result_rgn->init_req(1, control()); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1285 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1286 set_control(_gvn.transform(result_rgn)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1287 record_for_igvn(result_rgn); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1288 result = _gvn.transform(result_phi); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1289 |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1290 } else { // Use LibraryCallKit::string_indexOf |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1291 // don't intrinsify if argument isn't a constant string. |
681 | 1292 if (!argument->is_Con()) { |
1293 return false; | |
1294 } | |
1295 const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr(); | |
1296 if (str_type == NULL) { | |
1297 return false; | |
1298 } | |
1299 ciInstanceKlass* klass = env()->String_klass(); | |
1300 ciObject* str_const = str_type->const_oop(); | |
1301 if (str_const == NULL || str_const->klass() != klass) { | |
1302 return false; | |
1303 } | |
1304 ciInstance* str = str_const->as_instance(); | |
1305 assert(str != NULL, "must be instance"); | |
1306 | |
1307 ciObject* v = str->field_value_by_offset(value_offset).as_object(); | |
1308 int o = str->field_value_by_offset(offset_offset).as_int(); | |
1309 int c = str->field_value_by_offset(count_offset).as_int(); | |
1310 ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array | |
1311 | |
1312 // constant strings have no offset and count == length which | |
1313 // simplifies the resulting code somewhat so lets optimize for that. | |
1314 if (o != 0 || c != pat->length()) { | |
1315 return false; | |
1316 } | |
1317 | |
1318 // Null check on self without removing any arguments. The argument | |
1319 // null check technically happens in the wrong place, which can lead to | |
1320 // invalid stack traces when string compare is inlined into a method | |
1321 // which handles NullPointerExceptions. | |
1322 _sp += 2; | |
1323 receiver = do_null_check(receiver, T_OBJECT); | |
1324 // No null check on the argument is needed since it's a constant String oop. | |
1325 _sp -= 2; | |
1326 if (stopped()) { | |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1327 return true; |
681 | 1328 } |
1329 | |
1330 // The null string as a pattern always returns 0 (match at beginning of string) | |
1331 if (c == 0) { | |
1332 push(intcon(0)); | |
1333 return true; | |
1334 } | |
1335 | |
1336 // Generate default indexOf | |
1337 jchar lastChar = pat->char_at(o + (c - 1)); | |
1338 int cache = 0; | |
1339 int i; | |
1340 for (i = 0; i < c - 1; i++) { | |
1341 assert(i < pat->length(), "out of range"); | |
1342 cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1))); | |
1343 } | |
1344 | |
1345 int md2 = c; | |
1346 for (i = 0; i < c - 1; i++) { | |
1347 assert(i < pat->length(), "out of range"); | |
1348 if (pat->char_at(o + i) == lastChar) { | |
1349 md2 = (c - 1) - i; | |
1350 } | |
1351 } | |
1352 | |
1353 result = string_indexOf(receiver, pat, o, cache, md2); | |
0 | 1354 } |
1355 | |
1356 push(result); | |
1357 return true; | |
1358 } | |
1359 | |
1360 //--------------------------pop_math_arg-------------------------------- | |
1361 // Pop a double argument to a math function from the stack | |
1362 // rounding it if necessary. | |
1363 Node * LibraryCallKit::pop_math_arg() { | |
1364 Node *arg = pop_pair(); | |
1365 if( Matcher::strict_fp_requires_explicit_rounding && UseSSE<=1 ) | |
1366 arg = _gvn.transform( new (C, 2) RoundDoubleNode(0, arg) ); | |
1367 return arg; | |
1368 } | |
1369 | |
1370 //------------------------------inline_trig---------------------------------- | |
1371 // Inline sin/cos/tan instructions, if possible. If rounding is required, do | |
1372 // argument reduction which will turn into a fast/slow diamond. | |
1373 bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) { | |
1374 _sp += arg_size(); // restore stack pointer | |
1375 Node* arg = pop_math_arg(); | |
1376 Node* trig = NULL; | |
1377 | |
1378 switch (id) { | |
1379 case vmIntrinsics::_dsin: | |
1380 trig = _gvn.transform((Node*)new (C, 2) SinDNode(arg)); | |
1381 break; | |
1382 case vmIntrinsics::_dcos: | |
1383 trig = _gvn.transform((Node*)new (C, 2) CosDNode(arg)); | |
1384 break; | |
1385 case vmIntrinsics::_dtan: | |
1386 trig = _gvn.transform((Node*)new (C, 2) TanDNode(arg)); | |
1387 break; | |
1388 default: | |
1389 assert(false, "bad intrinsic was passed in"); | |
1390 return false; | |
1391 } | |
1392 | |
1393 // Rounding required? Check for argument reduction! | |
1394 if( Matcher::strict_fp_requires_explicit_rounding ) { | |
1395 | |
1396 static const double pi_4 = 0.7853981633974483; | |
1397 static const double neg_pi_4 = -0.7853981633974483; | |
1398 // pi/2 in 80-bit extended precision | |
1399 // static const unsigned char pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00}; | |
1400 // -pi/2 in 80-bit extended precision | |
1401 // static const unsigned char neg_pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0xbf,0x00,0x00,0x00,0x00,0x00,0x00}; | |
1402 // Cutoff value for using this argument reduction technique | |
1403 //static const double pi_2_minus_epsilon = 1.564660403643354; | |
1404 //static const double neg_pi_2_plus_epsilon = -1.564660403643354; | |
1405 | |
1406 // Pseudocode for sin: | |
1407 // if (x <= Math.PI / 4.0) { | |
1408 // if (x >= -Math.PI / 4.0) return fsin(x); | |
1409 // if (x >= -Math.PI / 2.0) return -fcos(x + Math.PI / 2.0); | |
1410 // } else { | |
1411 // if (x <= Math.PI / 2.0) return fcos(x - Math.PI / 2.0); | |
1412 // } | |
1413 // return StrictMath.sin(x); | |
1414 | |
1415 // Pseudocode for cos: | |
1416 // if (x <= Math.PI / 4.0) { | |
1417 // if (x >= -Math.PI / 4.0) return fcos(x); | |
1418 // if (x >= -Math.PI / 2.0) return fsin(x + Math.PI / 2.0); | |
1419 // } else { | |
1420 // if (x <= Math.PI / 2.0) return -fsin(x - Math.PI / 2.0); | |
1421 // } | |
1422 // return StrictMath.cos(x); | |
1423 | |
1424 // Actually, sticking in an 80-bit Intel value into C2 will be tough; it | |
1425 // requires a special machine instruction to load it. Instead we'll try | |
1426 // the 'easy' case. If we really need the extra range +/- PI/2 we'll | |
1427 // probably do the math inside the SIN encoding. | |
1428 | |
1429 // Make the merge point | |
1430 RegionNode *r = new (C, 3) RegionNode(3); | |
1431 Node *phi = new (C, 3) PhiNode(r,Type::DOUBLE); | |
1432 | |
1433 // Flatten arg so we need only 1 test | |
1434 Node *abs = _gvn.transform(new (C, 2) AbsDNode(arg)); | |
1435 // Node for PI/4 constant | |
1436 Node *pi4 = makecon(TypeD::make(pi_4)); | |
1437 // Check PI/4 : abs(arg) | |
1438 Node *cmp = _gvn.transform(new (C, 3) CmpDNode(pi4,abs)); | |
1439 // Check: If PI/4 < abs(arg) then go slow | |
1440 Node *bol = _gvn.transform( new (C, 2) BoolNode( cmp, BoolTest::lt ) ); | |
1441 // Branch either way | |
1442 IfNode *iff = create_and_xform_if(control(),bol, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); | |
1443 set_control(opt_iff(r,iff)); | |
1444 | |
1445 // Set fast path result | |
1446 phi->init_req(2,trig); | |
1447 | |
1448 // Slow path - non-blocking leaf call | |
1449 Node* call = NULL; | |
1450 switch (id) { | |
1451 case vmIntrinsics::_dsin: | |
1452 call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(), | |
1453 CAST_FROM_FN_PTR(address, SharedRuntime::dsin), | |
1454 "Sin", NULL, arg, top()); | |
1455 break; | |
1456 case vmIntrinsics::_dcos: | |
1457 call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(), | |
1458 CAST_FROM_FN_PTR(address, SharedRuntime::dcos), | |
1459 "Cos", NULL, arg, top()); | |
1460 break; | |
1461 case vmIntrinsics::_dtan: | |
1462 call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(), | |
1463 CAST_FROM_FN_PTR(address, SharedRuntime::dtan), | |
1464 "Tan", NULL, arg, top()); | |
1465 break; | |
1466 } | |
1467 assert(control()->in(0) == call, ""); | |
1468 Node* slow_result = _gvn.transform(new (C, 1) ProjNode(call,TypeFunc::Parms)); | |
1469 r->init_req(1,control()); | |
1470 phi->init_req(1,slow_result); | |
1471 | |
1472 // Post-merge | |
1473 set_control(_gvn.transform(r)); | |
1474 record_for_igvn(r); | |
1475 trig = _gvn.transform(phi); | |
1476 | |
1477 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
1478 } | |
1479 // Push result back on JVM stack | |
1480 push_pair(trig); | |
1481 return true; | |
1482 } | |
1483 | |
1484 //------------------------------inline_sqrt------------------------------------- | |
1485 // Inline square root instruction, if possible. | |
1486 bool LibraryCallKit::inline_sqrt(vmIntrinsics::ID id) { | |
1487 assert(id == vmIntrinsics::_dsqrt, "Not square root"); | |
1488 _sp += arg_size(); // restore stack pointer | |
1489 push_pair(_gvn.transform(new (C, 2) SqrtDNode(0, pop_math_arg()))); | |
1490 return true; | |
1491 } | |
1492 | |
1493 //------------------------------inline_abs------------------------------------- | |
1494 // Inline absolute value instruction, if possible. | |
1495 bool LibraryCallKit::inline_abs(vmIntrinsics::ID id) { | |
1496 assert(id == vmIntrinsics::_dabs, "Not absolute value"); | |
1497 _sp += arg_size(); // restore stack pointer | |
1498 push_pair(_gvn.transform(new (C, 2) AbsDNode(pop_math_arg()))); | |
1499 return true; | |
1500 } | |
1501 | |
1502 //------------------------------inline_exp------------------------------------- | |
1503 // Inline exp instructions, if possible. The Intel hardware only misses | |
1504 // really odd corner cases (+/- Infinity). Just uncommon-trap them. | |
1505 bool LibraryCallKit::inline_exp(vmIntrinsics::ID id) { | |
1506 assert(id == vmIntrinsics::_dexp, "Not exp"); | |
1507 | |
1508 // If this inlining ever returned NaN in the past, we do not intrinsify it | |
1509 // every again. NaN results requires StrictMath.exp handling. | |
1510 if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; | |
1511 | |
1512 // Do not intrinsify on older platforms which lack cmove. | |
1513 if (ConditionalMoveLimit == 0) return false; | |
1514 | |
1515 _sp += arg_size(); // restore stack pointer | |
1516 Node *x = pop_math_arg(); | |
1517 Node *result = _gvn.transform(new (C, 2) ExpDNode(0,x)); | |
1518 | |
1519 //------------------- | |
1520 //result=(result.isNaN())? StrictMath::exp():result; | |
1521 // Check: If isNaN() by checking result!=result? then go to Strict Math | |
1522 Node* cmpisnan = _gvn.transform(new (C, 3) CmpDNode(result,result)); | |
1523 // Build the boolean node | |
1524 Node* bolisnum = _gvn.transform( new (C, 2) BoolNode(cmpisnan, BoolTest::eq) ); | |
1525 | |
1526 { BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT); | |
1527 // End the current control-flow path | |
1528 push_pair(x); | |
1529 // Math.exp intrinsic returned a NaN, which requires StrictMath.exp | |
1530 // to handle. Recompile without intrinsifying Math.exp | |
1531 uncommon_trap(Deoptimization::Reason_intrinsic, | |
1532 Deoptimization::Action_make_not_entrant); | |
1533 } | |
1534 | |
1535 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
1536 | |
1537 push_pair(result); | |
1538 | |
1539 return true; | |
1540 } | |
1541 | |
1542 //------------------------------inline_pow------------------------------------- | |
1543 // Inline power instructions, if possible. | |
1544 bool LibraryCallKit::inline_pow(vmIntrinsics::ID id) { | |
1545 assert(id == vmIntrinsics::_dpow, "Not pow"); | |
1546 | |
1547 // If this inlining ever returned NaN in the past, we do not intrinsify it | |
1548 // every again. NaN results requires StrictMath.pow handling. | |
1549 if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; | |
1550 | |
1551 // Do not intrinsify on older platforms which lack cmove. | |
1552 if (ConditionalMoveLimit == 0) return false; | |
1553 | |
1554 // Pseudocode for pow | |
1555 // if (x <= 0.0) { | |
1556 // if ((double)((int)y)==y) { // if y is int | |
1557 // result = ((1&(int)y)==0)?-DPow(abs(x), y):DPow(abs(x), y) | |
1558 // } else { | |
1559 // result = NaN; | |
1560 // } | |
1561 // } else { | |
1562 // result = DPow(x,y); | |
1563 // } | |
1564 // if (result != result)? { | |
605 | 1565 // uncommon_trap(); |
0 | 1566 // } |
1567 // return result; | |
1568 | |
1569 _sp += arg_size(); // restore stack pointer | |
1570 Node* y = pop_math_arg(); | |
1571 Node* x = pop_math_arg(); | |
1572 | |
1573 Node *fast_result = _gvn.transform( new (C, 3) PowDNode(0, x, y) ); | |
1574 | |
1575 // Short form: if not top-level (i.e., Math.pow but inlining Math.pow | |
1576 // inside of something) then skip the fancy tests and just check for | |
1577 // NaN result. | |
1578 Node *result = NULL; | |
1579 if( jvms()->depth() >= 1 ) { | |
1580 result = fast_result; | |
1581 } else { | |
1582 | |
1583 // Set the merge point for If node with condition of (x <= 0.0) | |
1584 // There are four possible paths to region node and phi node | |
1585 RegionNode *r = new (C, 4) RegionNode(4); | |
1586 Node *phi = new (C, 4) PhiNode(r, Type::DOUBLE); | |
1587 | |
1588 // Build the first if node: if (x <= 0.0) | |
1589 // Node for 0 constant | |
1590 Node *zeronode = makecon(TypeD::ZERO); | |
1591 // Check x:0 | |
1592 Node *cmp = _gvn.transform(new (C, 3) CmpDNode(x, zeronode)); | |
1593 // Check: If (x<=0) then go complex path | |
1594 Node *bol1 = _gvn.transform( new (C, 2) BoolNode( cmp, BoolTest::le ) ); | |
1595 // Branch either way | |
1596 IfNode *if1 = create_and_xform_if(control(),bol1, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN); | |
1597 Node *opt_test = _gvn.transform(if1); | |
1598 //assert( opt_test->is_If(), "Expect an IfNode"); | |
1599 IfNode *opt_if1 = (IfNode*)opt_test; | |
1600 // Fast path taken; set region slot 3 | |
1601 Node *fast_taken = _gvn.transform( new (C, 1) IfFalseNode(opt_if1) ); | |
1602 r->init_req(3,fast_taken); // Capture fast-control | |
1603 | |
1604 // Fast path not-taken, i.e. slow path | |
1605 Node *complex_path = _gvn.transform( new (C, 1) IfTrueNode(opt_if1) ); | |
1606 | |
1607 // Set fast path result | |
1608 Node *fast_result = _gvn.transform( new (C, 3) PowDNode(0, y, x) ); | |
1609 phi->init_req(3, fast_result); | |
1610 | |
1611 // Complex path | |
1612 // Build the second if node (if y is int) | |
1613 // Node for (int)y | |
1614 Node *inty = _gvn.transform( new (C, 2) ConvD2INode(y)); | |
1615 // Node for (double)((int) y) | |
1616 Node *doubleinty= _gvn.transform( new (C, 2) ConvI2DNode(inty)); | |
1617 // Check (double)((int) y) : y | |
1618 Node *cmpinty= _gvn.transform(new (C, 3) CmpDNode(doubleinty, y)); | |
1619 // Check if (y isn't int) then go to slow path | |
1620 | |
1621 Node *bol2 = _gvn.transform( new (C, 2) BoolNode( cmpinty, BoolTest::ne ) ); | |
605 | 1622 // Branch either way |
0 | 1623 IfNode *if2 = create_and_xform_if(complex_path,bol2, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN); |
1624 Node *slow_path = opt_iff(r,if2); // Set region path 2 | |
1625 | |
1626 // Calculate DPow(abs(x), y)*(1 & (int)y) | |
1627 // Node for constant 1 | |
1628 Node *conone = intcon(1); | |
1629 // 1& (int)y | |
1630 Node *signnode= _gvn.transform( new (C, 3) AndINode(conone, inty) ); | |
1631 // zero node | |
1632 Node *conzero = intcon(0); | |
1633 // Check (1&(int)y)==0? | |
1634 Node *cmpeq1 = _gvn.transform(new (C, 3) CmpINode(signnode, conzero)); | |
1635 // Check if (1&(int)y)!=0?, if so the result is negative | |
1636 Node *bol3 = _gvn.transform( new (C, 2) BoolNode( cmpeq1, BoolTest::ne ) ); | |
1637 // abs(x) | |
1638 Node *absx=_gvn.transform( new (C, 2) AbsDNode(x)); | |
1639 // abs(x)^y | |
1640 Node *absxpowy = _gvn.transform( new (C, 3) PowDNode(0, y, absx) ); | |
1641 // -abs(x)^y | |
1642 Node *negabsxpowy = _gvn.transform(new (C, 2) NegDNode (absxpowy)); | |
1643 // (1&(int)y)==1?-DPow(abs(x), y):DPow(abs(x), y) | |
1644 Node *signresult = _gvn.transform( CMoveNode::make(C, NULL, bol3, absxpowy, negabsxpowy, Type::DOUBLE)); | |
1645 // Set complex path fast result | |
1646 phi->init_req(2, signresult); | |
1647 | |
1648 static const jlong nan_bits = CONST64(0x7ff8000000000000); | |
1649 Node *slow_result = makecon(TypeD::make(*(double*)&nan_bits)); // return NaN | |
1650 r->init_req(1,slow_path); | |
1651 phi->init_req(1,slow_result); | |
1652 | |
1653 // Post merge | |
1654 set_control(_gvn.transform(r)); | |
1655 record_for_igvn(r); | |
1656 result=_gvn.transform(phi); | |
1657 } | |
1658 | |
1659 //------------------- | |
1660 //result=(result.isNaN())? uncommon_trap():result; | |
1661 // Check: If isNaN() by checking result!=result? then go to Strict Math | |
1662 Node* cmpisnan = _gvn.transform(new (C, 3) CmpDNode(result,result)); | |
1663 // Build the boolean node | |
1664 Node* bolisnum = _gvn.transform( new (C, 2) BoolNode(cmpisnan, BoolTest::eq) ); | |
1665 | |
1666 { BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT); | |
1667 // End the current control-flow path | |
1668 push_pair(x); | |
1669 push_pair(y); | |
1670 // Math.pow intrinsic returned a NaN, which requires StrictMath.pow | |
1671 // to handle. Recompile without intrinsifying Math.pow. | |
1672 uncommon_trap(Deoptimization::Reason_intrinsic, | |
1673 Deoptimization::Action_make_not_entrant); | |
1674 } | |
1675 | |
1676 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
1677 | |
1678 push_pair(result); | |
1679 | |
1680 return true; | |
1681 } | |
1682 | |
1683 //------------------------------inline_trans------------------------------------- | |
1684 // Inline transcendental instructions, if possible. The Intel hardware gets | |
1685 // these right, no funny corner cases missed. | |
1686 bool LibraryCallKit::inline_trans(vmIntrinsics::ID id) { | |
1687 _sp += arg_size(); // restore stack pointer | |
1688 Node* arg = pop_math_arg(); | |
1689 Node* trans = NULL; | |
1690 | |
1691 switch (id) { | |
1692 case vmIntrinsics::_dlog: | |
1693 trans = _gvn.transform((Node*)new (C, 2) LogDNode(arg)); | |
1694 break; | |
1695 case vmIntrinsics::_dlog10: | |
1696 trans = _gvn.transform((Node*)new (C, 2) Log10DNode(arg)); | |
1697 break; | |
1698 default: | |
1699 assert(false, "bad intrinsic was passed in"); | |
1700 return false; | |
1701 } | |
1702 | |
1703 // Push result back on JVM stack | |
1704 push_pair(trans); | |
1705 return true; | |
1706 } | |
1707 | |
1708 //------------------------------runtime_math----------------------------- | |
1709 bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName) { | |
1710 Node* a = NULL; | |
1711 Node* b = NULL; | |
1712 | |
1713 assert(call_type == OptoRuntime::Math_DD_D_Type() || call_type == OptoRuntime::Math_D_D_Type(), | |
1714 "must be (DD)D or (D)D type"); | |
1715 | |
1716 // Inputs | |
1717 _sp += arg_size(); // restore stack pointer | |
1718 if (call_type == OptoRuntime::Math_DD_D_Type()) { | |
1719 b = pop_math_arg(); | |
1720 } | |
1721 a = pop_math_arg(); | |
1722 | |
1723 const TypePtr* no_memory_effects = NULL; | |
1724 Node* trig = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName, | |
1725 no_memory_effects, | |
1726 a, top(), b, b ? top() : NULL); | |
1727 Node* value = _gvn.transform(new (C, 1) ProjNode(trig, TypeFunc::Parms+0)); | |
1728 #ifdef ASSERT | |
1729 Node* value_top = _gvn.transform(new (C, 1) ProjNode(trig, TypeFunc::Parms+1)); | |
1730 assert(value_top == top(), "second value must be top"); | |
1731 #endif | |
1732 | |
1733 push_pair(value); | |
1734 return true; | |
1735 } | |
1736 | |
1737 //------------------------------inline_math_native----------------------------- | |
1738 bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) { | |
1739 switch (id) { | |
1740 // These intrinsics are not properly supported on all hardware | |
1741 case vmIntrinsics::_dcos: return Matcher::has_match_rule(Op_CosD) ? inline_trig(id) : | |
1742 runtime_math(OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dcos), "COS"); | |
1743 case vmIntrinsics::_dsin: return Matcher::has_match_rule(Op_SinD) ? inline_trig(id) : | |
1744 runtime_math(OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dsin), "SIN"); | |
1745 case vmIntrinsics::_dtan: return Matcher::has_match_rule(Op_TanD) ? inline_trig(id) : | |
1746 runtime_math(OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dtan), "TAN"); | |
1747 | |
1748 case vmIntrinsics::_dlog: return Matcher::has_match_rule(Op_LogD) ? inline_trans(id) : | |
1749 runtime_math(OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dlog), "LOG"); | |
1750 case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_trans(id) : | |
1751 runtime_math(OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dlog10), "LOG10"); | |
1752 | |
1753 // These intrinsics are supported on all hardware | |
1754 case vmIntrinsics::_dsqrt: return Matcher::has_match_rule(Op_SqrtD) ? inline_sqrt(id) : false; | |
1755 case vmIntrinsics::_dabs: return Matcher::has_match_rule(Op_AbsD) ? inline_abs(id) : false; | |
1756 | |
1757 // These intrinsics don't work on X86. The ad implementation doesn't | |
1758 // handle NaN's properly. Instead of returning infinity, the ad | |
1759 // implementation returns a NaN on overflow. See bug: 6304089 | |
1760 // Once the ad implementations are fixed, change the code below | |
1761 // to match the intrinsics above | |
1762 | |
1763 case vmIntrinsics::_dexp: return | |
1764 runtime_math(OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP"); | |
1765 case vmIntrinsics::_dpow: return | |
1766 runtime_math(OptoRuntime::Math_DD_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dpow), "POW"); | |
1767 | |
1768 // These intrinsics are not yet correctly implemented | |
1769 case vmIntrinsics::_datan2: | |
1770 return false; | |
1771 | |
1772 default: | |
1773 ShouldNotReachHere(); | |
1774 return false; | |
1775 } | |
1776 } | |
1777 | |
1778 static bool is_simple_name(Node* n) { | |
1779 return (n->req() == 1 // constant | |
1780 || (n->is_Type() && n->as_Type()->type()->singleton()) | |
1781 || n->is_Proj() // parameter or return value | |
1782 || n->is_Phi() // local of some sort | |
1783 ); | |
1784 } | |
1785 | |
1786 //----------------------------inline_min_max----------------------------------- | |
1787 bool LibraryCallKit::inline_min_max(vmIntrinsics::ID id) { | |
1788 push(generate_min_max(id, argument(0), argument(1))); | |
1789 | |
1790 return true; | |
1791 } | |
1792 | |
1793 Node* | |
1794 LibraryCallKit::generate_min_max(vmIntrinsics::ID id, Node* x0, Node* y0) { | |
1795 // These are the candidate return value: | |
1796 Node* xvalue = x0; | |
1797 Node* yvalue = y0; | |
1798 | |
1799 if (xvalue == yvalue) { | |
1800 return xvalue; | |
1801 } | |
1802 | |
1803 bool want_max = (id == vmIntrinsics::_max); | |
1804 | |
1805 const TypeInt* txvalue = _gvn.type(xvalue)->isa_int(); | |
1806 const TypeInt* tyvalue = _gvn.type(yvalue)->isa_int(); | |
1807 if (txvalue == NULL || tyvalue == NULL) return top(); | |
1808 // This is not really necessary, but it is consistent with a | |
1809 // hypothetical MaxINode::Value method: | |
1810 int widen = MAX2(txvalue->_widen, tyvalue->_widen); | |
1811 | |
1812 // %%% This folding logic should (ideally) be in a different place. | |
1813 // Some should be inside IfNode, and there to be a more reliable | |
1814 // transformation of ?: style patterns into cmoves. We also want | |
1815 // more powerful optimizations around cmove and min/max. | |
1816 | |
1817 // Try to find a dominating comparison of these guys. | |
1818 // It can simplify the index computation for Arrays.copyOf | |
1819 // and similar uses of System.arraycopy. | |
1820 // First, compute the normalized version of CmpI(x, y). | |
1821 int cmp_op = Op_CmpI; | |
1822 Node* xkey = xvalue; | |
1823 Node* ykey = yvalue; | |
1824 Node* ideal_cmpxy = _gvn.transform( new(C, 3) CmpINode(xkey, ykey) ); | |
1825 if (ideal_cmpxy->is_Cmp()) { | |
1826 // E.g., if we have CmpI(length - offset, count), | |
1827 // it might idealize to CmpI(length, count + offset) | |
1828 cmp_op = ideal_cmpxy->Opcode(); | |
1829 xkey = ideal_cmpxy->in(1); | |
1830 ykey = ideal_cmpxy->in(2); | |
1831 } | |
1832 | |
1833 // Start by locating any relevant comparisons. | |
1834 Node* start_from = (xkey->outcnt() < ykey->outcnt()) ? xkey : ykey; | |
1835 Node* cmpxy = NULL; | |
1836 Node* cmpyx = NULL; | |
1837 for (DUIterator_Fast kmax, k = start_from->fast_outs(kmax); k < kmax; k++) { | |
1838 Node* cmp = start_from->fast_out(k); | |
1839 if (cmp->outcnt() > 0 && // must have prior uses | |
1840 cmp->in(0) == NULL && // must be context-independent | |
1841 cmp->Opcode() == cmp_op) { // right kind of compare | |
1842 if (cmp->in(1) == xkey && cmp->in(2) == ykey) cmpxy = cmp; | |
1843 if (cmp->in(1) == ykey && cmp->in(2) == xkey) cmpyx = cmp; | |
1844 } | |
1845 } | |
1846 | |
1847 const int NCMPS = 2; | |
1848 Node* cmps[NCMPS] = { cmpxy, cmpyx }; | |
1849 int cmpn; | |
1850 for (cmpn = 0; cmpn < NCMPS; cmpn++) { | |
1851 if (cmps[cmpn] != NULL) break; // find a result | |
1852 } | |
1853 if (cmpn < NCMPS) { | |
1854 // Look for a dominating test that tells us the min and max. | |
1855 int depth = 0; // Limit search depth for speed | |
1856 Node* dom = control(); | |
1857 for (; dom != NULL; dom = IfNode::up_one_dom(dom, true)) { | |
1858 if (++depth >= 100) break; | |
1859 Node* ifproj = dom; | |
1860 if (!ifproj->is_Proj()) continue; | |
1861 Node* iff = ifproj->in(0); | |
1862 if (!iff->is_If()) continue; | |
1863 Node* bol = iff->in(1); | |
1864 if (!bol->is_Bool()) continue; | |
1865 Node* cmp = bol->in(1); | |
1866 if (cmp == NULL) continue; | |
1867 for (cmpn = 0; cmpn < NCMPS; cmpn++) | |
1868 if (cmps[cmpn] == cmp) break; | |
1869 if (cmpn == NCMPS) continue; | |
1870 BoolTest::mask btest = bol->as_Bool()->_test._test; | |
1871 if (ifproj->is_IfFalse()) btest = BoolTest(btest).negate(); | |
1872 if (cmp->in(1) == ykey) btest = BoolTest(btest).commute(); | |
1873 // At this point, we know that 'x btest y' is true. | |
1874 switch (btest) { | |
1875 case BoolTest::eq: | |
1876 // They are proven equal, so we can collapse the min/max. | |
1877 // Either value is the answer. Choose the simpler. | |
1878 if (is_simple_name(yvalue) && !is_simple_name(xvalue)) | |
1879 return yvalue; | |
1880 return xvalue; | |
1881 case BoolTest::lt: // x < y | |
1882 case BoolTest::le: // x <= y | |
1883 return (want_max ? yvalue : xvalue); | |
1884 case BoolTest::gt: // x > y | |
1885 case BoolTest::ge: // x >= y | |
1886 return (want_max ? xvalue : yvalue); | |
1887 } | |
1888 } | |
1889 } | |
1890 | |
1891 // We failed to find a dominating test. | |
1892 // Let's pick a test that might GVN with prior tests. | |
1893 Node* best_bol = NULL; | |
1894 BoolTest::mask best_btest = BoolTest::illegal; | |
1895 for (cmpn = 0; cmpn < NCMPS; cmpn++) { | |
1896 Node* cmp = cmps[cmpn]; | |
1897 if (cmp == NULL) continue; | |
1898 for (DUIterator_Fast jmax, j = cmp->fast_outs(jmax); j < jmax; j++) { | |
1899 Node* bol = cmp->fast_out(j); | |
1900 if (!bol->is_Bool()) continue; | |
1901 BoolTest::mask btest = bol->as_Bool()->_test._test; | |
1902 if (btest == BoolTest::eq || btest == BoolTest::ne) continue; | |
1903 if (cmp->in(1) == ykey) btest = BoolTest(btest).commute(); | |
1904 if (bol->outcnt() > (best_bol == NULL ? 0 : best_bol->outcnt())) { | |
1905 best_bol = bol->as_Bool(); | |
1906 best_btest = btest; | |
1907 } | |
1908 } | |
1909 } | |
1910 | |
1911 Node* answer_if_true = NULL; | |
1912 Node* answer_if_false = NULL; | |
1913 switch (best_btest) { | |
1914 default: | |
1915 if (cmpxy == NULL) | |
1916 cmpxy = ideal_cmpxy; | |
1917 best_bol = _gvn.transform( new(C, 2) BoolNode(cmpxy, BoolTest::lt) ); | |
1918 // and fall through: | |
1919 case BoolTest::lt: // x < y | |
1920 case BoolTest::le: // x <= y | |
1921 answer_if_true = (want_max ? yvalue : xvalue); | |
1922 answer_if_false = (want_max ? xvalue : yvalue); | |
1923 break; | |
1924 case BoolTest::gt: // x > y | |
1925 case BoolTest::ge: // x >= y | |
1926 answer_if_true = (want_max ? xvalue : yvalue); | |
1927 answer_if_false = (want_max ? yvalue : xvalue); | |
1928 break; | |
1929 } | |
1930 | |
1931 jint hi, lo; | |
1932 if (want_max) { | |
1933 // We can sharpen the minimum. | |
1934 hi = MAX2(txvalue->_hi, tyvalue->_hi); | |
1935 lo = MAX2(txvalue->_lo, tyvalue->_lo); | |
1936 } else { | |
1937 // We can sharpen the maximum. | |
1938 hi = MIN2(txvalue->_hi, tyvalue->_hi); | |
1939 lo = MIN2(txvalue->_lo, tyvalue->_lo); | |
1940 } | |
1941 | |
1942 // Use a flow-free graph structure, to avoid creating excess control edges | |
1943 // which could hinder other optimizations. | |
1944 // Since Math.min/max is often used with arraycopy, we want | |
1945 // tightly_coupled_allocation to be able to see beyond min/max expressions. | |
1946 Node* cmov = CMoveNode::make(C, NULL, best_bol, | |
1947 answer_if_false, answer_if_true, | |
1948 TypeInt::make(lo, hi, widen)); | |
1949 | |
1950 return _gvn.transform(cmov); | |
1951 | |
1952 /* | |
1953 // This is not as desirable as it may seem, since Min and Max | |
1954 // nodes do not have a full set of optimizations. | |
1955 // And they would interfere, anyway, with 'if' optimizations | |
1956 // and with CMoveI canonical forms. | |
1957 switch (id) { | |
1958 case vmIntrinsics::_min: | |
1959 result_val = _gvn.transform(new (C, 3) MinINode(x,y)); break; | |
1960 case vmIntrinsics::_max: | |
1961 result_val = _gvn.transform(new (C, 3) MaxINode(x,y)); break; | |
1962 default: | |
1963 ShouldNotReachHere(); | |
1964 } | |
1965 */ | |
1966 } | |
1967 | |
1968 inline int | |
1969 LibraryCallKit::classify_unsafe_addr(Node* &base, Node* &offset) { | |
1970 const TypePtr* base_type = TypePtr::NULL_PTR; | |
1971 if (base != NULL) base_type = _gvn.type(base)->isa_ptr(); | |
1972 if (base_type == NULL) { | |
1973 // Unknown type. | |
1974 return Type::AnyPtr; | |
1975 } else if (base_type == TypePtr::NULL_PTR) { | |
1976 // Since this is a NULL+long form, we have to switch to a rawptr. | |
1977 base = _gvn.transform( new (C, 2) CastX2PNode(offset) ); | |
1978 offset = MakeConX(0); | |
1979 return Type::RawPtr; | |
1980 } else if (base_type->base() == Type::RawPtr) { | |
1981 return Type::RawPtr; | |
1982 } else if (base_type->isa_oopptr()) { | |
1983 // Base is never null => always a heap address. | |
1984 if (base_type->ptr() == TypePtr::NotNull) { | |
1985 return Type::OopPtr; | |
1986 } | |
1987 // Offset is small => always a heap address. | |
1988 const TypeX* offset_type = _gvn.type(offset)->isa_intptr_t(); | |
1989 if (offset_type != NULL && | |
1990 base_type->offset() == 0 && // (should always be?) | |
1991 offset_type->_lo >= 0 && | |
1992 !MacroAssembler::needs_explicit_null_check(offset_type->_hi)) { | |
1993 return Type::OopPtr; | |
1994 } | |
1995 // Otherwise, it might either be oop+off or NULL+addr. | |
1996 return Type::AnyPtr; | |
1997 } else { | |
1998 // No information: | |
1999 return Type::AnyPtr; | |
2000 } | |
2001 } | |
2002 | |
2003 inline Node* LibraryCallKit::make_unsafe_address(Node* base, Node* offset) { | |
2004 int kind = classify_unsafe_addr(base, offset); | |
2005 if (kind == Type::RawPtr) { | |
2006 return basic_plus_adr(top(), base, offset); | |
2007 } else { | |
2008 return basic_plus_adr(base, offset); | |
2009 } | |
2010 } | |
2011 | |
775
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2012 //-------------------inline_numberOfLeadingZeros_int/long----------------------- |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2013 // inline int Integer.numberOfLeadingZeros(int) |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2014 // inline int Long.numberOfLeadingZeros(long) |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2015 bool LibraryCallKit::inline_numberOfLeadingZeros(vmIntrinsics::ID id) { |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2016 assert(id == vmIntrinsics::_numberOfLeadingZeros_i || id == vmIntrinsics::_numberOfLeadingZeros_l, "not numberOfLeadingZeros"); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2017 if (id == vmIntrinsics::_numberOfLeadingZeros_i && !Matcher::match_rule_supported(Op_CountLeadingZerosI)) return false; |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2018 if (id == vmIntrinsics::_numberOfLeadingZeros_l && !Matcher::match_rule_supported(Op_CountLeadingZerosL)) return false; |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2019 _sp += arg_size(); // restore stack pointer |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2020 switch (id) { |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2021 case vmIntrinsics::_numberOfLeadingZeros_i: |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2022 push(_gvn.transform(new (C, 2) CountLeadingZerosINode(pop()))); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2023 break; |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2024 case vmIntrinsics::_numberOfLeadingZeros_l: |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2025 push(_gvn.transform(new (C, 2) CountLeadingZerosLNode(pop_pair()))); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2026 break; |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2027 default: |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2028 ShouldNotReachHere(); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2029 } |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2030 return true; |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2031 } |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2032 |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2033 //-------------------inline_numberOfTrailingZeros_int/long---------------------- |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2034 // inline int Integer.numberOfTrailingZeros(int) |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2035 // inline int Long.numberOfTrailingZeros(long) |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2036 bool LibraryCallKit::inline_numberOfTrailingZeros(vmIntrinsics::ID id) { |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2037 assert(id == vmIntrinsics::_numberOfTrailingZeros_i || id == vmIntrinsics::_numberOfTrailingZeros_l, "not numberOfTrailingZeros"); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2038 if (id == vmIntrinsics::_numberOfTrailingZeros_i && !Matcher::match_rule_supported(Op_CountTrailingZerosI)) return false; |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2039 if (id == vmIntrinsics::_numberOfTrailingZeros_l && !Matcher::match_rule_supported(Op_CountTrailingZerosL)) return false; |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2040 _sp += arg_size(); // restore stack pointer |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2041 switch (id) { |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2042 case vmIntrinsics::_numberOfTrailingZeros_i: |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2043 push(_gvn.transform(new (C, 2) CountTrailingZerosINode(pop()))); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2044 break; |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2045 case vmIntrinsics::_numberOfTrailingZeros_l: |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2046 push(_gvn.transform(new (C, 2) CountTrailingZerosLNode(pop_pair()))); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2047 break; |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2048 default: |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2049 ShouldNotReachHere(); |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2050 } |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2051 return true; |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2052 } |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2053 |
643
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2054 //----------------------------inline_bitCount_int/long----------------------- |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2055 // inline int Integer.bitCount(int) |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2056 // inline int Long.bitCount(long) |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2057 bool LibraryCallKit::inline_bitCount(vmIntrinsics::ID id) { |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2058 assert(id == vmIntrinsics::_bitCount_i || id == vmIntrinsics::_bitCount_l, "not bitCount"); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2059 if (id == vmIntrinsics::_bitCount_i && !Matcher::has_match_rule(Op_PopCountI)) return false; |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2060 if (id == vmIntrinsics::_bitCount_l && !Matcher::has_match_rule(Op_PopCountL)) return false; |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2061 _sp += arg_size(); // restore stack pointer |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2062 switch (id) { |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2063 case vmIntrinsics::_bitCount_i: |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2064 push(_gvn.transform(new (C, 2) PopCountINode(pop()))); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2065 break; |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2066 case vmIntrinsics::_bitCount_l: |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2067 push(_gvn.transform(new (C, 2) PopCountLNode(pop_pair()))); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2068 break; |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2069 default: |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2070 ShouldNotReachHere(); |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2071 } |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2072 return true; |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2073 } |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
2074 |
1396
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2075 //----------------------------inline_reverseBytes_int/long/char/short------------------- |
605 | 2076 // inline Integer.reverseBytes(int) |
2077 // inline Long.reverseBytes(long) | |
1396
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2078 // inline Character.reverseBytes(char) |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2079 // inline Short.reverseBytes(short) |
0 | 2080 bool LibraryCallKit::inline_reverseBytes(vmIntrinsics::ID id) { |
1396
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2081 assert(id == vmIntrinsics::_reverseBytes_i || id == vmIntrinsics::_reverseBytes_l || |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2082 id == vmIntrinsics::_reverseBytes_c || id == vmIntrinsics::_reverseBytes_s, |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2083 "not reverse Bytes"); |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2084 if (id == vmIntrinsics::_reverseBytes_i && !Matcher::has_match_rule(Op_ReverseBytesI)) return false; |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2085 if (id == vmIntrinsics::_reverseBytes_l && !Matcher::has_match_rule(Op_ReverseBytesL)) return false; |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2086 if (id == vmIntrinsics::_reverseBytes_c && !Matcher::has_match_rule(Op_ReverseBytesUS)) return false; |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2087 if (id == vmIntrinsics::_reverseBytes_s && !Matcher::has_match_rule(Op_ReverseBytesS)) return false; |
0 | 2088 _sp += arg_size(); // restore stack pointer |
2089 switch (id) { | |
2090 case vmIntrinsics::_reverseBytes_i: | |
2091 push(_gvn.transform(new (C, 2) ReverseBytesINode(0, pop()))); | |
2092 break; | |
2093 case vmIntrinsics::_reverseBytes_l: | |
2094 push_pair(_gvn.transform(new (C, 2) ReverseBytesLNode(0, pop_pair()))); | |
2095 break; | |
1396
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2096 case vmIntrinsics::_reverseBytes_c: |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2097 push(_gvn.transform(new (C, 2) ReverseBytesUSNode(0, pop()))); |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2098 break; |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2099 case vmIntrinsics::_reverseBytes_s: |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2100 push(_gvn.transform(new (C, 2) ReverseBytesSNode(0, pop()))); |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
2101 break; |
0 | 2102 default: |
2103 ; | |
2104 } | |
2105 return true; | |
2106 } | |
2107 | |
2108 //----------------------------inline_unsafe_access---------------------------- | |
2109 | |
2110 const static BasicType T_ADDRESS_HOLDER = T_LONG; | |
2111 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2112 // Helper that guards and inserts a G1 pre-barrier. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2113 void LibraryCallKit::insert_g1_pre_barrier(Node* base_oop, Node* offset, Node* pre_val) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2114 assert(UseG1GC, "should not call this otherwise"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2115 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2116 // We could be accessing the referent field of a reference object. If so, when G1 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2117 // is enabled, we need to log the value in the referent field in an SATB buffer. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2118 // This routine performs some compile time filters and generates suitable |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2119 // runtime filters that guard the pre-barrier code. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2120 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2121 // Some compile time checks. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2122 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2123 // If offset is a constant, is it java_lang_ref_Reference::_reference_offset? |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2124 const TypeX* otype = offset->find_intptr_t_type(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2125 if (otype != NULL && otype->is_con() && |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2126 otype->get_con() != java_lang_ref_Reference::referent_offset) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2127 // Constant offset but not the reference_offset so just return |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2128 return; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2129 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2130 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2131 // We only need to generate the runtime guards for instances. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2132 const TypeOopPtr* btype = base_oop->bottom_type()->isa_oopptr(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2133 if (btype != NULL) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2134 if (btype->isa_aryptr()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2135 // Array type so nothing to do |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2136 return; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2137 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2138 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2139 const TypeInstPtr* itype = btype->isa_instptr(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2140 if (itype != NULL) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2141 // Can the klass of base_oop be statically determined |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2142 // to be _not_ a sub-class of Reference? |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2143 ciKlass* klass = itype->klass(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2144 if (klass->is_subtype_of(env()->Reference_klass()) && |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2145 !env()->Reference_klass()->is_subtype_of(klass)) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2146 return; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2147 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2148 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2149 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2150 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2151 // The compile time filters did not reject base_oop/offset so |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2152 // we need to generate the following runtime filters |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2153 // |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2154 // if (offset == java_lang_ref_Reference::_reference_offset) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2155 // if (base != null) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2156 // if (klass(base)->reference_type() != REF_NONE)) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2157 // pre_barrier(_, pre_val, ...); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2158 // } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2159 // } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2160 // } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2161 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2162 float likely = PROB_LIKELY(0.999); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2163 float unlikely = PROB_UNLIKELY(0.999); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2164 |
3255 | 2165 IdealKit ideal(this); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2166 #define __ ideal. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2167 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2168 const int reference_type_offset = instanceKlass::reference_type_offset_in_bytes() + |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2169 sizeof(oopDesc); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2170 |
3254
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3252
diff
changeset
|
2171 Node* referent_off = __ ConX(java_lang_ref_Reference::referent_offset); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2172 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2173 __ if_then(offset, BoolTest::eq, referent_off, unlikely); { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2174 __ if_then(base_oop, BoolTest::ne, null(), likely); { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2175 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2176 // Update graphKit memory and control from IdealKit. |
3255 | 2177 sync_kit(ideal); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2178 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2179 Node* ref_klass_con = makecon(TypeKlassPtr::make(env()->Reference_klass())); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2180 Node* is_instof = gen_instanceof(base_oop, ref_klass_con); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2181 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2182 // Update IdealKit memory and control from graphKit. |
3255 | 2183 __ sync_kit(this); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2184 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2185 Node* one = __ ConI(1); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2186 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2187 __ if_then(is_instof, BoolTest::eq, one, unlikely); { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2188 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2189 // Update graphKit from IdeakKit. |
3255 | 2190 sync_kit(ideal); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2191 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2192 // Use the pre-barrier to record the value in the referent field |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2193 pre_barrier(false /* do_load */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2194 __ ctrl(), |
3258
edd9b016deb6
7036021: G1: build failure on win64 and linux with hs21 in jdk6 build environment
johnc
parents:
3255
diff
changeset
|
2195 NULL /* obj */, NULL /* adr */, max_juint /* alias_idx */, NULL /* val */, NULL /* val_type */, |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2196 pre_val /* pre_val */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2197 T_OBJECT); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2198 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2199 // Update IdealKit from graphKit. |
3255 | 2200 __ sync_kit(this); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2201 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2202 } __ end_if(); // _ref_type != ref_none |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2203 } __ end_if(); // base != NULL |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2204 } __ end_if(); // offset == referent_offset |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2205 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2206 // Final sync IdealKit and GraphKit. |
3255 | 2207 final_sync(ideal); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2208 #undef __ |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2209 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2210 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2211 |
0 | 2212 // Interpret Unsafe.fieldOffset cookies correctly: |
2213 extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset); | |
2214 | |
2215 bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile) { | |
2216 if (callee()->is_static()) return false; // caller must have the capability! | |
2217 | |
2218 #ifndef PRODUCT | |
2219 { | |
2220 ResourceMark rm; | |
2221 // Check the signatures. | |
2222 ciSignature* sig = signature(); | |
2223 #ifdef ASSERT | |
2224 if (!is_store) { | |
2225 // Object getObject(Object base, int/long offset), etc. | |
2226 BasicType rtype = sig->return_type()->basic_type(); | |
2227 if (rtype == T_ADDRESS_HOLDER && callee()->name() == ciSymbol::getAddress_name()) | |
2228 rtype = T_ADDRESS; // it is really a C void* | |
2229 assert(rtype == type, "getter must return the expected value"); | |
2230 if (!is_native_ptr) { | |
2231 assert(sig->count() == 2, "oop getter has 2 arguments"); | |
2232 assert(sig->type_at(0)->basic_type() == T_OBJECT, "getter base is object"); | |
2233 assert(sig->type_at(1)->basic_type() == T_LONG, "getter offset is correct"); | |
2234 } else { | |
2235 assert(sig->count() == 1, "native getter has 1 argument"); | |
2236 assert(sig->type_at(0)->basic_type() == T_LONG, "getter base is long"); | |
2237 } | |
2238 } else { | |
2239 // void putObject(Object base, int/long offset, Object x), etc. | |
2240 assert(sig->return_type()->basic_type() == T_VOID, "putter must not return a value"); | |
2241 if (!is_native_ptr) { | |
2242 assert(sig->count() == 3, "oop putter has 3 arguments"); | |
2243 assert(sig->type_at(0)->basic_type() == T_OBJECT, "putter base is object"); | |
2244 assert(sig->type_at(1)->basic_type() == T_LONG, "putter offset is correct"); | |
2245 } else { | |
2246 assert(sig->count() == 2, "native putter has 2 arguments"); | |
2247 assert(sig->type_at(0)->basic_type() == T_LONG, "putter base is long"); | |
2248 } | |
2249 BasicType vtype = sig->type_at(sig->count()-1)->basic_type(); | |
2250 if (vtype == T_ADDRESS_HOLDER && callee()->name() == ciSymbol::putAddress_name()) | |
2251 vtype = T_ADDRESS; // it is really a C void* | |
2252 assert(vtype == type, "putter must accept the expected value"); | |
2253 } | |
2254 #endif // ASSERT | |
2255 } | |
2256 #endif //PRODUCT | |
2257 | |
2258 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
2259 | |
2260 int type_words = type2size[ (type == T_ADDRESS) ? T_LONG : type ]; | |
2261 | |
2262 // Argument words: "this" plus (oop/offset) or (lo/hi) args plus maybe 1 or 2 value words | |
2263 int nargs = 1 + (is_native_ptr ? 2 : 3) + (is_store ? type_words : 0); | |
2264 | |
2265 debug_only(int saved_sp = _sp); | |
2266 _sp += nargs; | |
2267 | |
2268 Node* val; | |
2269 debug_only(val = (Node*)(uintptr_t)-1); | |
2270 | |
2271 | |
2272 if (is_store) { | |
2273 // Get the value being stored. (Pop it first; it was pushed last.) | |
2274 switch (type) { | |
2275 case T_DOUBLE: | |
2276 case T_LONG: | |
2277 case T_ADDRESS: | |
2278 val = pop_pair(); | |
2279 break; | |
2280 default: | |
2281 val = pop(); | |
2282 } | |
2283 } | |
2284 | |
2285 // Build address expression. See the code in inline_unsafe_prefetch. | |
2286 Node *adr; | |
2287 Node *heap_base_oop = top(); | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2288 Node* offset = top(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2289 |
0 | 2290 if (!is_native_ptr) { |
2291 // The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2292 offset = pop_pair(); |
0 | 2293 // The base is either a Java object or a value produced by Unsafe.staticFieldBase |
2294 Node* base = pop(); | |
2295 // We currently rely on the cookies produced by Unsafe.xxxFieldOffset | |
2296 // to be plain byte offsets, which are also the same as those accepted | |
2297 // by oopDesc::field_base. | |
2298 assert(Unsafe_field_offset_to_byte_offset(11) == 11, | |
2299 "fieldOffset must be byte-scaled"); | |
2300 // 32-bit machines ignore the high half! | |
2301 offset = ConvL2X(offset); | |
2302 adr = make_unsafe_address(base, offset); | |
2303 heap_base_oop = base; | |
2304 } else { | |
2305 Node* ptr = pop_pair(); | |
2306 // Adjust Java long to machine word: | |
2307 ptr = ConvL2X(ptr); | |
2308 adr = make_unsafe_address(NULL, ptr); | |
2309 } | |
2310 | |
2311 // Pop receiver last: it was pushed first. | |
2312 Node *receiver = pop(); | |
2313 | |
2314 assert(saved_sp == _sp, "must have correct argument count"); | |
2315 | |
2316 const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); | |
2317 | |
2318 // First guess at the value type. | |
2319 const Type *value_type = Type::get_const_basic_type(type); | |
2320 | |
2321 // Try to categorize the address. If it comes up as TypeJavaPtr::BOTTOM, | |
2322 // there was not enough information to nail it down. | |
2323 Compile::AliasType* alias_type = C->alias_type(adr_type); | |
2324 assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here"); | |
2325 | |
2326 // We will need memory barriers unless we can determine a unique | |
2327 // alias category for this reference. (Note: If for some reason | |
2328 // the barriers get omitted and the unsafe reference begins to "pollute" | |
2329 // the alias analysis of the rest of the graph, either Compile::can_alias | |
2330 // or Compile::must_alias will throw a diagnostic assert.) | |
2331 bool need_mem_bar = (alias_type->adr_type() == TypeOopPtr::BOTTOM); | |
2332 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2333 // If we are reading the value of the referent field of a Reference |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2334 // object (either by using Unsafe directly or through reflection) |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2335 // then, if G1 is enabled, we need to record the referent in an |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2336 // SATB log buffer using the pre-barrier mechanism. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2337 bool need_read_barrier = UseG1GC && !is_native_ptr && !is_store && |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2338 offset != top() && heap_base_oop != top(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2339 |
0 | 2340 if (!is_store && type == T_OBJECT) { |
2341 // Attempt to infer a sharper value type from the offset and base type. | |
2342 ciKlass* sharpened_klass = NULL; | |
2343 | |
2344 // See if it is an instance field, with an object type. | |
2345 if (alias_type->field() != NULL) { | |
2346 assert(!is_native_ptr, "native pointer op cannot use a java address"); | |
2347 if (alias_type->field()->type()->is_klass()) { | |
2348 sharpened_klass = alias_type->field()->type()->as_klass(); | |
2349 } | |
2350 } | |
2351 | |
2352 // See if it is a narrow oop array. | |
2353 if (adr_type->isa_aryptr()) { | |
895
94b6d06fd759
6860920: serialize.cpp shouldn't use objArrayOopDesc::base_offset_in_bytes(T_BYTE)
twisti
parents:
851
diff
changeset
|
2354 if (adr_type->offset() >= objArrayOopDesc::base_offset_in_bytes()) { |
0 | 2355 const TypeOopPtr *elem_type = adr_type->is_aryptr()->elem()->isa_oopptr(); |
2356 if (elem_type != NULL) { | |
2357 sharpened_klass = elem_type->klass(); | |
2358 } | |
2359 } | |
2360 } | |
2361 | |
2362 if (sharpened_klass != NULL) { | |
2363 const TypeOopPtr* tjp = TypeOopPtr::make_from_klass(sharpened_klass); | |
2364 | |
2365 // Sharpen the value type. | |
2366 value_type = tjp; | |
2367 | |
2368 #ifndef PRODUCT | |
2369 if (PrintIntrinsics || PrintInlining || PrintOptoInlining) { | |
2370 tty->print(" from base type: "); adr_type->dump(); | |
2371 tty->print(" sharpened value: "); value_type->dump(); | |
2372 } | |
2373 #endif | |
2374 } | |
2375 } | |
2376 | |
2377 // Null check on self without removing any arguments. The argument | |
2378 // null check technically happens in the wrong place, which can lead to | |
2379 // invalid stack traces when the primitive is inlined into a method | |
2380 // which handles NullPointerExceptions. | |
2381 _sp += nargs; | |
2382 do_null_check(receiver, T_OBJECT); | |
2383 _sp -= nargs; | |
2384 if (stopped()) { | |
2385 return true; | |
2386 } | |
2387 // Heap pointers get a null-check from the interpreter, | |
2388 // as a courtesy. However, this is not guaranteed by Unsafe, | |
2389 // and it is not possible to fully distinguish unintended nulls | |
2390 // from intended ones in this API. | |
2391 | |
2392 if (is_volatile) { | |
2393 // We need to emit leading and trailing CPU membars (see below) in | |
2394 // addition to memory membars when is_volatile. This is a little | |
2395 // too strong, but avoids the need to insert per-alias-type | |
2396 // volatile membars (for stores; compare Parse::do_put_xxx), which | |
605 | 2397 // we cannot do effectively here because we probably only have a |
0 | 2398 // rough approximation of type. |
2399 need_mem_bar = true; | |
2400 // For Stores, place a memory ordering barrier now. | |
2401 if (is_store) | |
2402 insert_mem_bar(Op_MemBarRelease); | |
2403 } | |
2404 | |
2405 // Memory barrier to prevent normal and 'unsafe' accesses from | |
2406 // bypassing each other. Happens after null checks, so the | |
2407 // exception paths do not take memory state from the memory barrier, | |
2408 // so there's no problems making a strong assert about mixing users | |
2409 // of safe & unsafe memory. Otherwise fails in a CTW of rt.jar | |
2410 // around 5701, class sun/reflect/UnsafeBooleanFieldAccessorImpl. | |
2411 if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder); | |
2412 | |
2413 if (!is_store) { | |
2414 Node* p = make_load(control(), adr, value_type, type, adr_type, is_volatile); | |
2415 // load value and push onto stack | |
2416 switch (type) { | |
2417 case T_BOOLEAN: | |
2418 case T_CHAR: | |
2419 case T_BYTE: | |
2420 case T_SHORT: | |
2421 case T_INT: | |
2422 case T_FLOAT: | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2423 push(p); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2424 break; |
0 | 2425 case T_OBJECT: |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2426 if (need_read_barrier) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2427 insert_g1_pre_barrier(heap_base_oop, offset, p); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2428 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2429 push(p); |
0 | 2430 break; |
2431 case T_ADDRESS: | |
2432 // Cast to an int type. | |
2433 p = _gvn.transform( new (C, 2) CastP2XNode(NULL,p) ); | |
2434 p = ConvX2L(p); | |
2435 push_pair(p); | |
2436 break; | |
2437 case T_DOUBLE: | |
2438 case T_LONG: | |
2439 push_pair( p ); | |
2440 break; | |
2441 default: ShouldNotReachHere(); | |
2442 } | |
2443 } else { | |
2444 // place effect of store into memory | |
2445 switch (type) { | |
2446 case T_DOUBLE: | |
2447 val = dstore_rounding(val); | |
2448 break; | |
2449 case T_ADDRESS: | |
2450 // Repackage the long as a pointer. | |
2451 val = ConvL2X(val); | |
2452 val = _gvn.transform( new (C, 2) CastX2PNode(val) ); | |
2453 break; | |
2454 } | |
2455 | |
2456 if (type != T_OBJECT ) { | |
2457 (void) store_to_memory(control(), adr, val, type, adr_type, is_volatile); | |
2458 } else { | |
2459 // Possibly an oop being stored to Java heap or native memory | |
2460 if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) { | |
2461 // oop to Java heap. | |
825 | 2462 (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type); |
0 | 2463 } else { |
2464 // We can't tell at compile time if we are storing in the Java heap or outside | |
2465 // of it. So we need to emit code to conditionally do the proper type of | |
2466 // store. | |
2467 | |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
2468 IdealKit ideal(this); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2469 #define __ ideal. |
0 | 2470 // QQQ who knows what probability is here?? |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2471 __ if_then(heap_base_oop, BoolTest::ne, null(), PROB_UNLIKELY(0.999)); { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2472 // Sync IdealKit and graphKit. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
2473 sync_kit(ideal); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2474 Node* st = store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2475 // Update IdealKit memory. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
2476 __ sync_kit(this); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2477 } __ else_(); { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2478 __ store(__ ctrl(), adr, val, type, alias_type->index(), is_volatile); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2479 } __ end_if(); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2480 // Final sync IdealKit and GraphKit. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
2481 final_sync(ideal); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2482 #undef __ |
0 | 2483 } |
2484 } | |
2485 } | |
2486 | |
2487 if (is_volatile) { | |
2488 if (!is_store) | |
2489 insert_mem_bar(Op_MemBarAcquire); | |
2490 else | |
2491 insert_mem_bar(Op_MemBarVolatile); | |
2492 } | |
2493 | |
2494 if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder); | |
2495 | |
2496 return true; | |
2497 } | |
2498 | |
2499 //----------------------------inline_unsafe_prefetch---------------------------- | |
2500 | |
2501 bool LibraryCallKit::inline_unsafe_prefetch(bool is_native_ptr, bool is_store, bool is_static) { | |
2502 #ifndef PRODUCT | |
2503 { | |
2504 ResourceMark rm; | |
2505 // Check the signatures. | |
2506 ciSignature* sig = signature(); | |
2507 #ifdef ASSERT | |
2508 // Object getObject(Object base, int/long offset), etc. | |
2509 BasicType rtype = sig->return_type()->basic_type(); | |
2510 if (!is_native_ptr) { | |
2511 assert(sig->count() == 2, "oop prefetch has 2 arguments"); | |
2512 assert(sig->type_at(0)->basic_type() == T_OBJECT, "prefetch base is object"); | |
2513 assert(sig->type_at(1)->basic_type() == T_LONG, "prefetcha offset is correct"); | |
2514 } else { | |
2515 assert(sig->count() == 1, "native prefetch has 1 argument"); | |
2516 assert(sig->type_at(0)->basic_type() == T_LONG, "prefetch base is long"); | |
2517 } | |
2518 #endif // ASSERT | |
2519 } | |
2520 #endif // !PRODUCT | |
2521 | |
2522 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
2523 | |
2524 // Argument words: "this" if not static, plus (oop/offset) or (lo/hi) args | |
2525 int nargs = (is_static ? 0 : 1) + (is_native_ptr ? 2 : 3); | |
2526 | |
2527 debug_only(int saved_sp = _sp); | |
2528 _sp += nargs; | |
2529 | |
2530 // Build address expression. See the code in inline_unsafe_access. | |
2531 Node *adr; | |
2532 if (!is_native_ptr) { | |
2533 // The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset | |
2534 Node* offset = pop_pair(); | |
2535 // The base is either a Java object or a value produced by Unsafe.staticFieldBase | |
2536 Node* base = pop(); | |
2537 // We currently rely on the cookies produced by Unsafe.xxxFieldOffset | |
2538 // to be plain byte offsets, which are also the same as those accepted | |
2539 // by oopDesc::field_base. | |
2540 assert(Unsafe_field_offset_to_byte_offset(11) == 11, | |
2541 "fieldOffset must be byte-scaled"); | |
2542 // 32-bit machines ignore the high half! | |
2543 offset = ConvL2X(offset); | |
2544 adr = make_unsafe_address(base, offset); | |
2545 } else { | |
2546 Node* ptr = pop_pair(); | |
2547 // Adjust Java long to machine word: | |
2548 ptr = ConvL2X(ptr); | |
2549 adr = make_unsafe_address(NULL, ptr); | |
2550 } | |
2551 | |
2552 if (is_static) { | |
2553 assert(saved_sp == _sp, "must have correct argument count"); | |
2554 } else { | |
2555 // Pop receiver last: it was pushed first. | |
2556 Node *receiver = pop(); | |
2557 assert(saved_sp == _sp, "must have correct argument count"); | |
2558 | |
2559 // Null check on self without removing any arguments. The argument | |
2560 // null check technically happens in the wrong place, which can lead to | |
2561 // invalid stack traces when the primitive is inlined into a method | |
2562 // which handles NullPointerExceptions. | |
2563 _sp += nargs; | |
2564 do_null_check(receiver, T_OBJECT); | |
2565 _sp -= nargs; | |
2566 if (stopped()) { | |
2567 return true; | |
2568 } | |
2569 } | |
2570 | |
2571 // Generate the read or write prefetch | |
2572 Node *prefetch; | |
2573 if (is_store) { | |
2574 prefetch = new (C, 3) PrefetchWriteNode(i_o(), adr); | |
2575 } else { | |
2576 prefetch = new (C, 3) PrefetchReadNode(i_o(), adr); | |
2577 } | |
2578 prefetch->init_req(0, control()); | |
2579 set_i_o(_gvn.transform(prefetch)); | |
2580 | |
2581 return true; | |
2582 } | |
2583 | |
2584 //----------------------------inline_unsafe_CAS---------------------------- | |
2585 | |
2586 bool LibraryCallKit::inline_unsafe_CAS(BasicType type) { | |
2587 // This basic scheme here is the same as inline_unsafe_access, but | |
2588 // differs in enough details that combining them would make the code | |
2589 // overly confusing. (This is a true fact! I originally combined | |
2590 // them, but even I was confused by it!) As much code/comments as | |
2591 // possible are retained from inline_unsafe_access though to make | |
605 | 2592 // the correspondences clearer. - dl |
0 | 2593 |
2594 if (callee()->is_static()) return false; // caller must have the capability! | |
2595 | |
2596 #ifndef PRODUCT | |
2597 { | |
2598 ResourceMark rm; | |
2599 // Check the signatures. | |
2600 ciSignature* sig = signature(); | |
2601 #ifdef ASSERT | |
2602 BasicType rtype = sig->return_type()->basic_type(); | |
2603 assert(rtype == T_BOOLEAN, "CAS must return boolean"); | |
2604 assert(sig->count() == 4, "CAS has 4 arguments"); | |
2605 assert(sig->type_at(0)->basic_type() == T_OBJECT, "CAS base is object"); | |
2606 assert(sig->type_at(1)->basic_type() == T_LONG, "CAS offset is long"); | |
2607 #endif // ASSERT | |
2608 } | |
2609 #endif //PRODUCT | |
2610 | |
2611 // number of stack slots per value argument (1 or 2) | |
2612 int type_words = type2size[type]; | |
2613 | |
2614 // Cannot inline wide CAS on machines that don't support it natively | |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
0
diff
changeset
|
2615 if (type2aelembytes(type) > BytesPerInt && !VM_Version::supports_cx8()) |
0 | 2616 return false; |
2617 | |
2618 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
2619 | |
2620 // Argument words: "this" plus oop plus offset plus oldvalue plus newvalue; | |
2621 int nargs = 1 + 1 + 2 + type_words + type_words; | |
2622 | |
2623 // pop arguments: newval, oldval, offset, base, and receiver | |
2624 debug_only(int saved_sp = _sp); | |
2625 _sp += nargs; | |
2626 Node* newval = (type_words == 1) ? pop() : pop_pair(); | |
2627 Node* oldval = (type_words == 1) ? pop() : pop_pair(); | |
2628 Node *offset = pop_pair(); | |
2629 Node *base = pop(); | |
2630 Node *receiver = pop(); | |
2631 assert(saved_sp == _sp, "must have correct argument count"); | |
2632 | |
2633 // Null check receiver. | |
2634 _sp += nargs; | |
2635 do_null_check(receiver, T_OBJECT); | |
2636 _sp -= nargs; | |
2637 if (stopped()) { | |
2638 return true; | |
2639 } | |
2640 | |
2641 // Build field offset expression. | |
2642 // We currently rely on the cookies produced by Unsafe.xxxFieldOffset | |
2643 // to be plain byte offsets, which are also the same as those accepted | |
2644 // by oopDesc::field_base. | |
2645 assert(Unsafe_field_offset_to_byte_offset(11) == 11, "fieldOffset must be byte-scaled"); | |
2646 // 32-bit machines ignore the high half of long offsets | |
2647 offset = ConvL2X(offset); | |
2648 Node* adr = make_unsafe_address(base, offset); | |
2649 const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); | |
2650 | |
2651 // (Unlike inline_unsafe_access, there seems no point in trying | |
2652 // to refine types. Just use the coarse types here. | |
2653 const Type *value_type = Type::get_const_basic_type(type); | |
2654 Compile::AliasType* alias_type = C->alias_type(adr_type); | |
2655 assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here"); | |
2656 int alias_idx = C->get_alias_index(adr_type); | |
2657 | |
2658 // Memory-model-wise, a CAS acts like a little synchronized block, | |
605 | 2659 // so needs barriers on each side. These don't translate into |
0 | 2660 // actual barriers on most machines, but we still need rest of |
2661 // compiler to respect ordering. | |
2662 | |
2663 insert_mem_bar(Op_MemBarRelease); | |
2664 insert_mem_bar(Op_MemBarCPUOrder); | |
2665 | |
2666 // 4984716: MemBars must be inserted before this | |
2667 // memory node in order to avoid a false | |
2668 // dependency which will confuse the scheduler. | |
2669 Node *mem = memory(alias_idx); | |
2670 | |
2671 // For now, we handle only those cases that actually exist: ints, | |
2672 // longs, and Object. Adding others should be straightforward. | |
2673 Node* cas; | |
2674 switch(type) { | |
2675 case T_INT: | |
2676 cas = _gvn.transform(new (C, 5) CompareAndSwapINode(control(), mem, adr, newval, oldval)); | |
2677 break; | |
2678 case T_LONG: | |
2679 cas = _gvn.transform(new (C, 5) CompareAndSwapLNode(control(), mem, adr, newval, oldval)); | |
2680 break; | |
2681 case T_OBJECT: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
2682 // reference stores need a store barrier. |
0 | 2683 // (They don't if CAS fails, but it isn't worth checking.) |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2684 pre_barrier(true /* do_load*/, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2685 control(), base, adr, alias_idx, newval, value_type->make_oopptr(), |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2686 NULL /* pre_val*/, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2687 T_OBJECT); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
2688 #ifdef _LP64 |
163 | 2689 if (adr->bottom_type()->is_ptr_to_narrowoop()) { |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
174
diff
changeset
|
2690 Node *newval_enc = _gvn.transform(new (C, 2) EncodePNode(newval, newval->bottom_type()->make_narrowoop())); |
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
174
diff
changeset
|
2691 Node *oldval_enc = _gvn.transform(new (C, 2) EncodePNode(oldval, oldval->bottom_type()->make_narrowoop())); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
2692 cas = _gvn.transform(new (C, 5) CompareAndSwapNNode(control(), mem, adr, |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
174
diff
changeset
|
2693 newval_enc, oldval_enc)); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
2694 } else |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
2695 #endif |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
174
diff
changeset
|
2696 { |
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
174
diff
changeset
|
2697 cas = _gvn.transform(new (C, 5) CompareAndSwapPNode(control(), mem, adr, newval, oldval)); |
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
174
diff
changeset
|
2698 } |
0 | 2699 post_barrier(control(), cas, base, adr, alias_idx, newval, T_OBJECT, true); |
2700 break; | |
2701 default: | |
2702 ShouldNotReachHere(); | |
2703 break; | |
2704 } | |
2705 | |
2706 // SCMemProjNodes represent the memory state of CAS. Their main | |
2707 // role is to prevent CAS nodes from being optimized away when their | |
2708 // results aren't used. | |
2709 Node* proj = _gvn.transform( new (C, 1) SCMemProjNode(cas)); | |
2710 set_memory(proj, alias_idx); | |
2711 | |
2712 // Add the trailing membar surrounding the access | |
2713 insert_mem_bar(Op_MemBarCPUOrder); | |
2714 insert_mem_bar(Op_MemBarAcquire); | |
2715 | |
2716 push(cas); | |
2717 return true; | |
2718 } | |
2719 | |
2720 bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) { | |
2721 // This is another variant of inline_unsafe_access, differing in | |
2722 // that it always issues store-store ("release") barrier and ensures | |
2723 // store-atomicity (which only matters for "long"). | |
2724 | |
2725 if (callee()->is_static()) return false; // caller must have the capability! | |
2726 | |
2727 #ifndef PRODUCT | |
2728 { | |
2729 ResourceMark rm; | |
2730 // Check the signatures. | |
2731 ciSignature* sig = signature(); | |
2732 #ifdef ASSERT | |
2733 BasicType rtype = sig->return_type()->basic_type(); | |
2734 assert(rtype == T_VOID, "must return void"); | |
2735 assert(sig->count() == 3, "has 3 arguments"); | |
2736 assert(sig->type_at(0)->basic_type() == T_OBJECT, "base is object"); | |
2737 assert(sig->type_at(1)->basic_type() == T_LONG, "offset is long"); | |
2738 #endif // ASSERT | |
2739 } | |
2740 #endif //PRODUCT | |
2741 | |
2742 // number of stack slots per value argument (1 or 2) | |
2743 int type_words = type2size[type]; | |
2744 | |
2745 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
2746 | |
2747 // Argument words: "this" plus oop plus offset plus value; | |
2748 int nargs = 1 + 1 + 2 + type_words; | |
2749 | |
2750 // pop arguments: val, offset, base, and receiver | |
2751 debug_only(int saved_sp = _sp); | |
2752 _sp += nargs; | |
2753 Node* val = (type_words == 1) ? pop() : pop_pair(); | |
2754 Node *offset = pop_pair(); | |
2755 Node *base = pop(); | |
2756 Node *receiver = pop(); | |
2757 assert(saved_sp == _sp, "must have correct argument count"); | |
2758 | |
2759 // Null check receiver. | |
2760 _sp += nargs; | |
2761 do_null_check(receiver, T_OBJECT); | |
2762 _sp -= nargs; | |
2763 if (stopped()) { | |
2764 return true; | |
2765 } | |
2766 | |
2767 // Build field offset expression. | |
2768 assert(Unsafe_field_offset_to_byte_offset(11) == 11, "fieldOffset must be byte-scaled"); | |
2769 // 32-bit machines ignore the high half of long offsets | |
2770 offset = ConvL2X(offset); | |
2771 Node* adr = make_unsafe_address(base, offset); | |
2772 const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); | |
2773 const Type *value_type = Type::get_const_basic_type(type); | |
2774 Compile::AliasType* alias_type = C->alias_type(adr_type); | |
2775 | |
2776 insert_mem_bar(Op_MemBarRelease); | |
2777 insert_mem_bar(Op_MemBarCPUOrder); | |
2778 // Ensure that the store is atomic for longs: | |
2779 bool require_atomic_access = true; | |
2780 Node* store; | |
2781 if (type == T_OBJECT) // reference stores need a store barrier. | |
825 | 2782 store = store_oop_to_unknown(control(), base, adr, adr_type, val, type); |
0 | 2783 else { |
2784 store = store_to_memory(control(), adr, val, type, adr_type, require_atomic_access); | |
2785 } | |
2786 insert_mem_bar(Op_MemBarCPUOrder); | |
2787 return true; | |
2788 } | |
2789 | |
2790 bool LibraryCallKit::inline_unsafe_allocate() { | |
2791 if (callee()->is_static()) return false; // caller must have the capability! | |
2792 int nargs = 1 + 1; | |
2793 assert(signature()->size() == nargs-1, "alloc has 1 argument"); | |
2794 null_check_receiver(callee()); // check then ignore argument(0) | |
2795 _sp += nargs; // set original stack for use by uncommon_trap | |
2796 Node* cls = do_null_check(argument(1), T_OBJECT); | |
2797 _sp -= nargs; | |
2798 if (stopped()) return true; | |
2799 | |
2800 Node* kls = load_klass_from_mirror(cls, false, nargs, NULL, 0); | |
2801 _sp += nargs; // set original stack for use by uncommon_trap | |
2802 kls = do_null_check(kls, T_OBJECT); | |
2803 _sp -= nargs; | |
2804 if (stopped()) return true; // argument was like int.class | |
2805 | |
2806 // Note: The argument might still be an illegal value like | |
2807 // Serializable.class or Object[].class. The runtime will handle it. | |
2808 // But we must make an explicit check for initialization. | |
2809 Node* insp = basic_plus_adr(kls, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)); | |
2810 Node* inst = make_load(NULL, insp, TypeInt::INT, T_INT); | |
2811 Node* bits = intcon(instanceKlass::fully_initialized); | |
2812 Node* test = _gvn.transform( new (C, 3) SubINode(inst, bits) ); | |
2813 // The 'test' is non-zero if we need to take a slow path. | |
2814 | |
2815 Node* obj = new_instance(kls, test); | |
2816 push(obj); | |
2817 | |
2818 return true; | |
2819 } | |
2820 | |
2821 //------------------------inline_native_time_funcs-------------- | |
2822 // inline code for System.currentTimeMillis() and System.nanoTime() | |
2823 // these have the same type and signature | |
2824 bool LibraryCallKit::inline_native_time_funcs(bool isNano) { | |
2825 address funcAddr = isNano ? CAST_FROM_FN_PTR(address, os::javaTimeNanos) : | |
2826 CAST_FROM_FN_PTR(address, os::javaTimeMillis); | |
2827 const char * funcName = isNano ? "nanoTime" : "currentTimeMillis"; | |
2828 const TypeFunc *tf = OptoRuntime::current_time_millis_Type(); | |
2829 const TypePtr* no_memory_effects = NULL; | |
2830 Node* time = make_runtime_call(RC_LEAF, tf, funcAddr, funcName, no_memory_effects); | |
2831 Node* value = _gvn.transform(new (C, 1) ProjNode(time, TypeFunc::Parms+0)); | |
2832 #ifdef ASSERT | |
2833 Node* value_top = _gvn.transform(new (C, 1) ProjNode(time, TypeFunc::Parms + 1)); | |
2834 assert(value_top == top(), "second value must be top"); | |
2835 #endif | |
2836 push_pair(value); | |
2837 return true; | |
2838 } | |
2839 | |
2840 //------------------------inline_native_currentThread------------------ | |
2841 bool LibraryCallKit::inline_native_currentThread() { | |
2842 Node* junk = NULL; | |
2843 push(generate_current_thread(junk)); | |
2844 return true; | |
2845 } | |
2846 | |
2847 //------------------------inline_native_isInterrupted------------------ | |
2848 bool LibraryCallKit::inline_native_isInterrupted() { | |
2849 const int nargs = 1+1; // receiver + boolean | |
2850 assert(nargs == arg_size(), "sanity"); | |
2851 // Add a fast path to t.isInterrupted(clear_int): | |
2852 // (t == Thread.current() && (!TLS._osthread._interrupted || !clear_int)) | |
2853 // ? TLS._osthread._interrupted : /*slow path:*/ t.isInterrupted(clear_int) | |
2854 // So, in the common case that the interrupt bit is false, | |
2855 // we avoid making a call into the VM. Even if the interrupt bit | |
2856 // is true, if the clear_int argument is false, we avoid the VM call. | |
2857 // However, if the receiver is not currentThread, we must call the VM, | |
2858 // because there must be some locking done around the operation. | |
2859 | |
2860 // We only go to the fast case code if we pass two guards. | |
2861 // Paths which do not pass are accumulated in the slow_region. | |
2862 RegionNode* slow_region = new (C, 1) RegionNode(1); | |
2863 record_for_igvn(slow_region); | |
2864 RegionNode* result_rgn = new (C, 4) RegionNode(1+3); // fast1, fast2, slow | |
2865 PhiNode* result_val = new (C, 4) PhiNode(result_rgn, TypeInt::BOOL); | |
2866 enum { no_int_result_path = 1, | |
2867 no_clear_result_path = 2, | |
2868 slow_result_path = 3 | |
2869 }; | |
2870 | |
2871 // (a) Receiving thread must be the current thread. | |
2872 Node* rec_thr = argument(0); | |
2873 Node* tls_ptr = NULL; | |
2874 Node* cur_thr = generate_current_thread(tls_ptr); | |
2875 Node* cmp_thr = _gvn.transform( new (C, 3) CmpPNode(cur_thr, rec_thr) ); | |
2876 Node* bol_thr = _gvn.transform( new (C, 2) BoolNode(cmp_thr, BoolTest::ne) ); | |
2877 | |
2878 bool known_current_thread = (_gvn.type(bol_thr) == TypeInt::ZERO); | |
2879 if (!known_current_thread) | |
2880 generate_slow_guard(bol_thr, slow_region); | |
2881 | |
2882 // (b) Interrupt bit on TLS must be false. | |
2883 Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); | |
2884 Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS); | |
2885 p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::interrupted_offset())); | |
787
aabd393cf1ee
6772683: Thread.isInterrupted() fails to return true on multiprocessor PC
kvn
parents:
775
diff
changeset
|
2886 // Set the control input on the field _interrupted read to prevent it floating up. |
aabd393cf1ee
6772683: Thread.isInterrupted() fails to return true on multiprocessor PC
kvn
parents:
775
diff
changeset
|
2887 Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT); |
0 | 2888 Node* cmp_bit = _gvn.transform( new (C, 3) CmpINode(int_bit, intcon(0)) ); |
2889 Node* bol_bit = _gvn.transform( new (C, 2) BoolNode(cmp_bit, BoolTest::ne) ); | |
2890 | |
2891 IfNode* iff_bit = create_and_map_if(control(), bol_bit, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN); | |
2892 | |
2893 // First fast path: if (!TLS._interrupted) return false; | |
2894 Node* false_bit = _gvn.transform( new (C, 1) IfFalseNode(iff_bit) ); | |
2895 result_rgn->init_req(no_int_result_path, false_bit); | |
2896 result_val->init_req(no_int_result_path, intcon(0)); | |
2897 | |
2898 // drop through to next case | |
2899 set_control( _gvn.transform(new (C, 1) IfTrueNode(iff_bit)) ); | |
2900 | |
2901 // (c) Or, if interrupt bit is set and clear_int is false, use 2nd fast path. | |
2902 Node* clr_arg = argument(1); | |
2903 Node* cmp_arg = _gvn.transform( new (C, 3) CmpINode(clr_arg, intcon(0)) ); | |
2904 Node* bol_arg = _gvn.transform( new (C, 2) BoolNode(cmp_arg, BoolTest::ne) ); | |
2905 IfNode* iff_arg = create_and_map_if(control(), bol_arg, PROB_FAIR, COUNT_UNKNOWN); | |
2906 | |
2907 // Second fast path: ... else if (!clear_int) return true; | |
2908 Node* false_arg = _gvn.transform( new (C, 1) IfFalseNode(iff_arg) ); | |
2909 result_rgn->init_req(no_clear_result_path, false_arg); | |
2910 result_val->init_req(no_clear_result_path, intcon(1)); | |
2911 | |
2912 // drop through to next case | |
2913 set_control( _gvn.transform(new (C, 1) IfTrueNode(iff_arg)) ); | |
2914 | |
2915 // (d) Otherwise, go to the slow path. | |
2916 slow_region->add_req(control()); | |
2917 set_control( _gvn.transform(slow_region) ); | |
2918 | |
2919 if (stopped()) { | |
2920 // There is no slow path. | |
2921 result_rgn->init_req(slow_result_path, top()); | |
2922 result_val->init_req(slow_result_path, top()); | |
2923 } else { | |
2924 // non-virtual because it is a private non-static | |
2925 CallJavaNode* slow_call = generate_method_call(vmIntrinsics::_isInterrupted); | |
2926 | |
2927 Node* slow_val = set_results_for_java_call(slow_call); | |
2928 // this->control() comes from set_results_for_java_call | |
2929 | |
2930 // If we know that the result of the slow call will be true, tell the optimizer! | |
2931 if (known_current_thread) slow_val = intcon(1); | |
2932 | |
2933 Node* fast_io = slow_call->in(TypeFunc::I_O); | |
2934 Node* fast_mem = slow_call->in(TypeFunc::Memory); | |
2935 // These two phis are pre-filled with copies of of the fast IO and Memory | |
2936 Node* io_phi = PhiNode::make(result_rgn, fast_io, Type::ABIO); | |
2937 Node* mem_phi = PhiNode::make(result_rgn, fast_mem, Type::MEMORY, TypePtr::BOTTOM); | |
2938 | |
2939 result_rgn->init_req(slow_result_path, control()); | |
2940 io_phi ->init_req(slow_result_path, i_o()); | |
2941 mem_phi ->init_req(slow_result_path, reset_memory()); | |
2942 result_val->init_req(slow_result_path, slow_val); | |
2943 | |
2944 set_all_memory( _gvn.transform(mem_phi) ); | |
2945 set_i_o( _gvn.transform(io_phi) ); | |
2946 } | |
2947 | |
2948 push_result(result_rgn, result_val); | |
2949 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
2950 | |
2951 return true; | |
2952 } | |
2953 | |
2954 //---------------------------load_mirror_from_klass---------------------------- | |
2955 // Given a klass oop, load its java mirror (a java.lang.Class oop). | |
2956 Node* LibraryCallKit::load_mirror_from_klass(Node* klass) { | |
2957 Node* p = basic_plus_adr(klass, Klass::java_mirror_offset_in_bytes() + sizeof(oopDesc)); | |
2958 return make_load(NULL, p, TypeInstPtr::MIRROR, T_OBJECT); | |
2959 } | |
2960 | |
2961 //-----------------------load_klass_from_mirror_common------------------------- | |
2962 // Given a java mirror (a java.lang.Class oop), load its corresponding klass oop. | |
2963 // Test the klass oop for null (signifying a primitive Class like Integer.TYPE), | |
2964 // and branch to the given path on the region. | |
2965 // If never_see_null, take an uncommon trap on null, so we can optimistically | |
2966 // compile for the non-null case. | |
2967 // If the region is NULL, force never_see_null = true. | |
2968 Node* LibraryCallKit::load_klass_from_mirror_common(Node* mirror, | |
2969 bool never_see_null, | |
2970 int nargs, | |
2971 RegionNode* region, | |
2972 int null_path, | |
2973 int offset) { | |
2974 if (region == NULL) never_see_null = true; | |
2975 Node* p = basic_plus_adr(mirror, offset); | |
2976 const TypeKlassPtr* kls_type = TypeKlassPtr::OBJECT_OR_NULL; | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
2977 Node* kls = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeRawPtr::BOTTOM, kls_type) ); |
0 | 2978 _sp += nargs; // any deopt will start just before call to enclosing method |
2979 Node* null_ctl = top(); | |
2980 kls = null_check_oop(kls, &null_ctl, never_see_null); | |
2981 if (region != NULL) { | |
2982 // Set region->in(null_path) if the mirror is a primitive (e.g, int.class). | |
2983 region->init_req(null_path, null_ctl); | |
2984 } else { | |
2985 assert(null_ctl == top(), "no loose ends"); | |
2986 } | |
2987 _sp -= nargs; | |
2988 return kls; | |
2989 } | |
2990 | |
2991 //--------------------(inline_native_Class_query helpers)--------------------- | |
2992 // Use this for JVM_ACC_INTERFACE, JVM_ACC_IS_CLONEABLE, JVM_ACC_HAS_FINALIZER. | |
2993 // Fall through if (mods & mask) == bits, take the guard otherwise. | |
2994 Node* LibraryCallKit::generate_access_flags_guard(Node* kls, int modifier_mask, int modifier_bits, RegionNode* region) { | |
2995 // Branch around if the given klass has the given modifier bit set. | |
2996 // Like generate_guard, adds a new path onto the region. | |
2997 Node* modp = basic_plus_adr(kls, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc)); | |
2998 Node* mods = make_load(NULL, modp, TypeInt::INT, T_INT); | |
2999 Node* mask = intcon(modifier_mask); | |
3000 Node* bits = intcon(modifier_bits); | |
3001 Node* mbit = _gvn.transform( new (C, 3) AndINode(mods, mask) ); | |
3002 Node* cmp = _gvn.transform( new (C, 3) CmpINode(mbit, bits) ); | |
3003 Node* bol = _gvn.transform( new (C, 2) BoolNode(cmp, BoolTest::ne) ); | |
3004 return generate_fair_guard(bol, region); | |
3005 } | |
3006 Node* LibraryCallKit::generate_interface_guard(Node* kls, RegionNode* region) { | |
3007 return generate_access_flags_guard(kls, JVM_ACC_INTERFACE, 0, region); | |
3008 } | |
3009 | |
3010 //-------------------------inline_native_Class_query------------------- | |
3011 bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { | |
3012 int nargs = 1+0; // just the Class mirror, in most cases | |
3013 const Type* return_type = TypeInt::BOOL; | |
3014 Node* prim_return_value = top(); // what happens if it's a primitive class? | |
3015 bool never_see_null = !too_many_traps(Deoptimization::Reason_null_check); | |
3016 bool expect_prim = false; // most of these guys expect to work on refs | |
3017 | |
3018 enum { _normal_path = 1, _prim_path = 2, PATH_LIMIT }; | |
3019 | |
3020 switch (id) { | |
3021 case vmIntrinsics::_isInstance: | |
3022 nargs = 1+1; // the Class mirror, plus the object getting queried about | |
3023 // nothing is an instance of a primitive type | |
3024 prim_return_value = intcon(0); | |
3025 break; | |
3026 case vmIntrinsics::_getModifiers: | |
3027 prim_return_value = intcon(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC); | |
3028 assert(is_power_of_2((int)JVM_ACC_WRITTEN_FLAGS+1), "change next line"); | |
3029 return_type = TypeInt::make(0, JVM_ACC_WRITTEN_FLAGS, Type::WidenMin); | |
3030 break; | |
3031 case vmIntrinsics::_isInterface: | |
3032 prim_return_value = intcon(0); | |
3033 break; | |
3034 case vmIntrinsics::_isArray: | |
3035 prim_return_value = intcon(0); | |
3036 expect_prim = true; // cf. ObjectStreamClass.getClassSignature | |
3037 break; | |
3038 case vmIntrinsics::_isPrimitive: | |
3039 prim_return_value = intcon(1); | |
3040 expect_prim = true; // obviously | |
3041 break; | |
3042 case vmIntrinsics::_getSuperclass: | |
3043 prim_return_value = null(); | |
3044 return_type = TypeInstPtr::MIRROR->cast_to_ptr_type(TypePtr::BotPTR); | |
3045 break; | |
3046 case vmIntrinsics::_getComponentType: | |
3047 prim_return_value = null(); | |
3048 return_type = TypeInstPtr::MIRROR->cast_to_ptr_type(TypePtr::BotPTR); | |
3049 break; | |
3050 case vmIntrinsics::_getClassAccessFlags: | |
3051 prim_return_value = intcon(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC); | |
3052 return_type = TypeInt::INT; // not bool! 6297094 | |
3053 break; | |
3054 default: | |
3055 ShouldNotReachHere(); | |
3056 } | |
3057 | |
3058 Node* mirror = argument(0); | |
3059 Node* obj = (nargs <= 1)? top(): argument(1); | |
3060 | |
3061 const TypeInstPtr* mirror_con = _gvn.type(mirror)->isa_instptr(); | |
3062 if (mirror_con == NULL) return false; // cannot happen? | |
3063 | |
3064 #ifndef PRODUCT | |
3065 if (PrintIntrinsics || PrintInlining || PrintOptoInlining) { | |
3066 ciType* k = mirror_con->java_mirror_type(); | |
3067 if (k) { | |
3068 tty->print("Inlining %s on constant Class ", vmIntrinsics::name_at(intrinsic_id())); | |
3069 k->print_name(); | |
3070 tty->cr(); | |
3071 } | |
3072 } | |
3073 #endif | |
3074 | |
3075 // Null-check the mirror, and the mirror's klass ptr (in case it is a primitive). | |
3076 RegionNode* region = new (C, PATH_LIMIT) RegionNode(PATH_LIMIT); | |
3077 record_for_igvn(region); | |
3078 PhiNode* phi = new (C, PATH_LIMIT) PhiNode(region, return_type); | |
3079 | |
3080 // The mirror will never be null of Reflection.getClassAccessFlags, however | |
3081 // it may be null for Class.isInstance or Class.getModifiers. Throw a NPE | |
3082 // if it is. See bug 4774291. | |
3083 | |
3084 // For Reflection.getClassAccessFlags(), the null check occurs in | |
3085 // the wrong place; see inline_unsafe_access(), above, for a similar | |
3086 // situation. | |
3087 _sp += nargs; // set original stack for use by uncommon_trap | |
3088 mirror = do_null_check(mirror, T_OBJECT); | |
3089 _sp -= nargs; | |
3090 // If mirror or obj is dead, only null-path is taken. | |
3091 if (stopped()) return true; | |
3092 | |
3093 if (expect_prim) never_see_null = false; // expect nulls (meaning prims) | |
3094 | |
3095 // Now load the mirror's klass metaobject, and null-check it. | |
3096 // Side-effects region with the control path if the klass is null. | |
3097 Node* kls = load_klass_from_mirror(mirror, never_see_null, nargs, | |
3098 region, _prim_path); | |
3099 // If kls is null, we have a primitive mirror. | |
3100 phi->init_req(_prim_path, prim_return_value); | |
3101 if (stopped()) { push_result(region, phi); return true; } | |
3102 | |
3103 Node* p; // handy temp | |
3104 Node* null_ctl; | |
3105 | |
3106 // Now that we have the non-null klass, we can perform the real query. | |
3107 // For constant classes, the query will constant-fold in LoadNode::Value. | |
3108 Node* query_value = top(); | |
3109 switch (id) { | |
3110 case vmIntrinsics::_isInstance: | |
3111 // nothing is an instance of a primitive type | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
3112 _sp += nargs; // gen_instanceof might do an uncommon trap |
0 | 3113 query_value = gen_instanceof(obj, kls); |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1609
diff
changeset
|
3114 _sp -= nargs; |
0 | 3115 break; |
3116 | |
3117 case vmIntrinsics::_getModifiers: | |
3118 p = basic_plus_adr(kls, Klass::modifier_flags_offset_in_bytes() + sizeof(oopDesc)); | |
3119 query_value = make_load(NULL, p, TypeInt::INT, T_INT); | |
3120 break; | |
3121 | |
3122 case vmIntrinsics::_isInterface: | |
3123 // (To verify this code sequence, check the asserts in JVM_IsInterface.) | |
3124 if (generate_interface_guard(kls, region) != NULL) | |
3125 // A guard was added. If the guard is taken, it was an interface. | |
3126 phi->add_req(intcon(1)); | |
3127 // If we fall through, it's a plain class. | |
3128 query_value = intcon(0); | |
3129 break; | |
3130 | |
3131 case vmIntrinsics::_isArray: | |
3132 // (To verify this code sequence, check the asserts in JVM_IsArrayClass.) | |
3133 if (generate_array_guard(kls, region) != NULL) | |
3134 // A guard was added. If the guard is taken, it was an array. | |
3135 phi->add_req(intcon(1)); | |
3136 // If we fall through, it's a plain class. | |
3137 query_value = intcon(0); | |
3138 break; | |
3139 | |
3140 case vmIntrinsics::_isPrimitive: | |
3141 query_value = intcon(0); // "normal" path produces false | |
3142 break; | |
3143 | |
3144 case vmIntrinsics::_getSuperclass: | |
3145 // The rules here are somewhat unfortunate, but we can still do better | |
3146 // with random logic than with a JNI call. | |
3147 // Interfaces store null or Object as _super, but must report null. | |
3148 // Arrays store an intermediate super as _super, but must report Object. | |
3149 // Other types can report the actual _super. | |
3150 // (To verify this code sequence, check the asserts in JVM_IsInterface.) | |
3151 if (generate_interface_guard(kls, region) != NULL) | |
3152 // A guard was added. If the guard is taken, it was an interface. | |
3153 phi->add_req(null()); | |
3154 if (generate_array_guard(kls, region) != NULL) | |
3155 // A guard was added. If the guard is taken, it was an array. | |
3156 phi->add_req(makecon(TypeInstPtr::make(env()->Object_klass()->java_mirror()))); | |
3157 // If we fall through, it's a plain class. Get its _super. | |
3158 p = basic_plus_adr(kls, Klass::super_offset_in_bytes() + sizeof(oopDesc)); | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
3159 kls = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeRawPtr::BOTTOM, TypeKlassPtr::OBJECT_OR_NULL) ); |
0 | 3160 null_ctl = top(); |
3161 kls = null_check_oop(kls, &null_ctl); | |
3162 if (null_ctl != top()) { | |
3163 // If the guard is taken, Object.superClass is null (both klass and mirror). | |
3164 region->add_req(null_ctl); | |
3165 phi ->add_req(null()); | |
3166 } | |
3167 if (!stopped()) { | |
3168 query_value = load_mirror_from_klass(kls); | |
3169 } | |
3170 break; | |
3171 | |
3172 case vmIntrinsics::_getComponentType: | |
3173 if (generate_array_guard(kls, region) != NULL) { | |
3174 // Be sure to pin the oop load to the guard edge just created: | |
3175 Node* is_array_ctrl = region->in(region->req()-1); | |
3176 Node* cma = basic_plus_adr(kls, in_bytes(arrayKlass::component_mirror_offset()) + sizeof(oopDesc)); | |
3177 Node* cmo = make_load(is_array_ctrl, cma, TypeInstPtr::MIRROR, T_OBJECT); | |
3178 phi->add_req(cmo); | |
3179 } | |
3180 query_value = null(); // non-array case is null | |
3181 break; | |
3182 | |
3183 case vmIntrinsics::_getClassAccessFlags: | |
3184 p = basic_plus_adr(kls, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc)); | |
3185 query_value = make_load(NULL, p, TypeInt::INT, T_INT); | |
3186 break; | |
3187 | |
3188 default: | |
3189 ShouldNotReachHere(); | |
3190 } | |
3191 | |
3192 // Fall-through is the normal case of a query to a real class. | |
3193 phi->init_req(1, query_value); | |
3194 region->init_req(1, control()); | |
3195 | |
3196 push_result(region, phi); | |
3197 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
3198 | |
3199 return true; | |
3200 } | |
3201 | |
3202 //--------------------------inline_native_subtype_check------------------------ | |
3203 // This intrinsic takes the JNI calls out of the heart of | |
3204 // UnsafeFieldAccessorImpl.set, which improves Field.set, readObject, etc. | |
3205 bool LibraryCallKit::inline_native_subtype_check() { | |
3206 int nargs = 1+1; // the Class mirror, plus the other class getting examined | |
3207 | |
3208 // Pull both arguments off the stack. | |
3209 Node* args[2]; // two java.lang.Class mirrors: superc, subc | |
3210 args[0] = argument(0); | |
3211 args[1] = argument(1); | |
3212 Node* klasses[2]; // corresponding Klasses: superk, subk | |
3213 klasses[0] = klasses[1] = top(); | |
3214 | |
3215 enum { | |
3216 // A full decision tree on {superc is prim, subc is prim}: | |
3217 _prim_0_path = 1, // {P,N} => false | |
3218 // {P,P} & superc!=subc => false | |
3219 _prim_same_path, // {P,P} & superc==subc => true | |
3220 _prim_1_path, // {N,P} => false | |
3221 _ref_subtype_path, // {N,N} & subtype check wins => true | |
3222 _both_ref_path, // {N,N} & subtype check loses => false | |
3223 PATH_LIMIT | |
3224 }; | |
3225 | |
3226 RegionNode* region = new (C, PATH_LIMIT) RegionNode(PATH_LIMIT); | |
3227 Node* phi = new (C, PATH_LIMIT) PhiNode(region, TypeInt::BOOL); | |
3228 record_for_igvn(region); | |
3229 | |
3230 const TypePtr* adr_type = TypeRawPtr::BOTTOM; // memory type of loads | |
3231 const TypeKlassPtr* kls_type = TypeKlassPtr::OBJECT_OR_NULL; | |
3232 int class_klass_offset = java_lang_Class::klass_offset_in_bytes(); | |
3233 | |
3234 // First null-check both mirrors and load each mirror's klass metaobject. | |
3235 int which_arg; | |
3236 for (which_arg = 0; which_arg <= 1; which_arg++) { | |
3237 Node* arg = args[which_arg]; | |
3238 _sp += nargs; // set original stack for use by uncommon_trap | |
3239 arg = do_null_check(arg, T_OBJECT); | |
3240 _sp -= nargs; | |
3241 if (stopped()) break; | |
3242 args[which_arg] = _gvn.transform(arg); | |
3243 | |
3244 Node* p = basic_plus_adr(arg, class_klass_offset); | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
3245 Node* kls = LoadKlassNode::make(_gvn, immutable_memory(), p, adr_type, kls_type); |
0 | 3246 klasses[which_arg] = _gvn.transform(kls); |
3247 } | |
3248 | |
3249 // Having loaded both klasses, test each for null. | |
3250 bool never_see_null = !too_many_traps(Deoptimization::Reason_null_check); | |
3251 for (which_arg = 0; which_arg <= 1; which_arg++) { | |
3252 Node* kls = klasses[which_arg]; | |
3253 Node* null_ctl = top(); | |
3254 _sp += nargs; // set original stack for use by uncommon_trap | |
3255 kls = null_check_oop(kls, &null_ctl, never_see_null); | |
3256 _sp -= nargs; | |
3257 int prim_path = (which_arg == 0 ? _prim_0_path : _prim_1_path); | |
3258 region->init_req(prim_path, null_ctl); | |
3259 if (stopped()) break; | |
3260 klasses[which_arg] = kls; | |
3261 } | |
3262 | |
3263 if (!stopped()) { | |
3264 // now we have two reference types, in klasses[0..1] | |
3265 Node* subk = klasses[1]; // the argument to isAssignableFrom | |
3266 Node* superk = klasses[0]; // the receiver | |
3267 region->set_req(_both_ref_path, gen_subtype_check(subk, superk)); | |
3268 // now we have a successful reference subtype check | |
3269 region->set_req(_ref_subtype_path, control()); | |
3270 } | |
3271 | |
3272 // If both operands are primitive (both klasses null), then | |
3273 // we must return true when they are identical primitives. | |
3274 // It is convenient to test this after the first null klass check. | |
3275 set_control(region->in(_prim_0_path)); // go back to first null check | |
3276 if (!stopped()) { | |
3277 // Since superc is primitive, make a guard for the superc==subc case. | |
3278 Node* cmp_eq = _gvn.transform( new (C, 3) CmpPNode(args[0], args[1]) ); | |
3279 Node* bol_eq = _gvn.transform( new (C, 2) BoolNode(cmp_eq, BoolTest::eq) ); | |
3280 generate_guard(bol_eq, region, PROB_FAIR); | |
3281 if (region->req() == PATH_LIMIT+1) { | |
3282 // A guard was added. If the added guard is taken, superc==subc. | |
3283 region->swap_edges(PATH_LIMIT, _prim_same_path); | |
3284 region->del_req(PATH_LIMIT); | |
3285 } | |
3286 region->set_req(_prim_0_path, control()); // Not equal after all. | |
3287 } | |
3288 | |
3289 // these are the only paths that produce 'true': | |
3290 phi->set_req(_prim_same_path, intcon(1)); | |
3291 phi->set_req(_ref_subtype_path, intcon(1)); | |
3292 | |
3293 // pull together the cases: | |
3294 assert(region->req() == PATH_LIMIT, "sane region"); | |
3295 for (uint i = 1; i < region->req(); i++) { | |
3296 Node* ctl = region->in(i); | |
3297 if (ctl == NULL || ctl == top()) { | |
3298 region->set_req(i, top()); | |
3299 phi ->set_req(i, top()); | |
3300 } else if (phi->in(i) == NULL) { | |
3301 phi->set_req(i, intcon(0)); // all other paths produce 'false' | |
3302 } | |
3303 } | |
3304 | |
3305 set_control(_gvn.transform(region)); | |
3306 push(_gvn.transform(phi)); | |
3307 | |
3308 return true; | |
3309 } | |
3310 | |
3311 //---------------------generate_array_guard_common------------------------ | |
3312 Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region, | |
3313 bool obj_array, bool not_array) { | |
3314 // If obj_array/non_array==false/false: | |
3315 // Branch around if the given klass is in fact an array (either obj or prim). | |
3316 // If obj_array/non_array==false/true: | |
3317 // Branch around if the given klass is not an array klass of any kind. | |
3318 // If obj_array/non_array==true/true: | |
3319 // Branch around if the kls is not an oop array (kls is int[], String, etc.) | |
3320 // If obj_array/non_array==true/false: | |
3321 // Branch around if the kls is an oop array (Object[] or subtype) | |
3322 // | |
3323 // Like generate_guard, adds a new path onto the region. | |
3324 jint layout_con = 0; | |
3325 Node* layout_val = get_layout_helper(kls, layout_con); | |
3326 if (layout_val == NULL) { | |
3327 bool query = (obj_array | |
3328 ? Klass::layout_helper_is_objArray(layout_con) | |
3329 : Klass::layout_helper_is_javaArray(layout_con)); | |
3330 if (query == not_array) { | |
3331 return NULL; // never a branch | |
3332 } else { // always a branch | |
3333 Node* always_branch = control(); | |
3334 if (region != NULL) | |
3335 region->add_req(always_branch); | |
3336 set_control(top()); | |
3337 return always_branch; | |
3338 } | |
3339 } | |
3340 // Now test the correct condition. | |
3341 jint nval = (obj_array | |
3342 ? ((jint)Klass::_lh_array_tag_type_value | |
3343 << Klass::_lh_array_tag_shift) | |
3344 : Klass::_lh_neutral_value); | |
3345 Node* cmp = _gvn.transform( new(C, 3) CmpINode(layout_val, intcon(nval)) ); | |
3346 BoolTest::mask btest = BoolTest::lt; // correct for testing is_[obj]array | |
3347 // invert the test if we are looking for a non-array | |
3348 if (not_array) btest = BoolTest(btest).negate(); | |
3349 Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, btest) ); | |
3350 return generate_fair_guard(bol, region); | |
3351 } | |
3352 | |
3353 | |
3354 //-----------------------inline_native_newArray-------------------------- | |
3355 bool LibraryCallKit::inline_native_newArray() { | |
3356 int nargs = 2; | |
3357 Node* mirror = argument(0); | |
3358 Node* count_val = argument(1); | |
3359 | |
3360 _sp += nargs; // set original stack for use by uncommon_trap | |
3361 mirror = do_null_check(mirror, T_OBJECT); | |
3362 _sp -= nargs; | |
163 | 3363 // If mirror or obj is dead, only null-path is taken. |
3364 if (stopped()) return true; | |
0 | 3365 |
3366 enum { _normal_path = 1, _slow_path = 2, PATH_LIMIT }; | |
3367 RegionNode* result_reg = new(C, PATH_LIMIT) RegionNode(PATH_LIMIT); | |
3368 PhiNode* result_val = new(C, PATH_LIMIT) PhiNode(result_reg, | |
3369 TypeInstPtr::NOTNULL); | |
3370 PhiNode* result_io = new(C, PATH_LIMIT) PhiNode(result_reg, Type::ABIO); | |
3371 PhiNode* result_mem = new(C, PATH_LIMIT) PhiNode(result_reg, Type::MEMORY, | |
3372 TypePtr::BOTTOM); | |
3373 | |
3374 bool never_see_null = !too_many_traps(Deoptimization::Reason_null_check); | |
3375 Node* klass_node = load_array_klass_from_mirror(mirror, never_see_null, | |
3376 nargs, | |
3377 result_reg, _slow_path); | |
3378 Node* normal_ctl = control(); | |
3379 Node* no_array_ctl = result_reg->in(_slow_path); | |
3380 | |
3381 // Generate code for the slow case. We make a call to newArray(). | |
3382 set_control(no_array_ctl); | |
3383 if (!stopped()) { | |
3384 // Either the input type is void.class, or else the | |
3385 // array klass has not yet been cached. Either the | |
3386 // ensuing call will throw an exception, or else it | |
3387 // will cache the array klass for next time. | |
3388 PreserveJVMState pjvms(this); | |
3389 CallJavaNode* slow_call = generate_method_call_static(vmIntrinsics::_newArray); | |
3390 Node* slow_result = set_results_for_java_call(slow_call); | |
3391 // this->control() comes from set_results_for_java_call | |
3392 result_reg->set_req(_slow_path, control()); | |
3393 result_val->set_req(_slow_path, slow_result); | |
3394 result_io ->set_req(_slow_path, i_o()); | |
3395 result_mem->set_req(_slow_path, reset_memory()); | |
3396 } | |
3397 | |
3398 set_control(normal_ctl); | |
3399 if (!stopped()) { | |
3400 // Normal case: The array type has been cached in the java.lang.Class. | |
3401 // The following call works fine even if the array type is polymorphic. | |
3402 // It could be a dynamic mix of int[], boolean[], Object[], etc. | |
730
9c6be3edf0dc
6589834: deoptimization problem with -XX:+DeoptimizeALot
cfang
parents:
681
diff
changeset
|
3403 Node* obj = new_array(klass_node, count_val, nargs); |
0 | 3404 result_reg->init_req(_normal_path, control()); |
3405 result_val->init_req(_normal_path, obj); | |
3406 result_io ->init_req(_normal_path, i_o()); | |
3407 result_mem->init_req(_normal_path, reset_memory()); | |
3408 } | |
3409 | |
3410 // Return the combined state. | |
3411 set_i_o( _gvn.transform(result_io) ); | |
3412 set_all_memory( _gvn.transform(result_mem) ); | |
3413 push_result(result_reg, result_val); | |
3414 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
3415 | |
3416 return true; | |
3417 } | |
3418 | |
3419 //----------------------inline_native_getLength-------------------------- | |
3420 bool LibraryCallKit::inline_native_getLength() { | |
3421 if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; | |
3422 | |
3423 int nargs = 1; | |
3424 Node* array = argument(0); | |
3425 | |
3426 _sp += nargs; // set original stack for use by uncommon_trap | |
3427 array = do_null_check(array, T_OBJECT); | |
3428 _sp -= nargs; | |
3429 | |
3430 // If array is dead, only null-path is taken. | |
3431 if (stopped()) return true; | |
3432 | |
3433 // Deoptimize if it is a non-array. | |
3434 Node* non_array = generate_non_array_guard(load_object_klass(array), NULL); | |
3435 | |
3436 if (non_array != NULL) { | |
3437 PreserveJVMState pjvms(this); | |
3438 set_control(non_array); | |
3439 _sp += nargs; // push the arguments back on the stack | |
3440 uncommon_trap(Deoptimization::Reason_intrinsic, | |
3441 Deoptimization::Action_maybe_recompile); | |
3442 } | |
3443 | |
3444 // If control is dead, only non-array-path is taken. | |
3445 if (stopped()) return true; | |
3446 | |
3447 // The works fine even if the array type is polymorphic. | |
3448 // It could be a dynamic mix of int[], boolean[], Object[], etc. | |
3449 push( load_array_length(array) ); | |
3450 | |
3451 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
3452 | |
3453 return true; | |
3454 } | |
3455 | |
3456 //------------------------inline_array_copyOf---------------------------- | |
3457 bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { | |
3458 if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; | |
3459 | |
3460 // Restore the stack and pop off the arguments. | |
3461 int nargs = 3 + (is_copyOfRange? 1: 0); | |
3462 Node* original = argument(0); | |
3463 Node* start = is_copyOfRange? argument(1): intcon(0); | |
3464 Node* end = is_copyOfRange? argument(2): argument(1); | |
3465 Node* array_type_mirror = is_copyOfRange? argument(3): argument(2); | |
3466 | |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3467 Node* newcopy; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3468 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3469 //set the original stack and the reexecute bit for the interpreter to reexecute |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3470 //the bytecode that invokes Arrays.copyOf if deoptimization happens |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3471 { PreserveReexecuteState preexecs(this); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3472 _sp += nargs; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3473 jvms()->set_should_reexecute(true); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3474 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3475 array_type_mirror = do_null_check(array_type_mirror, T_OBJECT); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3476 original = do_null_check(original, T_OBJECT); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3477 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3478 // Check if a null path was taken unconditionally. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3479 if (stopped()) return true; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3480 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3481 Node* orig_length = load_array_length(original); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3482 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3483 Node* klass_node = load_klass_from_mirror(array_type_mirror, false, 0, |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3484 NULL, 0); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3485 klass_node = do_null_check(klass_node, T_OBJECT); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3486 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3487 RegionNode* bailout = new (C, 1) RegionNode(1); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3488 record_for_igvn(bailout); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3489 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3490 // Despite the generic type of Arrays.copyOf, the mirror might be int, int[], etc. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3491 // Bail out if that is so. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3492 Node* not_objArray = generate_non_objArray_guard(klass_node, bailout); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3493 if (not_objArray != NULL) { |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3494 // Improve the klass node's type from the new optimistic assumption: |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3495 ciKlass* ak = ciArrayKlass::make(env()->Object_klass()); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3496 const Type* akls = TypeKlassPtr::make(TypePtr::NotNull, ak, 0/*offset*/); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3497 Node* cast = new (C, 2) CastPPNode(klass_node, akls); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3498 cast->init_req(0, control()); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3499 klass_node = _gvn.transform(cast); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3500 } |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3501 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3502 // Bail out if either start or end is negative. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3503 generate_negative_guard(start, bailout, &start); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3504 generate_negative_guard(end, bailout, &end); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3505 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3506 Node* length = end; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3507 if (_gvn.type(start) != TypeInt::ZERO) { |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3508 length = _gvn.transform( new (C, 3) SubINode(end, start) ); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3509 } |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3510 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3511 // Bail out if length is negative. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3512 // ...Not needed, since the new_array will throw the right exception. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3513 //generate_negative_guard(length, bailout, &length); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3514 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3515 if (bailout->req() > 1) { |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3516 PreserveJVMState pjvms(this); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3517 set_control( _gvn.transform(bailout) ); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3518 uncommon_trap(Deoptimization::Reason_intrinsic, |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3519 Deoptimization::Action_maybe_recompile); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3520 } |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3521 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3522 if (!stopped()) { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3523 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3524 // How many elements will we copy from the original? |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3525 // The answer is MinI(orig_length - start, length). |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3526 Node* orig_tail = _gvn.transform( new(C, 3) SubINode(orig_length, start) ); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3527 Node* moved = generate_min_max(vmIntrinsics::_min, orig_tail, length); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3528 |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2446
diff
changeset
|
3529 newcopy = new_array(klass_node, length, 0); |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3530 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3531 // Generate a direct call to the right arraycopy function(s). |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3532 // We know the copy is disjoint but we might not know if the |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3533 // oop stores need checking. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3534 // Extreme case: Arrays.copyOf((Integer[])x, 10, String[].class). |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3535 // This will fail a store-check if x contains any non-nulls. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3536 bool disjoint_bases = true; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3537 bool length_never_negative = true; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3538 generate_arraycopy(TypeAryPtr::OOPS, T_OBJECT, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3539 original, start, newcopy, intcon(0), moved, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3540 disjoint_bases, length_never_negative); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3541 } |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3542 } //original reexecute and sp are set back here |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3543 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3544 if(!stopped()) { |
0 | 3545 push(newcopy); |
3546 } | |
3547 | |
3548 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
3549 | |
3550 return true; | |
3551 } | |
3552 | |
3553 | |
3554 //----------------------generate_virtual_guard--------------------------- | |
3555 // Helper for hashCode and clone. Peeks inside the vtable to avoid a call. | |
3556 Node* LibraryCallKit::generate_virtual_guard(Node* obj_klass, | |
3557 RegionNode* slow_region) { | |
3558 ciMethod* method = callee(); | |
3559 int vtable_index = method->vtable_index(); | |
3560 // Get the methodOop out of the appropriate vtable entry. | |
3561 int entry_offset = (instanceKlass::vtable_start_offset() + | |
3562 vtable_index*vtableEntry::size()) * wordSize + | |
3563 vtableEntry::method_offset_in_bytes(); | |
3564 Node* entry_addr = basic_plus_adr(obj_klass, entry_offset); | |
3565 Node* target_call = make_load(NULL, entry_addr, TypeInstPtr::NOTNULL, T_OBJECT); | |
3566 | |
3567 // Compare the target method with the expected method (e.g., Object.hashCode). | |
3568 const TypeInstPtr* native_call_addr = TypeInstPtr::make(method); | |
3569 | |
3570 Node* native_call = makecon(native_call_addr); | |
3571 Node* chk_native = _gvn.transform( new(C, 3) CmpPNode(target_call, native_call) ); | |
3572 Node* test_native = _gvn.transform( new(C, 2) BoolNode(chk_native, BoolTest::ne) ); | |
3573 | |
3574 return generate_slow_guard(test_native, slow_region); | |
3575 } | |
3576 | |
3577 //-----------------------generate_method_call---------------------------- | |
3578 // Use generate_method_call to make a slow-call to the real | |
3579 // method if the fast path fails. An alternative would be to | |
3580 // use a stub like OptoRuntime::slow_arraycopy_Java. | |
3581 // This only works for expanding the current library call, | |
3582 // not another intrinsic. (E.g., don't use this for making an | |
3583 // arraycopy call inside of the copyOf intrinsic.) | |
3584 CallJavaNode* | |
3585 LibraryCallKit::generate_method_call(vmIntrinsics::ID method_id, bool is_virtual, bool is_static) { | |
3586 // When compiling the intrinsic method itself, do not use this technique. | |
3587 guarantee(callee() != C->method(), "cannot make slow-call to self"); | |
3588 | |
3589 ciMethod* method = callee(); | |
3590 // ensure the JVMS we have will be correct for this call | |
3591 guarantee(method_id == method->intrinsic_id(), "must match"); | |
3592 | |
3593 const TypeFunc* tf = TypeFunc::make(method); | |
3594 int tfdc = tf->domain()->cnt(); | |
3595 CallJavaNode* slow_call; | |
3596 if (is_static) { | |
3597 assert(!is_virtual, ""); | |
3598 slow_call = new(C, tfdc) CallStaticJavaNode(tf, | |
3599 SharedRuntime::get_resolve_static_call_stub(), | |
3600 method, bci()); | |
3601 } else if (is_virtual) { | |
3602 null_check_receiver(method); | |
3603 int vtable_index = methodOopDesc::invalid_vtable_index; | |
3604 if (UseInlineCaches) { | |
3605 // Suppress the vtable call | |
3606 } else { | |
3607 // hashCode and clone are not a miranda methods, | |
3608 // so the vtable index is fixed. | |
3609 // No need to use the linkResolver to get it. | |
3610 vtable_index = method->vtable_index(); | |
3611 } | |
3612 slow_call = new(C, tfdc) CallDynamicJavaNode(tf, | |
3613 SharedRuntime::get_resolve_virtual_call_stub(), | |
3614 method, vtable_index, bci()); | |
3615 } else { // neither virtual nor static: opt_virtual | |
3616 null_check_receiver(method); | |
3617 slow_call = new(C, tfdc) CallStaticJavaNode(tf, | |
3618 SharedRuntime::get_resolve_opt_virtual_call_stub(), | |
3619 method, bci()); | |
3620 slow_call->set_optimized_virtual(true); | |
3621 } | |
3622 set_arguments_for_java_call(slow_call); | |
3623 set_edges_for_java_call(slow_call); | |
3624 return slow_call; | |
3625 } | |
3626 | |
3627 | |
3628 //------------------------------inline_native_hashcode-------------------- | |
3629 // Build special case code for calls to hashCode on an object. | |
3630 bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) { | |
3631 assert(is_static == callee()->is_static(), "correct intrinsic selection"); | |
3632 assert(!(is_virtual && is_static), "either virtual, special, or static"); | |
3633 | |
3634 enum { _slow_path = 1, _fast_path, _null_path, PATH_LIMIT }; | |
3635 | |
3636 RegionNode* result_reg = new(C, PATH_LIMIT) RegionNode(PATH_LIMIT); | |
3637 PhiNode* result_val = new(C, PATH_LIMIT) PhiNode(result_reg, | |
3638 TypeInt::INT); | |
3639 PhiNode* result_io = new(C, PATH_LIMIT) PhiNode(result_reg, Type::ABIO); | |
3640 PhiNode* result_mem = new(C, PATH_LIMIT) PhiNode(result_reg, Type::MEMORY, | |
3641 TypePtr::BOTTOM); | |
3642 Node* obj = NULL; | |
3643 if (!is_static) { | |
3644 // Check for hashing null object | |
3645 obj = null_check_receiver(callee()); | |
3646 if (stopped()) return true; // unconditionally null | |
3647 result_reg->init_req(_null_path, top()); | |
3648 result_val->init_req(_null_path, top()); | |
3649 } else { | |
3650 // Do a null check, and return zero if null. | |
3651 // System.identityHashCode(null) == 0 | |
3652 obj = argument(0); | |
3653 Node* null_ctl = top(); | |
3654 obj = null_check_oop(obj, &null_ctl); | |
3655 result_reg->init_req(_null_path, null_ctl); | |
3656 result_val->init_req(_null_path, _gvn.intcon(0)); | |
3657 } | |
3658 | |
3659 // Unconditionally null? Then return right away. | |
3660 if (stopped()) { | |
3661 set_control( result_reg->in(_null_path) ); | |
3662 if (!stopped()) | |
3663 push( result_val ->in(_null_path) ); | |
3664 return true; | |
3665 } | |
3666 | |
3667 // After null check, get the object's klass. | |
3668 Node* obj_klass = load_object_klass(obj); | |
3669 | |
3670 // This call may be virtual (invokevirtual) or bound (invokespecial). | |
3671 // For each case we generate slightly different code. | |
3672 | |
3673 // We only go to the fast case code if we pass a number of guards. The | |
3674 // paths which do not pass are accumulated in the slow_region. | |
3675 RegionNode* slow_region = new (C, 1) RegionNode(1); | |
3676 record_for_igvn(slow_region); | |
3677 | |
3678 // If this is a virtual call, we generate a funny guard. We pull out | |
3679 // the vtable entry corresponding to hashCode() from the target object. | |
3680 // If the target method which we are calling happens to be the native | |
3681 // Object hashCode() method, we pass the guard. We do not need this | |
3682 // guard for non-virtual calls -- the caller is known to be the native | |
3683 // Object hashCode(). | |
3684 if (is_virtual) { | |
3685 generate_virtual_guard(obj_klass, slow_region); | |
3686 } | |
3687 | |
3688 // Get the header out of the object, use LoadMarkNode when available | |
3689 Node* header_addr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes()); | |
1609 | 3690 Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type()); |
0 | 3691 |
3692 // Test the header to see if it is unlocked. | |
3693 Node *lock_mask = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place); | |
3694 Node *lmasked_header = _gvn.transform( new (C, 3) AndXNode(header, lock_mask) ); | |
3695 Node *unlocked_val = _gvn.MakeConX(markOopDesc::unlocked_value); | |
3696 Node *chk_unlocked = _gvn.transform( new (C, 3) CmpXNode( lmasked_header, unlocked_val)); | |
3697 Node *test_unlocked = _gvn.transform( new (C, 2) BoolNode( chk_unlocked, BoolTest::ne) ); | |
3698 | |
3699 generate_slow_guard(test_unlocked, slow_region); | |
3700 | |
3701 // Get the hash value and check to see that it has been properly assigned. | |
3702 // We depend on hash_mask being at most 32 bits and avoid the use of | |
3703 // hash_mask_in_place because it could be larger than 32 bits in a 64-bit | |
3704 // vm: see markOop.hpp. | |
3705 Node *hash_mask = _gvn.intcon(markOopDesc::hash_mask); | |
3706 Node *hash_shift = _gvn.intcon(markOopDesc::hash_shift); | |
3707 Node *hshifted_header= _gvn.transform( new (C, 3) URShiftXNode(header, hash_shift) ); | |
3708 // This hack lets the hash bits live anywhere in the mark object now, as long | |
605 | 3709 // as the shift drops the relevant bits into the low 32 bits. Note that |
0 | 3710 // Java spec says that HashCode is an int so there's no point in capturing |
3711 // an 'X'-sized hashcode (32 in 32-bit build or 64 in 64-bit build). | |
3712 hshifted_header = ConvX2I(hshifted_header); | |
3713 Node *hash_val = _gvn.transform( new (C, 3) AndINode(hshifted_header, hash_mask) ); | |
3714 | |
3715 Node *no_hash_val = _gvn.intcon(markOopDesc::no_hash); | |
3716 Node *chk_assigned = _gvn.transform( new (C, 3) CmpINode( hash_val, no_hash_val)); | |
3717 Node *test_assigned = _gvn.transform( new (C, 2) BoolNode( chk_assigned, BoolTest::eq) ); | |
3718 | |
3719 generate_slow_guard(test_assigned, slow_region); | |
3720 | |
3721 Node* init_mem = reset_memory(); | |
3722 // fill in the rest of the null path: | |
3723 result_io ->init_req(_null_path, i_o()); | |
3724 result_mem->init_req(_null_path, init_mem); | |
3725 | |
3726 result_val->init_req(_fast_path, hash_val); | |
3727 result_reg->init_req(_fast_path, control()); | |
3728 result_io ->init_req(_fast_path, i_o()); | |
3729 result_mem->init_req(_fast_path, init_mem); | |
3730 | |
3731 // Generate code for the slow case. We make a call to hashCode(). | |
3732 set_control(_gvn.transform(slow_region)); | |
3733 if (!stopped()) { | |
3734 // No need for PreserveJVMState, because we're using up the present state. | |
3735 set_all_memory(init_mem); | |
3736 vmIntrinsics::ID hashCode_id = vmIntrinsics::_hashCode; | |
3737 if (is_static) hashCode_id = vmIntrinsics::_identityHashCode; | |
3738 CallJavaNode* slow_call = generate_method_call(hashCode_id, is_virtual, is_static); | |
3739 Node* slow_result = set_results_for_java_call(slow_call); | |
3740 // this->control() comes from set_results_for_java_call | |
3741 result_reg->init_req(_slow_path, control()); | |
3742 result_val->init_req(_slow_path, slow_result); | |
3743 result_io ->set_req(_slow_path, i_o()); | |
3744 result_mem ->set_req(_slow_path, reset_memory()); | |
3745 } | |
3746 | |
3747 // Return the combined state. | |
3748 set_i_o( _gvn.transform(result_io) ); | |
3749 set_all_memory( _gvn.transform(result_mem) ); | |
3750 push_result(result_reg, result_val); | |
3751 | |
3752 return true; | |
3753 } | |
3754 | |
3755 //---------------------------inline_native_getClass---------------------------- | |
605 | 3756 // Build special case code for calls to getClass on an object. |
0 | 3757 bool LibraryCallKit::inline_native_getClass() { |
3758 Node* obj = null_check_receiver(callee()); | |
3759 if (stopped()) return true; | |
3760 push( load_mirror_from_klass(load_object_klass(obj)) ); | |
3761 return true; | |
3762 } | |
3763 | |
3764 //-----------------inline_native_Reflection_getCallerClass--------------------- | |
3765 // In the presence of deep enough inlining, getCallerClass() becomes a no-op. | |
3766 // | |
3767 // NOTE that this code must perform the same logic as | |
3768 // vframeStream::security_get_caller_frame in that it must skip | |
3769 // Method.invoke() and auxiliary frames. | |
3770 | |
3771 | |
3772 | |
3773 | |
3774 bool LibraryCallKit::inline_native_Reflection_getCallerClass() { | |
3775 ciMethod* method = callee(); | |
3776 | |
3777 #ifndef PRODUCT | |
3778 if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) { | |
3779 tty->print_cr("Attempting to inline sun.reflect.Reflection.getCallerClass"); | |
3780 } | |
3781 #endif | |
3782 | |
3783 debug_only(int saved_sp = _sp); | |
3784 | |
3785 // Argument words: (int depth) | |
3786 int nargs = 1; | |
3787 | |
3788 _sp += nargs; | |
3789 Node* caller_depth_node = pop(); | |
3790 | |
3791 assert(saved_sp == _sp, "must have correct argument count"); | |
3792 | |
3793 // The depth value must be a constant in order for the runtime call | |
3794 // to be eliminated. | |
3795 const TypeInt* caller_depth_type = _gvn.type(caller_depth_node)->isa_int(); | |
3796 if (caller_depth_type == NULL || !caller_depth_type->is_con()) { | |
3797 #ifndef PRODUCT | |
3798 if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) { | |
3799 tty->print_cr(" Bailing out because caller depth was not a constant"); | |
3800 } | |
3801 #endif | |
3802 return false; | |
3803 } | |
3804 // Note that the JVM state at this point does not include the | |
3805 // getCallerClass() frame which we are trying to inline. The | |
3806 // semantics of getCallerClass(), however, are that the "first" | |
3807 // frame is the getCallerClass() frame, so we subtract one from the | |
3808 // requested depth before continuing. We don't inline requests of | |
3809 // getCallerClass(0). | |
3810 int caller_depth = caller_depth_type->get_con() - 1; | |
3811 if (caller_depth < 0) { | |
3812 #ifndef PRODUCT | |
3813 if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) { | |
3814 tty->print_cr(" Bailing out because caller depth was %d", caller_depth); | |
3815 } | |
3816 #endif | |
3817 return false; | |
3818 } | |
3819 | |
3820 if (!jvms()->has_method()) { | |
3821 #ifndef PRODUCT | |
3822 if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) { | |
3823 tty->print_cr(" Bailing out because intrinsic was inlined at top level"); | |
3824 } | |
3825 #endif | |
3826 return false; | |
3827 } | |
3828 int _depth = jvms()->depth(); // cache call chain depth | |
3829 | |
3830 // Walk back up the JVM state to find the caller at the required | |
3831 // depth. NOTE that this code must perform the same logic as | |
3832 // vframeStream::security_get_caller_frame in that it must skip | |
3833 // Method.invoke() and auxiliary frames. Note also that depth is | |
3834 // 1-based (1 is the bottom of the inlining). | |
3835 int inlining_depth = _depth; | |
3836 JVMState* caller_jvms = NULL; | |
3837 | |
3838 if (inlining_depth > 0) { | |
3839 caller_jvms = jvms(); | |
3840 assert(caller_jvms = jvms()->of_depth(inlining_depth), "inlining_depth == our depth"); | |
3841 do { | |
3842 // The following if-tests should be performed in this order | |
3843 if (is_method_invoke_or_aux_frame(caller_jvms)) { | |
3844 // Skip a Method.invoke() or auxiliary frame | |
3845 } else if (caller_depth > 0) { | |
3846 // Skip real frame | |
3847 --caller_depth; | |
3848 } else { | |
3849 // We're done: reached desired caller after skipping. | |
3850 break; | |
3851 } | |
3852 caller_jvms = caller_jvms->caller(); | |
3853 --inlining_depth; | |
3854 } while (inlining_depth > 0); | |
3855 } | |
3856 | |
3857 if (inlining_depth == 0) { | |
3858 #ifndef PRODUCT | |
3859 if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) { | |
3860 tty->print_cr(" Bailing out because caller depth (%d) exceeded inlining depth (%d)", caller_depth_type->get_con(), _depth); | |
3861 tty->print_cr(" JVM state at this point:"); | |
3862 for (int i = _depth; i >= 1; i--) { | |
3863 tty->print_cr(" %d) %s", i, jvms()->of_depth(i)->method()->name()->as_utf8()); | |
3864 } | |
3865 } | |
3866 #endif | |
3867 return false; // Reached end of inlining | |
3868 } | |
3869 | |
3870 // Acquire method holder as java.lang.Class | |
3871 ciInstanceKlass* caller_klass = caller_jvms->method()->holder(); | |
3872 ciInstance* caller_mirror = caller_klass->java_mirror(); | |
3873 // Push this as a constant | |
3874 push(makecon(TypeInstPtr::make(caller_mirror))); | |
3875 #ifndef PRODUCT | |
3876 if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) { | |
3877 tty->print_cr(" Succeeded: caller = %s.%s, caller depth = %d, depth = %d", caller_klass->name()->as_utf8(), caller_jvms->method()->name()->as_utf8(), caller_depth_type->get_con(), _depth); | |
3878 tty->print_cr(" JVM state at this point:"); | |
3879 for (int i = _depth; i >= 1; i--) { | |
3880 tty->print_cr(" %d) %s", i, jvms()->of_depth(i)->method()->name()->as_utf8()); | |
3881 } | |
3882 } | |
3883 #endif | |
3884 return true; | |
3885 } | |
3886 | |
3887 // Helper routine for above | |
3888 bool LibraryCallKit::is_method_invoke_or_aux_frame(JVMState* jvms) { | |
1152
cd37471eaecc
6914206: change way of permission checking for generated MethodHandle adapters
twisti
parents:
1027
diff
changeset
|
3889 ciMethod* method = jvms->method(); |
cd37471eaecc
6914206: change way of permission checking for generated MethodHandle adapters
twisti
parents:
1027
diff
changeset
|
3890 |
0 | 3891 // Is this the Method.invoke method itself? |
1152
cd37471eaecc
6914206: change way of permission checking for generated MethodHandle adapters
twisti
parents:
1027
diff
changeset
|
3892 if (method->intrinsic_id() == vmIntrinsics::_invoke) |
0 | 3893 return true; |
3894 | |
3895 // Is this a helper, defined somewhere underneath MethodAccessorImpl. | |
1152
cd37471eaecc
6914206: change way of permission checking for generated MethodHandle adapters
twisti
parents:
1027
diff
changeset
|
3896 ciKlass* k = method->holder(); |
0 | 3897 if (k->is_instance_klass()) { |
3898 ciInstanceKlass* ik = k->as_instance_klass(); | |
3899 for (; ik != NULL; ik = ik->super()) { | |
3900 if (ik->name() == ciSymbol::sun_reflect_MethodAccessorImpl() && | |
3901 ik == env()->find_system_klass(ik->name())) { | |
3902 return true; | |
3903 } | |
3904 } | |
3905 } | |
1152
cd37471eaecc
6914206: change way of permission checking for generated MethodHandle adapters
twisti
parents:
1027
diff
changeset
|
3906 else if (method->is_method_handle_adapter()) { |
cd37471eaecc
6914206: change way of permission checking for generated MethodHandle adapters
twisti
parents:
1027
diff
changeset
|
3907 // This is an internal adapter frame from the MethodHandleCompiler -- skip it |
cd37471eaecc
6914206: change way of permission checking for generated MethodHandle adapters
twisti
parents:
1027
diff
changeset
|
3908 return true; |
cd37471eaecc
6914206: change way of permission checking for generated MethodHandle adapters
twisti
parents:
1027
diff
changeset
|
3909 } |
0 | 3910 |
3911 return false; | |
3912 } | |
3913 | |
3914 static int value_field_offset = -1; // offset of the "value" field of AtomicLongCSImpl. This is needed by | |
3915 // inline_native_AtomicLong_attemptUpdate() but it has no way of | |
3916 // computing it since there is no lookup field by name function in the | |
3917 // CI interface. This is computed and set by inline_native_AtomicLong_get(). | |
3918 // Using a static variable here is safe even if we have multiple compilation | |
3919 // threads because the offset is constant. At worst the same offset will be | |
3920 // computed and stored multiple | |
3921 | |
3922 bool LibraryCallKit::inline_native_AtomicLong_get() { | |
3923 // Restore the stack and pop off the argument | |
3924 _sp+=1; | |
3925 Node *obj = pop(); | |
3926 | |
3927 // get the offset of the "value" field. Since the CI interfaces | |
3928 // does not provide a way to look up a field by name, we scan the bytecodes | |
3929 // to get the field index. We expect the first 2 instructions of the method | |
3930 // to be: | |
3931 // 0 aload_0 | |
3932 // 1 getfield "value" | |
3933 ciMethod* method = callee(); | |
3934 if (value_field_offset == -1) | |
3935 { | |
3936 ciField* value_field; | |
3937 ciBytecodeStream iter(method); | |
3938 Bytecodes::Code bc = iter.next(); | |
3939 | |
3940 if ((bc != Bytecodes::_aload_0) && | |
3941 ((bc != Bytecodes::_aload) || (iter.get_index() != 0))) | |
3942 return false; | |
3943 bc = iter.next(); | |
3944 if (bc != Bytecodes::_getfield) | |
3945 return false; | |
3946 bool ignore; | |
3947 value_field = iter.get_field(ignore); | |
3948 value_field_offset = value_field->offset_in_bytes(); | |
3949 } | |
3950 | |
3951 // Null check without removing any arguments. | |
3952 _sp++; | |
3953 obj = do_null_check(obj, T_OBJECT); | |
3954 _sp--; | |
3955 // Check for locking null object | |
3956 if (stopped()) return true; | |
3957 | |
3958 Node *adr = basic_plus_adr(obj, obj, value_field_offset); | |
3959 const TypePtr *adr_type = _gvn.type(adr)->is_ptr(); | |
3960 int alias_idx = C->get_alias_index(adr_type); | |
3961 | |
3962 Node *result = _gvn.transform(new (C, 3) LoadLLockedNode(control(), memory(alias_idx), adr)); | |
3963 | |
3964 push_pair(result); | |
3965 | |
3966 return true; | |
3967 } | |
3968 | |
3969 bool LibraryCallKit::inline_native_AtomicLong_attemptUpdate() { | |
3970 // Restore the stack and pop off the arguments | |
3971 _sp+=5; | |
3972 Node *newVal = pop_pair(); | |
3973 Node *oldVal = pop_pair(); | |
3974 Node *obj = pop(); | |
3975 | |
3976 // we need the offset of the "value" field which was computed when | |
3977 // inlining the get() method. Give up if we don't have it. | |
3978 if (value_field_offset == -1) | |
3979 return false; | |
3980 | |
3981 // Null check without removing any arguments. | |
3982 _sp+=5; | |
3983 obj = do_null_check(obj, T_OBJECT); | |
3984 _sp-=5; | |
3985 // Check for locking null object | |
3986 if (stopped()) return true; | |
3987 | |
3988 Node *adr = basic_plus_adr(obj, obj, value_field_offset); | |
3989 const TypePtr *adr_type = _gvn.type(adr)->is_ptr(); | |
3990 int alias_idx = C->get_alias_index(adr_type); | |
3991 | |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
3992 Node *cas = _gvn.transform(new (C, 5) StoreLConditionalNode(control(), memory(alias_idx), adr, newVal, oldVal)); |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
3993 Node *store_proj = _gvn.transform( new (C, 1) SCMemProjNode(cas)); |
0 | 3994 set_memory(store_proj, alias_idx); |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
3995 Node *bol = _gvn.transform( new (C, 2) BoolNode( cas, BoolTest::eq ) ); |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
3996 |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
3997 Node *result; |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
3998 // CMove node is not used to be able fold a possible check code |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
3999 // after attemptUpdate() call. This code could be transformed |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4000 // into CMove node by loop optimizations. |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4001 { |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4002 RegionNode *r = new (C, 3) RegionNode(3); |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4003 result = new (C, 3) PhiNode(r, TypeInt::BOOL); |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4004 |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4005 Node *iff = create_and_xform_if(control(), bol, PROB_FAIR, COUNT_UNKNOWN); |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4006 Node *iftrue = opt_iff(r, iff); |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4007 r->init_req(1, iftrue); |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4008 result->init_req(1, intcon(1)); |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4009 result->init_req(2, intcon(0)); |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4010 |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4011 set_control(_gvn.transform(r)); |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4012 record_for_igvn(r); |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4013 |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4014 C->set_has_split_ifs(true); // Has chance for split-if optimization |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4015 } |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4016 |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
235
diff
changeset
|
4017 push(_gvn.transform(result)); |
0 | 4018 return true; |
4019 } | |
4020 | |
4021 bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) { | |
4022 // restore the arguments | |
4023 _sp += arg_size(); | |
4024 | |
4025 switch (id) { | |
4026 case vmIntrinsics::_floatToRawIntBits: | |
4027 push(_gvn.transform( new (C, 2) MoveF2INode(pop()))); | |
4028 break; | |
4029 | |
4030 case vmIntrinsics::_intBitsToFloat: | |
4031 push(_gvn.transform( new (C, 2) MoveI2FNode(pop()))); | |
4032 break; | |
4033 | |
4034 case vmIntrinsics::_doubleToRawLongBits: | |
4035 push_pair(_gvn.transform( new (C, 2) MoveD2LNode(pop_pair()))); | |
4036 break; | |
4037 | |
4038 case vmIntrinsics::_longBitsToDouble: | |
4039 push_pair(_gvn.transform( new (C, 2) MoveL2DNode(pop_pair()))); | |
4040 break; | |
4041 | |
4042 case vmIntrinsics::_doubleToLongBits: { | |
4043 Node* value = pop_pair(); | |
4044 | |
4045 // two paths (plus control) merge in a wood | |
4046 RegionNode *r = new (C, 3) RegionNode(3); | |
4047 Node *phi = new (C, 3) PhiNode(r, TypeLong::LONG); | |
4048 | |
4049 Node *cmpisnan = _gvn.transform( new (C, 3) CmpDNode(value, value)); | |
4050 // Build the boolean node | |
4051 Node *bolisnan = _gvn.transform( new (C, 2) BoolNode( cmpisnan, BoolTest::ne ) ); | |
4052 | |
4053 // Branch either way. | |
4054 // NaN case is less traveled, which makes all the difference. | |
4055 IfNode *ifisnan = create_and_xform_if(control(), bolisnan, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); | |
4056 Node *opt_isnan = _gvn.transform(ifisnan); | |
4057 assert( opt_isnan->is_If(), "Expect an IfNode"); | |
4058 IfNode *opt_ifisnan = (IfNode*)opt_isnan; | |
4059 Node *iftrue = _gvn.transform( new (C, 1) IfTrueNode(opt_ifisnan) ); | |
4060 | |
4061 set_control(iftrue); | |
4062 | |
4063 static const jlong nan_bits = CONST64(0x7ff8000000000000); | |
4064 Node *slow_result = longcon(nan_bits); // return NaN | |
4065 phi->init_req(1, _gvn.transform( slow_result )); | |
4066 r->init_req(1, iftrue); | |
4067 | |
4068 // Else fall through | |
4069 Node *iffalse = _gvn.transform( new (C, 1) IfFalseNode(opt_ifisnan) ); | |
4070 set_control(iffalse); | |
4071 | |
4072 phi->init_req(2, _gvn.transform( new (C, 2) MoveD2LNode(value))); | |
4073 r->init_req(2, iffalse); | |
4074 | |
4075 // Post merge | |
4076 set_control(_gvn.transform(r)); | |
4077 record_for_igvn(r); | |
4078 | |
4079 Node* result = _gvn.transform(phi); | |
4080 assert(result->bottom_type()->isa_long(), "must be"); | |
4081 push_pair(result); | |
4082 | |
4083 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
4084 | |
4085 break; | |
4086 } | |
4087 | |
4088 case vmIntrinsics::_floatToIntBits: { | |
4089 Node* value = pop(); | |
4090 | |
4091 // two paths (plus control) merge in a wood | |
4092 RegionNode *r = new (C, 3) RegionNode(3); | |
4093 Node *phi = new (C, 3) PhiNode(r, TypeInt::INT); | |
4094 | |
4095 Node *cmpisnan = _gvn.transform( new (C, 3) CmpFNode(value, value)); | |
4096 // Build the boolean node | |
4097 Node *bolisnan = _gvn.transform( new (C, 2) BoolNode( cmpisnan, BoolTest::ne ) ); | |
4098 | |
4099 // Branch either way. | |
4100 // NaN case is less traveled, which makes all the difference. | |
4101 IfNode *ifisnan = create_and_xform_if(control(), bolisnan, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); | |
4102 Node *opt_isnan = _gvn.transform(ifisnan); | |
4103 assert( opt_isnan->is_If(), "Expect an IfNode"); | |
4104 IfNode *opt_ifisnan = (IfNode*)opt_isnan; | |
4105 Node *iftrue = _gvn.transform( new (C, 1) IfTrueNode(opt_ifisnan) ); | |
4106 | |
4107 set_control(iftrue); | |
4108 | |
4109 static const jint nan_bits = 0x7fc00000; | |
4110 Node *slow_result = makecon(TypeInt::make(nan_bits)); // return NaN | |
4111 phi->init_req(1, _gvn.transform( slow_result )); | |
4112 r->init_req(1, iftrue); | |
4113 | |
4114 // Else fall through | |
4115 Node *iffalse = _gvn.transform( new (C, 1) IfFalseNode(opt_ifisnan) ); | |
4116 set_control(iffalse); | |
4117 | |
4118 phi->init_req(2, _gvn.transform( new (C, 2) MoveF2INode(value))); | |
4119 r->init_req(2, iffalse); | |
4120 | |
4121 // Post merge | |
4122 set_control(_gvn.transform(r)); | |
4123 record_for_igvn(r); | |
4124 | |
4125 Node* result = _gvn.transform(phi); | |
4126 assert(result->bottom_type()->isa_int(), "must be"); | |
4127 push(result); | |
4128 | |
4129 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
4130 | |
4131 break; | |
4132 } | |
4133 | |
4134 default: | |
4135 ShouldNotReachHere(); | |
4136 } | |
4137 | |
4138 return true; | |
4139 } | |
4140 | |
4141 #ifdef _LP64 | |
4142 #define XTOP ,top() /*additional argument*/ | |
4143 #else //_LP64 | |
4144 #define XTOP /*no additional argument*/ | |
4145 #endif //_LP64 | |
4146 | |
4147 //----------------------inline_unsafe_copyMemory------------------------- | |
4148 bool LibraryCallKit::inline_unsafe_copyMemory() { | |
4149 if (callee()->is_static()) return false; // caller must have the capability! | |
4150 int nargs = 1 + 5 + 3; // 5 args: (src: ptr,off, dst: ptr,off, size) | |
4151 assert(signature()->size() == nargs-1, "copy has 5 arguments"); | |
4152 null_check_receiver(callee()); // check then ignore argument(0) | |
4153 if (stopped()) return true; | |
4154 | |
4155 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
4156 | |
4157 Node* src_ptr = argument(1); | |
4158 Node* src_off = ConvL2X(argument(2)); | |
4159 assert(argument(3)->is_top(), "2nd half of long"); | |
4160 Node* dst_ptr = argument(4); | |
4161 Node* dst_off = ConvL2X(argument(5)); | |
4162 assert(argument(6)->is_top(), "2nd half of long"); | |
4163 Node* size = ConvL2X(argument(7)); | |
4164 assert(argument(8)->is_top(), "2nd half of long"); | |
4165 | |
4166 assert(Unsafe_field_offset_to_byte_offset(11) == 11, | |
4167 "fieldOffset must be byte-scaled"); | |
4168 | |
4169 Node* src = make_unsafe_address(src_ptr, src_off); | |
4170 Node* dst = make_unsafe_address(dst_ptr, dst_off); | |
4171 | |
4172 // Conservatively insert a memory barrier on all memory slices. | |
4173 // Do not let writes of the copy source or destination float below the copy. | |
4174 insert_mem_bar(Op_MemBarCPUOrder); | |
4175 | |
4176 // Call it. Note that the length argument is not scaled. | |
4177 make_runtime_call(RC_LEAF|RC_NO_FP, | |
4178 OptoRuntime::fast_arraycopy_Type(), | |
4179 StubRoutines::unsafe_arraycopy(), | |
4180 "unsafe_arraycopy", | |
4181 TypeRawPtr::BOTTOM, | |
4182 src, dst, size XTOP); | |
4183 | |
4184 // Do not let reads of the copy destination float above the copy. | |
4185 insert_mem_bar(Op_MemBarCPUOrder); | |
4186 | |
4187 return true; | |
4188 } | |
4189 | |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4190 //------------------------clone_coping----------------------------------- |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4191 // Helper function for inline_native_clone. |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4192 void LibraryCallKit::copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array, bool card_mark) { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4193 assert(obj_size != NULL, ""); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4194 Node* raw_obj = alloc_obj->in(1); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4195 assert(alloc_obj->is_CheckCastPP() && raw_obj->is_Proj() && raw_obj->in(0)->is_Allocate(), ""); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4196 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4197 if (ReduceBulkZeroing) { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4198 // We will be completely responsible for initializing this object - |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4199 // mark Initialize node as complete. |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4200 AllocateNode* alloc = AllocateNode::Ideal_allocation(alloc_obj, &_gvn); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4201 // The object was just allocated - there should be no any stores! |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4202 guarantee(alloc != NULL && alloc->maybe_set_complete(&_gvn), ""); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4203 } |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4204 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4205 // Copy the fastest available way. |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4206 // TODO: generate fields copies for small objects instead. |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4207 Node* src = obj; |
958
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
4208 Node* dest = alloc_obj; |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4209 Node* size = _gvn.transform(obj_size); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4210 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4211 // Exclude the header but include array length to copy by 8 bytes words. |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4212 // Can't use base_offset_in_bytes(bt) since basic type is unknown. |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4213 int base_off = is_array ? arrayOopDesc::length_offset_in_bytes() : |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4214 instanceOopDesc::base_offset_in_bytes(); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4215 // base_off: |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4216 // 8 - 32-bit VM |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4217 // 12 - 64-bit VM, compressed oops |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4218 // 16 - 64-bit VM, normal oops |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4219 if (base_off % BytesPerLong != 0) { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4220 assert(UseCompressedOops, ""); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4221 if (is_array) { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4222 // Exclude length to copy by 8 bytes words. |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4223 base_off += sizeof(int); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4224 } else { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4225 // Include klass to copy by 8 bytes words. |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4226 base_off = instanceOopDesc::klass_offset_in_bytes(); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4227 } |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4228 assert(base_off % BytesPerLong == 0, "expect 8 bytes alignment"); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4229 } |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4230 src = basic_plus_adr(src, base_off); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4231 dest = basic_plus_adr(dest, base_off); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4232 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4233 // Compute the length also, if needed: |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4234 Node* countx = size; |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4235 countx = _gvn.transform( new (C, 3) SubXNode(countx, MakeConX(base_off)) ); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4236 countx = _gvn.transform( new (C, 3) URShiftXNode(countx, intcon(LogBytesPerLong) )); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4237 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4238 const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4239 bool disjoint_bases = true; |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4240 generate_unchecked_arraycopy(raw_adr_type, T_LONG, disjoint_bases, |
2324 | 4241 src, NULL, dest, NULL, countx, |
4242 /*dest_uninitialized*/true); | |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4243 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4244 // If necessary, emit some card marks afterwards. (Non-arrays only.) |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4245 if (card_mark) { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4246 assert(!is_array, ""); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4247 // Put in store barrier for any and all oops we are sticking |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4248 // into this object. (We could avoid this if we could prove |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4249 // that the object type contains no oop fields at all.) |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4250 Node* no_particular_value = NULL; |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4251 Node* no_particular_field = NULL; |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4252 int raw_adr_idx = Compile::AliasIdxRaw; |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4253 post_barrier(control(), |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4254 memory(raw_adr_type), |
958
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
4255 alloc_obj, |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4256 no_particular_field, |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4257 raw_adr_idx, |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4258 no_particular_value, |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4259 T_OBJECT, |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4260 false); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4261 } |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4262 |
958
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
4263 // Do not let reads from the cloned object float above the arraycopy. |
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
4264 insert_mem_bar(Op_MemBarCPUOrder); |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4265 } |
0 | 4266 |
4267 //------------------------inline_native_clone---------------------------- | |
4268 // Here are the simple edge cases: | |
4269 // null receiver => normal trap | |
4270 // virtual and clone was overridden => slow path to out-of-line clone | |
4271 // not cloneable or finalizer => slow path to out-of-line Object.clone | |
4272 // | |
4273 // The general case has two steps, allocation and copying. | |
4274 // Allocation has two cases, and uses GraphKit::new_instance or new_array. | |
4275 // | |
4276 // Copying also has two cases, oop arrays and everything else. | |
4277 // Oop arrays use arrayof_oop_arraycopy (same as System.arraycopy). | |
4278 // Everything else uses the tight inline loop supplied by CopyArrayNode. | |
4279 // | |
4280 // These steps fold up nicely if and when the cloned object's klass | |
4281 // can be sharply typed as an object array, a type array, or an instance. | |
4282 // | |
4283 bool LibraryCallKit::inline_native_clone(bool is_virtual) { | |
4284 int nargs = 1; | |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4285 PhiNode* result_val; |
0 | 4286 |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4287 //set the original stack and the reexecute bit for the interpreter to reexecute |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4288 //the bytecode that invokes Object.clone if deoptimization happens |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4289 { PreserveReexecuteState preexecs(this); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4290 jvms()->set_should_reexecute(true); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4291 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4292 //null_check_receiver will adjust _sp (push and pop) |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4293 Node* obj = null_check_receiver(callee()); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4294 if (stopped()) return true; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4295 |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4296 _sp += nargs; |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4297 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4298 Node* obj_klass = load_object_klass(obj); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4299 const TypeKlassPtr* tklass = _gvn.type(obj_klass)->isa_klassptr(); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4300 const TypeOopPtr* toop = ((tklass != NULL) |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4301 ? tklass->as_instance_type() |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4302 : TypeInstPtr::NOTNULL); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4303 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4304 // Conservatively insert a memory barrier on all memory slices. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4305 // Do not let writes into the original float below the clone. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4306 insert_mem_bar(Op_MemBarCPUOrder); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4307 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4308 // paths into result_reg: |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4309 enum { |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4310 _slow_path = 1, // out-of-line call to clone method (virtual or not) |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4311 _objArray_path, // plain array allocation, plus arrayof_oop_arraycopy |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4312 _array_path, // plain array allocation, plus arrayof_long_arraycopy |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4313 _instance_path, // plain instance allocation, plus arrayof_long_arraycopy |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4314 PATH_LIMIT |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4315 }; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4316 RegionNode* result_reg = new(C, PATH_LIMIT) RegionNode(PATH_LIMIT); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4317 result_val = new(C, PATH_LIMIT) PhiNode(result_reg, |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4318 TypeInstPtr::NOTNULL); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4319 PhiNode* result_i_o = new(C, PATH_LIMIT) PhiNode(result_reg, Type::ABIO); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4320 PhiNode* result_mem = new(C, PATH_LIMIT) PhiNode(result_reg, Type::MEMORY, |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4321 TypePtr::BOTTOM); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4322 record_for_igvn(result_reg); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4323 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4324 const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4325 int raw_adr_idx = Compile::AliasIdxRaw; |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4326 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4327 Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)NULL); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4328 if (array_ctl != NULL) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4329 // It's an array. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4330 PreserveJVMState pjvms(this); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4331 set_control(array_ctl); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4332 Node* obj_length = load_array_length(obj); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4333 Node* obj_size = NULL; |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2446
diff
changeset
|
4334 Node* alloc_obj = new_array(obj_klass, obj_length, 0, &obj_size); |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4335 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4336 if (!use_ReduceInitialCardMarks()) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4337 // If it is an oop array, it requires very special treatment, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4338 // because card marking is required on each card of the array. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4339 Node* is_obja = generate_objArray_guard(obj_klass, (RegionNode*)NULL); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4340 if (is_obja != NULL) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4341 PreserveJVMState pjvms2(this); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4342 set_control(is_obja); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4343 // Generate a direct call to the right arraycopy function(s). |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4344 bool disjoint_bases = true; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4345 bool length_never_negative = true; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4346 generate_arraycopy(TypeAryPtr::OOPS, T_OBJECT, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4347 obj, intcon(0), alloc_obj, intcon(0), |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4348 obj_length, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4349 disjoint_bases, length_never_negative); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4350 result_reg->init_req(_objArray_path, control()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4351 result_val->init_req(_objArray_path, alloc_obj); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4352 result_i_o ->set_req(_objArray_path, i_o()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4353 result_mem ->set_req(_objArray_path, reset_memory()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4354 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4355 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4356 // Otherwise, there are no card marks to worry about. |
1027
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
986
diff
changeset
|
4357 // (We can dispense with card marks if we know the allocation |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
986
diff
changeset
|
4358 // comes out of eden (TLAB)... In fact, ReduceInitialCardMarks |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
986
diff
changeset
|
4359 // causes the non-eden paths to take compensating steps to |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
986
diff
changeset
|
4360 // simulate a fresh allocation, so that no further |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
986
diff
changeset
|
4361 // card marks are required in compiled code to initialize |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
986
diff
changeset
|
4362 // the object.) |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4363 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4364 if (!stopped()) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4365 copy_to_clone(obj, alloc_obj, obj_size, true, false); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4366 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4367 // Present the results of the copy. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4368 result_reg->init_req(_array_path, control()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4369 result_val->init_req(_array_path, alloc_obj); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4370 result_i_o ->set_req(_array_path, i_o()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4371 result_mem ->set_req(_array_path, reset_memory()); |
0 | 4372 } |
4373 } | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4374 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4375 // We only go to the instance fast case code if we pass a number of guards. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4376 // The paths which do not pass are accumulated in the slow_region. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4377 RegionNode* slow_region = new (C, 1) RegionNode(1); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4378 record_for_igvn(slow_region); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4379 if (!stopped()) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4380 // It's an instance (we did array above). Make the slow-path tests. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4381 // If this is a virtual call, we generate a funny guard. We grab |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4382 // the vtable entry corresponding to clone() from the target object. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4383 // If the target method which we are calling happens to be the |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4384 // Object clone() method, we pass the guard. We do not need this |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4385 // guard for non-virtual calls; the caller is known to be the native |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4386 // Object clone(). |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4387 if (is_virtual) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4388 generate_virtual_guard(obj_klass, slow_region); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4389 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4390 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4391 // The object must be cloneable and must not have a finalizer. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4392 // Both of these conditions may be checked in a single test. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4393 // We could optimize the cloneable test further, but we don't care. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4394 generate_access_flags_guard(obj_klass, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4395 // Test both conditions: |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4396 JVM_ACC_IS_CLONEABLE | JVM_ACC_HAS_FINALIZER, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4397 // Must be cloneable but not finalizer: |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4398 JVM_ACC_IS_CLONEABLE, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4399 slow_region); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4400 } |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4401 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4402 if (!stopped()) { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4403 // It's an instance, and it passed the slow-path tests. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4404 PreserveJVMState pjvms(this); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4405 Node* obj_size = NULL; |
3278
66b0e2371912
7026700: regression in 6u24-rev-b23: Crash in C2 compiler in PhaseIdealLoop::build_loop_late_post
kvn
parents:
2446
diff
changeset
|
4406 Node* alloc_obj = new_instance(obj_klass, NULL, &obj_size); |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4407 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4408 copy_to_clone(obj, alloc_obj, obj_size, false, !use_ReduceInitialCardMarks()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4409 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4410 // Present the results of the slow call. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4411 result_reg->init_req(_instance_path, control()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4412 result_val->init_req(_instance_path, alloc_obj); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4413 result_i_o ->set_req(_instance_path, i_o()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4414 result_mem ->set_req(_instance_path, reset_memory()); |
0 | 4415 } |
4416 | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4417 // Generate code for the slow case. We make a call to clone(). |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4418 set_control(_gvn.transform(slow_region)); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4419 if (!stopped()) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4420 PreserveJVMState pjvms(this); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4421 CallJavaNode* slow_call = generate_method_call(vmIntrinsics::_clone, is_virtual); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4422 Node* slow_result = set_results_for_java_call(slow_call); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4423 // this->control() comes from set_results_for_java_call |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4424 result_reg->init_req(_slow_path, control()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4425 result_val->init_req(_slow_path, slow_result); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4426 result_i_o ->set_req(_slow_path, i_o()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4427 result_mem ->set_req(_slow_path, reset_memory()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4428 } |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4429 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4430 // Return the combined state. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4431 set_control( _gvn.transform(result_reg) ); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4432 set_i_o( _gvn.transform(result_i_o) ); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4433 set_all_memory( _gvn.transform(result_mem) ); |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4434 } //original reexecute and sp are set back here |
0 | 4435 |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4436 push(_gvn.transform(result_val)); |
0 | 4437 |
4438 return true; | |
4439 } | |
4440 | |
4441 //------------------------------basictype2arraycopy---------------------------- | |
4442 address LibraryCallKit::basictype2arraycopy(BasicType t, | |
4443 Node* src_offset, | |
4444 Node* dest_offset, | |
4445 bool disjoint_bases, | |
2324 | 4446 const char* &name, |
4447 bool dest_uninitialized) { | |
0 | 4448 const TypeInt* src_offset_inttype = gvn().find_int_type(src_offset);; |
4449 const TypeInt* dest_offset_inttype = gvn().find_int_type(dest_offset);; | |
4450 | |
4451 bool aligned = false; | |
4452 bool disjoint = disjoint_bases; | |
4453 | |
4454 // if the offsets are the same, we can treat the memory regions as | |
4455 // disjoint, because either the memory regions are in different arrays, | |
4456 // or they are identical (which we can treat as disjoint.) We can also | |
4457 // treat a copy with a destination index less that the source index | |
4458 // as disjoint since a low->high copy will work correctly in this case. | |
4459 if (src_offset_inttype != NULL && src_offset_inttype->is_con() && | |
4460 dest_offset_inttype != NULL && dest_offset_inttype->is_con()) { | |
4461 // both indices are constants | |
4462 int s_offs = src_offset_inttype->get_con(); | |
4463 int d_offs = dest_offset_inttype->get_con(); | |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
0
diff
changeset
|
4464 int element_size = type2aelembytes(t); |
0 | 4465 aligned = ((arrayOopDesc::base_offset_in_bytes(t) + s_offs * element_size) % HeapWordSize == 0) && |
4466 ((arrayOopDesc::base_offset_in_bytes(t) + d_offs * element_size) % HeapWordSize == 0); | |
4467 if (s_offs >= d_offs) disjoint = true; | |
4468 } else if (src_offset == dest_offset && src_offset != NULL) { | |
4469 // This can occur if the offsets are identical non-constants. | |
4470 disjoint = true; | |
4471 } | |
4472 | |
2446 | 4473 return StubRoutines::select_arraycopy_function(t, aligned, disjoint, name, dest_uninitialized); |
0 | 4474 } |
4475 | |
4476 | |
4477 //------------------------------inline_arraycopy----------------------- | |
4478 bool LibraryCallKit::inline_arraycopy() { | |
4479 // Restore the stack and pop off the arguments. | |
4480 int nargs = 5; // 2 oops, 3 ints, no size_t or long | |
4481 assert(callee()->signature()->size() == nargs, "copy has 5 arguments"); | |
4482 | |
4483 Node *src = argument(0); | |
4484 Node *src_offset = argument(1); | |
4485 Node *dest = argument(2); | |
4486 Node *dest_offset = argument(3); | |
4487 Node *length = argument(4); | |
4488 | |
4489 // Compile time checks. If any of these checks cannot be verified at compile time, | |
4490 // we do not make a fast path for this call. Instead, we let the call remain as it | |
4491 // is. The checks we choose to mandate at compile time are: | |
4492 // | |
4493 // (1) src and dest are arrays. | |
4494 const Type* src_type = src->Value(&_gvn); | |
4495 const Type* dest_type = dest->Value(&_gvn); | |
4496 const TypeAryPtr* top_src = src_type->isa_aryptr(); | |
4497 const TypeAryPtr* top_dest = dest_type->isa_aryptr(); | |
4498 if (top_src == NULL || top_src->klass() == NULL || | |
4499 top_dest == NULL || top_dest->klass() == NULL) { | |
4500 // Conservatively insert a memory barrier on all memory slices. | |
4501 // Do not let writes into the source float below the arraycopy. | |
4502 insert_mem_bar(Op_MemBarCPUOrder); | |
4503 | |
4504 // Call StubRoutines::generic_arraycopy stub. | |
4505 generate_arraycopy(TypeRawPtr::BOTTOM, T_CONFLICT, | |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4506 src, src_offset, dest, dest_offset, length); |
0 | 4507 |
4508 // Do not let reads from the destination float above the arraycopy. | |
4509 // Since we cannot type the arrays, we don't know which slices | |
4510 // might be affected. We could restrict this barrier only to those | |
4511 // memory slices which pertain to array elements--but don't bother. | |
4512 if (!InsertMemBarAfterArraycopy) | |
4513 // (If InsertMemBarAfterArraycopy, there is already one in place.) | |
4514 insert_mem_bar(Op_MemBarCPUOrder); | |
4515 return true; | |
4516 } | |
4517 | |
4518 // (2) src and dest arrays must have elements of the same BasicType | |
4519 // Figure out the size and type of the elements we will be copying. | |
4520 BasicType src_elem = top_src->klass()->as_array_klass()->element_type()->basic_type(); | |
4521 BasicType dest_elem = top_dest->klass()->as_array_klass()->element_type()->basic_type(); | |
4522 if (src_elem == T_ARRAY) src_elem = T_OBJECT; | |
4523 if (dest_elem == T_ARRAY) dest_elem = T_OBJECT; | |
4524 | |
4525 if (src_elem != dest_elem || dest_elem == T_VOID) { | |
4526 // The component types are not the same or are not recognized. Punt. | |
4527 // (But, avoid the native method wrapper to JVM_ArrayCopy.) | |
4528 generate_slow_arraycopy(TypePtr::BOTTOM, | |
2324 | 4529 src, src_offset, dest, dest_offset, length, |
4530 /*dest_uninitialized*/false); | |
0 | 4531 return true; |
4532 } | |
4533 | |
4534 //--------------------------------------------------------------------------- | |
4535 // We will make a fast path for this call to arraycopy. | |
4536 | |
4537 // We have the following tests left to perform: | |
4538 // | |
4539 // (3) src and dest must not be null. | |
4540 // (4) src_offset must not be negative. | |
4541 // (5) dest_offset must not be negative. | |
4542 // (6) length must not be negative. | |
4543 // (7) src_offset + length must not exceed length of src. | |
4544 // (8) dest_offset + length must not exceed length of dest. | |
4545 // (9) each element of an oop array must be assignable | |
4546 | |
4547 RegionNode* slow_region = new (C, 1) RegionNode(1); | |
4548 record_for_igvn(slow_region); | |
4549 | |
4550 // (3) operands must not be null | |
4551 // We currently perform our null checks with the do_null_check routine. | |
4552 // This means that the null exceptions will be reported in the caller | |
4553 // rather than (correctly) reported inside of the native arraycopy call. | |
4554 // This should be corrected, given time. We do our null check with the | |
4555 // stack pointer restored. | |
4556 _sp += nargs; | |
4557 src = do_null_check(src, T_ARRAY); | |
4558 dest = do_null_check(dest, T_ARRAY); | |
4559 _sp -= nargs; | |
4560 | |
4561 // (4) src_offset must not be negative. | |
4562 generate_negative_guard(src_offset, slow_region); | |
4563 | |
4564 // (5) dest_offset must not be negative. | |
4565 generate_negative_guard(dest_offset, slow_region); | |
4566 | |
4567 // (6) length must not be negative (moved to generate_arraycopy()). | |
4568 // generate_negative_guard(length, slow_region); | |
4569 | |
4570 // (7) src_offset + length must not exceed length of src. | |
4571 generate_limit_guard(src_offset, length, | |
4572 load_array_length(src), | |
4573 slow_region); | |
4574 | |
4575 // (8) dest_offset + length must not exceed length of dest. | |
4576 generate_limit_guard(dest_offset, length, | |
4577 load_array_length(dest), | |
4578 slow_region); | |
4579 | |
4580 // (9) each element of an oop array must be assignable | |
4581 // The generate_arraycopy subroutine checks this. | |
4582 | |
4583 // This is where the memory effects are placed: | |
4584 const TypePtr* adr_type = TypeAryPtr::get_array_body_type(dest_elem); | |
4585 generate_arraycopy(adr_type, dest_elem, | |
4586 src, src_offset, dest, dest_offset, length, | |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4587 false, false, slow_region); |
0 | 4588 |
4589 return true; | |
4590 } | |
4591 | |
4592 //-----------------------------generate_arraycopy---------------------- | |
4593 // Generate an optimized call to arraycopy. | |
4594 // Caller must guard against non-arrays. | |
4595 // Caller must determine a common array basic-type for both arrays. | |
4596 // Caller must validate offsets against array bounds. | |
4597 // The slow_region has already collected guard failure paths | |
4598 // (such as out of bounds length or non-conformable array types). | |
4599 // The generated code has this shape, in general: | |
4600 // | |
4601 // if (length == 0) return // via zero_path | |
4602 // slowval = -1 | |
4603 // if (types unknown) { | |
4604 // slowval = call generic copy loop | |
4605 // if (slowval == 0) return // via checked_path | |
4606 // } else if (indexes in bounds) { | |
4607 // if ((is object array) && !(array type check)) { | |
4608 // slowval = call checked copy loop | |
4609 // if (slowval == 0) return // via checked_path | |
4610 // } else { | |
4611 // call bulk copy loop | |
4612 // return // via fast_path | |
4613 // } | |
4614 // } | |
4615 // // adjust params for remaining work: | |
4616 // if (slowval != -1) { | |
4617 // n = -1^slowval; src_offset += n; dest_offset += n; length -= n | |
4618 // } | |
4619 // slow_region: | |
4620 // call slow arraycopy(src, src_offset, dest, dest_offset, length) | |
4621 // return // via slow_call_path | |
4622 // | |
4623 // This routine is used from several intrinsics: System.arraycopy, | |
4624 // Object.clone (the array subcase), and Arrays.copyOf[Range]. | |
4625 // | |
4626 void | |
4627 LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, | |
4628 BasicType basic_elem_type, | |
4629 Node* src, Node* src_offset, | |
4630 Node* dest, Node* dest_offset, | |
4631 Node* copy_length, | |
4632 bool disjoint_bases, | |
4633 bool length_never_negative, | |
4634 RegionNode* slow_region) { | |
4635 | |
4636 if (slow_region == NULL) { | |
4637 slow_region = new(C,1) RegionNode(1); | |
4638 record_for_igvn(slow_region); | |
4639 } | |
4640 | |
4641 Node* original_dest = dest; | |
4642 AllocateArrayNode* alloc = NULL; // used for zeroing, if needed | |
2324 | 4643 bool dest_uninitialized = false; |
0 | 4644 |
4645 // See if this is the initialization of a newly-allocated array. | |
4646 // If so, we will take responsibility here for initializing it to zero. | |
4647 // (Note: Because tightly_coupled_allocation performs checks on the | |
4648 // out-edges of the dest, we need to avoid making derived pointers | |
4649 // from it until we have checked its uses.) | |
4650 if (ReduceBulkZeroing | |
4651 && !ZeroTLAB // pointless if already zeroed | |
4652 && basic_elem_type != T_CONFLICT // avoid corner case | |
4653 && !_gvn.eqv_uncast(src, dest) | |
4654 && ((alloc = tightly_coupled_allocation(dest, slow_region)) | |
4655 != NULL) | |
34
545c277a3ecf
6667581: Don't generate initialization (by 0) code for arrays with size 0
kvn
parents:
29
diff
changeset
|
4656 && _gvn.find_int_con(alloc->in(AllocateNode::ALength), 1) > 0 |
0 | 4657 && alloc->maybe_set_complete(&_gvn)) { |
4658 // "You break it, you buy it." | |
4659 InitializeNode* init = alloc->initialization(); | |
4660 assert(init->is_complete(), "we just did this"); | |
3961
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3742
diff
changeset
|
4661 init->set_complete_with_arraycopy(); |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4662 assert(dest->is_CheckCastPP(), "sanity"); |
0 | 4663 assert(dest->in(0)->in(0) == init, "dest pinned"); |
4664 adr_type = TypeRawPtr::BOTTOM; // all initializations are into raw memory | |
4665 // From this point on, every exit path is responsible for | |
4666 // initializing any non-copied parts of the object to zero. | |
2324 | 4667 // Also, if this flag is set we make sure that arraycopy interacts properly |
4668 // with G1, eliding pre-barriers. See CR 6627983. | |
4669 dest_uninitialized = true; | |
0 | 4670 } else { |
4671 // No zeroing elimination here. | |
4672 alloc = NULL; | |
4673 //original_dest = dest; | |
2324 | 4674 //dest_uninitialized = false; |
0 | 4675 } |
4676 | |
4677 // Results are placed here: | |
4678 enum { fast_path = 1, // normal void-returning assembly stub | |
4679 checked_path = 2, // special assembly stub with cleanup | |
4680 slow_call_path = 3, // something went wrong; call the VM | |
4681 zero_path = 4, // bypass when length of copy is zero | |
4682 bcopy_path = 5, // copy primitive array by 64-bit blocks | |
4683 PATH_LIMIT = 6 | |
4684 }; | |
4685 RegionNode* result_region = new(C, PATH_LIMIT) RegionNode(PATH_LIMIT); | |
4686 PhiNode* result_i_o = new(C, PATH_LIMIT) PhiNode(result_region, Type::ABIO); | |
4687 PhiNode* result_memory = new(C, PATH_LIMIT) PhiNode(result_region, Type::MEMORY, adr_type); | |
4688 record_for_igvn(result_region); | |
4689 _gvn.set_type_bottom(result_i_o); | |
4690 _gvn.set_type_bottom(result_memory); | |
4691 assert(adr_type != TypePtr::BOTTOM, "must be RawMem or a T[] slice"); | |
4692 | |
4693 // The slow_control path: | |
4694 Node* slow_control; | |
4695 Node* slow_i_o = i_o(); | |
4696 Node* slow_mem = memory(adr_type); | |
4697 debug_only(slow_control = (Node*) badAddress); | |
4698 | |
4699 // Checked control path: | |
4700 Node* checked_control = top(); | |
4701 Node* checked_mem = NULL; | |
4702 Node* checked_i_o = NULL; | |
4703 Node* checked_value = NULL; | |
4704 | |
4705 if (basic_elem_type == T_CONFLICT) { | |
2324 | 4706 assert(!dest_uninitialized, ""); |
0 | 4707 Node* cv = generate_generic_arraycopy(adr_type, |
4708 src, src_offset, dest, dest_offset, | |
2324 | 4709 copy_length, dest_uninitialized); |
0 | 4710 if (cv == NULL) cv = intcon(-1); // failure (no stub available) |
4711 checked_control = control(); | |
4712 checked_i_o = i_o(); | |
4713 checked_mem = memory(adr_type); | |
4714 checked_value = cv; | |
4715 set_control(top()); // no fast path | |
4716 } | |
4717 | |
4718 Node* not_pos = generate_nonpositive_guard(copy_length, length_never_negative); | |
4719 if (not_pos != NULL) { | |
4720 PreserveJVMState pjvms(this); | |
4721 set_control(not_pos); | |
4722 | |
4723 // (6) length must not be negative. | |
4724 if (!length_never_negative) { | |
4725 generate_negative_guard(copy_length, slow_region); | |
4726 } | |
4727 | |
836
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
4728 // copy_length is 0. |
2324 | 4729 if (!stopped() && dest_uninitialized) { |
0 | 4730 Node* dest_length = alloc->in(AllocateNode::ALength); |
4731 if (_gvn.eqv_uncast(copy_length, dest_length) | |
4732 || _gvn.find_int_con(dest_length, 1) <= 0) { | |
836
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
4733 // There is no zeroing to do. No need for a secondary raw memory barrier. |
0 | 4734 } else { |
4735 // Clear the whole thing since there are no source elements to copy. | |
4736 generate_clear_array(adr_type, dest, basic_elem_type, | |
4737 intcon(0), NULL, | |
4738 alloc->in(AllocateNode::AllocSize)); | |
836
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
4739 // Use a secondary InitializeNode as raw memory barrier. |
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
4740 // Currently it is needed only on this path since other |
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
4741 // paths have stub or runtime calls as raw memory barriers. |
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
4742 InitializeNode* init = insert_mem_bar_volatile(Op_Initialize, |
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
4743 Compile::AliasIdxRaw, |
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
4744 top())->as_Initialize(); |
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
4745 init->set_complete(&_gvn); // (there is no corresponding AllocateNode) |
0 | 4746 } |
4747 } | |
4748 | |
4749 // Present the results of the fast call. | |
4750 result_region->init_req(zero_path, control()); | |
4751 result_i_o ->init_req(zero_path, i_o()); | |
4752 result_memory->init_req(zero_path, memory(adr_type)); | |
4753 } | |
4754 | |
2324 | 4755 if (!stopped() && dest_uninitialized) { |
0 | 4756 // We have to initialize the *uncopied* part of the array to zero. |
4757 // The copy destination is the slice dest[off..off+len]. The other slices | |
4758 // are dest_head = dest[0..off] and dest_tail = dest[off+len..dest.length]. | |
4759 Node* dest_size = alloc->in(AllocateNode::AllocSize); | |
4760 Node* dest_length = alloc->in(AllocateNode::ALength); | |
4761 Node* dest_tail = _gvn.transform( new(C,3) AddINode(dest_offset, | |
4762 copy_length) ); | |
4763 | |
4764 // If there is a head section that needs zeroing, do it now. | |
4765 if (find_int_con(dest_offset, -1) != 0) { | |
4766 generate_clear_array(adr_type, dest, basic_elem_type, | |
4767 intcon(0), dest_offset, | |
4768 NULL); | |
4769 } | |
4770 | |
4771 // Next, perform a dynamic check on the tail length. | |
4772 // It is often zero, and we can win big if we prove this. | |
4773 // There are two wins: Avoid generating the ClearArray | |
4774 // with its attendant messy index arithmetic, and upgrade | |
4775 // the copy to a more hardware-friendly word size of 64 bits. | |
4776 Node* tail_ctl = NULL; | |
4777 if (!stopped() && !_gvn.eqv_uncast(dest_tail, dest_length)) { | |
4778 Node* cmp_lt = _gvn.transform( new(C,3) CmpINode(dest_tail, dest_length) ); | |
4779 Node* bol_lt = _gvn.transform( new(C,2) BoolNode(cmp_lt, BoolTest::lt) ); | |
4780 tail_ctl = generate_slow_guard(bol_lt, NULL); | |
4781 assert(tail_ctl != NULL || !stopped(), "must be an outcome"); | |
4782 } | |
4783 | |
4784 // At this point, let's assume there is no tail. | |
4785 if (!stopped() && alloc != NULL && basic_elem_type != T_OBJECT) { | |
4786 // There is no tail. Try an upgrade to a 64-bit copy. | |
4787 bool didit = false; | |
4788 { PreserveJVMState pjvms(this); | |
4789 didit = generate_block_arraycopy(adr_type, basic_elem_type, alloc, | |
4790 src, src_offset, dest, dest_offset, | |
2324 | 4791 dest_size, dest_uninitialized); |
0 | 4792 if (didit) { |
4793 // Present the results of the block-copying fast call. | |
4794 result_region->init_req(bcopy_path, control()); | |
4795 result_i_o ->init_req(bcopy_path, i_o()); | |
4796 result_memory->init_req(bcopy_path, memory(adr_type)); | |
4797 } | |
4798 } | |
4799 if (didit) | |
4800 set_control(top()); // no regular fast path | |
4801 } | |
4802 | |
4803 // Clear the tail, if any. | |
4804 if (tail_ctl != NULL) { | |
4805 Node* notail_ctl = stopped() ? NULL : control(); | |
4806 set_control(tail_ctl); | |
4807 if (notail_ctl == NULL) { | |
4808 generate_clear_array(adr_type, dest, basic_elem_type, | |
4809 dest_tail, NULL, | |
4810 dest_size); | |
4811 } else { | |
4812 // Make a local merge. | |
4813 Node* done_ctl = new(C,3) RegionNode(3); | |
4814 Node* done_mem = new(C,3) PhiNode(done_ctl, Type::MEMORY, adr_type); | |
4815 done_ctl->init_req(1, notail_ctl); | |
4816 done_mem->init_req(1, memory(adr_type)); | |
4817 generate_clear_array(adr_type, dest, basic_elem_type, | |
4818 dest_tail, NULL, | |
4819 dest_size); | |
4820 done_ctl->init_req(2, control()); | |
4821 done_mem->init_req(2, memory(adr_type)); | |
4822 set_control( _gvn.transform(done_ctl) ); | |
4823 set_memory( _gvn.transform(done_mem), adr_type ); | |
4824 } | |
4825 } | |
4826 } | |
4827 | |
4828 BasicType copy_type = basic_elem_type; | |
4829 assert(basic_elem_type != T_ARRAY, "caller must fix this"); | |
4830 if (!stopped() && copy_type == T_OBJECT) { | |
4831 // If src and dest have compatible element types, we can copy bits. | |
4832 // Types S[] and D[] are compatible if D is a supertype of S. | |
4833 // | |
4834 // If they are not, we will use checked_oop_disjoint_arraycopy, | |
4835 // which performs a fast optimistic per-oop check, and backs off | |
4836 // further to JVM_ArrayCopy on the first per-oop check that fails. | |
4837 // (Actually, we don't move raw bits only; the GC requires card marks.) | |
4838 | |
4839 // Get the klassOop for both src and dest | |
4840 Node* src_klass = load_object_klass(src); | |
4841 Node* dest_klass = load_object_klass(dest); | |
4842 | |
4843 // Generate the subtype check. | |
4844 // This might fold up statically, or then again it might not. | |
4845 // | |
4846 // Non-static example: Copying List<String>.elements to a new String[]. | |
4847 // The backing store for a List<String> is always an Object[], | |
4848 // but its elements are always type String, if the generic types | |
4849 // are correct at the source level. | |
4850 // | |
4851 // Test S[] against D[], not S against D, because (probably) | |
4852 // the secondary supertype cache is less busy for S[] than S. | |
4853 // This usually only matters when D is an interface. | |
4854 Node* not_subtype_ctrl = gen_subtype_check(src_klass, dest_klass); | |
4855 // Plug failing path into checked_oop_disjoint_arraycopy | |
4856 if (not_subtype_ctrl != top()) { | |
4857 PreserveJVMState pjvms(this); | |
4858 set_control(not_subtype_ctrl); | |
4859 // (At this point we can assume disjoint_bases, since types differ.) | |
4860 int ek_offset = objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc); | |
4861 Node* p1 = basic_plus_adr(dest_klass, ek_offset); | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
163
diff
changeset
|
4862 Node* n1 = LoadKlassNode::make(_gvn, immutable_memory(), p1, TypeRawPtr::BOTTOM); |
0 | 4863 Node* dest_elem_klass = _gvn.transform(n1); |
4864 Node* cv = generate_checkcast_arraycopy(adr_type, | |
4865 dest_elem_klass, | |
4866 src, src_offset, dest, dest_offset, | |
2324 | 4867 ConvI2X(copy_length), dest_uninitialized); |
0 | 4868 if (cv == NULL) cv = intcon(-1); // failure (no stub available) |
4869 checked_control = control(); | |
4870 checked_i_o = i_o(); | |
4871 checked_mem = memory(adr_type); | |
4872 checked_value = cv; | |
4873 } | |
4874 // At this point we know we do not need type checks on oop stores. | |
4875 | |
4876 // Let's see if we need card marks: | |
4877 if (alloc != NULL && use_ReduceInitialCardMarks()) { | |
4878 // If we do not need card marks, copy using the jint or jlong stub. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
4879 copy_type = LP64_ONLY(UseCompressedOops ? T_INT : T_LONG) NOT_LP64(T_INT); |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
0
diff
changeset
|
4880 assert(type2aelembytes(basic_elem_type) == type2aelembytes(copy_type), |
0 | 4881 "sizes agree"); |
4882 } | |
4883 } | |
4884 | |
4885 if (!stopped()) { | |
4886 // Generate the fast path, if possible. | |
4887 PreserveJVMState pjvms(this); | |
4888 generate_unchecked_arraycopy(adr_type, copy_type, disjoint_bases, | |
4889 src, src_offset, dest, dest_offset, | |
2324 | 4890 ConvI2X(copy_length), dest_uninitialized); |
0 | 4891 |
4892 // Present the results of the fast call. | |
4893 result_region->init_req(fast_path, control()); | |
4894 result_i_o ->init_req(fast_path, i_o()); | |
4895 result_memory->init_req(fast_path, memory(adr_type)); | |
4896 } | |
4897 | |
4898 // Here are all the slow paths up to this point, in one bundle: | |
4899 slow_control = top(); | |
4900 if (slow_region != NULL) | |
4901 slow_control = _gvn.transform(slow_region); | |
4902 debug_only(slow_region = (RegionNode*)badAddress); | |
4903 | |
4904 set_control(checked_control); | |
4905 if (!stopped()) { | |
4906 // Clean up after the checked call. | |
4907 // The returned value is either 0 or -1^K, | |
4908 // where K = number of partially transferred array elements. | |
4909 Node* cmp = _gvn.transform( new(C, 3) CmpINode(checked_value, intcon(0)) ); | |
4910 Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::eq) ); | |
4911 IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN); | |
4912 | |
4913 // If it is 0, we are done, so transfer to the end. | |
4914 Node* checks_done = _gvn.transform( new(C, 1) IfTrueNode(iff) ); | |
4915 result_region->init_req(checked_path, checks_done); | |
4916 result_i_o ->init_req(checked_path, checked_i_o); | |
4917 result_memory->init_req(checked_path, checked_mem); | |
4918 | |
4919 // If it is not zero, merge into the slow call. | |
4920 set_control( _gvn.transform( new(C, 1) IfFalseNode(iff) )); | |
4921 RegionNode* slow_reg2 = new(C, 3) RegionNode(3); | |
4922 PhiNode* slow_i_o2 = new(C, 3) PhiNode(slow_reg2, Type::ABIO); | |
4923 PhiNode* slow_mem2 = new(C, 3) PhiNode(slow_reg2, Type::MEMORY, adr_type); | |
4924 record_for_igvn(slow_reg2); | |
4925 slow_reg2 ->init_req(1, slow_control); | |
4926 slow_i_o2 ->init_req(1, slow_i_o); | |
4927 slow_mem2 ->init_req(1, slow_mem); | |
4928 slow_reg2 ->init_req(2, control()); | |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4929 slow_i_o2 ->init_req(2, checked_i_o); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4930 slow_mem2 ->init_req(2, checked_mem); |
0 | 4931 |
4932 slow_control = _gvn.transform(slow_reg2); | |
4933 slow_i_o = _gvn.transform(slow_i_o2); | |
4934 slow_mem = _gvn.transform(slow_mem2); | |
4935 | |
4936 if (alloc != NULL) { | |
4937 // We'll restart from the very beginning, after zeroing the whole thing. | |
4938 // This can cause double writes, but that's OK since dest is brand new. | |
4939 // So we ignore the low 31 bits of the value returned from the stub. | |
4940 } else { | |
4941 // We must continue the copy exactly where it failed, or else | |
4942 // another thread might see the wrong number of writes to dest. | |
4943 Node* checked_offset = _gvn.transform( new(C, 3) XorINode(checked_value, intcon(-1)) ); | |
4944 Node* slow_offset = new(C, 3) PhiNode(slow_reg2, TypeInt::INT); | |
4945 slow_offset->init_req(1, intcon(0)); | |
4946 slow_offset->init_req(2, checked_offset); | |
4947 slow_offset = _gvn.transform(slow_offset); | |
4948 | |
4949 // Adjust the arguments by the conditionally incoming offset. | |
4950 Node* src_off_plus = _gvn.transform( new(C, 3) AddINode(src_offset, slow_offset) ); | |
4951 Node* dest_off_plus = _gvn.transform( new(C, 3) AddINode(dest_offset, slow_offset) ); | |
4952 Node* length_minus = _gvn.transform( new(C, 3) SubINode(copy_length, slow_offset) ); | |
4953 | |
4954 // Tweak the node variables to adjust the code produced below: | |
4955 src_offset = src_off_plus; | |
4956 dest_offset = dest_off_plus; | |
4957 copy_length = length_minus; | |
4958 } | |
4959 } | |
4960 | |
4961 set_control(slow_control); | |
4962 if (!stopped()) { | |
4963 // Generate the slow path, if needed. | |
4964 PreserveJVMState pjvms(this); // replace_in_map may trash the map | |
4965 | |
4966 set_memory(slow_mem, adr_type); | |
4967 set_i_o(slow_i_o); | |
4968 | |
2324 | 4969 if (dest_uninitialized) { |
0 | 4970 generate_clear_array(adr_type, dest, basic_elem_type, |
4971 intcon(0), NULL, | |
4972 alloc->in(AllocateNode::AllocSize)); | |
4973 } | |
4974 | |
4975 generate_slow_arraycopy(adr_type, | |
4976 src, src_offset, dest, dest_offset, | |
2324 | 4977 copy_length, /*dest_uninitialized*/false); |
0 | 4978 |
4979 result_region->init_req(slow_call_path, control()); | |
4980 result_i_o ->init_req(slow_call_path, i_o()); | |
4981 result_memory->init_req(slow_call_path, memory(adr_type)); | |
4982 } | |
4983 | |
4984 // Remove unused edges. | |
4985 for (uint i = 1; i < result_region->req(); i++) { | |
4986 if (result_region->in(i) == NULL) | |
4987 result_region->init_req(i, top()); | |
4988 } | |
4989 | |
4990 // Finished; return the combined state. | |
4991 set_control( _gvn.transform(result_region) ); | |
4992 set_i_o( _gvn.transform(result_i_o) ); | |
4993 set_memory( _gvn.transform(result_memory), adr_type ); | |
4994 | |
4995 // The memory edges above are precise in order to model effects around | |
605 | 4996 // array copies accurately to allow value numbering of field loads around |
0 | 4997 // arraycopy. Such field loads, both before and after, are common in Java |
4998 // collections and similar classes involving header/array data structures. | |
4999 // | |
5000 // But with low number of register or when some registers are used or killed | |
5001 // by arraycopy calls it causes registers spilling on stack. See 6544710. | |
5002 // The next memory barrier is added to avoid it. If the arraycopy can be | |
5003 // optimized away (which it can, sometimes) then we can manually remove | |
5004 // the membar also. | |
958
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
5005 // |
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
5006 // Do not let reads from the cloned object float above the arraycopy. |
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
5007 if (InsertMemBarAfterArraycopy || alloc != NULL) |
0 | 5008 insert_mem_bar(Op_MemBarCPUOrder); |
5009 } | |
5010 | |
5011 | |
5012 // Helper function which determines if an arraycopy immediately follows | |
5013 // an allocation, with no intervening tests or other escapes for the object. | |
5014 AllocateArrayNode* | |
5015 LibraryCallKit::tightly_coupled_allocation(Node* ptr, | |
5016 RegionNode* slow_region) { | |
5017 if (stopped()) return NULL; // no fast path | |
5018 if (C->AliasLevel() == 0) return NULL; // no MergeMems around | |
5019 | |
5020 AllocateArrayNode* alloc = AllocateArrayNode::Ideal_array_allocation(ptr, &_gvn); | |
5021 if (alloc == NULL) return NULL; | |
5022 | |
5023 Node* rawmem = memory(Compile::AliasIdxRaw); | |
5024 // Is the allocation's memory state untouched? | |
5025 if (!(rawmem->is_Proj() && rawmem->in(0)->is_Initialize())) { | |
5026 // Bail out if there have been raw-memory effects since the allocation. | |
5027 // (Example: There might have been a call or safepoint.) | |
5028 return NULL; | |
5029 } | |
5030 rawmem = rawmem->in(0)->as_Initialize()->memory(Compile::AliasIdxRaw); | |
5031 if (!(rawmem->is_Proj() && rawmem->in(0) == alloc)) { | |
5032 return NULL; | |
5033 } | |
5034 | |
5035 // There must be no unexpected observers of this allocation. | |
5036 for (DUIterator_Fast imax, i = ptr->fast_outs(imax); i < imax; i++) { | |
5037 Node* obs = ptr->fast_out(i); | |
5038 if (obs != this->map()) { | |
5039 return NULL; | |
5040 } | |
5041 } | |
5042 | |
5043 // This arraycopy must unconditionally follow the allocation of the ptr. | |
5044 Node* alloc_ctl = ptr->in(0); | |
5045 assert(just_allocated_object(alloc_ctl) == ptr, "most recent allo"); | |
5046 | |
5047 Node* ctl = control(); | |
5048 while (ctl != alloc_ctl) { | |
5049 // There may be guards which feed into the slow_region. | |
5050 // Any other control flow means that we might not get a chance | |
5051 // to finish initializing the allocated object. | |
5052 if ((ctl->is_IfFalse() || ctl->is_IfTrue()) && ctl->in(0)->is_If()) { | |
5053 IfNode* iff = ctl->in(0)->as_If(); | |
5054 Node* not_ctl = iff->proj_out(1 - ctl->as_Proj()->_con); | |
5055 assert(not_ctl != NULL && not_ctl != ctl, "found alternate"); | |
5056 if (slow_region != NULL && slow_region->find_edge(not_ctl) >= 1) { | |
5057 ctl = iff->in(0); // This test feeds the known slow_region. | |
5058 continue; | |
5059 } | |
5060 // One more try: Various low-level checks bottom out in | |
5061 // uncommon traps. If the debug-info of the trap omits | |
5062 // any reference to the allocation, as we've already | |
5063 // observed, then there can be no objection to the trap. | |
5064 bool found_trap = false; | |
5065 for (DUIterator_Fast jmax, j = not_ctl->fast_outs(jmax); j < jmax; j++) { | |
5066 Node* obs = not_ctl->fast_out(j); | |
5067 if (obs->in(0) == not_ctl && obs->is_Call() && | |
1748 | 5068 (obs->as_Call()->entry_point() == SharedRuntime::uncommon_trap_blob()->entry_point())) { |
0 | 5069 found_trap = true; break; |
5070 } | |
5071 } | |
5072 if (found_trap) { | |
5073 ctl = iff->in(0); // This test feeds a harmless uncommon trap. | |
5074 continue; | |
5075 } | |
5076 } | |
5077 return NULL; | |
5078 } | |
5079 | |
5080 // If we get this far, we have an allocation which immediately | |
5081 // precedes the arraycopy, and we can take over zeroing the new object. | |
5082 // The arraycopy will finish the initialization, and provide | |
5083 // a new control state to which we will anchor the destination pointer. | |
5084 | |
5085 return alloc; | |
5086 } | |
5087 | |
5088 // Helper for initialization of arrays, creating a ClearArray. | |
5089 // It writes zero bits in [start..end), within the body of an array object. | |
5090 // The memory effects are all chained onto the 'adr_type' alias category. | |
5091 // | |
5092 // Since the object is otherwise uninitialized, we are free | |
5093 // to put a little "slop" around the edges of the cleared area, | |
5094 // as long as it does not go back into the array's header, | |
5095 // or beyond the array end within the heap. | |
5096 // | |
5097 // The lower edge can be rounded down to the nearest jint and the | |
5098 // upper edge can be rounded up to the nearest MinObjAlignmentInBytes. | |
5099 // | |
5100 // Arguments: | |
5101 // adr_type memory slice where writes are generated | |
5102 // dest oop of the destination array | |
5103 // basic_elem_type element type of the destination | |
5104 // slice_idx array index of first element to store | |
5105 // slice_len number of elements to store (or NULL) | |
5106 // dest_size total size in bytes of the array object | |
5107 // | |
5108 // Exactly one of slice_len or dest_size must be non-NULL. | |
5109 // If dest_size is non-NULL, zeroing extends to the end of the object. | |
5110 // If slice_len is non-NULL, the slice_idx value must be a constant. | |
5111 void | |
5112 LibraryCallKit::generate_clear_array(const TypePtr* adr_type, | |
5113 Node* dest, | |
5114 BasicType basic_elem_type, | |
5115 Node* slice_idx, | |
5116 Node* slice_len, | |
5117 Node* dest_size) { | |
5118 // one or the other but not both of slice_len and dest_size: | |
5119 assert((slice_len != NULL? 1: 0) + (dest_size != NULL? 1: 0) == 1, ""); | |
5120 if (slice_len == NULL) slice_len = top(); | |
5121 if (dest_size == NULL) dest_size = top(); | |
5122 | |
5123 // operate on this memory slice: | |
5124 Node* mem = memory(adr_type); // memory slice to operate on | |
5125 | |
5126 // scaling and rounding of indexes: | |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
0
diff
changeset
|
5127 int scale = exact_log2(type2aelembytes(basic_elem_type)); |
0 | 5128 int abase = arrayOopDesc::base_offset_in_bytes(basic_elem_type); |
5129 int clear_low = (-1 << scale) & (BytesPerInt - 1); | |
5130 int bump_bit = (-1 << scale) & BytesPerInt; | |
5131 | |
5132 // determine constant starts and ends | |
5133 const intptr_t BIG_NEG = -128; | |
5134 assert(BIG_NEG + 2*abase < 0, "neg enough"); | |
5135 intptr_t slice_idx_con = (intptr_t) find_int_con(slice_idx, BIG_NEG); | |
5136 intptr_t slice_len_con = (intptr_t) find_int_con(slice_len, BIG_NEG); | |
5137 if (slice_len_con == 0) { | |
5138 return; // nothing to do here | |
5139 } | |
5140 intptr_t start_con = (abase + (slice_idx_con << scale)) & ~clear_low; | |
5141 intptr_t end_con = find_intptr_t_con(dest_size, -1); | |
5142 if (slice_idx_con >= 0 && slice_len_con >= 0) { | |
5143 assert(end_con < 0, "not two cons"); | |
5144 end_con = round_to(abase + ((slice_idx_con + slice_len_con) << scale), | |
5145 BytesPerLong); | |
5146 } | |
5147 | |
5148 if (start_con >= 0 && end_con >= 0) { | |
5149 // Constant start and end. Simple. | |
5150 mem = ClearArrayNode::clear_memory(control(), mem, dest, | |
5151 start_con, end_con, &_gvn); | |
5152 } else if (start_con >= 0 && dest_size != top()) { | |
5153 // Constant start, pre-rounded end after the tail of the array. | |
5154 Node* end = dest_size; | |
5155 mem = ClearArrayNode::clear_memory(control(), mem, dest, | |
5156 start_con, end, &_gvn); | |
5157 } else if (start_con >= 0 && slice_len != top()) { | |
5158 // Constant start, non-constant end. End needs rounding up. | |
5159 // End offset = round_up(abase + ((slice_idx_con + slice_len) << scale), 8) | |
5160 intptr_t end_base = abase + (slice_idx_con << scale); | |
5161 int end_round = (-1 << scale) & (BytesPerLong - 1); | |
5162 Node* end = ConvI2X(slice_len); | |
5163 if (scale != 0) | |
5164 end = _gvn.transform( new(C,3) LShiftXNode(end, intcon(scale) )); | |
5165 end_base += end_round; | |
5166 end = _gvn.transform( new(C,3) AddXNode(end, MakeConX(end_base)) ); | |
5167 end = _gvn.transform( new(C,3) AndXNode(end, MakeConX(~end_round)) ); | |
5168 mem = ClearArrayNode::clear_memory(control(), mem, dest, | |
5169 start_con, end, &_gvn); | |
5170 } else if (start_con < 0 && dest_size != top()) { | |
5171 // Non-constant start, pre-rounded end after the tail of the array. | |
5172 // This is almost certainly a "round-to-end" operation. | |
5173 Node* start = slice_idx; | |
5174 start = ConvI2X(start); | |
5175 if (scale != 0) | |
5176 start = _gvn.transform( new(C,3) LShiftXNode( start, intcon(scale) )); | |
5177 start = _gvn.transform( new(C,3) AddXNode(start, MakeConX(abase)) ); | |
5178 if ((bump_bit | clear_low) != 0) { | |
5179 int to_clear = (bump_bit | clear_low); | |
5180 // Align up mod 8, then store a jint zero unconditionally | |
5181 // just before the mod-8 boundary. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5182 if (((abase + bump_bit) & ~to_clear) - bump_bit |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5183 < arrayOopDesc::length_offset_in_bytes() + BytesPerInt) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5184 bump_bit = 0; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5185 assert((abase & to_clear) == 0, "array base must be long-aligned"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5186 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5187 // Bump 'start' up to (or past) the next jint boundary: |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5188 start = _gvn.transform( new(C,3) AddXNode(start, MakeConX(bump_bit)) ); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5189 assert((abase & clear_low) == 0, "array base must be int-aligned"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5190 } |
0 | 5191 // Round bumped 'start' down to jlong boundary in body of array. |
5192 start = _gvn.transform( new(C,3) AndXNode(start, MakeConX(~to_clear)) ); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5193 if (bump_bit != 0) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5194 // Store a zero to the immediately preceding jint: |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5195 Node* x1 = _gvn.transform( new(C,3) AddXNode(start, MakeConX(-bump_bit)) ); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5196 Node* p1 = basic_plus_adr(dest, x1); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5197 mem = StoreNode::make(_gvn, control(), mem, p1, adr_type, intcon(0), T_INT); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5198 mem = _gvn.transform(mem); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5199 } |
0 | 5200 } |
5201 Node* end = dest_size; // pre-rounded | |
5202 mem = ClearArrayNode::clear_memory(control(), mem, dest, | |
5203 start, end, &_gvn); | |
5204 } else { | |
5205 // Non-constant start, unrounded non-constant end. | |
5206 // (Nobody zeroes a random midsection of an array using this routine.) | |
5207 ShouldNotReachHere(); // fix caller | |
5208 } | |
5209 | |
5210 // Done. | |
5211 set_memory(mem, adr_type); | |
5212 } | |
5213 | |
5214 | |
5215 bool | |
5216 LibraryCallKit::generate_block_arraycopy(const TypePtr* adr_type, | |
5217 BasicType basic_elem_type, | |
5218 AllocateNode* alloc, | |
5219 Node* src, Node* src_offset, | |
5220 Node* dest, Node* dest_offset, | |
2324 | 5221 Node* dest_size, bool dest_uninitialized) { |
0 | 5222 // See if there is an advantage from block transfer. |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
0
diff
changeset
|
5223 int scale = exact_log2(type2aelembytes(basic_elem_type)); |
0 | 5224 if (scale >= LogBytesPerLong) |
5225 return false; // it is already a block transfer | |
5226 | |
5227 // Look at the alignment of the starting offsets. | |
5228 int abase = arrayOopDesc::base_offset_in_bytes(basic_elem_type); | |
3742
b2cb497dec28
7047069: Array can dynamically change size when assigned to an object field
kvn
parents:
3337
diff
changeset
|
5229 |
b2cb497dec28
7047069: Array can dynamically change size when assigned to an object field
kvn
parents:
3337
diff
changeset
|
5230 intptr_t src_off_con = (intptr_t) find_int_con(src_offset, -1); |
b2cb497dec28
7047069: Array can dynamically change size when assigned to an object field
kvn
parents:
3337
diff
changeset
|
5231 intptr_t dest_off_con = (intptr_t) find_int_con(dest_offset, -1); |
b2cb497dec28
7047069: Array can dynamically change size when assigned to an object field
kvn
parents:
3337
diff
changeset
|
5232 if (src_off_con < 0 || dest_off_con < 0) |
0 | 5233 // At present, we can only understand constants. |
5234 return false; | |
5235 | |
3742
b2cb497dec28
7047069: Array can dynamically change size when assigned to an object field
kvn
parents:
3337
diff
changeset
|
5236 intptr_t src_off = abase + (src_off_con << scale); |
b2cb497dec28
7047069: Array can dynamically change size when assigned to an object field
kvn
parents:
3337
diff
changeset
|
5237 intptr_t dest_off = abase + (dest_off_con << scale); |
b2cb497dec28
7047069: Array can dynamically change size when assigned to an object field
kvn
parents:
3337
diff
changeset
|
5238 |
0 | 5239 if (((src_off | dest_off) & (BytesPerLong-1)) != 0) { |
5240 // Non-aligned; too bad. | |
5241 // One more chance: Pick off an initial 32-bit word. | |
5242 // This is a common case, since abase can be odd mod 8. | |
5243 if (((src_off | dest_off) & (BytesPerLong-1)) == BytesPerInt && | |
5244 ((src_off ^ dest_off) & (BytesPerLong-1)) == 0) { | |
5245 Node* sptr = basic_plus_adr(src, src_off); | |
5246 Node* dptr = basic_plus_adr(dest, dest_off); | |
5247 Node* sval = make_load(control(), sptr, TypeInt::INT, T_INT, adr_type); | |
5248 store_to_memory(control(), dptr, sval, T_INT, adr_type); | |
5249 src_off += BytesPerInt; | |
5250 dest_off += BytesPerInt; | |
5251 } else { | |
5252 return false; | |
5253 } | |
5254 } | |
5255 assert(src_off % BytesPerLong == 0, ""); | |
5256 assert(dest_off % BytesPerLong == 0, ""); | |
5257 | |
5258 // Do this copy by giant steps. | |
5259 Node* sptr = basic_plus_adr(src, src_off); | |
5260 Node* dptr = basic_plus_adr(dest, dest_off); | |
5261 Node* countx = dest_size; | |
5262 countx = _gvn.transform( new (C, 3) SubXNode(countx, MakeConX(dest_off)) ); | |
5263 countx = _gvn.transform( new (C, 3) URShiftXNode(countx, intcon(LogBytesPerLong)) ); | |
5264 | |
5265 bool disjoint_bases = true; // since alloc != NULL | |
5266 generate_unchecked_arraycopy(adr_type, T_LONG, disjoint_bases, | |
2324 | 5267 sptr, NULL, dptr, NULL, countx, dest_uninitialized); |
0 | 5268 |
5269 return true; | |
5270 } | |
5271 | |
5272 | |
5273 // Helper function; generates code for the slow case. | |
5274 // We make a call to a runtime method which emulates the native method, | |
5275 // but without the native wrapper overhead. | |
5276 void | |
5277 LibraryCallKit::generate_slow_arraycopy(const TypePtr* adr_type, | |
5278 Node* src, Node* src_offset, | |
5279 Node* dest, Node* dest_offset, | |
2324 | 5280 Node* copy_length, bool dest_uninitialized) { |
5281 assert(!dest_uninitialized, "Invariant"); | |
0 | 5282 Node* call = make_runtime_call(RC_NO_LEAF | RC_UNCOMMON, |
5283 OptoRuntime::slow_arraycopy_Type(), | |
5284 OptoRuntime::slow_arraycopy_Java(), | |
5285 "slow_arraycopy", adr_type, | |
5286 src, src_offset, dest, dest_offset, | |
5287 copy_length); | |
5288 | |
5289 // Handle exceptions thrown by this fellow: | |
5290 make_slow_call_ex(call, env()->Throwable_klass(), false); | |
5291 } | |
5292 | |
5293 // Helper function; generates code for cases requiring runtime checks. | |
5294 Node* | |
5295 LibraryCallKit::generate_checkcast_arraycopy(const TypePtr* adr_type, | |
5296 Node* dest_elem_klass, | |
5297 Node* src, Node* src_offset, | |
5298 Node* dest, Node* dest_offset, | |
2324 | 5299 Node* copy_length, bool dest_uninitialized) { |
0 | 5300 if (stopped()) return NULL; |
5301 | |
2324 | 5302 address copyfunc_addr = StubRoutines::checkcast_arraycopy(dest_uninitialized); |
0 | 5303 if (copyfunc_addr == NULL) { // Stub was not generated, go slow path. |
5304 return NULL; | |
5305 } | |
5306 | |
5307 // Pick out the parameters required to perform a store-check | |
5308 // for the target array. This is an optimistic check. It will | |
5309 // look in each non-null element's class, at the desired klass's | |
5310 // super_check_offset, for the desired klass. | |
5311 int sco_offset = Klass::super_check_offset_offset_in_bytes() + sizeof(oopDesc); | |
5312 Node* p3 = basic_plus_adr(dest_elem_klass, sco_offset); | |
1609 | 5313 Node* n3 = new(C, 3) LoadINode(NULL, memory(p3), p3, _gvn.type(p3)->is_ptr()); |
1844
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1748
diff
changeset
|
5314 Node* check_offset = ConvI2X(_gvn.transform(n3)); |
0 | 5315 Node* check_value = dest_elem_klass; |
5316 | |
5317 Node* src_start = array_element_address(src, src_offset, T_OBJECT); | |
5318 Node* dest_start = array_element_address(dest, dest_offset, T_OBJECT); | |
5319 | |
5320 // (We know the arrays are never conjoint, because their types differ.) | |
5321 Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, | |
5322 OptoRuntime::checkcast_arraycopy_Type(), | |
5323 copyfunc_addr, "checkcast_arraycopy", adr_type, | |
5324 // five arguments, of which two are | |
5325 // intptr_t (jlong in LP64) | |
5326 src_start, dest_start, | |
5327 copy_length XTOP, | |
5328 check_offset XTOP, | |
5329 check_value); | |
5330 | |
5331 return _gvn.transform(new (C, 1) ProjNode(call, TypeFunc::Parms)); | |
5332 } | |
5333 | |
5334 | |
5335 // Helper function; generates code for cases requiring runtime checks. | |
5336 Node* | |
5337 LibraryCallKit::generate_generic_arraycopy(const TypePtr* adr_type, | |
5338 Node* src, Node* src_offset, | |
5339 Node* dest, Node* dest_offset, | |
2324 | 5340 Node* copy_length, bool dest_uninitialized) { |
5341 assert(!dest_uninitialized, "Invariant"); | |
0 | 5342 if (stopped()) return NULL; |
5343 address copyfunc_addr = StubRoutines::generic_arraycopy(); | |
5344 if (copyfunc_addr == NULL) { // Stub was not generated, go slow path. | |
5345 return NULL; | |
5346 } | |
5347 | |
5348 Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, | |
5349 OptoRuntime::generic_arraycopy_Type(), | |
5350 copyfunc_addr, "generic_arraycopy", adr_type, | |
5351 src, src_offset, dest, dest_offset, copy_length); | |
5352 | |
5353 return _gvn.transform(new (C, 1) ProjNode(call, TypeFunc::Parms)); | |
5354 } | |
5355 | |
5356 // Helper function; generates the fast out-of-line call to an arraycopy stub. | |
5357 void | |
5358 LibraryCallKit::generate_unchecked_arraycopy(const TypePtr* adr_type, | |
5359 BasicType basic_elem_type, | |
5360 bool disjoint_bases, | |
5361 Node* src, Node* src_offset, | |
5362 Node* dest, Node* dest_offset, | |
2324 | 5363 Node* copy_length, bool dest_uninitialized) { |
0 | 5364 if (stopped()) return; // nothing to do |
5365 | |
5366 Node* src_start = src; | |
5367 Node* dest_start = dest; | |
5368 if (src_offset != NULL || dest_offset != NULL) { | |
5369 assert(src_offset != NULL && dest_offset != NULL, ""); | |
5370 src_start = array_element_address(src, src_offset, basic_elem_type); | |
5371 dest_start = array_element_address(dest, dest_offset, basic_elem_type); | |
5372 } | |
5373 | |
5374 // Figure out which arraycopy runtime method to call. | |
5375 const char* copyfunc_name = "arraycopy"; | |
5376 address copyfunc_addr = | |
5377 basictype2arraycopy(basic_elem_type, src_offset, dest_offset, | |
2324 | 5378 disjoint_bases, copyfunc_name, dest_uninitialized); |
0 | 5379 |
5380 // Call it. Note that the count_ix value is not scaled to a byte-size. | |
5381 make_runtime_call(RC_LEAF|RC_NO_FP, | |
5382 OptoRuntime::fast_arraycopy_Type(), | |
5383 copyfunc_addr, copyfunc_name, adr_type, | |
5384 src_start, dest_start, copy_length XTOP); | |
5385 } | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5386 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5387 //----------------------------inline_reference_get---------------------------- |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5388 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5389 bool LibraryCallKit::inline_reference_get() { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5390 const int nargs = 1; // self |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5391 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5392 guarantee(java_lang_ref_Reference::referent_offset > 0, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5393 "should have already been set"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5394 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5395 int referent_offset = java_lang_ref_Reference::referent_offset; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5396 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5397 // Restore the stack and pop off the argument |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5398 _sp += nargs; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5399 Node *reference_obj = pop(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5400 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5401 // Null check on self without removing any arguments. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5402 _sp += nargs; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5403 reference_obj = do_null_check(reference_obj, T_OBJECT); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5404 _sp -= nargs;; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5405 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5406 if (stopped()) return true; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5407 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5408 Node *adr = basic_plus_adr(reference_obj, reference_obj, referent_offset); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5409 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5410 ciInstanceKlass* klass = env()->Object_klass(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5411 const TypeOopPtr* object_type = TypeOopPtr::make_from_klass(klass); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5412 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5413 Node* no_ctrl = NULL; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5414 Node *result = make_load(no_ctrl, adr, object_type, T_OBJECT); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5415 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5416 // Use the pre-barrier to record the value in the referent field |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5417 pre_barrier(false /* do_load */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5418 control(), |
3258
edd9b016deb6
7036021: G1: build failure on win64 and linux with hs21 in jdk6 build environment
johnc
parents:
3255
diff
changeset
|
5419 NULL /* obj */, NULL /* adr */, max_juint /* alias_idx */, NULL /* val */, NULL /* val_type */, |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5420 result /* pre_val */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5421 T_OBJECT); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5422 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5423 push(result); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5424 return true; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5425 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5426 |