Mercurial > hg > truffle
annotate src/share/vm/opto/library_call.cpp @ 17716:cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set.
Reviewed-by: acorn, kvn
Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author | minqi |
---|---|
date | Wed, 26 Feb 2014 15:20:41 -0800 |
parents | 04d32e7fad07 |
children | 085b304a1cc5 |
rev | line source |
---|---|
0 | 1 /* |
10405 | 2 * Copyright (c) 1999, 2013, 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" | |
12323 | 35 #include "opto/mathexactnode.hpp" |
1972 | 36 #include "opto/mulnode.hpp" |
37 #include "opto/parse.hpp" | |
38 #include "opto/runtime.hpp" | |
39 #include "opto/subnode.hpp" | |
40 #include "prims/nativeLookup.hpp" | |
41 #include "runtime/sharedRuntime.hpp" | |
10405 | 42 #include "trace/traceMacros.hpp" |
0 | 43 |
44 class LibraryIntrinsic : public InlineCallGenerator { | |
45 // Extend the set of intrinsics known to the runtime: | |
46 public: | |
47 private: | |
48 bool _is_virtual; | |
6894 | 49 bool _is_predicted; |
12330
29bdcf12457c
8014447: Object.hashCode intrinsic breaks inline caches
shade
parents:
12323
diff
changeset
|
50 bool _does_virtual_dispatch; |
0 | 51 vmIntrinsics::ID _intrinsic_id; |
52 | |
53 public: | |
12330
29bdcf12457c
8014447: Object.hashCode intrinsic breaks inline caches
shade
parents:
12323
diff
changeset
|
54 LibraryIntrinsic(ciMethod* m, bool is_virtual, bool is_predicted, bool does_virtual_dispatch, vmIntrinsics::ID id) |
0 | 55 : InlineCallGenerator(m), |
56 _is_virtual(is_virtual), | |
6894 | 57 _is_predicted(is_predicted), |
12330
29bdcf12457c
8014447: Object.hashCode intrinsic breaks inline caches
shade
parents:
12323
diff
changeset
|
58 _does_virtual_dispatch(does_virtual_dispatch), |
0 | 59 _intrinsic_id(id) |
60 { | |
61 } | |
62 virtual bool is_intrinsic() const { return true; } | |
63 virtual bool is_virtual() const { return _is_virtual; } | |
6894 | 64 virtual bool is_predicted() const { return _is_predicted; } |
12330
29bdcf12457c
8014447: Object.hashCode intrinsic breaks inline caches
shade
parents:
12323
diff
changeset
|
65 virtual bool does_virtual_dispatch() const { return _does_virtual_dispatch; } |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12330
diff
changeset
|
66 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser); |
6894 | 67 virtual Node* generate_predicate(JVMState* jvms); |
0 | 68 vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; } |
69 }; | |
70 | |
71 | |
72 // Local helper class for LibraryIntrinsic: | |
73 class LibraryCallKit : public GraphKit { | |
74 private: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
75 LibraryIntrinsic* _intrinsic; // the library intrinsic being called |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
76 Node* _result; // the result node, if any |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
77 int _reexecute_sp; // the stack pointer when bytecode needs to be reexecuted |
0 | 78 |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
79 const TypeOopPtr* sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type, bool is_native_ptr = false); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
80 |
0 | 81 public: |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
82 LibraryCallKit(JVMState* jvms, LibraryIntrinsic* intrinsic) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
83 : GraphKit(jvms), |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
84 _intrinsic(intrinsic), |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
85 _result(NULL) |
0 | 86 { |
7200
dd38cfd12c3a
8004319: test/gc/7168848/HumongousAlloc.java fails after 7172640
twisti
parents:
7194
diff
changeset
|
87 // Check if this is a root compile. In that case we don't have a caller. |
dd38cfd12c3a
8004319: test/gc/7168848/HumongousAlloc.java fails after 7172640
twisti
parents:
7194
diff
changeset
|
88 if (!jvms->has_method()) { |
dd38cfd12c3a
8004319: test/gc/7168848/HumongousAlloc.java fails after 7172640
twisti
parents:
7194
diff
changeset
|
89 _reexecute_sp = sp(); |
dd38cfd12c3a
8004319: test/gc/7168848/HumongousAlloc.java fails after 7172640
twisti
parents:
7194
diff
changeset
|
90 } else { |
dd38cfd12c3a
8004319: test/gc/7168848/HumongousAlloc.java fails after 7172640
twisti
parents:
7194
diff
changeset
|
91 // Find out how many arguments the interpreter needs when deoptimizing |
dd38cfd12c3a
8004319: test/gc/7168848/HumongousAlloc.java fails after 7172640
twisti
parents:
7194
diff
changeset
|
92 // and save the stack pointer value so it can used by uncommon_trap. |
dd38cfd12c3a
8004319: test/gc/7168848/HumongousAlloc.java fails after 7172640
twisti
parents:
7194
diff
changeset
|
93 // We find the argument count by looking at the declared signature. |
dd38cfd12c3a
8004319: test/gc/7168848/HumongousAlloc.java fails after 7172640
twisti
parents:
7194
diff
changeset
|
94 bool ignored_will_link; |
dd38cfd12c3a
8004319: test/gc/7168848/HumongousAlloc.java fails after 7172640
twisti
parents:
7194
diff
changeset
|
95 ciSignature* declared_signature = NULL; |
dd38cfd12c3a
8004319: test/gc/7168848/HumongousAlloc.java fails after 7172640
twisti
parents:
7194
diff
changeset
|
96 ciMethod* ignored_callee = caller()->get_method_at_bci(bci(), ignored_will_link, &declared_signature); |
dd38cfd12c3a
8004319: test/gc/7168848/HumongousAlloc.java fails after 7172640
twisti
parents:
7194
diff
changeset
|
97 const int nargs = declared_signature->arg_size_for_bc(caller()->java_code_at_bci(bci())); |
dd38cfd12c3a
8004319: test/gc/7168848/HumongousAlloc.java fails after 7172640
twisti
parents:
7194
diff
changeset
|
98 _reexecute_sp = sp() + nargs; // "push" arguments back on stack |
dd38cfd12c3a
8004319: test/gc/7168848/HumongousAlloc.java fails after 7172640
twisti
parents:
7194
diff
changeset
|
99 } |
0 | 100 } |
101 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
102 virtual LibraryCallKit* is_LibraryCallKit() const { return (LibraryCallKit*)this; } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
103 |
0 | 104 ciMethod* caller() const { return jvms()->method(); } |
105 int bci() const { return jvms()->bci(); } | |
106 LibraryIntrinsic* intrinsic() const { return _intrinsic; } | |
107 vmIntrinsics::ID intrinsic_id() const { return _intrinsic->intrinsic_id(); } | |
108 ciMethod* callee() const { return _intrinsic->method(); } | |
109 | |
110 bool try_to_inline(); | |
6894 | 111 Node* try_to_predicate(); |
0 | 112 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
113 void push_result() { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
114 // Push the result onto the stack. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
115 if (!stopped() && result() != NULL) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
116 BasicType bt = result()->bottom_type()->basic_type(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
117 push_node(bt, result()); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
118 } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
119 } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
120 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
121 private: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
122 void fatal_unexpected_iid(vmIntrinsics::ID iid) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
123 fatal(err_msg_res("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid))); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
124 } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
125 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
126 void set_result(Node* n) { assert(_result == NULL, "only set once"); _result = n; } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
127 void set_result(RegionNode* region, PhiNode* value); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
128 Node* result() { return _result; } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
129 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
130 virtual int reexecute_sp() { return _reexecute_sp; } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
131 |
0 | 132 // Helper functions to inline natives |
133 Node* generate_guard(Node* test, RegionNode* region, float true_prob); | |
134 Node* generate_slow_guard(Node* test, RegionNode* region); | |
135 Node* generate_fair_guard(Node* test, RegionNode* region); | |
136 Node* generate_negative_guard(Node* index, RegionNode* region, | |
137 // resulting CastII of index: | |
138 Node* *pos_index = NULL); | |
139 Node* generate_nonpositive_guard(Node* index, bool never_negative, | |
140 // resulting CastII of index: | |
141 Node* *pos_index = NULL); | |
142 Node* generate_limit_guard(Node* offset, Node* subseq_length, | |
143 Node* array_length, | |
144 RegionNode* region); | |
145 Node* generate_current_thread(Node* &tls_output); | |
146 address basictype2arraycopy(BasicType t, Node *src_offset, Node *dest_offset, | |
2324 | 147 bool disjoint_bases, const char* &name, bool dest_uninitialized); |
0 | 148 Node* load_mirror_from_klass(Node* klass); |
149 Node* load_klass_from_mirror_common(Node* mirror, bool never_see_null, | |
150 RegionNode* region, int null_path, | |
151 int offset); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
152 Node* load_klass_from_mirror(Node* mirror, bool never_see_null, |
0 | 153 RegionNode* region, int null_path) { |
154 int offset = java_lang_Class::klass_offset_in_bytes(); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
155 return load_klass_from_mirror_common(mirror, never_see_null, |
0 | 156 region, null_path, |
157 offset); | |
158 } | |
159 Node* load_array_klass_from_mirror(Node* mirror, bool never_see_null, | |
160 RegionNode* region, int null_path) { | |
161 int offset = java_lang_Class::array_klass_offset_in_bytes(); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
162 return load_klass_from_mirror_common(mirror, never_see_null, |
0 | 163 region, null_path, |
164 offset); | |
165 } | |
166 Node* generate_access_flags_guard(Node* kls, | |
167 int modifier_mask, int modifier_bits, | |
168 RegionNode* region); | |
169 Node* generate_interface_guard(Node* kls, RegionNode* region); | |
170 Node* generate_array_guard(Node* kls, RegionNode* region) { | |
171 return generate_array_guard_common(kls, region, false, false); | |
172 } | |
173 Node* generate_non_array_guard(Node* kls, RegionNode* region) { | |
174 return generate_array_guard_common(kls, region, false, true); | |
175 } | |
176 Node* generate_objArray_guard(Node* kls, RegionNode* region) { | |
177 return generate_array_guard_common(kls, region, true, false); | |
178 } | |
179 Node* generate_non_objArray_guard(Node* kls, RegionNode* region) { | |
180 return generate_array_guard_common(kls, region, true, true); | |
181 } | |
182 Node* generate_array_guard_common(Node* kls, RegionNode* region, | |
183 bool obj_array, bool not_array); | |
184 Node* generate_virtual_guard(Node* obj_klass, RegionNode* slow_region); | |
185 CallJavaNode* generate_method_call(vmIntrinsics::ID method_id, | |
186 bool is_virtual = false, bool is_static = false); | |
187 CallJavaNode* generate_method_call_static(vmIntrinsics::ID method_id) { | |
188 return generate_method_call(method_id, false, true); | |
189 } | |
190 CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) { | |
191 return generate_method_call(method_id, true, false); | |
192 } | |
6894 | 193 Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static); |
0 | 194 |
6057 | 195 Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2); |
196 Node* make_string_method_node(int opcode, Node* str1, Node* str2); | |
0 | 197 bool inline_string_compareTo(); |
198 bool inline_string_indexOf(); | |
199 Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i); | |
681 | 200 bool inline_string_equals(); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
201 Node* round_double_node(Node* n); |
0 | 202 bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName); |
203 bool inline_math_native(vmIntrinsics::ID id); | |
204 bool inline_trig(vmIntrinsics::ID id); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
205 bool inline_math(vmIntrinsics::ID id); |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
206 void inline_math_mathExact(Node* math); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
207 bool inline_math_addExactI(bool is_increment); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
208 bool inline_math_addExactL(bool is_increment); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
209 bool inline_math_multiplyExactI(); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
210 bool inline_math_multiplyExactL(); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
211 bool inline_math_negateExactI(); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
212 bool inline_math_negateExactL(); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
213 bool inline_math_subtractExactI(bool is_decrement); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
214 bool inline_math_subtractExactL(bool is_decrement); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
215 bool inline_exp(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
216 bool inline_pow(); |
6205 | 217 void finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName); |
0 | 218 bool inline_min_max(vmIntrinsics::ID id); |
219 Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y); | |
220 // This returns Type::AnyPtr, RawPtr, or OopPtr. | |
221 int classify_unsafe_addr(Node* &base, Node* &offset); | |
222 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
|
223 // Helper for inline_unsafe_access. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
224 // 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
|
225 // Unsafe.getObject should be recorded in an SATB log buffer. |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
226 void insert_pre_barrier(Node* base_oop, Node* offset, Node* pre_val, bool need_mem_bar); |
0 | 227 bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile); |
228 bool inline_unsafe_prefetch(bool is_native_ptr, bool is_store, bool is_static); | |
12078 | 229 static bool klass_needs_init_guard(Node* kls); |
0 | 230 bool inline_unsafe_allocate(); |
231 bool inline_unsafe_copyMemory(); | |
232 bool inline_native_currentThread(); | |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
233 #ifdef TRACE_HAVE_INTRINSICS |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
234 bool inline_native_classID(); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
235 bool inline_native_threadID(); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
236 #endif |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
237 bool inline_native_time_funcs(address method, const char* funcName); |
0 | 238 bool inline_native_isInterrupted(); |
239 bool inline_native_Class_query(vmIntrinsics::ID id); | |
240 bool inline_native_subtype_check(); | |
241 | |
242 bool inline_native_newArray(); | |
243 bool inline_native_getLength(); | |
244 bool inline_array_copyOf(bool is_copyOfRange); | |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
245 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
|
246 void copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array, bool card_mark); |
0 | 247 bool inline_native_clone(bool is_virtual); |
248 bool inline_native_Reflection_getCallerClass(); | |
249 // Helper function for inlining native object hash method | |
250 bool inline_native_hashcode(bool is_virtual, bool is_static); | |
251 bool inline_native_getClass(); | |
252 | |
253 // Helper functions for inlining arraycopy | |
254 bool inline_arraycopy(); | |
255 void generate_arraycopy(const TypePtr* adr_type, | |
256 BasicType basic_elem_type, | |
257 Node* src, Node* src_offset, | |
258 Node* dest, Node* dest_offset, | |
259 Node* copy_length, | |
260 bool disjoint_bases = false, | |
261 bool length_never_negative = false, | |
262 RegionNode* slow_region = NULL); | |
263 AllocateArrayNode* tightly_coupled_allocation(Node* ptr, | |
264 RegionNode* slow_region); | |
265 void generate_clear_array(const TypePtr* adr_type, | |
266 Node* dest, | |
267 BasicType basic_elem_type, | |
268 Node* slice_off, | |
269 Node* slice_len, | |
270 Node* slice_end); | |
271 bool generate_block_arraycopy(const TypePtr* adr_type, | |
272 BasicType basic_elem_type, | |
273 AllocateNode* alloc, | |
274 Node* src, Node* src_offset, | |
275 Node* dest, Node* dest_offset, | |
2324 | 276 Node* dest_size, bool dest_uninitialized); |
0 | 277 void generate_slow_arraycopy(const TypePtr* adr_type, |
278 Node* src, Node* src_offset, | |
279 Node* dest, Node* dest_offset, | |
2324 | 280 Node* copy_length, bool dest_uninitialized); |
0 | 281 Node* generate_checkcast_arraycopy(const TypePtr* adr_type, |
282 Node* dest_elem_klass, | |
283 Node* src, Node* src_offset, | |
284 Node* dest, Node* dest_offset, | |
2324 | 285 Node* copy_length, bool dest_uninitialized); |
0 | 286 Node* generate_generic_arraycopy(const TypePtr* adr_type, |
287 Node* src, Node* src_offset, | |
288 Node* dest, Node* dest_offset, | |
2324 | 289 Node* copy_length, bool dest_uninitialized); |
0 | 290 void generate_unchecked_arraycopy(const TypePtr* adr_type, |
291 BasicType basic_elem_type, | |
292 bool disjoint_bases, | |
293 Node* src, Node* src_offset, | |
294 Node* dest, Node* dest_offset, | |
2324 | 295 Node* copy_length, bool dest_uninitialized); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
296 typedef enum { LS_xadd, LS_xchg, LS_cmpxchg } LoadStoreKind; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
297 bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind); |
0 | 298 bool inline_unsafe_ordered_store(BasicType type); |
7425 | 299 bool inline_unsafe_fence(vmIntrinsics::ID id); |
0 | 300 bool inline_fp_conversions(vmIntrinsics::ID id); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
301 bool inline_number_methods(vmIntrinsics::ID id); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
302 bool inline_reference_get(); |
6894 | 303 bool inline_aescrypt_Block(vmIntrinsics::ID id); |
304 bool inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id); | |
305 Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting); | |
306 Node* get_key_start_from_aescrypt_object(Node* aescrypt_object); | |
17670 | 307 Node* get_original_key_start_from_aescrypt_object(Node* aescrypt_object); |
7637
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
308 bool inline_encodeISOArray(); |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
309 bool inline_updateCRC32(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
310 bool inline_updateBytesCRC32(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
311 bool inline_updateByteBufferCRC32(); |
0 | 312 }; |
313 | |
314 | |
315 //---------------------------make_vm_intrinsic---------------------------- | |
316 CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { | |
317 vmIntrinsics::ID id = m->intrinsic_id(); | |
318 assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); | |
319 | |
320 if (DisableIntrinsic[0] != '\0' | |
321 && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) { | |
322 // disabled by a user request on the command line: | |
323 // example: -XX:DisableIntrinsic=_hashCode,_getClass | |
324 return NULL; | |
325 } | |
326 | |
327 if (!m->is_loaded()) { | |
328 // do not attempt to inline unloaded methods | |
329 return NULL; | |
330 } | |
331 | |
332 // Only a few intrinsics implement a virtual dispatch. | |
333 // They are expensive calls which are also frequently overridden. | |
334 if (is_virtual) { | |
335 switch (id) { | |
336 case vmIntrinsics::_hashCode: | |
337 case vmIntrinsics::_clone: | |
338 // OK, Object.hashCode and Object.clone intrinsics come in both flavors | |
339 break; | |
340 default: | |
341 return NULL; | |
342 } | |
343 } | |
344 | |
345 // -XX:-InlineNatives disables nearly all intrinsics: | |
346 if (!InlineNatives) { | |
347 switch (id) { | |
348 case vmIntrinsics::_indexOf: | |
349 case vmIntrinsics::_compareTo: | |
681 | 350 case vmIntrinsics::_equals: |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
351 case vmIntrinsics::_equalsC: |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
352 case vmIntrinsics::_getAndAddInt: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
353 case vmIntrinsics::_getAndAddLong: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
354 case vmIntrinsics::_getAndSetInt: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
355 case vmIntrinsics::_getAndSetLong: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
356 case vmIntrinsics::_getAndSetObject: |
7425 | 357 case vmIntrinsics::_loadFence: |
358 case vmIntrinsics::_storeFence: | |
359 case vmIntrinsics::_fullFence: | |
0 | 360 break; // InlineNatives does not control String.compareTo |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
361 case vmIntrinsics::_Reference_get: |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
362 break; // InlineNatives does not control Reference.get |
0 | 363 default: |
364 return NULL; | |
365 } | |
366 } | |
367 | |
6894 | 368 bool is_predicted = false; |
12330
29bdcf12457c
8014447: Object.hashCode intrinsic breaks inline caches
shade
parents:
12323
diff
changeset
|
369 bool does_virtual_dispatch = false; |
6894 | 370 |
0 | 371 switch (id) { |
372 case vmIntrinsics::_compareTo: | |
373 if (!SpecialStringCompareTo) return NULL; | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
374 if (!Matcher::match_rule_supported(Op_StrComp)) return NULL; |
0 | 375 break; |
376 case vmIntrinsics::_indexOf: | |
377 if (!SpecialStringIndexOf) return NULL; | |
378 break; | |
681 | 379 case vmIntrinsics::_equals: |
380 if (!SpecialStringEquals) return NULL; | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
381 if (!Matcher::match_rule_supported(Op_StrEquals)) return NULL; |
681 | 382 break; |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
383 case vmIntrinsics::_equalsC: |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
384 if (!SpecialArraysEquals) return NULL; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
385 if (!Matcher::match_rule_supported(Op_AryEq)) return NULL; |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
386 break; |
0 | 387 case vmIntrinsics::_arraycopy: |
388 if (!InlineArrayCopy) return NULL; | |
389 break; | |
390 case vmIntrinsics::_copyMemory: | |
391 if (StubRoutines::unsafe_arraycopy() == NULL) return NULL; | |
392 if (!InlineArrayCopy) return NULL; | |
393 break; | |
394 case vmIntrinsics::_hashCode: | |
395 if (!InlineObjectHash) return NULL; | |
12330
29bdcf12457c
8014447: Object.hashCode intrinsic breaks inline caches
shade
parents:
12323
diff
changeset
|
396 does_virtual_dispatch = true; |
0 | 397 break; |
398 case vmIntrinsics::_clone: | |
12330
29bdcf12457c
8014447: Object.hashCode intrinsic breaks inline caches
shade
parents:
12323
diff
changeset
|
399 does_virtual_dispatch = true; |
0 | 400 case vmIntrinsics::_copyOf: |
401 case vmIntrinsics::_copyOfRange: | |
402 if (!InlineObjectCopy) return NULL; | |
403 // These also use the arraycopy intrinsic mechanism: | |
404 if (!InlineArrayCopy) return NULL; | |
405 break; | |
7637
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
406 case vmIntrinsics::_encodeISOArray: |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
407 if (!SpecialEncodeISOArray) return NULL; |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
408 if (!Matcher::match_rule_supported(Op_EncodeISOArray)) return NULL; |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
409 break; |
0 | 410 case vmIntrinsics::_checkIndex: |
411 // We do not intrinsify this. The optimizer does fine with it. | |
412 return NULL; | |
413 | |
414 case vmIntrinsics::_getCallerClass: | |
415 if (!UseNewReflection) return NULL; | |
416 if (!InlineReflectionGetCallerClass) return NULL; | |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
417 if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) return NULL; |
0 | 418 break; |
419 | |
643
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
420 case vmIntrinsics::_bitCount_i: |
5934
61b82be3b1ff
7152957: VM crashes with assert(false) failed: bad AD file
never
parents:
5927
diff
changeset
|
421 if (!Matcher::match_rule_supported(Op_PopCountI)) return NULL; |
5927
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
422 break; |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
423 |
643
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
424 case vmIntrinsics::_bitCount_l: |
5934
61b82be3b1ff
7152957: VM crashes with assert(false) failed: bad AD file
never
parents:
5927
diff
changeset
|
425 if (!Matcher::match_rule_supported(Op_PopCountL)) return NULL; |
5927
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
426 break; |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
427 |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
428 case vmIntrinsics::_numberOfLeadingZeros_i: |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
429 if (!Matcher::match_rule_supported(Op_CountLeadingZerosI)) return NULL; |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
430 break; |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
431 |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
432 case vmIntrinsics::_numberOfLeadingZeros_l: |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
433 if (!Matcher::match_rule_supported(Op_CountLeadingZerosL)) return NULL; |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
434 break; |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
435 |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
436 case vmIntrinsics::_numberOfTrailingZeros_i: |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
437 if (!Matcher::match_rule_supported(Op_CountTrailingZerosI)) return NULL; |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
438 break; |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
439 |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
440 case vmIntrinsics::_numberOfTrailingZeros_l: |
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
441 if (!Matcher::match_rule_supported(Op_CountTrailingZerosL)) return NULL; |
643
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
442 break; |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
443 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
444 case vmIntrinsics::_reverseBytes_c: |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7200
diff
changeset
|
445 if (!Matcher::match_rule_supported(Op_ReverseBytesUS)) return NULL; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
446 break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
447 case vmIntrinsics::_reverseBytes_s: |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7200
diff
changeset
|
448 if (!Matcher::match_rule_supported(Op_ReverseBytesS)) return NULL; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
449 break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
450 case vmIntrinsics::_reverseBytes_i: |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7200
diff
changeset
|
451 if (!Matcher::match_rule_supported(Op_ReverseBytesI)) return NULL; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
452 break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
453 case vmIntrinsics::_reverseBytes_l: |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7200
diff
changeset
|
454 if (!Matcher::match_rule_supported(Op_ReverseBytesL)) return NULL; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
455 break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
456 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
457 case vmIntrinsics::_Reference_get: |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
458 // Use the intrinsic version of Reference.get() so that the value in |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
459 // the referent field can be registered by the G1 pre-barrier code. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
460 // Also add memory barrier to prevent commoning reads from this field |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
461 // across safepoint since GC can change it value. |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
462 break; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
463 |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
464 case vmIntrinsics::_compareAndSwapObject: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
465 #ifdef _LP64 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
466 if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapP)) return NULL; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
467 #endif |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
468 break; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
469 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
470 case vmIntrinsics::_compareAndSwapLong: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
471 if (!Matcher::match_rule_supported(Op_CompareAndSwapL)) return NULL; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
472 break; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
473 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
474 case vmIntrinsics::_getAndAddInt: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
475 if (!Matcher::match_rule_supported(Op_GetAndAddI)) return NULL; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
476 break; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
477 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
478 case vmIntrinsics::_getAndAddLong: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
479 if (!Matcher::match_rule_supported(Op_GetAndAddL)) return NULL; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
480 break; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
481 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
482 case vmIntrinsics::_getAndSetInt: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
483 if (!Matcher::match_rule_supported(Op_GetAndSetI)) return NULL; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
484 break; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
485 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
486 case vmIntrinsics::_getAndSetLong: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
487 if (!Matcher::match_rule_supported(Op_GetAndSetL)) return NULL; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
488 break; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
489 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
490 case vmIntrinsics::_getAndSetObject: |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
491 #ifdef _LP64 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
492 if (!UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetP)) return NULL; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
493 if (UseCompressedOops && !Matcher::match_rule_supported(Op_GetAndSetN)) return NULL; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
494 break; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
495 #else |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
496 if (!Matcher::match_rule_supported(Op_GetAndSetP)) return NULL; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
497 break; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
498 #endif |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
499 |
6894 | 500 case vmIntrinsics::_aescrypt_encryptBlock: |
501 case vmIntrinsics::_aescrypt_decryptBlock: | |
502 if (!UseAESIntrinsics) return NULL; | |
503 break; | |
504 | |
505 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: | |
506 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: | |
507 if (!UseAESIntrinsics) return NULL; | |
508 // these two require the predicated logic | |
509 is_predicted = true; | |
510 break; | |
511 | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
512 case vmIntrinsics::_updateCRC32: |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
513 case vmIntrinsics::_updateBytesCRC32: |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
514 case vmIntrinsics::_updateByteBufferCRC32: |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
515 if (!UseCRC32Intrinsics) return NULL; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
516 break; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
517 |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
518 case vmIntrinsics::_incrementExactI: |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
519 case vmIntrinsics::_addExactI: |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
520 if (!Matcher::match_rule_supported(Op_AddExactI) || !UseMathExactIntrinsics) return NULL; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
521 break; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
522 case vmIntrinsics::_incrementExactL: |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
523 case vmIntrinsics::_addExactL: |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
524 if (!Matcher::match_rule_supported(Op_AddExactL) || !UseMathExactIntrinsics) return NULL; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
525 break; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
526 case vmIntrinsics::_decrementExactI: |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
527 case vmIntrinsics::_subtractExactI: |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
528 if (!Matcher::match_rule_supported(Op_SubExactI) || !UseMathExactIntrinsics) return NULL; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
529 break; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
530 case vmIntrinsics::_decrementExactL: |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
531 case vmIntrinsics::_subtractExactL: |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
532 if (!Matcher::match_rule_supported(Op_SubExactL) || !UseMathExactIntrinsics) return NULL; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
533 break; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
534 case vmIntrinsics::_negateExactI: |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
535 if (!Matcher::match_rule_supported(Op_NegExactI) || !UseMathExactIntrinsics) return NULL; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
536 break; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
537 case vmIntrinsics::_negateExactL: |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
538 if (!Matcher::match_rule_supported(Op_NegExactL) || !UseMathExactIntrinsics) return NULL; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
539 break; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
540 case vmIntrinsics::_multiplyExactI: |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
541 if (!Matcher::match_rule_supported(Op_MulExactI) || !UseMathExactIntrinsics) return NULL; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
542 break; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
543 case vmIntrinsics::_multiplyExactL: |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
544 if (!Matcher::match_rule_supported(Op_MulExactL) || !UseMathExactIntrinsics) return NULL; |
12323 | 545 break; |
546 | |
0 | 547 default: |
856
75596850f863
6862576: vmIntrinsics needs cleanup in order to support JSR 292 intrinsics
jrose
parents:
851
diff
changeset
|
548 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
|
549 assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?"); |
0 | 550 break; |
551 } | |
552 | |
553 // -XX:-InlineClassNatives disables natives from the Class class. | |
554 // The flag applies to all reflective calls, notably Array.newArray | |
555 // (visible to Java programmers as Array.newInstance). | |
556 if (m->holder()->name() == ciSymbol::java_lang_Class() || | |
557 m->holder()->name() == ciSymbol::java_lang_reflect_Array()) { | |
558 if (!InlineClassNatives) return NULL; | |
559 } | |
560 | |
561 // -XX:-InlineThreadNatives disables natives from the Thread class. | |
562 if (m->holder()->name() == ciSymbol::java_lang_Thread()) { | |
563 if (!InlineThreadNatives) return NULL; | |
564 } | |
565 | |
566 // -XX:-InlineMathNatives disables natives from the Math,Float and Double classes. | |
567 if (m->holder()->name() == ciSymbol::java_lang_Math() || | |
568 m->holder()->name() == ciSymbol::java_lang_Float() || | |
569 m->holder()->name() == ciSymbol::java_lang_Double()) { | |
570 if (!InlineMathNatives) return NULL; | |
571 } | |
572 | |
573 // -XX:-InlineUnsafeOps disables natives from the Unsafe class. | |
574 if (m->holder()->name() == ciSymbol::sun_misc_Unsafe()) { | |
575 if (!InlineUnsafeOps) return NULL; | |
576 } | |
577 | |
12330
29bdcf12457c
8014447: Object.hashCode intrinsic breaks inline caches
shade
parents:
12323
diff
changeset
|
578 return new LibraryIntrinsic(m, is_virtual, is_predicted, does_virtual_dispatch, (vmIntrinsics::ID) id); |
0 | 579 } |
580 | |
581 //----------------------register_library_intrinsics----------------------- | |
582 // Initialize this file's data structures, for each Compile instance. | |
583 void Compile::register_library_intrinsics() { | |
584 // Nothing to do here. | |
585 } | |
586 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
12330
diff
changeset
|
587 JVMState* LibraryIntrinsic::generate(JVMState* jvms, Parse* parent_parser) { |
0 | 588 LibraryCallKit kit(jvms, this); |
589 Compile* C = kit.C; | |
590 int nodes = C->unique(); | |
591 #ifndef PRODUCT | |
12295 | 592 if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { |
0 | 593 char buf[1000]; |
594 const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf)); | |
595 tty->print_cr("Intrinsic %s", str); | |
596 } | |
597 #endif | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
598 ciMethod* callee = kit.callee(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
599 const int bci = kit.bci(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
600 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
601 // Try to inline the intrinsic. |
0 | 602 if (kit.try_to_inline()) { |
12295 | 603 if (C->print_intrinsics() || C->print_inlining()) { |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7200
diff
changeset
|
604 C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); |
0 | 605 } |
606 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); | |
607 if (C->log()) { | |
608 C->log()->elem("intrinsic id='%s'%s nodes='%d'", | |
609 vmIntrinsics::name_at(intrinsic_id()), | |
610 (is_virtual() ? " virtual='1'" : ""), | |
611 C->unique() - nodes); | |
612 } | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
613 // Push the result from the inlined method onto the stack. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
614 kit.push_result(); |
0 | 615 return kit.transfer_exceptions_into_jvms(); |
616 } | |
617 | |
5927
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
618 // The intrinsic bailed out |
12295 | 619 if (C->print_intrinsics() || C->print_inlining()) { |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
620 if (jvms->has_method()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
621 // Not a root compile. |
5927
b40ac3579043
6658428: C2 doesn't inline java method if corresponding intrinsic failed to inline.
never
parents:
4902
diff
changeset
|
622 const char* msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)"; |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7200
diff
changeset
|
623 C->print_inlining(callee, jvms->depth() - 1, bci, msg); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
624 } else { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
625 // Root compile |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
626 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
|
627 vmIntrinsics::name_at(intrinsic_id()), |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
628 (is_virtual() ? " (virtual)" : ""), bci); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
629 } |
0 | 630 } |
631 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); | |
632 return NULL; | |
633 } | |
634 | |
6894 | 635 Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) { |
636 LibraryCallKit kit(jvms, this); | |
637 Compile* C = kit.C; | |
638 int nodes = C->unique(); | |
639 #ifndef PRODUCT | |
640 assert(is_predicted(), "sanity"); | |
12295 | 641 if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { |
6894 | 642 char buf[1000]; |
643 const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf)); | |
644 tty->print_cr("Predicate for intrinsic %s", str); | |
645 } | |
646 #endif | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
647 ciMethod* callee = kit.callee(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
648 const int bci = kit.bci(); |
6894 | 649 |
650 Node* slow_ctl = kit.try_to_predicate(); | |
651 if (!kit.failing()) { | |
12295 | 652 if (C->print_intrinsics() || C->print_inlining()) { |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7200
diff
changeset
|
653 C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
654 } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
655 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); |
6894 | 656 if (C->log()) { |
657 C->log()->elem("predicate_intrinsic id='%s'%s nodes='%d'", | |
658 vmIntrinsics::name_at(intrinsic_id()), | |
659 (is_virtual() ? " virtual='1'" : ""), | |
660 C->unique() - nodes); | |
661 } | |
662 return slow_ctl; // Could be NULL if the check folds. | |
663 } | |
664 | |
665 // The intrinsic bailed out | |
12295 | 666 if (C->print_intrinsics() || C->print_inlining()) { |
6894 | 667 if (jvms->has_method()) { |
668 // Not a root compile. | |
669 const char* msg = "failed to generate predicate for intrinsic"; | |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7200
diff
changeset
|
670 C->print_inlining(kit.callee(), jvms->depth() - 1, bci, msg); |
6894 | 671 } else { |
672 // Root compile | |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7200
diff
changeset
|
673 C->print_inlining_stream()->print("Did not generate predicate for intrinsic %s%s at bci:%d in", |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7200
diff
changeset
|
674 vmIntrinsics::name_at(intrinsic_id()), |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7200
diff
changeset
|
675 (is_virtual() ? " (virtual)" : ""), bci); |
6894 | 676 } |
677 } | |
678 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); | |
679 return NULL; | |
680 } | |
681 | |
0 | 682 bool LibraryCallKit::try_to_inline() { |
683 // Handle symbolic names for otherwise undistinguished boolean switches: | |
684 const bool is_store = true; | |
685 const bool is_native_ptr = true; | |
686 const bool is_static = true; | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
687 const bool is_volatile = true; |
0 | 688 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
689 if (!jvms()->has_method()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
690 // Root JVMState has a null method. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
691 assert(map()->memory()->Opcode() == Op_Parm, ""); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
692 // Insert the memory aliasing node |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
693 set_all_memory(reset_memory()); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
694 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
695 assert(merged_memory(), ""); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
696 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
697 |
0 | 698 switch (intrinsic_id()) { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
699 case vmIntrinsics::_hashCode: return inline_native_hashcode(intrinsic()->is_virtual(), !is_static); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
700 case vmIntrinsics::_identityHashCode: return inline_native_hashcode(/*!virtual*/ false, is_static); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
701 case vmIntrinsics::_getClass: return inline_native_getClass(); |
0 | 702 |
703 case vmIntrinsics::_dsin: | |
704 case vmIntrinsics::_dcos: | |
705 case vmIntrinsics::_dtan: | |
706 case vmIntrinsics::_dabs: | |
707 case vmIntrinsics::_datan2: | |
708 case vmIntrinsics::_dsqrt: | |
709 case vmIntrinsics::_dexp: | |
710 case vmIntrinsics::_dlog: | |
711 case vmIntrinsics::_dlog10: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
712 case vmIntrinsics::_dpow: return inline_math_native(intrinsic_id()); |
0 | 713 |
714 case vmIntrinsics::_min: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
715 case vmIntrinsics::_max: return inline_min_max(intrinsic_id()); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
716 |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
717 case vmIntrinsics::_addExactI: return inline_math_addExactI(false /* add */); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
718 case vmIntrinsics::_addExactL: return inline_math_addExactL(false /* add */); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
719 case vmIntrinsics::_decrementExactI: return inline_math_subtractExactI(true /* decrement */); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
720 case vmIntrinsics::_decrementExactL: return inline_math_subtractExactL(true /* decrement */); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
721 case vmIntrinsics::_incrementExactI: return inline_math_addExactI(true /* increment */); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
722 case vmIntrinsics::_incrementExactL: return inline_math_addExactL(true /* increment */); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
723 case vmIntrinsics::_multiplyExactI: return inline_math_multiplyExactI(); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
724 case vmIntrinsics::_multiplyExactL: return inline_math_multiplyExactL(); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
725 case vmIntrinsics::_negateExactI: return inline_math_negateExactI(); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
726 case vmIntrinsics::_negateExactL: return inline_math_negateExactL(); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
727 case vmIntrinsics::_subtractExactI: return inline_math_subtractExactI(false /* subtract */); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
728 case vmIntrinsics::_subtractExactL: return inline_math_subtractExactL(false /* subtract */); |
12323 | 729 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
730 case vmIntrinsics::_arraycopy: return inline_arraycopy(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
731 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
732 case vmIntrinsics::_compareTo: return inline_string_compareTo(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
733 case vmIntrinsics::_indexOf: return inline_string_indexOf(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
734 case vmIntrinsics::_equals: return inline_string_equals(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
735 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
736 case vmIntrinsics::_getObject: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
737 case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
738 case vmIntrinsics::_getByte: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
739 case vmIntrinsics::_getShort: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
740 case vmIntrinsics::_getChar: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
741 case vmIntrinsics::_getInt: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
742 case vmIntrinsics::_getLong: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
743 case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
744 case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
745 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
746 case vmIntrinsics::_putObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
747 case vmIntrinsics::_putBoolean: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
748 case vmIntrinsics::_putByte: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
749 case vmIntrinsics::_putShort: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
750 case vmIntrinsics::_putChar: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
751 case vmIntrinsics::_putInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
752 case vmIntrinsics::_putLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
753 case vmIntrinsics::_putFloat: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
754 case vmIntrinsics::_putDouble: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
755 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
756 case vmIntrinsics::_getByte_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_BYTE, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
757 case vmIntrinsics::_getShort_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_SHORT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
758 case vmIntrinsics::_getChar_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_CHAR, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
759 case vmIntrinsics::_getInt_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_INT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
760 case vmIntrinsics::_getLong_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_LONG, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
761 case vmIntrinsics::_getFloat_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_FLOAT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
762 case vmIntrinsics::_getDouble_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_DOUBLE, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
763 case vmIntrinsics::_getAddress_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_ADDRESS, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
764 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
765 case vmIntrinsics::_putByte_raw: return inline_unsafe_access( is_native_ptr, is_store, T_BYTE, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
766 case vmIntrinsics::_putShort_raw: return inline_unsafe_access( is_native_ptr, is_store, T_SHORT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
767 case vmIntrinsics::_putChar_raw: return inline_unsafe_access( is_native_ptr, is_store, T_CHAR, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
768 case vmIntrinsics::_putInt_raw: return inline_unsafe_access( is_native_ptr, is_store, T_INT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
769 case vmIntrinsics::_putLong_raw: return inline_unsafe_access( is_native_ptr, is_store, T_LONG, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
770 case vmIntrinsics::_putFloat_raw: return inline_unsafe_access( is_native_ptr, is_store, T_FLOAT, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
771 case vmIntrinsics::_putDouble_raw: return inline_unsafe_access( is_native_ptr, is_store, T_DOUBLE, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
772 case vmIntrinsics::_putAddress_raw: return inline_unsafe_access( is_native_ptr, is_store, T_ADDRESS, !is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
773 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
774 case vmIntrinsics::_getObjectVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
775 case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
776 case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
777 case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
778 case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
779 case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
780 case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
781 case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
782 case vmIntrinsics::_getDoubleVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
783 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
784 case vmIntrinsics::_putObjectVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
785 case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
786 case vmIntrinsics::_putByteVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
787 case vmIntrinsics::_putShortVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
788 case vmIntrinsics::_putCharVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
789 case vmIntrinsics::_putIntVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
790 case vmIntrinsics::_putLongVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
791 case vmIntrinsics::_putFloatVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
792 case vmIntrinsics::_putDoubleVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, is_volatile); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
793 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
794 case vmIntrinsics::_prefetchRead: return inline_unsafe_prefetch(!is_native_ptr, !is_store, !is_static); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
795 case vmIntrinsics::_prefetchWrite: return inline_unsafe_prefetch(!is_native_ptr, is_store, !is_static); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
796 case vmIntrinsics::_prefetchReadStatic: return inline_unsafe_prefetch(!is_native_ptr, !is_store, is_static); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
797 case vmIntrinsics::_prefetchWriteStatic: return inline_unsafe_prefetch(!is_native_ptr, is_store, is_static); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
798 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
799 case vmIntrinsics::_compareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmpxchg); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
800 case vmIntrinsics::_compareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmpxchg); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
801 case vmIntrinsics::_compareAndSwapLong: return inline_unsafe_load_store(T_LONG, LS_cmpxchg); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
802 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
803 case vmIntrinsics::_putOrderedObject: return inline_unsafe_ordered_store(T_OBJECT); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
804 case vmIntrinsics::_putOrderedInt: return inline_unsafe_ordered_store(T_INT); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
805 case vmIntrinsics::_putOrderedLong: return inline_unsafe_ordered_store(T_LONG); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
806 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
807 case vmIntrinsics::_getAndAddInt: return inline_unsafe_load_store(T_INT, LS_xadd); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
808 case vmIntrinsics::_getAndAddLong: return inline_unsafe_load_store(T_LONG, LS_xadd); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
809 case vmIntrinsics::_getAndSetInt: return inline_unsafe_load_store(T_INT, LS_xchg); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
810 case vmIntrinsics::_getAndSetLong: return inline_unsafe_load_store(T_LONG, LS_xchg); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
811 case vmIntrinsics::_getAndSetObject: return inline_unsafe_load_store(T_OBJECT, LS_xchg); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
812 |
7425 | 813 case vmIntrinsics::_loadFence: |
814 case vmIntrinsics::_storeFence: | |
815 case vmIntrinsics::_fullFence: return inline_unsafe_fence(intrinsic_id()); | |
816 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
817 case vmIntrinsics::_currentThread: return inline_native_currentThread(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
818 case vmIntrinsics::_isInterrupted: return inline_native_isInterrupted(); |
0 | 819 |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
820 #ifdef TRACE_HAVE_INTRINSICS |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
821 case vmIntrinsics::_classID: return inline_native_classID(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
822 case vmIntrinsics::_threadID: return inline_native_threadID(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
823 case vmIntrinsics::_counterTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), "counterTime"); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
824 #endif |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
825 case vmIntrinsics::_currentTimeMillis: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeMillis), "currentTimeMillis"); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
826 case vmIntrinsics::_nanoTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeNanos), "nanoTime"); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
827 case vmIntrinsics::_allocateInstance: return inline_unsafe_allocate(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
828 case vmIntrinsics::_copyMemory: return inline_unsafe_copyMemory(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
829 case vmIntrinsics::_newArray: return inline_native_newArray(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
830 case vmIntrinsics::_getLength: return inline_native_getLength(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
831 case vmIntrinsics::_copyOf: return inline_array_copyOf(false); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
832 case vmIntrinsics::_copyOfRange: return inline_array_copyOf(true); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
833 case vmIntrinsics::_equalsC: return inline_array_equals(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
834 case vmIntrinsics::_clone: return inline_native_clone(intrinsic()->is_virtual()); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
835 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
836 case vmIntrinsics::_isAssignableFrom: return inline_native_subtype_check(); |
0 | 837 |
838 case vmIntrinsics::_isInstance: | |
839 case vmIntrinsics::_getModifiers: | |
840 case vmIntrinsics::_isInterface: | |
841 case vmIntrinsics::_isArray: | |
842 case vmIntrinsics::_isPrimitive: | |
843 case vmIntrinsics::_getSuperclass: | |
844 case vmIntrinsics::_getComponentType: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
845 case vmIntrinsics::_getClassAccessFlags: return inline_native_Class_query(intrinsic_id()); |
0 | 846 |
847 case vmIntrinsics::_floatToRawIntBits: | |
848 case vmIntrinsics::_floatToIntBits: | |
849 case vmIntrinsics::_intBitsToFloat: | |
850 case vmIntrinsics::_doubleToRawLongBits: | |
851 case vmIntrinsics::_doubleToLongBits: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
852 case vmIntrinsics::_longBitsToDouble: return inline_fp_conversions(intrinsic_id()); |
0 | 853 |
775
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
854 case vmIntrinsics::_numberOfLeadingZeros_i: |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
855 case vmIntrinsics::_numberOfLeadingZeros_l: |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
856 case vmIntrinsics::_numberOfTrailingZeros_i: |
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
857 case vmIntrinsics::_numberOfTrailingZeros_l: |
643
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
858 case vmIntrinsics::_bitCount_i: |
c771b7f43bbf
6378821: bitCount() should use POPC on SPARC processors and AMD+10h
twisti
parents:
605
diff
changeset
|
859 case vmIntrinsics::_bitCount_l: |
0 | 860 case vmIntrinsics::_reverseBytes_i: |
861 case vmIntrinsics::_reverseBytes_l: | |
1396
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
1152
diff
changeset
|
862 case vmIntrinsics::_reverseBytes_s: |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
863 case vmIntrinsics::_reverseBytes_c: return inline_number_methods(intrinsic_id()); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
864 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
865 case vmIntrinsics::_getCallerClass: return inline_native_Reflection_getCallerClass(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
866 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
867 case vmIntrinsics::_Reference_get: return inline_reference_get(); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
868 |
6894 | 869 case vmIntrinsics::_aescrypt_encryptBlock: |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
870 case vmIntrinsics::_aescrypt_decryptBlock: return inline_aescrypt_Block(intrinsic_id()); |
6894 | 871 |
872 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: | |
873 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: | |
874 return inline_cipherBlockChaining_AESCrypt(intrinsic_id()); | |
875 | |
7637
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
876 case vmIntrinsics::_encodeISOArray: |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
877 return inline_encodeISOArray(); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
878 |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
879 case vmIntrinsics::_updateCRC32: |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
880 return inline_updateCRC32(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
881 case vmIntrinsics::_updateBytesCRC32: |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
882 return inline_updateBytesCRC32(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
883 case vmIntrinsics::_updateByteBufferCRC32: |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
884 return inline_updateByteBufferCRC32(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
885 |
0 | 886 default: |
887 // If you get here, it may be that someone has added a new intrinsic | |
888 // to the list in vmSymbols.hpp without implementing it here. | |
889 #ifndef PRODUCT | |
890 if ((PrintMiscellaneous && (Verbose || WizardMode)) || PrintOpto) { | |
891 tty->print_cr("*** Warning: Unimplemented intrinsic %s(%d)", | |
892 vmIntrinsics::name_at(intrinsic_id()), intrinsic_id()); | |
893 } | |
894 #endif | |
895 return false; | |
896 } | |
897 } | |
898 | |
6894 | 899 Node* LibraryCallKit::try_to_predicate() { |
900 if (!jvms()->has_method()) { | |
901 // Root JVMState has a null method. | |
902 assert(map()->memory()->Opcode() == Op_Parm, ""); | |
903 // Insert the memory aliasing node | |
904 set_all_memory(reset_memory()); | |
905 } | |
906 assert(merged_memory(), ""); | |
907 | |
908 switch (intrinsic_id()) { | |
909 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: | |
910 return inline_cipherBlockChaining_AESCrypt_predicate(false); | |
911 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: | |
912 return inline_cipherBlockChaining_AESCrypt_predicate(true); | |
913 | |
914 default: | |
915 // If you get here, it may be that someone has added a new intrinsic | |
916 // to the list in vmSymbols.hpp without implementing it here. | |
917 #ifndef PRODUCT | |
918 if ((PrintMiscellaneous && (Verbose || WizardMode)) || PrintOpto) { | |
919 tty->print_cr("*** Warning: Unimplemented predicate for intrinsic %s(%d)", | |
920 vmIntrinsics::name_at(intrinsic_id()), intrinsic_id()); | |
921 } | |
922 #endif | |
923 Node* slow_ctl = control(); | |
924 set_control(top()); // No fast path instrinsic | |
925 return slow_ctl; | |
926 } | |
927 } | |
928 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
929 //------------------------------set_result------------------------------- |
0 | 930 // Helper function for finishing intrinsics. |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
931 void LibraryCallKit::set_result(RegionNode* region, PhiNode* value) { |
0 | 932 record_for_igvn(region); |
933 set_control(_gvn.transform(region)); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
934 set_result( _gvn.transform(value)); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
935 assert(value->type()->basic_type() == result()->bottom_type()->basic_type(), "sanity"); |
0 | 936 } |
937 | |
938 //------------------------------generate_guard--------------------------- | |
939 // Helper function for generating guarded fast-slow graph structures. | |
940 // The given 'test', if true, guards a slow path. If the test fails | |
941 // then a fast path can be taken. (We generally hope it fails.) | |
942 // In all cases, GraphKit::control() is updated to the fast path. | |
943 // The returned value represents the control for the slow path. | |
944 // The return value is never 'top'; it is either a valid control | |
945 // or NULL if it is obvious that the slow path can never be taken. | |
946 // Also, if region and the slow control are not NULL, the slow edge | |
947 // is appended to the region. | |
948 Node* LibraryCallKit::generate_guard(Node* test, RegionNode* region, float true_prob) { | |
949 if (stopped()) { | |
950 // Already short circuited. | |
951 return NULL; | |
952 } | |
953 | |
954 // Build an if node and its projections. | |
955 // If test is true we take the slow path, which we assume is uncommon. | |
956 if (_gvn.type(test) == TypeInt::ZERO) { | |
957 // The slow branch is never taken. No need to build this guard. | |
958 return NULL; | |
959 } | |
960 | |
961 IfNode* iff = create_and_map_if(control(), test, true_prob, COUNT_UNKNOWN); | |
962 | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
963 Node* if_slow = _gvn.transform(new (C) IfTrueNode(iff)); |
0 | 964 if (if_slow == top()) { |
965 // The slow branch is never taken. No need to build this guard. | |
966 return NULL; | |
967 } | |
968 | |
969 if (region != NULL) | |
970 region->add_req(if_slow); | |
971 | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
972 Node* if_fast = _gvn.transform(new (C) IfFalseNode(iff)); |
0 | 973 set_control(if_fast); |
974 | |
975 return if_slow; | |
976 } | |
977 | |
978 inline Node* LibraryCallKit::generate_slow_guard(Node* test, RegionNode* region) { | |
979 return generate_guard(test, region, PROB_UNLIKELY_MAG(3)); | |
980 } | |
981 inline Node* LibraryCallKit::generate_fair_guard(Node* test, RegionNode* region) { | |
982 return generate_guard(test, region, PROB_FAIR); | |
983 } | |
984 | |
985 inline Node* LibraryCallKit::generate_negative_guard(Node* index, RegionNode* region, | |
986 Node* *pos_index) { | |
987 if (stopped()) | |
988 return NULL; // already stopped | |
989 if (_gvn.type(index)->higher_equal(TypeInt::POS)) // [0,maxint] | |
990 return NULL; // index is already adequately typed | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
991 Node* cmp_lt = _gvn.transform(new (C) CmpINode(index, intcon(0))); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
992 Node* bol_lt = _gvn.transform(new (C) BoolNode(cmp_lt, BoolTest::lt)); |
0 | 993 Node* is_neg = generate_guard(bol_lt, region, PROB_MIN); |
994 if (is_neg != NULL && pos_index != NULL) { | |
995 // Emulate effect of Parse::adjust_map_after_if. | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
996 Node* ccast = new (C) CastIINode(index, TypeInt::POS); |
0 | 997 ccast->set_req(0, control()); |
998 (*pos_index) = _gvn.transform(ccast); | |
999 } | |
1000 return is_neg; | |
1001 } | |
1002 | |
1003 inline Node* LibraryCallKit::generate_nonpositive_guard(Node* index, bool never_negative, | |
1004 Node* *pos_index) { | |
1005 if (stopped()) | |
1006 return NULL; // already stopped | |
1007 if (_gvn.type(index)->higher_equal(TypeInt::POS1)) // [1,maxint] | |
1008 return NULL; // index is already adequately typed | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1009 Node* cmp_le = _gvn.transform(new (C) CmpINode(index, intcon(0))); |
0 | 1010 BoolTest::mask le_or_eq = (never_negative ? BoolTest::eq : BoolTest::le); |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1011 Node* bol_le = _gvn.transform(new (C) BoolNode(cmp_le, le_or_eq)); |
0 | 1012 Node* is_notp = generate_guard(bol_le, NULL, PROB_MIN); |
1013 if (is_notp != NULL && pos_index != NULL) { | |
1014 // Emulate effect of Parse::adjust_map_after_if. | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1015 Node* ccast = new (C) CastIINode(index, TypeInt::POS1); |
0 | 1016 ccast->set_req(0, control()); |
1017 (*pos_index) = _gvn.transform(ccast); | |
1018 } | |
1019 return is_notp; | |
1020 } | |
1021 | |
1022 // Make sure that 'position' is a valid limit index, in [0..length]. | |
1023 // There are two equivalent plans for checking this: | |
1024 // A. (offset + copyLength) unsigned<= arrayLength | |
1025 // B. offset <= (arrayLength - copyLength) | |
1026 // We require that all of the values above, except for the sum and | |
1027 // difference, are already known to be non-negative. | |
1028 // Plan A is robust in the face of overflow, if offset and copyLength | |
1029 // are both hugely positive. | |
1030 // | |
1031 // Plan B is less direct and intuitive, but it does not overflow at | |
1032 // all, since the difference of two non-negatives is always | |
1033 // representable. Whenever Java methods must perform the equivalent | |
1034 // check they generally use Plan B instead of Plan A. | |
1035 // For the moment we use Plan A. | |
1036 inline Node* LibraryCallKit::generate_limit_guard(Node* offset, | |
1037 Node* subseq_length, | |
1038 Node* array_length, | |
1039 RegionNode* region) { | |
1040 if (stopped()) | |
1041 return NULL; // already stopped | |
1042 bool zero_offset = _gvn.type(offset) == TypeInt::ZERO; | |
4778 | 1043 if (zero_offset && subseq_length->eqv_uncast(array_length)) |
0 | 1044 return NULL; // common case of whole-array copy |
1045 Node* last = subseq_length; | |
1046 if (!zero_offset) // last += offset | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1047 last = _gvn.transform(new (C) AddINode(last, offset)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1048 Node* cmp_lt = _gvn.transform(new (C) CmpUNode(array_length, last)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1049 Node* bol_lt = _gvn.transform(new (C) BoolNode(cmp_lt, BoolTest::lt)); |
0 | 1050 Node* is_over = generate_guard(bol_lt, region, PROB_MIN); |
1051 return is_over; | |
1052 } | |
1053 | |
1054 | |
1055 //--------------------------generate_current_thread-------------------- | |
1056 Node* LibraryCallKit::generate_current_thread(Node* &tls_output) { | |
1057 ciKlass* thread_klass = env()->Thread_klass(); | |
1058 const Type* thread_type = TypeOopPtr::make_from_klass(thread_klass)->cast_to_ptr_type(TypePtr::NotNull); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1059 Node* thread = _gvn.transform(new (C) ThreadLocalNode()); |
0 | 1060 Node* p = basic_plus_adr(top()/*!oop*/, thread, in_bytes(JavaThread::threadObj_offset())); |
1061 Node* threadObj = make_load(NULL, p, thread_type, T_OBJECT); | |
1062 tls_output = thread; | |
1063 return threadObj; | |
1064 } | |
1065 | |
1066 | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1067 //------------------------------make_string_method_node------------------------ |
6057 | 1068 // Helper method for String intrinsic functions. This version is called |
1069 // with str1 and str2 pointing to String object nodes. | |
1070 // | |
1071 Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* str2) { | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1072 Node* no_ctrl = NULL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1073 |
6057 | 1074 // Get start addr of string |
1075 Node* str1_value = load_String_value(no_ctrl, str1); | |
1076 Node* str1_offset = load_String_offset(no_ctrl, str1); | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1077 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
|
1078 |
6057 | 1079 // Get length of string 1 |
1080 Node* str1_len = load_String_length(no_ctrl, str1); | |
1081 | |
1082 Node* str2_value = load_String_value(no_ctrl, str2); | |
1083 Node* str2_offset = load_String_offset(no_ctrl, str2); | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1084 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
|
1085 |
6057 | 1086 Node* str2_len = NULL; |
1087 Node* result = NULL; | |
1088 | |
1089 switch (opcode) { | |
1090 case Op_StrIndexOf: | |
1091 // Get length of string 2 | |
1092 str2_len = load_String_length(no_ctrl, str2); | |
1093 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1094 result = new (C) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS), |
6057 | 1095 str1_start, str1_len, str2_start, str2_len); |
1096 break; | |
1097 case Op_StrComp: | |
1098 // Get length of string 2 | |
1099 str2_len = load_String_length(no_ctrl, str2); | |
1100 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1101 result = new (C) StrCompNode(control(), memory(TypeAryPtr::CHARS), |
6057 | 1102 str1_start, str1_len, str2_start, str2_len); |
1103 break; | |
1104 case Op_StrEquals: | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1105 result = new (C) StrEqualsNode(control(), memory(TypeAryPtr::CHARS), |
6057 | 1106 str1_start, str2_start, str1_len); |
1107 break; | |
1108 default: | |
1109 ShouldNotReachHere(); | |
1110 return NULL; | |
1111 } | |
1112 | |
1113 // All these intrinsics have checks. | |
1114 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
1115 | |
1116 return _gvn.transform(result); | |
1117 } | |
1118 | |
1119 // Helper method for String intrinsic functions. This version is called | |
1120 // with str1 and str2 pointing to char[] nodes, with cnt1 and cnt2 pointing | |
1121 // to Int nodes containing the lenghts of str1 and str2. | |
1122 // | |
1123 Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2) { | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1124 Node* result = NULL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1125 switch (opcode) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1126 case Op_StrIndexOf: |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1127 result = new (C) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS), |
6057 | 1128 str1_start, cnt1, str2_start, cnt2); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1129 break; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1130 case Op_StrComp: |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1131 result = new (C) StrCompNode(control(), memory(TypeAryPtr::CHARS), |
6057 | 1132 str1_start, cnt1, str2_start, cnt2); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1133 break; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1134 case Op_StrEquals: |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1135 result = new (C) StrEqualsNode(control(), memory(TypeAryPtr::CHARS), |
6057 | 1136 str1_start, str2_start, cnt1); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1137 break; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1138 default: |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1139 ShouldNotReachHere(); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1140 return NULL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1141 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1142 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1143 // All these intrinsics have checks. |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1144 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
|
1145 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1146 return _gvn.transform(result); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1147 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1148 |
0 | 1149 //------------------------------inline_string_compareTo------------------------ |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1150 // public int java.lang.String.compareTo(String anotherString); |
0 | 1151 bool LibraryCallKit::inline_string_compareTo() { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1152 Node* receiver = null_check(argument(0)); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1153 Node* arg = null_check(argument(1)); |
0 | 1154 if (stopped()) { |
1155 return true; | |
1156 } | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1157 set_result(make_string_method_node(Op_StrComp, receiver, arg)); |
0 | 1158 return true; |
1159 } | |
1160 | |
681 | 1161 //------------------------------inline_string_equals------------------------ |
1162 bool LibraryCallKit::inline_string_equals() { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1163 Node* receiver = null_check_receiver(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1164 // NOTE: Do not null check argument for String.equals() because spec |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1165 // allows to specify NULL as argument. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1166 Node* argument = this->argument(1); |
681 | 1167 if (stopped()) { |
1168 return true; | |
1169 } | |
1170 | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1171 // paths (plus control) merge |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1172 RegionNode* region = new (C) RegionNode(5); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1173 Node* phi = new (C) PhiNode(region, TypeInt::BOOL); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1174 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1175 // does source == target string? |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1176 Node* cmp = _gvn.transform(new (C) CmpPNode(receiver, argument)); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1177 Node* bol = _gvn.transform(new (C) BoolNode(cmp, BoolTest::eq)); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1178 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1179 Node* if_eq = generate_slow_guard(bol, NULL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1180 if (if_eq != NULL) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1181 // receiver == argument |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1182 phi->init_req(2, intcon(1)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1183 region->init_req(2, if_eq); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1184 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1185 |
681 | 1186 // get String klass for instanceOf |
1187 ciInstanceKlass* klass = env()->String_klass(); | |
1188 | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1189 if (!stopped()) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1190 Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass))); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1191 Node* cmp = _gvn.transform(new (C) CmpINode(inst, intcon(1))); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1192 Node* bol = _gvn.transform(new (C) BoolNode(cmp, BoolTest::ne)); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1193 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1194 Node* inst_false = generate_guard(bol, NULL, PROB_MIN); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1195 //instanceOf == true, fallthrough |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1196 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1197 if (inst_false != NULL) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1198 phi->init_req(3, intcon(0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1199 region->init_req(3, inst_false); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1200 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1201 } |
681 | 1202 |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1203 if (!stopped()) { |
6057 | 1204 const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass); |
1205 | |
1496
e8e83be27dd7
6951190: assert(!klass_is_exact(),"only non-exact klass") while building JDK
never
parents:
1396
diff
changeset
|
1206 // Properly cast the argument to String |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1207 argument = _gvn.transform(new (C) CheckCastPPNode(control(), argument, string_type)); |
3337
e6d7eed3330c
7041100: The load in String.equals intrinsic executed before null check
kvn
parents:
3284
diff
changeset
|
1208 // 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
|
1209 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
|
1210 |
6057 | 1211 Node* no_ctrl = NULL; |
1212 | |
1213 // Get start addr of receiver | |
1214 Node* receiver_val = load_String_value(no_ctrl, receiver); | |
1215 Node* receiver_offset = load_String_offset(no_ctrl, receiver); | |
1216 Node* receiver_start = array_element_address(receiver_val, receiver_offset, T_CHAR); | |
1217 | |
1218 // Get length of receiver | |
1219 Node* receiver_cnt = load_String_length(no_ctrl, receiver); | |
1220 | |
1221 // Get start addr of argument | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1222 Node* argument_val = load_String_value(no_ctrl, argument); |
6057 | 1223 Node* argument_offset = load_String_offset(no_ctrl, argument); |
1224 Node* argument_start = array_element_address(argument_val, argument_offset, T_CHAR); | |
1225 | |
1226 // Get length of argument | |
1227 Node* argument_cnt = load_String_length(no_ctrl, argument); | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1228 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1229 // Check for receiver count != argument count |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1230 Node* cmp = _gvn.transform(new(C) CmpINode(receiver_cnt, argument_cnt)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1231 Node* bol = _gvn.transform(new(C) BoolNode(cmp, BoolTest::ne)); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1232 Node* if_ne = generate_slow_guard(bol, NULL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1233 if (if_ne != NULL) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1234 phi->init_req(4, intcon(0)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1235 region->init_req(4, if_ne); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1236 } |
6057 | 1237 |
1238 // Check for count == 0 is done by assembler code for StrEquals. | |
1239 | |
1240 if (!stopped()) { | |
1241 Node* equals = make_string_method_node(Op_StrEquals, receiver_start, receiver_cnt, argument_start, argument_cnt); | |
1242 phi->init_req(1, equals); | |
1243 region->init_req(1, control()); | |
1244 } | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1245 } |
681 | 1246 |
1247 // post merge | |
1248 set_control(_gvn.transform(region)); | |
1249 record_for_igvn(region); | |
1250 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1251 set_result(_gvn.transform(phi)); |
681 | 1252 return true; |
1253 } | |
1254 | |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1255 //------------------------------inline_array_equals---------------------------- |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1256 bool LibraryCallKit::inline_array_equals() { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1257 Node* arg1 = argument(0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1258 Node* arg2 = argument(1); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1259 set_result(_gvn.transform(new (C) AryEqNode(control(), memory(TypeAryPtr::CHARS), arg1, arg2))); |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1260 return true; |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1261 } |
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
1262 |
0 | 1263 // Java version of String.indexOf(constant string) |
1264 // class StringDecl { | |
1265 // StringDecl(char[] ca) { | |
1266 // offset = 0; | |
1267 // count = ca.length; | |
1268 // value = ca; | |
1269 // } | |
1270 // int offset; | |
1271 // int count; | |
1272 // char[] value; | |
1273 // } | |
1274 // | |
1275 // static int string_indexOf_J(StringDecl string_object, char[] target_object, | |
1276 // int targetOffset, int cache_i, int md2) { | |
1277 // int cache = cache_i; | |
1278 // int sourceOffset = string_object.offset; | |
1279 // int sourceCount = string_object.count; | |
1280 // int targetCount = target_object.length; | |
1281 // | |
1282 // int targetCountLess1 = targetCount - 1; | |
1283 // int sourceEnd = sourceOffset + sourceCount - targetCountLess1; | |
1284 // | |
1285 // char[] source = string_object.value; | |
1286 // char[] target = target_object; | |
1287 // int lastChar = target[targetCountLess1]; | |
1288 // | |
1289 // outer_loop: | |
1290 // for (int i = sourceOffset; i < sourceEnd; ) { | |
1291 // int src = source[i + targetCountLess1]; | |
1292 // if (src == lastChar) { | |
1293 // // With random strings and a 4-character alphabet, | |
1294 // // reverse matching at this point sets up 0.8% fewer | |
1295 // // frames, but (paradoxically) makes 0.3% more probes. | |
1296 // // Since those probes are nearer the lastChar probe, | |
1297 // // there is may be a net D$ win with reverse matching. | |
1298 // // But, reversing loop inhibits unroll of inner loop | |
1299 // // for unknown reason. So, does running outer loop from | |
1300 // // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount) | |
1301 // for (int j = 0; j < targetCountLess1; j++) { | |
1302 // if (target[targetOffset + j] != source[i+j]) { | |
1303 // if ((cache & (1 << source[i+j])) == 0) { | |
1304 // if (md2 < j+1) { | |
1305 // i += j+1; | |
1306 // continue outer_loop; | |
1307 // } | |
1308 // } | |
1309 // i += md2; | |
1310 // continue outer_loop; | |
1311 // } | |
1312 // } | |
1313 // return i - sourceOffset; | |
1314 // } | |
1315 // if ((cache & (1 << src)) == 0) { | |
1316 // i += targetCountLess1; | |
1317 // } // using "i += targetCount;" and an "else i++;" causes a jump to jump. | |
1318 // i++; | |
1319 // } | |
1320 // return -1; | |
1321 // } | |
1322 | |
1323 //------------------------------string_indexOf------------------------ | |
1324 Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_array, jint targetOffset_i, | |
1325 jint cache_i, jint md2_i) { | |
1326 | |
1327 Node* no_ctrl = NULL; | |
1328 float likely = PROB_LIKELY(0.9); | |
1329 float unlikely = PROB_UNLIKELY(0.9); | |
1330 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1331 const int nargs = 0; // no arguments to push back for uncommon trap in predicate |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2324
diff
changeset
|
1332 |
6057 | 1333 Node* source = load_String_value(no_ctrl, string_object); |
1334 Node* sourceOffset = load_String_offset(no_ctrl, string_object); | |
1335 Node* sourceCount = load_String_length(no_ctrl, string_object); | |
0 | 1336 |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1337 Node* target = _gvn.transform( makecon(TypeOopPtr::make_from_constant(target_array, true))); |
0 | 1338 jint target_length = target_array->length(); |
1339 const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin)); | |
1340 const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot); | |
1341 | |
12190
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
1342 // String.value field is known to be @Stable. |
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
1343 if (UseImplicitStableValues) { |
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
1344 target = cast_array_to_stable(target, target_type); |
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
1345 } |
edb5ab0f3fe5
8001107: @Stable annotation for constant folding of lazily evaluated variables
vlivanov
parents:
12169
diff
changeset
|
1346 |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
1347 IdealKit kit(this, false, true); |
0 | 1348 #define __ kit. |
1349 Node* zero = __ ConI(0); | |
1350 Node* one = __ ConI(1); | |
1351 Node* cache = __ ConI(cache_i); | |
1352 Node* md2 = __ ConI(md2_i); | |
1353 Node* lastChar = __ ConI(target_array->char_at(target_length - 1)); | |
1354 Node* targetCount = __ ConI(target_length); | |
1355 Node* targetCountLess1 = __ ConI(target_length - 1); | |
1356 Node* targetOffset = __ ConI(targetOffset_i); | |
1357 Node* sourceEnd = __ SubI(__ AddI(sourceOffset, sourceCount), targetCountLess1); | |
1358 | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
1359 IdealVariable rtn(kit), i(kit), j(kit); __ declarations_done(); |
0 | 1360 Node* outer_loop = __ make_label(2 /* goto */); |
1361 Node* return_ = __ make_label(1); | |
1362 | |
1363 __ set(rtn,__ ConI(-1)); | |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2324
diff
changeset
|
1364 __ loop(this, nargs, i, sourceOffset, BoolTest::lt, sourceEnd); { |
0 | 1365 Node* i2 = __ AddI(__ value(i), targetCountLess1); |
1366 // pin to prohibit loading of "next iteration" value which may SEGV (rare) | |
1367 Node* src = load_array_element(__ ctrl(), source, i2, TypeAryPtr::CHARS); | |
1368 __ if_then(src, BoolTest::eq, lastChar, unlikely); { | |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
2324
diff
changeset
|
1369 __ loop(this, nargs, j, zero, BoolTest::lt, targetCountLess1); { |
0 | 1370 Node* tpj = __ AddI(targetOffset, __ value(j)); |
1371 Node* targ = load_array_element(no_ctrl, target, tpj, target_type); | |
1372 Node* ipj = __ AddI(__ value(i), __ value(j)); | |
1373 Node* src2 = load_array_element(no_ctrl, source, ipj, TypeAryPtr::CHARS); | |
1374 __ if_then(targ, BoolTest::ne, src2); { | |
1375 __ if_then(__ AndI(cache, __ LShiftI(one, src2)), BoolTest::eq, zero); { | |
1376 __ if_then(md2, BoolTest::lt, __ AddI(__ value(j), one)); { | |
1377 __ increment(i, __ AddI(__ value(j), one)); | |
1378 __ goto_(outer_loop); | |
1379 } __ end_if(); __ dead(j); | |
1380 }__ end_if(); __ dead(j); | |
1381 __ increment(i, md2); | |
1382 __ goto_(outer_loop); | |
1383 }__ end_if(); | |
1384 __ increment(j, one); | |
1385 }__ end_loop(); __ dead(j); | |
1386 __ set(rtn, __ SubI(__ value(i), sourceOffset)); __ dead(i); | |
1387 __ goto_(return_); | |
1388 }__ end_if(); | |
1389 __ if_then(__ AndI(cache, __ LShiftI(one, src)), BoolTest::eq, zero, likely); { | |
1390 __ increment(i, targetCountLess1); | |
1391 }__ end_if(); | |
1392 __ increment(i, one); | |
1393 __ bind(outer_loop); | |
1394 }__ end_loop(); __ dead(i); | |
1395 __ bind(return_); | |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
1396 |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
1397 // Final sync IdealKit and GraphKit. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
1398 final_sync(kit); |
0 | 1399 Node* result = __ value(rtn); |
1400 #undef __ | |
1401 C->set_has_loops(true); | |
1402 return result; | |
1403 } | |
1404 | |
1405 //------------------------------inline_string_indexOf------------------------ | |
1406 bool LibraryCallKit::inline_string_indexOf() { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1407 Node* receiver = argument(0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1408 Node* arg = argument(1); |
681 | 1409 |
1410 Node* result; | |
1504
ae8f909e5fc7
6948602: Disable use of SSE4.2 in String.indexOf intrinsic until 6942326 is fixed
iveresov
parents:
1396
diff
changeset
|
1411 // 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
|
1412 // 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
|
1413 if (Matcher::has_match_rule(Op_StrIndexOf) && |
681 | 1414 UseSSE42Intrinsics) { |
1415 // Generate SSE4.2 version of indexOf | |
1416 // We currently only have match rules that use SSE4.2 | |
1417 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1418 receiver = null_check(receiver); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1419 arg = null_check(arg); |
681 | 1420 if (stopped()) { |
1421 return true; | |
1422 } | |
1423 | |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1424 ciInstanceKlass* str_klass = env()->String_klass(); |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1425 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
|
1426 |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1427 // Make the merge point |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1428 RegionNode* result_rgn = new (C) RegionNode(4); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1429 Node* result_phi = new (C) PhiNode(result_rgn, TypeInt::INT); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1430 Node* no_ctrl = NULL; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1431 |
6057 | 1432 // Get start addr of source string |
1433 Node* source = load_String_value(no_ctrl, receiver); | |
1434 Node* source_offset = load_String_offset(no_ctrl, receiver); | |
1435 Node* source_start = array_element_address(source, source_offset, T_CHAR); | |
1436 | |
1437 // Get length of source string | |
1438 Node* source_cnt = load_String_length(no_ctrl, receiver); | |
1439 | |
1440 // Get start addr of substring | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1441 Node* substr = load_String_value(no_ctrl, arg); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1442 Node* substr_offset = load_String_offset(no_ctrl, arg); |
6057 | 1443 Node* substr_start = array_element_address(substr, substr_offset, T_CHAR); |
1444 | |
1445 // Get length of source string | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1446 Node* substr_cnt = load_String_length(no_ctrl, arg); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1447 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1448 // Check for substr count > string count |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1449 Node* cmp = _gvn.transform(new(C) CmpINode(substr_cnt, source_cnt)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1450 Node* bol = _gvn.transform(new(C) BoolNode(cmp, BoolTest::gt)); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1451 Node* if_gt = generate_slow_guard(bol, NULL); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1452 if (if_gt != NULL) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1453 result_phi->init_req(2, intcon(-1)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1454 result_rgn->init_req(2, if_gt); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1455 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1456 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1457 if (!stopped()) { |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1458 // Check for substr count == 0 |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1459 cmp = _gvn.transform(new(C) CmpINode(substr_cnt, intcon(0))); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1460 bol = _gvn.transform(new(C) BoolNode(cmp, BoolTest::eq)); |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1461 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
|
1462 if (if_zero != NULL) { |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1463 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
|
1464 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
|
1465 } |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1466 } |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1467 |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1468 if (!stopped()) { |
6057 | 1469 result = make_string_method_node(Op_StrIndexOf, source_start, source_cnt, substr_start, substr_cnt); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1470 result_phi->init_req(1, result); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1471 result_rgn->init_req(1, control()); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1472 } |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1473 set_control(_gvn.transform(result_rgn)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1474 record_for_igvn(result_rgn); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1475 result = _gvn.transform(result_phi); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
958
diff
changeset
|
1476 |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1477 } else { // Use LibraryCallKit::string_indexOf |
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1478 // don't intrinsify if argument isn't a constant string. |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1479 if (!arg->is_Con()) { |
681 | 1480 return false; |
1481 } | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1482 const TypeOopPtr* str_type = _gvn.type(arg)->isa_oopptr(); |
681 | 1483 if (str_type == NULL) { |
1484 return false; | |
1485 } | |
1486 ciInstanceKlass* klass = env()->String_klass(); | |
1487 ciObject* str_const = str_type->const_oop(); | |
1488 if (str_const == NULL || str_const->klass() != klass) { | |
1489 return false; | |
1490 } | |
1491 ciInstance* str = str_const->as_instance(); | |
1492 assert(str != NULL, "must be instance"); | |
1493 | |
6057 | 1494 ciObject* v = str->field_value_by_offset(java_lang_String::value_offset_in_bytes()).as_object(); |
681 | 1495 ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array |
1496 | |
6057 | 1497 int o; |
1498 int c; | |
1499 if (java_lang_String::has_offset_field()) { | |
1500 o = str->field_value_by_offset(java_lang_String::offset_offset_in_bytes()).as_int(); | |
1501 c = str->field_value_by_offset(java_lang_String::count_offset_in_bytes()).as_int(); | |
1502 } else { | |
1503 o = 0; | |
1504 c = pat->length(); | |
1505 } | |
1506 | |
681 | 1507 // constant strings have no offset and count == length which |
1508 // simplifies the resulting code somewhat so lets optimize for that. | |
1509 if (o != 0 || c != pat->length()) { | |
1510 return false; | |
1511 } | |
1512 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1513 receiver = null_check(receiver, T_OBJECT); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1514 // NOTE: No null check on the argument is needed since it's a constant String oop. |
681 | 1515 if (stopped()) { |
2320
41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
kvn
parents:
1972
diff
changeset
|
1516 return true; |
681 | 1517 } |
1518 | |
1519 // The null string as a pattern always returns 0 (match at beginning of string) | |
1520 if (c == 0) { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1521 set_result(intcon(0)); |
681 | 1522 return true; |
1523 } | |
1524 | |
1525 // Generate default indexOf | |
1526 jchar lastChar = pat->char_at(o + (c - 1)); | |
1527 int cache = 0; | |
1528 int i; | |
1529 for (i = 0; i < c - 1; i++) { | |
1530 assert(i < pat->length(), "out of range"); | |
1531 cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1))); | |
1532 } | |
1533 | |
1534 int md2 = c; | |
1535 for (i = 0; i < c - 1; i++) { | |
1536 assert(i < pat->length(), "out of range"); | |
1537 if (pat->char_at(o + i) == lastChar) { | |
1538 md2 = (c - 1) - i; | |
1539 } | |
1540 } | |
1541 | |
1542 result = string_indexOf(receiver, pat, o, cache, md2); | |
0 | 1543 } |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1544 set_result(result); |
0 | 1545 return true; |
1546 } | |
1547 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1548 //--------------------------round_double_node-------------------------------- |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1549 // Round a double node if necessary. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1550 Node* LibraryCallKit::round_double_node(Node* n) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1551 if (Matcher::strict_fp_requires_explicit_rounding && UseSSE <= 1) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1552 n = _gvn.transform(new (C) RoundDoubleNode(0, n)); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1553 return n; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1554 } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1555 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1556 //------------------------------inline_math----------------------------------- |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1557 // public static double Math.abs(double) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1558 // public static double Math.sqrt(double) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1559 // public static double Math.log(double) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1560 // public static double Math.log10(double) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1561 bool LibraryCallKit::inline_math(vmIntrinsics::ID id) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1562 Node* arg = round_double_node(argument(0)); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1563 Node* n; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1564 switch (id) { |
8076
c59b7900a2bd
8007959: Use expensive node logic for more math nodes
roland
parents:
8048
diff
changeset
|
1565 case vmIntrinsics::_dabs: n = new (C) AbsDNode( arg); break; |
c59b7900a2bd
8007959: Use expensive node logic for more math nodes
roland
parents:
8048
diff
changeset
|
1566 case vmIntrinsics::_dsqrt: n = new (C) SqrtDNode(C, control(), arg); break; |
c59b7900a2bd
8007959: Use expensive node logic for more math nodes
roland
parents:
8048
diff
changeset
|
1567 case vmIntrinsics::_dlog: n = new (C) LogDNode(C, control(), arg); break; |
c59b7900a2bd
8007959: Use expensive node logic for more math nodes
roland
parents:
8048
diff
changeset
|
1568 case vmIntrinsics::_dlog10: n = new (C) Log10DNode(C, control(), arg); break; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1569 default: fatal_unexpected_iid(id); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1570 } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1571 set_result(_gvn.transform(n)); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1572 return true; |
0 | 1573 } |
1574 | |
1575 //------------------------------inline_trig---------------------------------- | |
1576 // Inline sin/cos/tan instructions, if possible. If rounding is required, do | |
1577 // argument reduction which will turn into a fast/slow diamond. | |
1578 bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1579 Node* arg = round_double_node(argument(0)); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1580 Node* n = NULL; |
0 | 1581 |
1582 switch (id) { | |
8076
c59b7900a2bd
8007959: Use expensive node logic for more math nodes
roland
parents:
8048
diff
changeset
|
1583 case vmIntrinsics::_dsin: n = new (C) SinDNode(C, control(), arg); break; |
c59b7900a2bd
8007959: Use expensive node logic for more math nodes
roland
parents:
8048
diff
changeset
|
1584 case vmIntrinsics::_dcos: n = new (C) CosDNode(C, control(), arg); break; |
c59b7900a2bd
8007959: Use expensive node logic for more math nodes
roland
parents:
8048
diff
changeset
|
1585 case vmIntrinsics::_dtan: n = new (C) TanDNode(C, control(), arg); break; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1586 default: fatal_unexpected_iid(id); break; |
0 | 1587 } |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1588 n = _gvn.transform(n); |
0 | 1589 |
1590 // Rounding required? Check for argument reduction! | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1591 if (Matcher::strict_fp_requires_explicit_rounding) { |
0 | 1592 static const double pi_4 = 0.7853981633974483; |
1593 static const double neg_pi_4 = -0.7853981633974483; | |
1594 // pi/2 in 80-bit extended precision | |
1595 // static const unsigned char pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00}; | |
1596 // -pi/2 in 80-bit extended precision | |
1597 // 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}; | |
1598 // Cutoff value for using this argument reduction technique | |
1599 //static const double pi_2_minus_epsilon = 1.564660403643354; | |
1600 //static const double neg_pi_2_plus_epsilon = -1.564660403643354; | |
1601 | |
1602 // Pseudocode for sin: | |
1603 // if (x <= Math.PI / 4.0) { | |
1604 // if (x >= -Math.PI / 4.0) return fsin(x); | |
1605 // if (x >= -Math.PI / 2.0) return -fcos(x + Math.PI / 2.0); | |
1606 // } else { | |
1607 // if (x <= Math.PI / 2.0) return fcos(x - Math.PI / 2.0); | |
1608 // } | |
1609 // return StrictMath.sin(x); | |
1610 | |
1611 // Pseudocode for cos: | |
1612 // if (x <= Math.PI / 4.0) { | |
1613 // if (x >= -Math.PI / 4.0) return fcos(x); | |
1614 // if (x >= -Math.PI / 2.0) return fsin(x + Math.PI / 2.0); | |
1615 // } else { | |
1616 // if (x <= Math.PI / 2.0) return -fsin(x - Math.PI / 2.0); | |
1617 // } | |
1618 // return StrictMath.cos(x); | |
1619 | |
1620 // Actually, sticking in an 80-bit Intel value into C2 will be tough; it | |
1621 // requires a special machine instruction to load it. Instead we'll try | |
1622 // the 'easy' case. If we really need the extra range +/- PI/2 we'll | |
1623 // probably do the math inside the SIN encoding. | |
1624 | |
1625 // Make the merge point | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1626 RegionNode* r = new (C) RegionNode(3); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1627 Node* phi = new (C) PhiNode(r, Type::DOUBLE); |
0 | 1628 |
1629 // Flatten arg so we need only 1 test | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1630 Node *abs = _gvn.transform(new (C) AbsDNode(arg)); |
0 | 1631 // Node for PI/4 constant |
1632 Node *pi4 = makecon(TypeD::make(pi_4)); | |
1633 // Check PI/4 : abs(arg) | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1634 Node *cmp = _gvn.transform(new (C) CmpDNode(pi4,abs)); |
0 | 1635 // Check: If PI/4 < abs(arg) then go slow |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1636 Node *bol = _gvn.transform(new (C) BoolNode( cmp, BoolTest::lt )); |
0 | 1637 // Branch either way |
1638 IfNode *iff = create_and_xform_if(control(),bol, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); | |
1639 set_control(opt_iff(r,iff)); | |
1640 | |
1641 // Set fast path result | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1642 phi->init_req(2, n); |
0 | 1643 |
1644 // Slow path - non-blocking leaf call | |
1645 Node* call = NULL; | |
1646 switch (id) { | |
1647 case vmIntrinsics::_dsin: | |
1648 call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(), | |
1649 CAST_FROM_FN_PTR(address, SharedRuntime::dsin), | |
1650 "Sin", NULL, arg, top()); | |
1651 break; | |
1652 case vmIntrinsics::_dcos: | |
1653 call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(), | |
1654 CAST_FROM_FN_PTR(address, SharedRuntime::dcos), | |
1655 "Cos", NULL, arg, top()); | |
1656 break; | |
1657 case vmIntrinsics::_dtan: | |
1658 call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(), | |
1659 CAST_FROM_FN_PTR(address, SharedRuntime::dtan), | |
1660 "Tan", NULL, arg, top()); | |
1661 break; | |
1662 } | |
1663 assert(control()->in(0) == call, ""); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1664 Node* slow_result = _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms)); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1665 r->init_req(1, control()); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1666 phi->init_req(1, slow_result); |
0 | 1667 |
1668 // Post-merge | |
1669 set_control(_gvn.transform(r)); | |
1670 record_for_igvn(r); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1671 n = _gvn.transform(phi); |
0 | 1672 |
1673 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
1674 } | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1675 set_result(n); |
0 | 1676 return true; |
1677 } | |
1678 | |
6205 | 1679 void LibraryCallKit::finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName) { |
1680 //------------------- | |
1681 //result=(result.isNaN())? funcAddr():result; | |
1682 // Check: If isNaN() by checking result!=result? then either trap | |
1683 // or go to runtime | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1684 Node* cmpisnan = _gvn.transform(new (C) CmpDNode(result, result)); |
6205 | 1685 // Build the boolean node |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1686 Node* bolisnum = _gvn.transform(new (C) BoolNode(cmpisnan, BoolTest::eq)); |
6205 | 1687 |
1688 if (!too_many_traps(Deoptimization::Reason_intrinsic)) { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1689 { BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT); |
6205 | 1690 // The pow or exp intrinsic returned a NaN, which requires a call |
1691 // to the runtime. Recompile with the runtime call. | |
1692 uncommon_trap(Deoptimization::Reason_intrinsic, | |
1693 Deoptimization::Action_make_not_entrant); | |
1694 } | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1695 set_result(result); |
6205 | 1696 } else { |
1697 // If this inlining ever returned NaN in the past, we compile a call | |
1698 // to the runtime to properly handle corner cases | |
1699 | |
1700 IfNode* iff = create_and_xform_if(control(), bolisnum, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1701 Node* if_slow = _gvn.transform(new (C) IfFalseNode(iff)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1702 Node* if_fast = _gvn.transform(new (C) IfTrueNode(iff)); |
6205 | 1703 |
1704 if (!if_slow->is_top()) { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1705 RegionNode* result_region = new (C) RegionNode(3); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1706 PhiNode* result_val = new (C) PhiNode(result_region, Type::DOUBLE); |
6205 | 1707 |
1708 result_region->init_req(1, if_fast); | |
1709 result_val->init_req(1, result); | |
1710 | |
1711 set_control(if_slow); | |
1712 | |
1713 const TypePtr* no_memory_effects = NULL; | |
1714 Node* rt = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName, | |
1715 no_memory_effects, | |
1716 x, top(), y, y ? top() : NULL); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1717 Node* value = _gvn.transform(new (C) ProjNode(rt, TypeFunc::Parms+0)); |
6205 | 1718 #ifdef ASSERT |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1719 Node* value_top = _gvn.transform(new (C) ProjNode(rt, TypeFunc::Parms+1)); |
6205 | 1720 assert(value_top == top(), "second value must be top"); |
1721 #endif | |
1722 | |
1723 result_region->init_req(2, control()); | |
1724 result_val->init_req(2, value); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1725 set_result(result_region, result_val); |
6205 | 1726 } else { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1727 set_result(result); |
6205 | 1728 } |
1729 } | |
1730 } | |
1731 | |
0 | 1732 //------------------------------inline_exp------------------------------------- |
1733 // Inline exp instructions, if possible. The Intel hardware only misses | |
1734 // really odd corner cases (+/- Infinity). Just uncommon-trap them. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1735 bool LibraryCallKit::inline_exp() { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1736 Node* arg = round_double_node(argument(0)); |
8048
8b3da8d14c93
7197327: 40% regression on 8 b41 comp 8 b40 on specjvm2008.mpegaudio on oob
roland
parents:
7637
diff
changeset
|
1737 Node* n = _gvn.transform(new (C) ExpDNode(C, control(), arg)); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1738 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1739 finish_pow_exp(n, arg, NULL, OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP"); |
0 | 1740 |
1741 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
1742 return true; | |
1743 } | |
1744 | |
1745 //------------------------------inline_pow------------------------------------- | |
1746 // Inline power instructions, if possible. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1747 bool LibraryCallKit::inline_pow() { |
0 | 1748 // Pseudocode for pow |
1749 // if (x <= 0.0) { | |
6205 | 1750 // long longy = (long)y; |
1751 // if ((double)longy == y) { // if y is long | |
1752 // if (y + 1 == y) longy = 0; // huge number: even | |
1753 // result = ((1&longy) == 0)?-DPow(abs(x), y):DPow(abs(x), y); | |
0 | 1754 // } else { |
1755 // result = NaN; | |
1756 // } | |
1757 // } else { | |
1758 // result = DPow(x,y); | |
1759 // } | |
1760 // if (result != result)? { | |
6205 | 1761 // result = uncommon_trap() or runtime_call(); |
0 | 1762 // } |
1763 // return result; | |
1764 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1765 Node* x = round_double_node(argument(0)); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1766 Node* y = round_double_node(argument(2)); |
0 | 1767 |
6205 | 1768 Node* result = NULL; |
1769 | |
1770 if (!too_many_traps(Deoptimization::Reason_intrinsic)) { | |
1771 // Short form: skip the fancy tests and just check for NaN result. | |
8048
8b3da8d14c93
7197327: 40% regression on 8 b41 comp 8 b40 on specjvm2008.mpegaudio on oob
roland
parents:
7637
diff
changeset
|
1772 result = _gvn.transform(new (C) PowDNode(C, control(), x, y)); |
0 | 1773 } else { |
6205 | 1774 // If this inlining ever returned NaN in the past, include all |
1775 // checks + call to the runtime. | |
0 | 1776 |
1777 // Set the merge point for If node with condition of (x <= 0.0) | |
1778 // There are four possible paths to region node and phi node | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1779 RegionNode *r = new (C) RegionNode(4); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1780 Node *phi = new (C) PhiNode(r, Type::DOUBLE); |
0 | 1781 |
1782 // Build the first if node: if (x <= 0.0) | |
1783 // Node for 0 constant | |
1784 Node *zeronode = makecon(TypeD::ZERO); | |
1785 // Check x:0 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1786 Node *cmp = _gvn.transform(new (C) CmpDNode(x, zeronode)); |
0 | 1787 // Check: If (x<=0) then go complex path |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1788 Node *bol1 = _gvn.transform(new (C) BoolNode( cmp, BoolTest::le )); |
0 | 1789 // Branch either way |
1790 IfNode *if1 = create_and_xform_if(control(),bol1, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN); | |
1791 // Fast path taken; set region slot 3 | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1792 Node *fast_taken = _gvn.transform(new (C) IfFalseNode(if1)); |
0 | 1793 r->init_req(3,fast_taken); // Capture fast-control |
1794 | |
1795 // Fast path not-taken, i.e. slow path | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1796 Node *complex_path = _gvn.transform(new (C) IfTrueNode(if1)); |
0 | 1797 |
1798 // Set fast path result | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1799 Node *fast_result = _gvn.transform(new (C) PowDNode(C, control(), x, y)); |
0 | 1800 phi->init_req(3, fast_result); |
1801 | |
1802 // Complex path | |
6205 | 1803 // Build the second if node (if y is long) |
1804 // Node for (long)y | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1805 Node *longy = _gvn.transform(new (C) ConvD2LNode(y)); |
6205 | 1806 // Node for (double)((long) y) |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1807 Node *doublelongy= _gvn.transform(new (C) ConvL2DNode(longy)); |
6205 | 1808 // Check (double)((long) y) : y |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1809 Node *cmplongy= _gvn.transform(new (C) CmpDNode(doublelongy, y)); |
6205 | 1810 // Check if (y isn't long) then go to slow path |
1811 | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1812 Node *bol2 = _gvn.transform(new (C) BoolNode( cmplongy, BoolTest::ne )); |
605 | 1813 // Branch either way |
0 | 1814 IfNode *if2 = create_and_xform_if(complex_path,bol2, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN); |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1815 Node* ylong_path = _gvn.transform(new (C) IfFalseNode(if2)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1816 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1817 Node *slow_path = _gvn.transform(new (C) IfTrueNode(if2)); |
6205 | 1818 |
1819 // Calculate DPow(abs(x), y)*(1 & (long)y) | |
0 | 1820 // Node for constant 1 |
6205 | 1821 Node *conone = longcon(1); |
1822 // 1& (long)y | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1823 Node *signnode= _gvn.transform(new (C) AndLNode(conone, longy)); |
6205 | 1824 |
1825 // A huge number is always even. Detect a huge number by checking | |
1826 // if y + 1 == y and set integer to be tested for parity to 0. | |
1827 // Required for corner case: | |
1828 // (long)9.223372036854776E18 = max_jlong | |
1829 // (double)(long)9.223372036854776E18 = 9.223372036854776E18 | |
1830 // max_jlong is odd but 9.223372036854776E18 is even | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1831 Node* yplus1 = _gvn.transform(new (C) AddDNode(y, makecon(TypeD::make(1)))); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1832 Node *cmpyplus1= _gvn.transform(new (C) CmpDNode(yplus1, y)); |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1833 Node *bolyplus1 = _gvn.transform(new (C) BoolNode( cmpyplus1, BoolTest::eq )); |
6205 | 1834 Node* correctedsign = NULL; |
1835 if (ConditionalMoveLimit != 0) { | |
1836 correctedsign = _gvn.transform( CMoveNode::make(C, NULL, bolyplus1, signnode, longcon(0), TypeLong::LONG)); | |
1837 } else { | |
1838 IfNode *ifyplus1 = create_and_xform_if(ylong_path,bolyplus1, PROB_FAIR, COUNT_UNKNOWN); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1839 RegionNode *r = new (C) RegionNode(3); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1840 Node *phi = new (C) PhiNode(r, TypeLong::LONG); |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1841 r->init_req(1, _gvn.transform(new (C) IfFalseNode(ifyplus1))); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1842 r->init_req(2, _gvn.transform(new (C) IfTrueNode(ifyplus1))); |
6205 | 1843 phi->init_req(1, signnode); |
1844 phi->init_req(2, longcon(0)); | |
1845 correctedsign = _gvn.transform(phi); | |
1846 ylong_path = _gvn.transform(r); | |
1847 record_for_igvn(r); | |
1848 } | |
1849 | |
0 | 1850 // zero node |
6205 | 1851 Node *conzero = longcon(0); |
1852 // Check (1&(long)y)==0? | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1853 Node *cmpeq1 = _gvn.transform(new (C) CmpLNode(correctedsign, conzero)); |
6205 | 1854 // Check if (1&(long)y)!=0?, if so the result is negative |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1855 Node *bol3 = _gvn.transform(new (C) BoolNode( cmpeq1, BoolTest::ne )); |
0 | 1856 // abs(x) |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1857 Node *absx=_gvn.transform(new (C) AbsDNode(x)); |
0 | 1858 // abs(x)^y |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1859 Node *absxpowy = _gvn.transform(new (C) PowDNode(C, control(), absx, y)); |
0 | 1860 // -abs(x)^y |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1861 Node *negabsxpowy = _gvn.transform(new (C) NegDNode (absxpowy)); |
6205 | 1862 // (1&(long)y)==1?-DPow(abs(x), y):DPow(abs(x), y) |
1863 Node *signresult = NULL; | |
1864 if (ConditionalMoveLimit != 0) { | |
1865 signresult = _gvn.transform( CMoveNode::make(C, NULL, bol3, absxpowy, negabsxpowy, Type::DOUBLE)); | |
1866 } else { | |
1867 IfNode *ifyeven = create_and_xform_if(ylong_path,bol3, PROB_FAIR, COUNT_UNKNOWN); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1868 RegionNode *r = new (C) RegionNode(3); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1869 Node *phi = new (C) PhiNode(r, Type::DOUBLE); |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1870 r->init_req(1, _gvn.transform(new (C) IfFalseNode(ifyeven))); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
1871 r->init_req(2, _gvn.transform(new (C) IfTrueNode(ifyeven))); |
6205 | 1872 phi->init_req(1, absxpowy); |
1873 phi->init_req(2, negabsxpowy); | |
1874 signresult = _gvn.transform(phi); | |
1875 ylong_path = _gvn.transform(r); | |
1876 record_for_igvn(r); | |
1877 } | |
0 | 1878 // Set complex path fast result |
6205 | 1879 r->init_req(2, ylong_path); |
0 | 1880 phi->init_req(2, signresult); |
1881 | |
1882 static const jlong nan_bits = CONST64(0x7ff8000000000000); | |
1883 Node *slow_result = makecon(TypeD::make(*(double*)&nan_bits)); // return NaN | |
1884 r->init_req(1,slow_path); | |
1885 phi->init_req(1,slow_result); | |
1886 | |
1887 // Post merge | |
1888 set_control(_gvn.transform(r)); | |
1889 record_for_igvn(r); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1890 result = _gvn.transform(phi); |
0 | 1891 } |
1892 | |
6205 | 1893 finish_pow_exp(result, x, y, OptoRuntime::Math_DD_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dpow), "POW"); |
0 | 1894 |
1895 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
1896 return true; | |
1897 } | |
1898 | |
1899 //------------------------------runtime_math----------------------------- | |
1900 bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName) { | |
1901 assert(call_type == OptoRuntime::Math_DD_D_Type() || call_type == OptoRuntime::Math_D_D_Type(), | |
1902 "must be (DD)D or (D)D type"); | |
1903 | |
1904 // Inputs | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1905 Node* a = round_double_node(argument(0)); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1906 Node* b = (call_type == OptoRuntime::Math_DD_D_Type()) ? round_double_node(argument(2)) : NULL; |
0 | 1907 |
1908 const TypePtr* no_memory_effects = NULL; | |
1909 Node* trig = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName, | |
1910 no_memory_effects, | |
1911 a, top(), b, b ? top() : NULL); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1912 Node* value = _gvn.transform(new (C) ProjNode(trig, TypeFunc::Parms+0)); |
0 | 1913 #ifdef ASSERT |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
1914 Node* value_top = _gvn.transform(new (C) ProjNode(trig, TypeFunc::Parms+1)); |
0 | 1915 assert(value_top == top(), "second value must be top"); |
1916 #endif | |
1917 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1918 set_result(value); |
0 | 1919 return true; |
1920 } | |
1921 | |
1922 //------------------------------inline_math_native----------------------------- | |
1923 bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1924 #define FN_PTR(f) CAST_FROM_FN_PTR(address, f) |
0 | 1925 switch (id) { |
1926 // These intrinsics are not properly supported on all hardware | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1927 case vmIntrinsics::_dcos: return Matcher::has_match_rule(Op_CosD) ? inline_trig(id) : |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1928 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dcos), "COS"); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1929 case vmIntrinsics::_dsin: return Matcher::has_match_rule(Op_SinD) ? inline_trig(id) : |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1930 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dsin), "SIN"); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1931 case vmIntrinsics::_dtan: return Matcher::has_match_rule(Op_TanD) ? inline_trig(id) : |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1932 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dtan), "TAN"); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1933 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1934 case vmIntrinsics::_dlog: return Matcher::has_match_rule(Op_LogD) ? inline_math(id) : |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1935 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog), "LOG"); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1936 case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_math(id) : |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1937 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10"); |
0 | 1938 |
1939 // These intrinsics are supported on all hardware | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1940 case vmIntrinsics::_dsqrt: return Matcher::has_match_rule(Op_SqrtD) ? inline_math(id) : false; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1941 case vmIntrinsics::_dabs: return Matcher::has_match_rule(Op_AbsD) ? inline_math(id) : false; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1942 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1943 case vmIntrinsics::_dexp: return Matcher::has_match_rule(Op_ExpD) ? inline_exp() : |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1944 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dexp), "EXP"); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1945 case vmIntrinsics::_dpow: return Matcher::has_match_rule(Op_PowD) ? inline_pow() : |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1946 runtime_math(OptoRuntime::Math_DD_D_Type(), FN_PTR(SharedRuntime::dpow), "POW"); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1947 #undef FN_PTR |
0 | 1948 |
1949 // These intrinsics are not yet correctly implemented | |
1950 case vmIntrinsics::_datan2: | |
1951 return false; | |
1952 | |
1953 default: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1954 fatal_unexpected_iid(id); |
0 | 1955 return false; |
1956 } | |
1957 } | |
1958 | |
1959 static bool is_simple_name(Node* n) { | |
1960 return (n->req() == 1 // constant | |
1961 || (n->is_Type() && n->as_Type()->type()->singleton()) | |
1962 || n->is_Proj() // parameter or return value | |
1963 || n->is_Phi() // local of some sort | |
1964 ); | |
1965 } | |
1966 | |
1967 //----------------------------inline_min_max----------------------------------- | |
1968 bool LibraryCallKit::inline_min_max(vmIntrinsics::ID id) { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
1969 set_result(generate_min_max(id, argument(0), argument(1))); |
0 | 1970 return true; |
1971 } | |
1972 | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
1973 void LibraryCallKit::inline_math_mathExact(Node* math) { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
1974 // If we didn't get the expected opcode it means we have optimized |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
1975 // the node to something else and don't need the exception edge. |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
1976 if (!math->is_MathExact()) { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
1977 set_result(math); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
1978 return; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
1979 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
1980 |
12323 | 1981 Node* result = _gvn.transform( new(C) ProjNode(math, MathExactNode::result_proj_node)); |
1982 Node* flags = _gvn.transform( new(C) FlagsProjNode(math, MathExactNode::flags_proj_node)); | |
1983 | |
1984 Node* bol = _gvn.transform( new (C) BoolNode(flags, BoolTest::overflow) ); | |
1985 IfNode* check = create_and_map_if(control(), bol, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN); | |
1986 Node* fast_path = _gvn.transform( new (C) IfFalseNode(check)); | |
1987 Node* slow_path = _gvn.transform( new (C) IfTrueNode(check) ); | |
1988 | |
1989 { | |
1990 PreserveJVMState pjvms(this); | |
1991 PreserveReexecuteState preexecs(this); | |
1992 jvms()->set_should_reexecute(true); | |
1993 | |
1994 set_control(slow_path); | |
1995 set_i_o(i_o()); | |
1996 | |
1997 uncommon_trap(Deoptimization::Reason_intrinsic, | |
1998 Deoptimization::Action_none); | |
1999 } | |
2000 | |
2001 set_control(fast_path); | |
2002 set_result(result); | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2003 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2004 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2005 bool LibraryCallKit::inline_math_addExactI(bool is_increment) { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2006 Node* arg1 = argument(0); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2007 Node* arg2 = NULL; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2008 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2009 if (is_increment) { |
13019
a57a165b8296
8027353: Exact intrinsics: assert(n != NULL) failed: must not be null
rbackman
parents:
12972
diff
changeset
|
2010 arg2 = intcon(1); |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2011 } else { |
13019
a57a165b8296
8027353: Exact intrinsics: assert(n != NULL) failed: must not be null
rbackman
parents:
12972
diff
changeset
|
2012 arg2 = argument(1); |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2013 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2014 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2015 Node* add = _gvn.transform( new(C) AddExactINode(NULL, arg1, arg2) ); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2016 inline_math_mathExact(add); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2017 return true; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2018 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2019 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2020 bool LibraryCallKit::inline_math_addExactL(bool is_increment) { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2021 Node* arg1 = argument(0); // type long |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2022 // argument(1) == TOP |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2023 Node* arg2 = NULL; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2024 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2025 if (is_increment) { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2026 arg2 = longcon(1); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2027 } else { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2028 arg2 = argument(2); // type long |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2029 // argument(3) == TOP |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2030 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2031 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2032 Node* add = _gvn.transform(new(C) AddExactLNode(NULL, arg1, arg2)); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2033 inline_math_mathExact(add); |
12323 | 2034 return true; |
2035 } | |
2036 | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2037 bool LibraryCallKit::inline_math_subtractExactI(bool is_decrement) { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2038 Node* arg1 = argument(0); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2039 Node* arg2 = NULL; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2040 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2041 if (is_decrement) { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2042 arg2 = intcon(1); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2043 } else { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2044 arg2 = argument(1); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2045 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2046 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2047 Node* sub = _gvn.transform(new(C) SubExactINode(NULL, arg1, arg2)); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2048 inline_math_mathExact(sub); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2049 return true; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2050 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2051 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2052 bool LibraryCallKit::inline_math_subtractExactL(bool is_decrement) { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2053 Node* arg1 = argument(0); // type long |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2054 // argument(1) == TOP |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2055 Node* arg2 = NULL; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2056 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2057 if (is_decrement) { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2058 arg2 = longcon(1); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2059 } else { |
13019
a57a165b8296
8027353: Exact intrinsics: assert(n != NULL) failed: must not be null
rbackman
parents:
12972
diff
changeset
|
2060 arg2 = argument(2); // type long |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2061 // argument(3) == TOP |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2062 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2063 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2064 Node* sub = _gvn.transform(new(C) SubExactLNode(NULL, arg1, arg2)); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2065 inline_math_mathExact(sub); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2066 return true; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2067 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2068 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2069 bool LibraryCallKit::inline_math_negateExactI() { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2070 Node* arg1 = argument(0); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2071 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2072 Node* neg = _gvn.transform(new(C) NegExactINode(NULL, arg1)); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2073 inline_math_mathExact(neg); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2074 return true; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2075 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2076 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2077 bool LibraryCallKit::inline_math_negateExactL() { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2078 Node* arg1 = argument(0); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2079 // argument(1) == TOP |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2080 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2081 Node* neg = _gvn.transform(new(C) NegExactLNode(NULL, arg1)); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2082 inline_math_mathExact(neg); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2083 return true; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2084 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2085 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2086 bool LibraryCallKit::inline_math_multiplyExactI() { |
12323 | 2087 Node* arg1 = argument(0); |
2088 Node* arg2 = argument(1); | |
2089 | |
12972
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2090 Node* mul = _gvn.transform(new(C) MulExactINode(NULL, arg1, arg2)); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2091 inline_math_mathExact(mul); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2092 return true; |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2093 } |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2094 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2095 bool LibraryCallKit::inline_math_multiplyExactL() { |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2096 Node* arg1 = argument(0); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2097 // argument(1) == TOP |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2098 Node* arg2 = argument(2); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2099 // argument(3) == TOP |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2100 |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2101 Node* mul = _gvn.transform(new(C) MulExactLNode(NULL, arg1, arg2)); |
59e8ad757e19
8026844: Various Math functions needs intrinsification
rbackman
parents:
12966
diff
changeset
|
2102 inline_math_mathExact(mul); |
12323 | 2103 return true; |
2104 } | |
2105 | |
0 | 2106 Node* |
2107 LibraryCallKit::generate_min_max(vmIntrinsics::ID id, Node* x0, Node* y0) { | |
2108 // These are the candidate return value: | |
2109 Node* xvalue = x0; | |
2110 Node* yvalue = y0; | |
2111 | |
2112 if (xvalue == yvalue) { | |
2113 return xvalue; | |
2114 } | |
2115 | |
2116 bool want_max = (id == vmIntrinsics::_max); | |
2117 | |
2118 const TypeInt* txvalue = _gvn.type(xvalue)->isa_int(); | |
2119 const TypeInt* tyvalue = _gvn.type(yvalue)->isa_int(); | |
2120 if (txvalue == NULL || tyvalue == NULL) return top(); | |
2121 // This is not really necessary, but it is consistent with a | |
2122 // hypothetical MaxINode::Value method: | |
2123 int widen = MAX2(txvalue->_widen, tyvalue->_widen); | |
2124 | |
2125 // %%% This folding logic should (ideally) be in a different place. | |
2126 // Some should be inside IfNode, and there to be a more reliable | |
2127 // transformation of ?: style patterns into cmoves. We also want | |
2128 // more powerful optimizations around cmove and min/max. | |
2129 | |
2130 // Try to find a dominating comparison of these guys. | |
2131 // It can simplify the index computation for Arrays.copyOf | |
2132 // and similar uses of System.arraycopy. | |
2133 // First, compute the normalized version of CmpI(x, y). | |
2134 int cmp_op = Op_CmpI; | |
2135 Node* xkey = xvalue; | |
2136 Node* ykey = yvalue; | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
2137 Node* ideal_cmpxy = _gvn.transform(new(C) CmpINode(xkey, ykey)); |
0 | 2138 if (ideal_cmpxy->is_Cmp()) { |
2139 // E.g., if we have CmpI(length - offset, count), | |
2140 // it might idealize to CmpI(length, count + offset) | |
2141 cmp_op = ideal_cmpxy->Opcode(); | |
2142 xkey = ideal_cmpxy->in(1); | |
2143 ykey = ideal_cmpxy->in(2); | |
2144 } | |
2145 | |
2146 // Start by locating any relevant comparisons. | |
2147 Node* start_from = (xkey->outcnt() < ykey->outcnt()) ? xkey : ykey; | |
2148 Node* cmpxy = NULL; | |
2149 Node* cmpyx = NULL; | |
2150 for (DUIterator_Fast kmax, k = start_from->fast_outs(kmax); k < kmax; k++) { | |
2151 Node* cmp = start_from->fast_out(k); | |
2152 if (cmp->outcnt() > 0 && // must have prior uses | |
2153 cmp->in(0) == NULL && // must be context-independent | |
2154 cmp->Opcode() == cmp_op) { // right kind of compare | |
2155 if (cmp->in(1) == xkey && cmp->in(2) == ykey) cmpxy = cmp; | |
2156 if (cmp->in(1) == ykey && cmp->in(2) == xkey) cmpyx = cmp; | |
2157 } | |
2158 } | |
2159 | |
2160 const int NCMPS = 2; | |
2161 Node* cmps[NCMPS] = { cmpxy, cmpyx }; | |
2162 int cmpn; | |
2163 for (cmpn = 0; cmpn < NCMPS; cmpn++) { | |
2164 if (cmps[cmpn] != NULL) break; // find a result | |
2165 } | |
2166 if (cmpn < NCMPS) { | |
2167 // Look for a dominating test that tells us the min and max. | |
2168 int depth = 0; // Limit search depth for speed | |
2169 Node* dom = control(); | |
2170 for (; dom != NULL; dom = IfNode::up_one_dom(dom, true)) { | |
2171 if (++depth >= 100) break; | |
2172 Node* ifproj = dom; | |
2173 if (!ifproj->is_Proj()) continue; | |
2174 Node* iff = ifproj->in(0); | |
2175 if (!iff->is_If()) continue; | |
2176 Node* bol = iff->in(1); | |
2177 if (!bol->is_Bool()) continue; | |
2178 Node* cmp = bol->in(1); | |
2179 if (cmp == NULL) continue; | |
2180 for (cmpn = 0; cmpn < NCMPS; cmpn++) | |
2181 if (cmps[cmpn] == cmp) break; | |
2182 if (cmpn == NCMPS) continue; | |
2183 BoolTest::mask btest = bol->as_Bool()->_test._test; | |
2184 if (ifproj->is_IfFalse()) btest = BoolTest(btest).negate(); | |
2185 if (cmp->in(1) == ykey) btest = BoolTest(btest).commute(); | |
2186 // At this point, we know that 'x btest y' is true. | |
2187 switch (btest) { | |
2188 case BoolTest::eq: | |
2189 // They are proven equal, so we can collapse the min/max. | |
2190 // Either value is the answer. Choose the simpler. | |
2191 if (is_simple_name(yvalue) && !is_simple_name(xvalue)) | |
2192 return yvalue; | |
2193 return xvalue; | |
2194 case BoolTest::lt: // x < y | |
2195 case BoolTest::le: // x <= y | |
2196 return (want_max ? yvalue : xvalue); | |
2197 case BoolTest::gt: // x > y | |
2198 case BoolTest::ge: // x >= y | |
2199 return (want_max ? xvalue : yvalue); | |
2200 } | |
2201 } | |
2202 } | |
2203 | |
2204 // We failed to find a dominating test. | |
2205 // Let's pick a test that might GVN with prior tests. | |
2206 Node* best_bol = NULL; | |
2207 BoolTest::mask best_btest = BoolTest::illegal; | |
2208 for (cmpn = 0; cmpn < NCMPS; cmpn++) { | |
2209 Node* cmp = cmps[cmpn]; | |
2210 if (cmp == NULL) continue; | |
2211 for (DUIterator_Fast jmax, j = cmp->fast_outs(jmax); j < jmax; j++) { | |
2212 Node* bol = cmp->fast_out(j); | |
2213 if (!bol->is_Bool()) continue; | |
2214 BoolTest::mask btest = bol->as_Bool()->_test._test; | |
2215 if (btest == BoolTest::eq || btest == BoolTest::ne) continue; | |
2216 if (cmp->in(1) == ykey) btest = BoolTest(btest).commute(); | |
2217 if (bol->outcnt() > (best_bol == NULL ? 0 : best_bol->outcnt())) { | |
2218 best_bol = bol->as_Bool(); | |
2219 best_btest = btest; | |
2220 } | |
2221 } | |
2222 } | |
2223 | |
2224 Node* answer_if_true = NULL; | |
2225 Node* answer_if_false = NULL; | |
2226 switch (best_btest) { | |
2227 default: | |
2228 if (cmpxy == NULL) | |
2229 cmpxy = ideal_cmpxy; | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
2230 best_bol = _gvn.transform(new(C) BoolNode(cmpxy, BoolTest::lt)); |
0 | 2231 // and fall through: |
2232 case BoolTest::lt: // x < y | |
2233 case BoolTest::le: // x <= y | |
2234 answer_if_true = (want_max ? yvalue : xvalue); | |
2235 answer_if_false = (want_max ? xvalue : yvalue); | |
2236 break; | |
2237 case BoolTest::gt: // x > y | |
2238 case BoolTest::ge: // x >= y | |
2239 answer_if_true = (want_max ? xvalue : yvalue); | |
2240 answer_if_false = (want_max ? yvalue : xvalue); | |
2241 break; | |
2242 } | |
2243 | |
2244 jint hi, lo; | |
2245 if (want_max) { | |
2246 // We can sharpen the minimum. | |
2247 hi = MAX2(txvalue->_hi, tyvalue->_hi); | |
2248 lo = MAX2(txvalue->_lo, tyvalue->_lo); | |
2249 } else { | |
2250 // We can sharpen the maximum. | |
2251 hi = MIN2(txvalue->_hi, tyvalue->_hi); | |
2252 lo = MIN2(txvalue->_lo, tyvalue->_lo); | |
2253 } | |
2254 | |
2255 // Use a flow-free graph structure, to avoid creating excess control edges | |
2256 // which could hinder other optimizations. | |
2257 // Since Math.min/max is often used with arraycopy, we want | |
2258 // tightly_coupled_allocation to be able to see beyond min/max expressions. | |
2259 Node* cmov = CMoveNode::make(C, NULL, best_bol, | |
2260 answer_if_false, answer_if_true, | |
2261 TypeInt::make(lo, hi, widen)); | |
2262 | |
2263 return _gvn.transform(cmov); | |
2264 | |
2265 /* | |
2266 // This is not as desirable as it may seem, since Min and Max | |
2267 // nodes do not have a full set of optimizations. | |
2268 // And they would interfere, anyway, with 'if' optimizations | |
2269 // and with CMoveI canonical forms. | |
2270 switch (id) { | |
2271 case vmIntrinsics::_min: | |
2272 result_val = _gvn.transform(new (C, 3) MinINode(x,y)); break; | |
2273 case vmIntrinsics::_max: | |
2274 result_val = _gvn.transform(new (C, 3) MaxINode(x,y)); break; | |
2275 default: | |
2276 ShouldNotReachHere(); | |
2277 } | |
2278 */ | |
2279 } | |
2280 | |
2281 inline int | |
2282 LibraryCallKit::classify_unsafe_addr(Node* &base, Node* &offset) { | |
2283 const TypePtr* base_type = TypePtr::NULL_PTR; | |
2284 if (base != NULL) base_type = _gvn.type(base)->isa_ptr(); | |
2285 if (base_type == NULL) { | |
2286 // Unknown type. | |
2287 return Type::AnyPtr; | |
2288 } else if (base_type == TypePtr::NULL_PTR) { | |
2289 // Since this is a NULL+long form, we have to switch to a rawptr. | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
2290 base = _gvn.transform(new (C) CastX2PNode(offset)); |
0 | 2291 offset = MakeConX(0); |
2292 return Type::RawPtr; | |
2293 } else if (base_type->base() == Type::RawPtr) { | |
2294 return Type::RawPtr; | |
2295 } else if (base_type->isa_oopptr()) { | |
2296 // Base is never null => always a heap address. | |
2297 if (base_type->ptr() == TypePtr::NotNull) { | |
2298 return Type::OopPtr; | |
2299 } | |
2300 // Offset is small => always a heap address. | |
2301 const TypeX* offset_type = _gvn.type(offset)->isa_intptr_t(); | |
2302 if (offset_type != NULL && | |
2303 base_type->offset() == 0 && // (should always be?) | |
2304 offset_type->_lo >= 0 && | |
2305 !MacroAssembler::needs_explicit_null_check(offset_type->_hi)) { | |
2306 return Type::OopPtr; | |
2307 } | |
2308 // Otherwise, it might either be oop+off or NULL+addr. | |
2309 return Type::AnyPtr; | |
2310 } else { | |
2311 // No information: | |
2312 return Type::AnyPtr; | |
2313 } | |
2314 } | |
2315 | |
2316 inline Node* LibraryCallKit::make_unsafe_address(Node* base, Node* offset) { | |
2317 int kind = classify_unsafe_addr(base, offset); | |
2318 if (kind == Type::RawPtr) { | |
2319 return basic_plus_adr(top(), base, offset); | |
2320 } else { | |
2321 return basic_plus_adr(base, offset); | |
2322 } | |
2323 } | |
2324 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2325 //--------------------------inline_number_methods----------------------------- |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2326 // inline int Integer.numberOfLeadingZeros(int) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2327 // inline int Long.numberOfLeadingZeros(long) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2328 // |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2329 // inline int Integer.numberOfTrailingZeros(int) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2330 // inline int Long.numberOfTrailingZeros(long) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2331 // |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2332 // inline int Integer.bitCount(int) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2333 // inline int Long.bitCount(long) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2334 // |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2335 // inline char Character.reverseBytes(char) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2336 // inline short Short.reverseBytes(short) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2337 // inline int Integer.reverseBytes(int) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2338 // inline long Long.reverseBytes(long) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2339 bool LibraryCallKit::inline_number_methods(vmIntrinsics::ID id) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2340 Node* arg = argument(0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2341 Node* n; |
775
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2342 switch (id) { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2343 case vmIntrinsics::_numberOfLeadingZeros_i: n = new (C) CountLeadingZerosINode( arg); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2344 case vmIntrinsics::_numberOfLeadingZeros_l: n = new (C) CountLeadingZerosLNode( arg); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2345 case vmIntrinsics::_numberOfTrailingZeros_i: n = new (C) CountTrailingZerosINode(arg); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2346 case vmIntrinsics::_numberOfTrailingZeros_l: n = new (C) CountTrailingZerosLNode(arg); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2347 case vmIntrinsics::_bitCount_i: n = new (C) PopCountINode( arg); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2348 case vmIntrinsics::_bitCount_l: n = new (C) PopCountLNode( arg); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2349 case vmIntrinsics::_reverseBytes_c: n = new (C) ReverseBytesUSNode(0, arg); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2350 case vmIntrinsics::_reverseBytes_s: n = new (C) ReverseBytesSNode( 0, arg); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2351 case vmIntrinsics::_reverseBytes_i: n = new (C) ReverseBytesINode( 0, arg); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2352 case vmIntrinsics::_reverseBytes_l: n = new (C) ReverseBytesLNode( 0, arg); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2353 default: fatal_unexpected_iid(id); break; |
775
93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
twisti
parents:
730
diff
changeset
|
2354 } |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2355 set_result(_gvn.transform(n)); |
0 | 2356 return true; |
2357 } | |
2358 | |
2359 //----------------------------inline_unsafe_access---------------------------- | |
2360 | |
2361 const static BasicType T_ADDRESS_HOLDER = T_LONG; | |
2362 | |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2363 // Helper that guards and inserts a pre-barrier. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2364 void LibraryCallKit::insert_pre_barrier(Node* base_oop, Node* offset, |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2365 Node* pre_val, bool need_mem_bar) { |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2366 // 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
|
2367 // 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
|
2368 // 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
|
2369 // runtime filters that guard the pre-barrier code. |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2370 // Also add memory barrier for non volatile load from the referent field |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2371 // to prevent commoning of loads across safepoint. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2372 if (!UseG1GC && !need_mem_bar) |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2373 return; |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2374 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2375 // Some compile time checks. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2376 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2377 // 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
|
2378 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
|
2379 if (otype != NULL && otype->is_con() && |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2380 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
|
2381 // 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
|
2382 return; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2383 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2384 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2385 // 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
|
2386 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
|
2387 if (btype != NULL) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2388 if (btype->isa_aryptr()) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2389 // Array type so nothing to do |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2390 return; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2391 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2392 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2393 const TypeInstPtr* itype = btype->isa_instptr(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2394 if (itype != NULL) { |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2395 // Can the klass of base_oop be statically determined to be |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2396 // _not_ a sub-class of Reference and _not_ Object? |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2397 ciKlass* klass = itype->klass(); |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2398 if ( klass->is_loaded() && |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2399 !klass->is_subtype_of(env()->Reference_klass()) && |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2400 !env()->Object_klass()->is_subtype_of(klass)) { |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2401 return; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2402 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2403 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2404 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2405 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2406 // 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
|
2407 // 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
|
2408 // |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2409 // if (offset == java_lang_ref_Reference::_reference_offset) { |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2410 // if (instance_of(base, java.lang.ref.Reference)) { |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2411 // pre_barrier(_, pre_val, ...); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2412 // } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2413 // } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2414 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2415 float likely = PROB_LIKELY( 0.999); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2416 float unlikely = PROB_UNLIKELY(0.999); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2417 |
3255 | 2418 IdealKit ideal(this); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2419 #define __ ideal. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2420 |
3254
59766fd005ff
7035117: G1: nsk/stress/jni/jnistress002 fails with assertion failure
johnc
parents:
3252
diff
changeset
|
2421 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
|
2422 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2423 __ 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
|
2424 // Update graphKit memory and control from IdealKit. |
3255 | 2425 sync_kit(ideal); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2426 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2427 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
|
2428 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
|
2429 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2430 // Update IdealKit memory and control from graphKit. |
3255 | 2431 __ sync_kit(this); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2432 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2433 Node* one = __ ConI(1); |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2434 // is_instof == 0 if base_oop == NULL |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2435 __ 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
|
2436 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2437 // Update graphKit from IdeakKit. |
3255 | 2438 sync_kit(ideal); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2439 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2440 // 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
|
2441 pre_barrier(false /* do_load */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2442 __ ctrl(), |
3258
edd9b016deb6
7036021: G1: build failure on win64 and linux with hs21 in jdk6 build environment
johnc
parents:
3255
diff
changeset
|
2443 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
|
2444 pre_val /* pre_val */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2445 T_OBJECT); |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2446 if (need_mem_bar) { |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2447 // Add memory barrier to prevent commoning reads from this field |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2448 // across safepoint since GC can change its value. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2449 insert_mem_bar(Op_MemBarCPUOrder); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2450 } |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2451 // Update IdealKit from graphKit. |
3255 | 2452 __ sync_kit(this); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2453 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2454 } __ end_if(); // _ref_type != ref_none |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2455 } __ end_if(); // offset == referent_offset |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2456 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2457 // Final sync IdealKit and GraphKit. |
3255 | 2458 final_sync(ideal); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2459 #undef __ |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2460 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2461 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2462 |
0 | 2463 // Interpret Unsafe.fieldOffset cookies correctly: |
2464 extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset); | |
2465 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2466 const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type, bool is_native_ptr) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2467 // Attempt to infer a sharper value type from the offset and base type. |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2468 ciKlass* sharpened_klass = NULL; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2469 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2470 // See if it is an instance field, with an object type. |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2471 if (alias_type->field() != NULL) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2472 assert(!is_native_ptr, "native pointer op cannot use a java address"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2473 if (alias_type->field()->type()->is_klass()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2474 sharpened_klass = alias_type->field()->type()->as_klass(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2475 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2476 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2477 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2478 // See if it is a narrow oop array. |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2479 if (adr_type->isa_aryptr()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2480 if (adr_type->offset() >= objArrayOopDesc::base_offset_in_bytes()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2481 const TypeOopPtr *elem_type = adr_type->is_aryptr()->elem()->isa_oopptr(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2482 if (elem_type != NULL) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2483 sharpened_klass = elem_type->klass(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2484 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2485 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2486 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2487 |
6847
65d07d9ee446
8000263: JSR 292: signature types may appear to be unloaded
twisti
parents:
6804
diff
changeset
|
2488 // The sharpened class might be unloaded if there is no class loader |
65d07d9ee446
8000263: JSR 292: signature types may appear to be unloaded
twisti
parents:
6804
diff
changeset
|
2489 // contraint in place. |
65d07d9ee446
8000263: JSR 292: signature types may appear to be unloaded
twisti
parents:
6804
diff
changeset
|
2490 if (sharpened_klass != NULL && sharpened_klass->is_loaded()) { |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2491 const TypeOopPtr* tjp = TypeOopPtr::make_from_klass(sharpened_klass); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2492 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2493 #ifndef PRODUCT |
12295 | 2494 if (C->print_intrinsics() || C->print_inlining()) { |
6847
65d07d9ee446
8000263: JSR 292: signature types may appear to be unloaded
twisti
parents:
6804
diff
changeset
|
2495 tty->print(" from base type: "); adr_type->dump(); |
65d07d9ee446
8000263: JSR 292: signature types may appear to be unloaded
twisti
parents:
6804
diff
changeset
|
2496 tty->print(" sharpened value: "); tjp->dump(); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2497 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2498 #endif |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2499 // Sharpen the value type. |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2500 return tjp; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2501 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2502 return NULL; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2503 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2504 |
0 | 2505 bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile) { |
2506 if (callee()->is_static()) return false; // caller must have the capability! | |
2507 | |
2508 #ifndef PRODUCT | |
2509 { | |
2510 ResourceMark rm; | |
2511 // Check the signatures. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2512 ciSignature* sig = callee()->signature(); |
0 | 2513 #ifdef ASSERT |
2514 if (!is_store) { | |
2515 // Object getObject(Object base, int/long offset), etc. | |
2516 BasicType rtype = sig->return_type()->basic_type(); | |
2517 if (rtype == T_ADDRESS_HOLDER && callee()->name() == ciSymbol::getAddress_name()) | |
2518 rtype = T_ADDRESS; // it is really a C void* | |
2519 assert(rtype == type, "getter must return the expected value"); | |
2520 if (!is_native_ptr) { | |
2521 assert(sig->count() == 2, "oop getter has 2 arguments"); | |
2522 assert(sig->type_at(0)->basic_type() == T_OBJECT, "getter base is object"); | |
2523 assert(sig->type_at(1)->basic_type() == T_LONG, "getter offset is correct"); | |
2524 } else { | |
2525 assert(sig->count() == 1, "native getter has 1 argument"); | |
2526 assert(sig->type_at(0)->basic_type() == T_LONG, "getter base is long"); | |
2527 } | |
2528 } else { | |
2529 // void putObject(Object base, int/long offset, Object x), etc. | |
2530 assert(sig->return_type()->basic_type() == T_VOID, "putter must not return a value"); | |
2531 if (!is_native_ptr) { | |
2532 assert(sig->count() == 3, "oop putter has 3 arguments"); | |
2533 assert(sig->type_at(0)->basic_type() == T_OBJECT, "putter base is object"); | |
2534 assert(sig->type_at(1)->basic_type() == T_LONG, "putter offset is correct"); | |
2535 } else { | |
2536 assert(sig->count() == 2, "native putter has 2 arguments"); | |
2537 assert(sig->type_at(0)->basic_type() == T_LONG, "putter base is long"); | |
2538 } | |
2539 BasicType vtype = sig->type_at(sig->count()-1)->basic_type(); | |
2540 if (vtype == T_ADDRESS_HOLDER && callee()->name() == ciSymbol::putAddress_name()) | |
2541 vtype = T_ADDRESS; // it is really a C void* | |
2542 assert(vtype == type, "putter must accept the expected value"); | |
2543 } | |
2544 #endif // ASSERT | |
2545 } | |
2546 #endif //PRODUCT | |
2547 | |
2548 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
2549 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2550 Node* receiver = argument(0); // type: oop |
0 | 2551 |
2552 // Build address expression. See the code in inline_unsafe_prefetch. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2553 Node* adr; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2554 Node* heap_base_oop = top(); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2555 Node* offset = top(); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2556 Node* val; |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2557 |
0 | 2558 if (!is_native_ptr) { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2559 // The base is either a Java object or a value produced by Unsafe.staticFieldBase |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2560 Node* base = argument(1); // type: oop |
0 | 2561 // The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2562 offset = argument(2); // type: long |
0 | 2563 // We currently rely on the cookies produced by Unsafe.xxxFieldOffset |
2564 // to be plain byte offsets, which are also the same as those accepted | |
2565 // by oopDesc::field_base. | |
2566 assert(Unsafe_field_offset_to_byte_offset(11) == 11, | |
2567 "fieldOffset must be byte-scaled"); | |
2568 // 32-bit machines ignore the high half! | |
2569 offset = ConvL2X(offset); | |
2570 adr = make_unsafe_address(base, offset); | |
2571 heap_base_oop = base; | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2572 val = is_store ? argument(4) : NULL; |
0 | 2573 } else { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2574 Node* ptr = argument(1); // type: long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2575 ptr = ConvL2X(ptr); // adjust Java long to machine word |
0 | 2576 adr = make_unsafe_address(NULL, ptr); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2577 val = is_store ? argument(3) : NULL; |
0 | 2578 } |
2579 | |
2580 const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); | |
2581 | |
2582 // First guess at the value type. | |
2583 const Type *value_type = Type::get_const_basic_type(type); | |
2584 | |
2585 // Try to categorize the address. If it comes up as TypeJavaPtr::BOTTOM, | |
2586 // there was not enough information to nail it down. | |
2587 Compile::AliasType* alias_type = C->alias_type(adr_type); | |
2588 assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here"); | |
2589 | |
2590 // We will need memory barriers unless we can determine a unique | |
2591 // alias category for this reference. (Note: If for some reason | |
2592 // the barriers get omitted and the unsafe reference begins to "pollute" | |
2593 // the alias analysis of the rest of the graph, either Compile::can_alias | |
2594 // or Compile::must_alias will throw a diagnostic assert.) | |
2595 bool need_mem_bar = (alias_type->adr_type() == TypeOopPtr::BOTTOM); | |
2596 | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2597 // 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
|
2598 // 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
|
2599 // 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
|
2600 // SATB log buffer using the pre-barrier mechanism. |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2601 // Also we need to add memory barrier to prevent commoning reads |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2602 // from this field across safepoint since GC can change its value. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
2603 bool need_read_barrier = !is_native_ptr && !is_store && |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2604 offset != top() && heap_base_oop != top(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2605 |
0 | 2606 if (!is_store && type == T_OBJECT) { |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2607 const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type, is_native_ptr); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2608 if (tjp != NULL) { |
0 | 2609 value_type = tjp; |
2610 } | |
2611 } | |
2612 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2613 receiver = null_check(receiver); |
0 | 2614 if (stopped()) { |
2615 return true; | |
2616 } | |
2617 // Heap pointers get a null-check from the interpreter, | |
2618 // as a courtesy. However, this is not guaranteed by Unsafe, | |
2619 // and it is not possible to fully distinguish unintended nulls | |
2620 // from intended ones in this API. | |
2621 | |
2622 if (is_volatile) { | |
2623 // We need to emit leading and trailing CPU membars (see below) in | |
2624 // addition to memory membars when is_volatile. This is a little | |
2625 // too strong, but avoids the need to insert per-alias-type | |
2626 // volatile membars (for stores; compare Parse::do_put_xxx), which | |
605 | 2627 // we cannot do effectively here because we probably only have a |
0 | 2628 // rough approximation of type. |
2629 need_mem_bar = true; | |
2630 // For Stores, place a memory ordering barrier now. | |
2631 if (is_store) | |
2632 insert_mem_bar(Op_MemBarRelease); | |
2633 } | |
2634 | |
2635 // Memory barrier to prevent normal and 'unsafe' accesses from | |
2636 // bypassing each other. Happens after null checks, so the | |
2637 // exception paths do not take memory state from the memory barrier, | |
2638 // so there's no problems making a strong assert about mixing users | |
2639 // of safe & unsafe memory. Otherwise fails in a CTW of rt.jar | |
2640 // around 5701, class sun/reflect/UnsafeBooleanFieldAccessorImpl. | |
2641 if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder); | |
2642 | |
2643 if (!is_store) { | |
2644 Node* p = make_load(control(), adr, value_type, type, adr_type, is_volatile); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2645 // load value |
0 | 2646 switch (type) { |
2647 case T_BOOLEAN: | |
2648 case T_CHAR: | |
2649 case T_BYTE: | |
2650 case T_SHORT: | |
2651 case T_INT: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2652 case T_LONG: |
0 | 2653 case T_FLOAT: |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2654 case T_DOUBLE: |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2655 break; |
0 | 2656 case T_OBJECT: |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2657 if (need_read_barrier) { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2658 insert_pre_barrier(heap_base_oop, offset, p, !(is_volatile || need_mem_bar)); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2659 } |
0 | 2660 break; |
2661 case T_ADDRESS: | |
2662 // Cast to an int type. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2663 p = _gvn.transform(new (C) CastP2XNode(NULL, p)); |
0 | 2664 p = ConvX2L(p); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2665 break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2666 default: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2667 fatal(err_msg_res("unexpected type %d: %s", type, type2name(type))); |
0 | 2668 break; |
2669 } | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2670 // The load node has the control of the preceding MemBarCPUOrder. All |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2671 // following nodes will have the control of the MemBarCPUOrder inserted at |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2672 // the end of this method. So, pushing the load onto the stack at a later |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2673 // point is fine. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2674 set_result(p); |
0 | 2675 } else { |
2676 // place effect of store into memory | |
2677 switch (type) { | |
2678 case T_DOUBLE: | |
2679 val = dstore_rounding(val); | |
2680 break; | |
2681 case T_ADDRESS: | |
2682 // Repackage the long as a pointer. | |
2683 val = ConvL2X(val); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
2684 val = _gvn.transform(new (C) CastX2PNode(val)); |
0 | 2685 break; |
2686 } | |
2687 | |
2688 if (type != T_OBJECT ) { | |
2689 (void) store_to_memory(control(), adr, val, type, adr_type, is_volatile); | |
2690 } else { | |
2691 // Possibly an oop being stored to Java heap or native memory | |
2692 if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) { | |
2693 // oop to Java heap. | |
825 | 2694 (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type); |
0 | 2695 } else { |
2696 // We can't tell at compile time if we are storing in the Java heap or outside | |
2697 // of it. So we need to emit code to conditionally do the proper type of | |
2698 // store. | |
2699 | |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
2700 IdealKit ideal(this); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2701 #define __ ideal. |
0 | 2702 // QQQ who knows what probability is here?? |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2703 __ 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
|
2704 // Sync IdealKit and graphKit. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
2705 sync_kit(ideal); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2706 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
|
2707 // Update IdealKit memory. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
2708 __ sync_kit(this); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2709 } __ else_(); { |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2710 __ 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
|
2711 } __ end_if(); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2712 // Final sync IdealKit and GraphKit. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
2713 final_sync(ideal); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2714 #undef __ |
0 | 2715 } |
2716 } | |
2717 } | |
2718 | |
2719 if (is_volatile) { | |
2720 if (!is_store) | |
2721 insert_mem_bar(Op_MemBarAcquire); | |
2722 else | |
2723 insert_mem_bar(Op_MemBarVolatile); | |
2724 } | |
2725 | |
2726 if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder); | |
2727 | |
2728 return true; | |
2729 } | |
2730 | |
2731 //----------------------------inline_unsafe_prefetch---------------------------- | |
2732 | |
2733 bool LibraryCallKit::inline_unsafe_prefetch(bool is_native_ptr, bool is_store, bool is_static) { | |
2734 #ifndef PRODUCT | |
2735 { | |
2736 ResourceMark rm; | |
2737 // Check the signatures. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2738 ciSignature* sig = callee()->signature(); |
0 | 2739 #ifdef ASSERT |
2740 // Object getObject(Object base, int/long offset), etc. | |
2741 BasicType rtype = sig->return_type()->basic_type(); | |
2742 if (!is_native_ptr) { | |
2743 assert(sig->count() == 2, "oop prefetch has 2 arguments"); | |
2744 assert(sig->type_at(0)->basic_type() == T_OBJECT, "prefetch base is object"); | |
2745 assert(sig->type_at(1)->basic_type() == T_LONG, "prefetcha offset is correct"); | |
2746 } else { | |
2747 assert(sig->count() == 1, "native prefetch has 1 argument"); | |
2748 assert(sig->type_at(0)->basic_type() == T_LONG, "prefetch base is long"); | |
2749 } | |
2750 #endif // ASSERT | |
2751 } | |
2752 #endif // !PRODUCT | |
2753 | |
2754 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
2755 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2756 const int idx = is_static ? 0 : 1; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2757 if (!is_static) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2758 null_check_receiver(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2759 if (stopped()) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2760 return true; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2761 } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2762 } |
0 | 2763 |
2764 // Build address expression. See the code in inline_unsafe_access. | |
2765 Node *adr; | |
2766 if (!is_native_ptr) { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2767 // The base is either a Java object or a value produced by Unsafe.staticFieldBase |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2768 Node* base = argument(idx + 0); // type: oop |
0 | 2769 // The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2770 Node* offset = argument(idx + 1); // type: long |
0 | 2771 // We currently rely on the cookies produced by Unsafe.xxxFieldOffset |
2772 // to be plain byte offsets, which are also the same as those accepted | |
2773 // by oopDesc::field_base. | |
2774 assert(Unsafe_field_offset_to_byte_offset(11) == 11, | |
2775 "fieldOffset must be byte-scaled"); | |
2776 // 32-bit machines ignore the high half! | |
2777 offset = ConvL2X(offset); | |
2778 adr = make_unsafe_address(base, offset); | |
2779 } else { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2780 Node* ptr = argument(idx + 0); // type: long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2781 ptr = ConvL2X(ptr); // adjust Java long to machine word |
0 | 2782 adr = make_unsafe_address(NULL, ptr); |
2783 } | |
2784 | |
2785 // Generate the read or write prefetch | |
2786 Node *prefetch; | |
2787 if (is_store) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2788 prefetch = new (C) PrefetchWriteNode(i_o(), adr); |
0 | 2789 } else { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2790 prefetch = new (C) PrefetchReadNode(i_o(), adr); |
0 | 2791 } |
2792 prefetch->init_req(0, control()); | |
2793 set_i_o(_gvn.transform(prefetch)); | |
2794 | |
2795 return true; | |
2796 } | |
2797 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2798 //----------------------------inline_unsafe_load_store---------------------------- |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2799 // This method serves a couple of different customers (depending on LoadStoreKind): |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2800 // |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2801 // LS_cmpxchg: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2802 // public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object x); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2803 // public final native boolean compareAndSwapInt( Object o, long offset, int expected, int x); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2804 // public final native boolean compareAndSwapLong( Object o, long offset, long expected, long x); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2805 // |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2806 // LS_xadd: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2807 // public int getAndAddInt( Object o, long offset, int delta) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2808 // public long getAndAddLong(Object o, long offset, long delta) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2809 // |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2810 // LS_xchg: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2811 // int getAndSet(Object o, long offset, int newValue) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2812 // long getAndSet(Object o, long offset, long newValue) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2813 // Object getAndSet(Object o, long offset, Object newValue) |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2814 // |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2815 bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind) { |
0 | 2816 // This basic scheme here is the same as inline_unsafe_access, but |
2817 // differs in enough details that combining them would make the code | |
2818 // overly confusing. (This is a true fact! I originally combined | |
2819 // them, but even I was confused by it!) As much code/comments as | |
2820 // possible are retained from inline_unsafe_access though to make | |
605 | 2821 // the correspondences clearer. - dl |
0 | 2822 |
2823 if (callee()->is_static()) return false; // caller must have the capability! | |
2824 | |
2825 #ifndef PRODUCT | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2826 BasicType rtype; |
0 | 2827 { |
2828 ResourceMark rm; | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2829 // Check the signatures. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2830 ciSignature* sig = callee()->signature(); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2831 rtype = sig->return_type()->basic_type(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2832 if (kind == LS_xadd || kind == LS_xchg) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2833 // Check the signatures. |
0 | 2834 #ifdef ASSERT |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2835 assert(rtype == type, "get and set must return the expected type"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2836 assert(sig->count() == 3, "get and set has 3 arguments"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2837 assert(sig->type_at(0)->basic_type() == T_OBJECT, "get and set base is object"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2838 assert(sig->type_at(1)->basic_type() == T_LONG, "get and set offset is long"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2839 assert(sig->type_at(2)->basic_type() == type, "get and set must take expected type as new value/delta"); |
0 | 2840 #endif // ASSERT |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2841 } else if (kind == LS_cmpxchg) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2842 // Check the signatures. |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2843 #ifdef ASSERT |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2844 assert(rtype == T_BOOLEAN, "CAS must return boolean"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2845 assert(sig->count() == 4, "CAS has 4 arguments"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2846 assert(sig->type_at(0)->basic_type() == T_OBJECT, "CAS base is object"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2847 assert(sig->type_at(1)->basic_type() == T_LONG, "CAS offset is long"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2848 #endif // ASSERT |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2849 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2850 ShouldNotReachHere(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2851 } |
0 | 2852 } |
2853 #endif //PRODUCT | |
2854 | |
2855 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
2856 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2857 // Get arguments: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2858 Node* receiver = NULL; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2859 Node* base = NULL; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2860 Node* offset = NULL; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2861 Node* oldval = NULL; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2862 Node* newval = NULL; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2863 if (kind == LS_cmpxchg) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2864 const bool two_slot_type = type2size[type] == 2; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2865 receiver = argument(0); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2866 base = argument(1); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2867 offset = argument(2); // type: long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2868 oldval = argument(4); // type: oop, int, or long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2869 newval = argument(two_slot_type ? 6 : 5); // type: oop, int, or long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2870 } else if (kind == LS_xadd || kind == LS_xchg){ |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2871 receiver = argument(0); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2872 base = argument(1); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2873 offset = argument(2); // type: long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2874 oldval = NULL; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2875 newval = argument(4); // type: oop, int, or long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2876 } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2877 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2878 // Null check receiver. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2879 receiver = null_check(receiver); |
0 | 2880 if (stopped()) { |
2881 return true; | |
2882 } | |
2883 | |
2884 // Build field offset expression. | |
2885 // We currently rely on the cookies produced by Unsafe.xxxFieldOffset | |
2886 // to be plain byte offsets, which are also the same as those accepted | |
2887 // by oopDesc::field_base. | |
2888 assert(Unsafe_field_offset_to_byte_offset(11) == 11, "fieldOffset must be byte-scaled"); | |
2889 // 32-bit machines ignore the high half of long offsets | |
2890 offset = ConvL2X(offset); | |
2891 Node* adr = make_unsafe_address(base, offset); | |
2892 const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); | |
2893 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2894 // For CAS, unlike inline_unsafe_access, there seems no point in |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2895 // trying to refine types. Just use the coarse types here. |
0 | 2896 const Type *value_type = Type::get_const_basic_type(type); |
2897 Compile::AliasType* alias_type = C->alias_type(adr_type); | |
2898 assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here"); | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2899 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2900 if (kind == LS_xchg && type == T_OBJECT) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2901 const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2902 if (tjp != NULL) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2903 value_type = tjp; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2904 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2905 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2906 |
0 | 2907 int alias_idx = C->get_alias_index(adr_type); |
2908 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2909 // Memory-model-wise, a LoadStore acts like a little synchronized |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2910 // block, so needs barriers on each side. These don't translate |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2911 // into actual barriers on most machines, but we still need rest of |
0 | 2912 // compiler to respect ordering. |
2913 | |
2914 insert_mem_bar(Op_MemBarRelease); | |
2915 insert_mem_bar(Op_MemBarCPUOrder); | |
2916 | |
2917 // 4984716: MemBars must be inserted before this | |
2918 // memory node in order to avoid a false | |
2919 // dependency which will confuse the scheduler. | |
2920 Node *mem = memory(alias_idx); | |
2921 | |
2922 // For now, we handle only those cases that actually exist: ints, | |
2923 // longs, and Object. Adding others should be straightforward. | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2924 Node* load_store; |
0 | 2925 switch(type) { |
2926 case T_INT: | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2927 if (kind == LS_xadd) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2928 load_store = _gvn.transform(new (C) GetAndAddINode(control(), mem, adr, newval, adr_type)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2929 } else if (kind == LS_xchg) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2930 load_store = _gvn.transform(new (C) GetAndSetINode(control(), mem, adr, newval, adr_type)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2931 } else if (kind == LS_cmpxchg) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2932 load_store = _gvn.transform(new (C) CompareAndSwapINode(control(), mem, adr, newval, oldval)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2933 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2934 ShouldNotReachHere(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2935 } |
0 | 2936 break; |
2937 case T_LONG: | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2938 if (kind == LS_xadd) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2939 load_store = _gvn.transform(new (C) GetAndAddLNode(control(), mem, adr, newval, adr_type)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2940 } else if (kind == LS_xchg) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2941 load_store = _gvn.transform(new (C) GetAndSetLNode(control(), mem, adr, newval, adr_type)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2942 } else if (kind == LS_cmpxchg) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2943 load_store = _gvn.transform(new (C) CompareAndSwapLNode(control(), mem, adr, newval, oldval)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2944 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2945 ShouldNotReachHere(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2946 } |
0 | 2947 break; |
2948 case T_OBJECT: | |
4894
b9bc6cae88f2
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
4778
diff
changeset
|
2949 // Transformation of a value which could be NULL pointer (CastPP #NULL) |
b9bc6cae88f2
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
4778
diff
changeset
|
2950 // could be delayed during Parse (for example, in adjust_map_after_if()). |
b9bc6cae88f2
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
4778
diff
changeset
|
2951 // Execute transformation here to avoid barrier generation in such case. |
b9bc6cae88f2
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
4778
diff
changeset
|
2952 if (_gvn.type(newval) == TypePtr::NULL_PTR) |
b9bc6cae88f2
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
4778
diff
changeset
|
2953 newval = _gvn.makecon(TypePtr::NULL_PTR); |
b9bc6cae88f2
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
4778
diff
changeset
|
2954 |
b9bc6cae88f2
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
4778
diff
changeset
|
2955 // Reference stores need a store barrier. |
12169
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2956 if (kind == LS_xchg) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2957 // If pre-barrier must execute before the oop store, old value will require do_load here. |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2958 if (!can_move_pre_barrier()) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2959 pre_barrier(true /* do_load*/, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2960 control(), base, adr, alias_idx, newval, value_type->make_oopptr(), |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2961 NULL /* pre_val*/, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2962 T_OBJECT); |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2963 } // Else move pre_barrier to use load_store value, see below. |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2964 } else if (kind == LS_cmpxchg) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2965 // Same as for newval above: |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2966 if (_gvn.type(oldval) == TypePtr::NULL_PTR) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2967 oldval = _gvn.makecon(TypePtr::NULL_PTR); |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2968 } |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2969 // The only known value which might get overwritten is oldval. |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2970 pre_barrier(false /* do_load */, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2971 control(), NULL, NULL, max_juint, NULL, NULL, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2972 oldval /* pre_val */, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2973 T_OBJECT); |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2974 } else { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2975 ShouldNotReachHere(); |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2976 } |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2977 |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
2978 #ifdef _LP64 |
163 | 2979 if (adr->bottom_type()->is_ptr_to_narrowoop()) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2980 Node *newval_enc = _gvn.transform(new (C) EncodePNode(newval, newval->bottom_type()->make_narrowoop())); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2981 if (kind == LS_xchg) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2982 load_store = _gvn.transform(new (C) GetAndSetNNode(control(), mem, adr, |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2983 newval_enc, adr_type, value_type->make_narrowoop())); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2984 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2985 assert(kind == LS_cmpxchg, "wrong LoadStore operation"); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2986 Node *oldval_enc = _gvn.transform(new (C) EncodePNode(oldval, oldval->bottom_type()->make_narrowoop())); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2987 load_store = _gvn.transform(new (C) CompareAndSwapNNode(control(), mem, adr, |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2988 newval_enc, oldval_enc)); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2989 } |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
2990 } else |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
2991 #endif |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
174
diff
changeset
|
2992 { |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2993 if (kind == LS_xchg) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2994 load_store = _gvn.transform(new (C) GetAndSetPNode(control(), mem, adr, newval, adr_type, value_type->is_oopptr())); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2995 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2996 assert(kind == LS_cmpxchg, "wrong LoadStore operation"); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2997 load_store = _gvn.transform(new (C) CompareAndSwapPNode(control(), mem, adr, newval, oldval)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2998 } |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
174
diff
changeset
|
2999 } |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3000 post_barrier(control(), load_store, base, adr, alias_idx, newval, T_OBJECT, true); |
0 | 3001 break; |
3002 default: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3003 fatal(err_msg_res("unexpected type %d: %s", type, type2name(type))); |
0 | 3004 break; |
3005 } | |
3006 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3007 // SCMemProjNodes represent the memory state of a LoadStore. Their |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3008 // main role is to prevent LoadStore nodes from being optimized away |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3009 // when their results aren't used. |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3010 Node* proj = _gvn.transform(new (C) SCMemProjNode(load_store)); |
0 | 3011 set_memory(proj, alias_idx); |
3012 | |
12169
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3013 if (type == T_OBJECT && kind == LS_xchg) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3014 #ifdef _LP64 |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3015 if (adr->bottom_type()->is_ptr_to_narrowoop()) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3016 load_store = _gvn.transform(new (C) DecodeNNode(load_store, load_store->get_ptr_type())); |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3017 } |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3018 #endif |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3019 if (can_move_pre_barrier()) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3020 // Don't need to load pre_val. The old value is returned by load_store. |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3021 // The pre_barrier can execute after the xchg as long as no safepoint |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3022 // gets inserted between them. |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3023 pre_barrier(false /* do_load */, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3024 control(), NULL, NULL, max_juint, NULL, NULL, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3025 load_store /* pre_val */, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3026 T_OBJECT); |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3027 } |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3028 } |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3029 |
0 | 3030 // Add the trailing membar surrounding the access |
3031 insert_mem_bar(Op_MemBarCPUOrder); | |
3032 insert_mem_bar(Op_MemBarAcquire); | |
3033 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3034 assert(type2size[load_store->bottom_type()->basic_type()] == type2size[rtype], "result type should match"); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3035 set_result(load_store); |
0 | 3036 return true; |
3037 } | |
3038 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3039 //----------------------------inline_unsafe_ordered_store---------------------- |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3040 // public native void sun.misc.Unsafe.putOrderedObject(Object o, long offset, Object x); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3041 // public native void sun.misc.Unsafe.putOrderedInt(Object o, long offset, int x); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3042 // public native void sun.misc.Unsafe.putOrderedLong(Object o, long offset, long x); |
0 | 3043 bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) { |
3044 // This is another variant of inline_unsafe_access, differing in | |
3045 // that it always issues store-store ("release") barrier and ensures | |
3046 // store-atomicity (which only matters for "long"). | |
3047 | |
3048 if (callee()->is_static()) return false; // caller must have the capability! | |
3049 | |
3050 #ifndef PRODUCT | |
3051 { | |
3052 ResourceMark rm; | |
3053 // Check the signatures. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3054 ciSignature* sig = callee()->signature(); |
0 | 3055 #ifdef ASSERT |
3056 BasicType rtype = sig->return_type()->basic_type(); | |
3057 assert(rtype == T_VOID, "must return void"); | |
3058 assert(sig->count() == 3, "has 3 arguments"); | |
3059 assert(sig->type_at(0)->basic_type() == T_OBJECT, "base is object"); | |
3060 assert(sig->type_at(1)->basic_type() == T_LONG, "offset is long"); | |
3061 #endif // ASSERT | |
3062 } | |
3063 #endif //PRODUCT | |
3064 | |
3065 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
3066 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3067 // Get arguments: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3068 Node* receiver = argument(0); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3069 Node* base = argument(1); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3070 Node* offset = argument(2); // type: long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3071 Node* val = argument(4); // type: oop, int, or long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3072 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3073 // Null check receiver. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3074 receiver = null_check(receiver); |
0 | 3075 if (stopped()) { |
3076 return true; | |
3077 } | |
3078 | |
3079 // Build field offset expression. | |
3080 assert(Unsafe_field_offset_to_byte_offset(11) == 11, "fieldOffset must be byte-scaled"); | |
3081 // 32-bit machines ignore the high half of long offsets | |
3082 offset = ConvL2X(offset); | |
3083 Node* adr = make_unsafe_address(base, offset); | |
3084 const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); | |
3085 const Type *value_type = Type::get_const_basic_type(type); | |
3086 Compile::AliasType* alias_type = C->alias_type(adr_type); | |
3087 | |
3088 insert_mem_bar(Op_MemBarRelease); | |
3089 insert_mem_bar(Op_MemBarCPUOrder); | |
3090 // Ensure that the store is atomic for longs: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3091 const bool require_atomic_access = true; |
0 | 3092 Node* store; |
3093 if (type == T_OBJECT) // reference stores need a store barrier. | |
825 | 3094 store = store_oop_to_unknown(control(), base, adr, adr_type, val, type); |
0 | 3095 else { |
3096 store = store_to_memory(control(), adr, val, type, adr_type, require_atomic_access); | |
3097 } | |
3098 insert_mem_bar(Op_MemBarCPUOrder); | |
3099 return true; | |
3100 } | |
3101 | |
7425 | 3102 bool LibraryCallKit::inline_unsafe_fence(vmIntrinsics::ID id) { |
3103 // Regardless of form, don't allow previous ld/st to move down, | |
3104 // then issue acquire, release, or volatile mem_bar. | |
3105 insert_mem_bar(Op_MemBarCPUOrder); | |
3106 switch(id) { | |
3107 case vmIntrinsics::_loadFence: | |
3108 insert_mem_bar(Op_MemBarAcquire); | |
3109 return true; | |
3110 case vmIntrinsics::_storeFence: | |
3111 insert_mem_bar(Op_MemBarRelease); | |
3112 return true; | |
3113 case vmIntrinsics::_fullFence: | |
3114 insert_mem_bar(Op_MemBarVolatile); | |
3115 return true; | |
3116 default: | |
3117 fatal_unexpected_iid(id); | |
3118 return false; | |
3119 } | |
3120 } | |
3121 | |
12078 | 3122 bool LibraryCallKit::klass_needs_init_guard(Node* kls) { |
3123 if (!kls->is_Con()) { | |
3124 return true; | |
3125 } | |
3126 const TypeKlassPtr* klsptr = kls->bottom_type()->isa_klassptr(); | |
3127 if (klsptr == NULL) { | |
3128 return true; | |
3129 } | |
3130 ciInstanceKlass* ik = klsptr->klass()->as_instance_klass(); | |
3131 // don't need a guard for a klass that is already initialized | |
3132 return !ik->is_initialized(); | |
3133 } | |
3134 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3135 //----------------------------inline_unsafe_allocate--------------------------- |
12078 | 3136 // public native Object sun.misc.Unsafe.allocateInstance(Class<?> cls); |
0 | 3137 bool LibraryCallKit::inline_unsafe_allocate() { |
3138 if (callee()->is_static()) return false; // caller must have the capability! | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3139 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3140 null_check_receiver(); // null-check, then ignore |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3141 Node* cls = null_check(argument(1)); |
0 | 3142 if (stopped()) return true; |
3143 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3144 Node* kls = load_klass_from_mirror(cls, false, NULL, 0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3145 kls = null_check(kls); |
0 | 3146 if (stopped()) return true; // argument was like int.class |
3147 | |
12078 | 3148 Node* test = NULL; |
3149 if (LibraryCallKit::klass_needs_init_guard(kls)) { | |
3150 // Note: The argument might still be an illegal value like | |
3151 // Serializable.class or Object[].class. The runtime will handle it. | |
3152 // But we must make an explicit check for initialization. | |
3153 Node* insp = basic_plus_adr(kls, in_bytes(InstanceKlass::init_state_offset())); | |
3154 // Use T_BOOLEAN for InstanceKlass::_init_state so the compiler | |
3155 // can generate code to load it as unsigned byte. | |
3156 Node* inst = make_load(NULL, insp, TypeInt::UBYTE, T_BOOLEAN); | |
3157 Node* bits = intcon(InstanceKlass::fully_initialized); | |
3158 test = _gvn.transform(new (C) SubINode(inst, bits)); | |
3159 // The 'test' is non-zero if we need to take a slow path. | |
3160 } | |
0 | 3161 |
3162 Node* obj = new_instance(kls, test); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3163 set_result(obj); |
0 | 3164 return true; |
3165 } | |
3166 | |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3167 #ifdef TRACE_HAVE_INTRINSICS |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3168 /* |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3169 * oop -> myklass |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3170 * myklass->trace_id |= USED |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3171 * return myklass->trace_id & ~0x3 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3172 */ |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3173 bool LibraryCallKit::inline_native_classID() { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3174 null_check_receiver(); // null-check, then ignore |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3175 Node* cls = null_check(argument(1), T_OBJECT); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3176 Node* kls = load_klass_from_mirror(cls, false, NULL, 0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3177 kls = null_check(kls, T_OBJECT); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3178 ByteSize offset = TRACE_ID_OFFSET; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3179 Node* insp = basic_plus_adr(kls, in_bytes(offset)); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3180 Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3181 Node* bits = longcon(~0x03l); // ignore bit 0 & 1 |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3182 Node* andl = _gvn.transform(new (C) AndLNode(tvalue, bits)); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3183 Node* clsused = longcon(0x01l); // set the class bit |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3184 Node* orl = _gvn.transform(new (C) OrLNode(tvalue, clsused)); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3185 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3186 const TypePtr *adr_type = _gvn.type(insp)->isa_ptr(); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3187 store_to_memory(control(), insp, orl, T_LONG, adr_type); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3188 set_result(andl); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3189 return true; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3190 } |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3191 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3192 bool LibraryCallKit::inline_native_threadID() { |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3193 Node* tls_ptr = NULL; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3194 Node* cur_thr = generate_current_thread(tls_ptr); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3195 Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3196 Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3197 p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::thread_id_offset())); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3198 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3199 Node* threadid = NULL; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3200 size_t thread_id_size = OSThread::thread_id_size(); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3201 if (thread_id_size == (size_t) BytesPerLong) { |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3202 threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG)); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3203 } else if (thread_id_size == (size_t) BytesPerInt) { |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3204 threadid = make_load(control(), p, TypeInt::INT, T_INT); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3205 } else { |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3206 ShouldNotReachHere(); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3207 } |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3208 set_result(threadid); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3209 return true; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3210 } |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3211 #endif |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3212 |
0 | 3213 //------------------------inline_native_time_funcs-------------- |
3214 // inline code for System.currentTimeMillis() and System.nanoTime() | |
3215 // these have the same type and signature | |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3216 bool LibraryCallKit::inline_native_time_funcs(address funcAddr, const char* funcName) { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3217 const TypeFunc* tf = OptoRuntime::void_long_Type(); |
0 | 3218 const TypePtr* no_memory_effects = NULL; |
3219 Node* time = make_runtime_call(RC_LEAF, tf, funcAddr, funcName, no_memory_effects); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3220 Node* value = _gvn.transform(new (C) ProjNode(time, TypeFunc::Parms+0)); |
0 | 3221 #ifdef ASSERT |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3222 Node* value_top = _gvn.transform(new (C) ProjNode(time, TypeFunc::Parms+1)); |
0 | 3223 assert(value_top == top(), "second value must be top"); |
3224 #endif | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3225 set_result(value); |
0 | 3226 return true; |
3227 } | |
3228 | |
3229 //------------------------inline_native_currentThread------------------ | |
3230 bool LibraryCallKit::inline_native_currentThread() { | |
3231 Node* junk = NULL; | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3232 set_result(generate_current_thread(junk)); |
0 | 3233 return true; |
3234 } | |
3235 | |
3236 //------------------------inline_native_isInterrupted------------------ | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3237 // private native boolean java.lang.Thread.isInterrupted(boolean ClearInterrupted); |
0 | 3238 bool LibraryCallKit::inline_native_isInterrupted() { |
3239 // Add a fast path to t.isInterrupted(clear_int): | |
17716
cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
17670
diff
changeset
|
3240 // (t == Thread.current() && |
cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
17670
diff
changeset
|
3241 // (!TLS._osthread._interrupted || WINDOWS_ONLY(false) NOT_WINDOWS(!clear_int))) |
0 | 3242 // ? TLS._osthread._interrupted : /*slow path:*/ t.isInterrupted(clear_int) |
3243 // So, in the common case that the interrupt bit is false, | |
3244 // we avoid making a call into the VM. Even if the interrupt bit | |
3245 // is true, if the clear_int argument is false, we avoid the VM call. | |
3246 // However, if the receiver is not currentThread, we must call the VM, | |
3247 // because there must be some locking done around the operation. | |
3248 | |
3249 // We only go to the fast case code if we pass two guards. | |
3250 // Paths which do not pass are accumulated in the slow_region. | |
7422
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3251 |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3252 enum { |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3253 no_int_result_path = 1, // t == Thread.current() && !TLS._osthread._interrupted |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3254 no_clear_result_path = 2, // t == Thread.current() && TLS._osthread._interrupted && !clear_int |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3255 slow_result_path = 3, // slow path: t.isInterrupted(clear_int) |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3256 PATH_LIMIT |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3257 }; |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3258 |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3259 // Ensure that it's not possible to move the load of TLS._osthread._interrupted flag |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3260 // out of the function. |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3261 insert_mem_bar(Op_MemBarCPUOrder); |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3262 |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3263 RegionNode* result_rgn = new (C) RegionNode(PATH_LIMIT); |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3264 PhiNode* result_val = new (C) PhiNode(result_rgn, TypeInt::BOOL); |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3265 |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3266 RegionNode* slow_region = new (C) RegionNode(1); |
0 | 3267 record_for_igvn(slow_region); |
3268 | |
3269 // (a) Receiving thread must be the current thread. | |
3270 Node* rec_thr = argument(0); | |
3271 Node* tls_ptr = NULL; | |
3272 Node* cur_thr = generate_current_thread(tls_ptr); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3273 Node* cmp_thr = _gvn.transform(new (C) CmpPNode(cur_thr, rec_thr)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3274 Node* bol_thr = _gvn.transform(new (C) BoolNode(cmp_thr, BoolTest::ne)); |
0 | 3275 |
7422
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3276 generate_slow_guard(bol_thr, slow_region); |
0 | 3277 |
3278 // (b) Interrupt bit on TLS must be false. | |
3279 Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); | |
3280 Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS); | |
3281 p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::interrupted_offset())); | |
7422
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3282 |
787
aabd393cf1ee
6772683: Thread.isInterrupted() fails to return true on multiprocessor PC
kvn
parents:
775
diff
changeset
|
3283 // 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
|
3284 Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT); |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3285 Node* cmp_bit = _gvn.transform(new (C) CmpINode(int_bit, intcon(0))); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3286 Node* bol_bit = _gvn.transform(new (C) BoolNode(cmp_bit, BoolTest::ne)); |
0 | 3287 |
3288 IfNode* iff_bit = create_and_map_if(control(), bol_bit, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN); | |
3289 | |
3290 // First fast path: if (!TLS._interrupted) return false; | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3291 Node* false_bit = _gvn.transform(new (C) IfFalseNode(iff_bit)); |
0 | 3292 result_rgn->init_req(no_int_result_path, false_bit); |
3293 result_val->init_req(no_int_result_path, intcon(0)); | |
3294 | |
3295 // drop through to next case | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3296 set_control( _gvn.transform(new (C) IfTrueNode(iff_bit))); |
0 | 3297 |
17716
cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
17670
diff
changeset
|
3298 #ifndef TARGET_OS_FAMILY_windows |
0 | 3299 // (c) Or, if interrupt bit is set and clear_int is false, use 2nd fast path. |
3300 Node* clr_arg = argument(1); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3301 Node* cmp_arg = _gvn.transform(new (C) CmpINode(clr_arg, intcon(0))); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3302 Node* bol_arg = _gvn.transform(new (C) BoolNode(cmp_arg, BoolTest::ne)); |
0 | 3303 IfNode* iff_arg = create_and_map_if(control(), bol_arg, PROB_FAIR, COUNT_UNKNOWN); |
3304 | |
3305 // Second fast path: ... else if (!clear_int) return true; | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3306 Node* false_arg = _gvn.transform(new (C) IfFalseNode(iff_arg)); |
0 | 3307 result_rgn->init_req(no_clear_result_path, false_arg); |
3308 result_val->init_req(no_clear_result_path, intcon(1)); | |
3309 | |
3310 // drop through to next case | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3311 set_control( _gvn.transform(new (C) IfTrueNode(iff_arg))); |
17716
cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
17670
diff
changeset
|
3312 #else |
cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
17670
diff
changeset
|
3313 // To return true on Windows you must read the _interrupted field |
cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
17670
diff
changeset
|
3314 // and check the the event state i.e. take the slow path. |
cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
17670
diff
changeset
|
3315 #endif // TARGET_OS_FAMILY_windows |
0 | 3316 |
3317 // (d) Otherwise, go to the slow path. | |
3318 slow_region->add_req(control()); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3319 set_control( _gvn.transform(slow_region)); |
0 | 3320 |
3321 if (stopped()) { | |
3322 // There is no slow path. | |
3323 result_rgn->init_req(slow_result_path, top()); | |
3324 result_val->init_req(slow_result_path, top()); | |
3325 } else { | |
3326 // non-virtual because it is a private non-static | |
3327 CallJavaNode* slow_call = generate_method_call(vmIntrinsics::_isInterrupted); | |
3328 | |
3329 Node* slow_val = set_results_for_java_call(slow_call); | |
3330 // this->control() comes from set_results_for_java_call | |
3331 | |
3332 Node* fast_io = slow_call->in(TypeFunc::I_O); | |
3333 Node* fast_mem = slow_call->in(TypeFunc::Memory); | |
7422
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3334 |
0 | 3335 // These two phis are pre-filled with copies of of the fast IO and Memory |
7422
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3336 PhiNode* result_mem = PhiNode::make(result_rgn, fast_mem, Type::MEMORY, TypePtr::BOTTOM); |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3337 PhiNode* result_io = PhiNode::make(result_rgn, fast_io, Type::ABIO); |
0 | 3338 |
3339 result_rgn->init_req(slow_result_path, control()); | |
7422
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3340 result_io ->init_req(slow_result_path, i_o()); |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3341 result_mem->init_req(slow_result_path, reset_memory()); |
0 | 3342 result_val->init_req(slow_result_path, slow_val); |
3343 | |
7422
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3344 set_all_memory(_gvn.transform(result_mem)); |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3345 set_i_o( _gvn.transform(result_io)); |
0 | 3346 } |
3347 | |
3348 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3349 set_result(result_rgn, result_val); |
0 | 3350 return true; |
3351 } | |
3352 | |
3353 //---------------------------load_mirror_from_klass---------------------------- | |
3354 // Given a klass oop, load its java mirror (a java.lang.Class oop). | |
3355 Node* LibraryCallKit::load_mirror_from_klass(Node* klass) { | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3961
diff
changeset
|
3356 Node* p = basic_plus_adr(klass, in_bytes(Klass::java_mirror_offset())); |
0 | 3357 return make_load(NULL, p, TypeInstPtr::MIRROR, T_OBJECT); |
3358 } | |
3359 | |
3360 //-----------------------load_klass_from_mirror_common------------------------- | |
3361 // Given a java mirror (a java.lang.Class oop), load its corresponding klass oop. | |
3362 // Test the klass oop for null (signifying a primitive Class like Integer.TYPE), | |
3363 // and branch to the given path on the region. | |
3364 // If never_see_null, take an uncommon trap on null, so we can optimistically | |
3365 // compile for the non-null case. | |
3366 // If the region is NULL, force never_see_null = true. | |
3367 Node* LibraryCallKit::load_klass_from_mirror_common(Node* mirror, | |
3368 bool never_see_null, | |
3369 RegionNode* region, | |
3370 int null_path, | |
3371 int offset) { | |
3372 if (region == NULL) never_see_null = true; | |
3373 Node* p = basic_plus_adr(mirror, offset); | |
3374 const TypeKlassPtr* kls_type = TypeKlassPtr::OBJECT_OR_NULL; | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3375 Node* kls = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeRawPtr::BOTTOM, kls_type)); |
0 | 3376 Node* null_ctl = top(); |
3377 kls = null_check_oop(kls, &null_ctl, never_see_null); | |
3378 if (region != NULL) { | |
3379 // Set region->in(null_path) if the mirror is a primitive (e.g, int.class). | |
3380 region->init_req(null_path, null_ctl); | |
3381 } else { | |
3382 assert(null_ctl == top(), "no loose ends"); | |
3383 } | |
3384 return kls; | |
3385 } | |
3386 | |
3387 //--------------------(inline_native_Class_query helpers)--------------------- | |
3388 // Use this for JVM_ACC_INTERFACE, JVM_ACC_IS_CLONEABLE, JVM_ACC_HAS_FINALIZER. | |
3389 // Fall through if (mods & mask) == bits, take the guard otherwise. | |
3390 Node* LibraryCallKit::generate_access_flags_guard(Node* kls, int modifier_mask, int modifier_bits, RegionNode* region) { | |
3391 // Branch around if the given klass has the given modifier bit set. | |
3392 // Like generate_guard, adds a new path onto the region. | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3961
diff
changeset
|
3393 Node* modp = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset())); |
0 | 3394 Node* mods = make_load(NULL, modp, TypeInt::INT, T_INT); |
3395 Node* mask = intcon(modifier_mask); | |
3396 Node* bits = intcon(modifier_bits); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3397 Node* mbit = _gvn.transform(new (C) AndINode(mods, mask)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3398 Node* cmp = _gvn.transform(new (C) CmpINode(mbit, bits)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3399 Node* bol = _gvn.transform(new (C) BoolNode(cmp, BoolTest::ne)); |
0 | 3400 return generate_fair_guard(bol, region); |
3401 } | |
3402 Node* LibraryCallKit::generate_interface_guard(Node* kls, RegionNode* region) { | |
3403 return generate_access_flags_guard(kls, JVM_ACC_INTERFACE, 0, region); | |
3404 } | |
3405 | |
3406 //-------------------------inline_native_Class_query------------------- | |
3407 bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { | |
3408 const Type* return_type = TypeInt::BOOL; | |
3409 Node* prim_return_value = top(); // what happens if it's a primitive class? | |
3410 bool never_see_null = !too_many_traps(Deoptimization::Reason_null_check); | |
3411 bool expect_prim = false; // most of these guys expect to work on refs | |
3412 | |
3413 enum { _normal_path = 1, _prim_path = 2, PATH_LIMIT }; | |
3414 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3415 Node* mirror = argument(0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3416 Node* obj = top(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3417 |
0 | 3418 switch (id) { |
3419 case vmIntrinsics::_isInstance: | |
3420 // nothing is an instance of a primitive type | |
3421 prim_return_value = intcon(0); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3422 obj = argument(1); |
0 | 3423 break; |
3424 case vmIntrinsics::_getModifiers: | |
3425 prim_return_value = intcon(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC); | |
3426 assert(is_power_of_2((int)JVM_ACC_WRITTEN_FLAGS+1), "change next line"); | |
3427 return_type = TypeInt::make(0, JVM_ACC_WRITTEN_FLAGS, Type::WidenMin); | |
3428 break; | |
3429 case vmIntrinsics::_isInterface: | |
3430 prim_return_value = intcon(0); | |
3431 break; | |
3432 case vmIntrinsics::_isArray: | |
3433 prim_return_value = intcon(0); | |
3434 expect_prim = true; // cf. ObjectStreamClass.getClassSignature | |
3435 break; | |
3436 case vmIntrinsics::_isPrimitive: | |
3437 prim_return_value = intcon(1); | |
3438 expect_prim = true; // obviously | |
3439 break; | |
3440 case vmIntrinsics::_getSuperclass: | |
3441 prim_return_value = null(); | |
3442 return_type = TypeInstPtr::MIRROR->cast_to_ptr_type(TypePtr::BotPTR); | |
3443 break; | |
3444 case vmIntrinsics::_getComponentType: | |
3445 prim_return_value = null(); | |
3446 return_type = TypeInstPtr::MIRROR->cast_to_ptr_type(TypePtr::BotPTR); | |
3447 break; | |
3448 case vmIntrinsics::_getClassAccessFlags: | |
3449 prim_return_value = intcon(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC); | |
3450 return_type = TypeInt::INT; // not bool! 6297094 | |
3451 break; | |
3452 default: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3453 fatal_unexpected_iid(id); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3454 break; |
0 | 3455 } |
3456 | |
3457 const TypeInstPtr* mirror_con = _gvn.type(mirror)->isa_instptr(); | |
3458 if (mirror_con == NULL) return false; // cannot happen? | |
3459 | |
3460 #ifndef PRODUCT | |
12295 | 3461 if (C->print_intrinsics() || C->print_inlining()) { |
0 | 3462 ciType* k = mirror_con->java_mirror_type(); |
3463 if (k) { | |
3464 tty->print("Inlining %s on constant Class ", vmIntrinsics::name_at(intrinsic_id())); | |
3465 k->print_name(); | |
3466 tty->cr(); | |
3467 } | |
3468 } | |
3469 #endif | |
3470 | |
3471 // Null-check the mirror, and the mirror's klass ptr (in case it is a primitive). | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3472 RegionNode* region = new (C) RegionNode(PATH_LIMIT); |
0 | 3473 record_for_igvn(region); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3474 PhiNode* phi = new (C) PhiNode(region, return_type); |
0 | 3475 |
3476 // The mirror will never be null of Reflection.getClassAccessFlags, however | |
3477 // it may be null for Class.isInstance or Class.getModifiers. Throw a NPE | |
3478 // if it is. See bug 4774291. | |
3479 | |
3480 // For Reflection.getClassAccessFlags(), the null check occurs in | |
3481 // the wrong place; see inline_unsafe_access(), above, for a similar | |
3482 // situation. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3483 mirror = null_check(mirror); |
0 | 3484 // If mirror or obj is dead, only null-path is taken. |
3485 if (stopped()) return true; | |
3486 | |
3487 if (expect_prim) never_see_null = false; // expect nulls (meaning prims) | |
3488 | |
3489 // Now load the mirror's klass metaobject, and null-check it. | |
3490 // Side-effects region with the control path if the klass is null. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3491 Node* kls = load_klass_from_mirror(mirror, never_see_null, region, _prim_path); |
0 | 3492 // If kls is null, we have a primitive mirror. |
3493 phi->init_req(_prim_path, prim_return_value); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3494 if (stopped()) { set_result(region, phi); return true; } |
12966 | 3495 bool safe_for_replace = (region->in(_prim_path) == top()); |
0 | 3496 |
3497 Node* p; // handy temp | |
3498 Node* null_ctl; | |
3499 | |
3500 // Now that we have the non-null klass, we can perform the real query. | |
3501 // For constant classes, the query will constant-fold in LoadNode::Value. | |
3502 Node* query_value = top(); | |
3503 switch (id) { | |
3504 case vmIntrinsics::_isInstance: | |
3505 // nothing is an instance of a primitive type | |
12966 | 3506 query_value = gen_instanceof(obj, kls, safe_for_replace); |
0 | 3507 break; |
3508 | |
3509 case vmIntrinsics::_getModifiers: | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3961
diff
changeset
|
3510 p = basic_plus_adr(kls, in_bytes(Klass::modifier_flags_offset())); |
0 | 3511 query_value = make_load(NULL, p, TypeInt::INT, T_INT); |
3512 break; | |
3513 | |
3514 case vmIntrinsics::_isInterface: | |
3515 // (To verify this code sequence, check the asserts in JVM_IsInterface.) | |
3516 if (generate_interface_guard(kls, region) != NULL) | |
3517 // A guard was added. If the guard is taken, it was an interface. | |
3518 phi->add_req(intcon(1)); | |
3519 // If we fall through, it's a plain class. | |
3520 query_value = intcon(0); | |
3521 break; | |
3522 | |
3523 case vmIntrinsics::_isArray: | |
3524 // (To verify this code sequence, check the asserts in JVM_IsArrayClass.) | |
3525 if (generate_array_guard(kls, region) != NULL) | |
3526 // A guard was added. If the guard is taken, it was an array. | |
3527 phi->add_req(intcon(1)); | |
3528 // If we fall through, it's a plain class. | |
3529 query_value = intcon(0); | |
3530 break; | |
3531 | |
3532 case vmIntrinsics::_isPrimitive: | |
3533 query_value = intcon(0); // "normal" path produces false | |
3534 break; | |
3535 | |
3536 case vmIntrinsics::_getSuperclass: | |
3537 // The rules here are somewhat unfortunate, but we can still do better | |
3538 // with random logic than with a JNI call. | |
3539 // Interfaces store null or Object as _super, but must report null. | |
3540 // Arrays store an intermediate super as _super, but must report Object. | |
3541 // Other types can report the actual _super. | |
3542 // (To verify this code sequence, check the asserts in JVM_IsInterface.) | |
3543 if (generate_interface_guard(kls, region) != NULL) | |
3544 // A guard was added. If the guard is taken, it was an interface. | |
3545 phi->add_req(null()); | |
3546 if (generate_array_guard(kls, region) != NULL) | |
3547 // A guard was added. If the guard is taken, it was an array. | |
3548 phi->add_req(makecon(TypeInstPtr::make(env()->Object_klass()->java_mirror()))); | |
3549 // If we fall through, it's a plain class. Get its _super. | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3961
diff
changeset
|
3550 p = basic_plus_adr(kls, in_bytes(Klass::super_offset())); |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3551 kls = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeRawPtr::BOTTOM, TypeKlassPtr::OBJECT_OR_NULL)); |
0 | 3552 null_ctl = top(); |
3553 kls = null_check_oop(kls, &null_ctl); | |
3554 if (null_ctl != top()) { | |
3555 // If the guard is taken, Object.superClass is null (both klass and mirror). | |
3556 region->add_req(null_ctl); | |
3557 phi ->add_req(null()); | |
3558 } | |
3559 if (!stopped()) { | |
3560 query_value = load_mirror_from_klass(kls); | |
3561 } | |
3562 break; | |
3563 | |
3564 case vmIntrinsics::_getComponentType: | |
3565 if (generate_array_guard(kls, region) != NULL) { | |
3566 // Be sure to pin the oop load to the guard edge just created: | |
3567 Node* is_array_ctrl = region->in(region->req()-1); | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6804
diff
changeset
|
3568 Node* cma = basic_plus_adr(kls, in_bytes(ArrayKlass::component_mirror_offset())); |
0 | 3569 Node* cmo = make_load(is_array_ctrl, cma, TypeInstPtr::MIRROR, T_OBJECT); |
3570 phi->add_req(cmo); | |
3571 } | |
3572 query_value = null(); // non-array case is null | |
3573 break; | |
3574 | |
3575 case vmIntrinsics::_getClassAccessFlags: | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3961
diff
changeset
|
3576 p = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset())); |
0 | 3577 query_value = make_load(NULL, p, TypeInt::INT, T_INT); |
3578 break; | |
3579 | |
3580 default: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3581 fatal_unexpected_iid(id); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3582 break; |
0 | 3583 } |
3584 | |
3585 // Fall-through is the normal case of a query to a real class. | |
3586 phi->init_req(1, query_value); | |
3587 region->init_req(1, control()); | |
3588 | |
3589 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3590 set_result(region, phi); |
0 | 3591 return true; |
3592 } | |
3593 | |
3594 //--------------------------inline_native_subtype_check------------------------ | |
3595 // This intrinsic takes the JNI calls out of the heart of | |
3596 // UnsafeFieldAccessorImpl.set, which improves Field.set, readObject, etc. | |
3597 bool LibraryCallKit::inline_native_subtype_check() { | |
3598 // Pull both arguments off the stack. | |
3599 Node* args[2]; // two java.lang.Class mirrors: superc, subc | |
3600 args[0] = argument(0); | |
3601 args[1] = argument(1); | |
3602 Node* klasses[2]; // corresponding Klasses: superk, subk | |
3603 klasses[0] = klasses[1] = top(); | |
3604 | |
3605 enum { | |
3606 // A full decision tree on {superc is prim, subc is prim}: | |
3607 _prim_0_path = 1, // {P,N} => false | |
3608 // {P,P} & superc!=subc => false | |
3609 _prim_same_path, // {P,P} & superc==subc => true | |
3610 _prim_1_path, // {N,P} => false | |
3611 _ref_subtype_path, // {N,N} & subtype check wins => true | |
3612 _both_ref_path, // {N,N} & subtype check loses => false | |
3613 PATH_LIMIT | |
3614 }; | |
3615 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3616 RegionNode* region = new (C) RegionNode(PATH_LIMIT); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3617 Node* phi = new (C) PhiNode(region, TypeInt::BOOL); |
0 | 3618 record_for_igvn(region); |
3619 | |
3620 const TypePtr* adr_type = TypeRawPtr::BOTTOM; // memory type of loads | |
3621 const TypeKlassPtr* kls_type = TypeKlassPtr::OBJECT_OR_NULL; | |
3622 int class_klass_offset = java_lang_Class::klass_offset_in_bytes(); | |
3623 | |
3624 // First null-check both mirrors and load each mirror's klass metaobject. | |
3625 int which_arg; | |
3626 for (which_arg = 0; which_arg <= 1; which_arg++) { | |
3627 Node* arg = args[which_arg]; | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3628 arg = null_check(arg); |
0 | 3629 if (stopped()) break; |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7200
diff
changeset
|
3630 args[which_arg] = arg; |
0 | 3631 |
3632 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
|
3633 Node* kls = LoadKlassNode::make(_gvn, immutable_memory(), p, adr_type, kls_type); |
0 | 3634 klasses[which_arg] = _gvn.transform(kls); |
3635 } | |
3636 | |
3637 // Having loaded both klasses, test each for null. | |
3638 bool never_see_null = !too_many_traps(Deoptimization::Reason_null_check); | |
3639 for (which_arg = 0; which_arg <= 1; which_arg++) { | |
3640 Node* kls = klasses[which_arg]; | |
3641 Node* null_ctl = top(); | |
3642 kls = null_check_oop(kls, &null_ctl, never_see_null); | |
3643 int prim_path = (which_arg == 0 ? _prim_0_path : _prim_1_path); | |
3644 region->init_req(prim_path, null_ctl); | |
3645 if (stopped()) break; | |
3646 klasses[which_arg] = kls; | |
3647 } | |
3648 | |
3649 if (!stopped()) { | |
3650 // now we have two reference types, in klasses[0..1] | |
3651 Node* subk = klasses[1]; // the argument to isAssignableFrom | |
3652 Node* superk = klasses[0]; // the receiver | |
3653 region->set_req(_both_ref_path, gen_subtype_check(subk, superk)); | |
3654 // now we have a successful reference subtype check | |
3655 region->set_req(_ref_subtype_path, control()); | |
3656 } | |
3657 | |
3658 // If both operands are primitive (both klasses null), then | |
3659 // we must return true when they are identical primitives. | |
3660 // It is convenient to test this after the first null klass check. | |
3661 set_control(region->in(_prim_0_path)); // go back to first null check | |
3662 if (!stopped()) { | |
3663 // Since superc is primitive, make a guard for the superc==subc case. | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3664 Node* cmp_eq = _gvn.transform(new (C) CmpPNode(args[0], args[1])); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3665 Node* bol_eq = _gvn.transform(new (C) BoolNode(cmp_eq, BoolTest::eq)); |
0 | 3666 generate_guard(bol_eq, region, PROB_FAIR); |
3667 if (region->req() == PATH_LIMIT+1) { | |
3668 // A guard was added. If the added guard is taken, superc==subc. | |
3669 region->swap_edges(PATH_LIMIT, _prim_same_path); | |
3670 region->del_req(PATH_LIMIT); | |
3671 } | |
3672 region->set_req(_prim_0_path, control()); // Not equal after all. | |
3673 } | |
3674 | |
3675 // these are the only paths that produce 'true': | |
3676 phi->set_req(_prim_same_path, intcon(1)); | |
3677 phi->set_req(_ref_subtype_path, intcon(1)); | |
3678 | |
3679 // pull together the cases: | |
3680 assert(region->req() == PATH_LIMIT, "sane region"); | |
3681 for (uint i = 1; i < region->req(); i++) { | |
3682 Node* ctl = region->in(i); | |
3683 if (ctl == NULL || ctl == top()) { | |
3684 region->set_req(i, top()); | |
3685 phi ->set_req(i, top()); | |
3686 } else if (phi->in(i) == NULL) { | |
3687 phi->set_req(i, intcon(0)); // all other paths produce 'false' | |
3688 } | |
3689 } | |
3690 | |
3691 set_control(_gvn.transform(region)); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3692 set_result(_gvn.transform(phi)); |
0 | 3693 return true; |
3694 } | |
3695 | |
3696 //---------------------generate_array_guard_common------------------------ | |
3697 Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region, | |
3698 bool obj_array, bool not_array) { | |
3699 // If obj_array/non_array==false/false: | |
3700 // Branch around if the given klass is in fact an array (either obj or prim). | |
3701 // If obj_array/non_array==false/true: | |
3702 // Branch around if the given klass is not an array klass of any kind. | |
3703 // If obj_array/non_array==true/true: | |
3704 // Branch around if the kls is not an oop array (kls is int[], String, etc.) | |
3705 // If obj_array/non_array==true/false: | |
3706 // Branch around if the kls is an oop array (Object[] or subtype) | |
3707 // | |
3708 // Like generate_guard, adds a new path onto the region. | |
3709 jint layout_con = 0; | |
3710 Node* layout_val = get_layout_helper(kls, layout_con); | |
3711 if (layout_val == NULL) { | |
3712 bool query = (obj_array | |
3713 ? Klass::layout_helper_is_objArray(layout_con) | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6615
diff
changeset
|
3714 : Klass::layout_helper_is_array(layout_con)); |
0 | 3715 if (query == not_array) { |
3716 return NULL; // never a branch | |
3717 } else { // always a branch | |
3718 Node* always_branch = control(); | |
3719 if (region != NULL) | |
3720 region->add_req(always_branch); | |
3721 set_control(top()); | |
3722 return always_branch; | |
3723 } | |
3724 } | |
3725 // Now test the correct condition. | |
3726 jint nval = (obj_array | |
3727 ? ((jint)Klass::_lh_array_tag_type_value | |
3728 << Klass::_lh_array_tag_shift) | |
3729 : Klass::_lh_neutral_value); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3730 Node* cmp = _gvn.transform(new(C) CmpINode(layout_val, intcon(nval))); |
0 | 3731 BoolTest::mask btest = BoolTest::lt; // correct for testing is_[obj]array |
3732 // invert the test if we are looking for a non-array | |
3733 if (not_array) btest = BoolTest(btest).negate(); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3734 Node* bol = _gvn.transform(new(C) BoolNode(cmp, btest)); |
0 | 3735 return generate_fair_guard(bol, region); |
3736 } | |
3737 | |
3738 | |
3739 //-----------------------inline_native_newArray-------------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3740 // private static native Object java.lang.reflect.newArray(Class<?> componentType, int length); |
0 | 3741 bool LibraryCallKit::inline_native_newArray() { |
3742 Node* mirror = argument(0); | |
3743 Node* count_val = argument(1); | |
3744 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3745 mirror = null_check(mirror); |
163 | 3746 // If mirror or obj is dead, only null-path is taken. |
3747 if (stopped()) return true; | |
0 | 3748 |
3749 enum { _normal_path = 1, _slow_path = 2, PATH_LIMIT }; | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3750 RegionNode* result_reg = new(C) RegionNode(PATH_LIMIT); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3751 PhiNode* result_val = new(C) PhiNode(result_reg, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3752 TypeInstPtr::NOTNULL); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3753 PhiNode* result_io = new(C) PhiNode(result_reg, Type::ABIO); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3754 PhiNode* result_mem = new(C) PhiNode(result_reg, Type::MEMORY, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3755 TypePtr::BOTTOM); |
0 | 3756 |
3757 bool never_see_null = !too_many_traps(Deoptimization::Reason_null_check); | |
3758 Node* klass_node = load_array_klass_from_mirror(mirror, never_see_null, | |
3759 result_reg, _slow_path); | |
3760 Node* normal_ctl = control(); | |
3761 Node* no_array_ctl = result_reg->in(_slow_path); | |
3762 | |
3763 // Generate code for the slow case. We make a call to newArray(). | |
3764 set_control(no_array_ctl); | |
3765 if (!stopped()) { | |
3766 // Either the input type is void.class, or else the | |
3767 // array klass has not yet been cached. Either the | |
3768 // ensuing call will throw an exception, or else it | |
3769 // will cache the array klass for next time. | |
3770 PreserveJVMState pjvms(this); | |
3771 CallJavaNode* slow_call = generate_method_call_static(vmIntrinsics::_newArray); | |
3772 Node* slow_result = set_results_for_java_call(slow_call); | |
3773 // this->control() comes from set_results_for_java_call | |
3774 result_reg->set_req(_slow_path, control()); | |
3775 result_val->set_req(_slow_path, slow_result); | |
3776 result_io ->set_req(_slow_path, i_o()); | |
3777 result_mem->set_req(_slow_path, reset_memory()); | |
3778 } | |
3779 | |
3780 set_control(normal_ctl); | |
3781 if (!stopped()) { | |
3782 // Normal case: The array type has been cached in the java.lang.Class. | |
3783 // The following call works fine even if the array type is polymorphic. | |
3784 // It could be a dynamic mix of int[], boolean[], Object[], etc. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3785 Node* obj = new_array(klass_node, count_val, 0); // no arguments to push |
0 | 3786 result_reg->init_req(_normal_path, control()); |
3787 result_val->init_req(_normal_path, obj); | |
3788 result_io ->init_req(_normal_path, i_o()); | |
3789 result_mem->init_req(_normal_path, reset_memory()); | |
3790 } | |
3791 | |
3792 // Return the combined state. | |
3793 set_i_o( _gvn.transform(result_io) ); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3794 set_all_memory( _gvn.transform(result_mem)); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3795 |
0 | 3796 C->set_has_split_ifs(true); // Has chance for split-if optimization |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3797 set_result(result_reg, result_val); |
0 | 3798 return true; |
3799 } | |
3800 | |
3801 //----------------------inline_native_getLength-------------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3802 // public static native int java.lang.reflect.Array.getLength(Object array); |
0 | 3803 bool LibraryCallKit::inline_native_getLength() { |
3804 if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; | |
3805 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3806 Node* array = null_check(argument(0)); |
0 | 3807 // If array is dead, only null-path is taken. |
3808 if (stopped()) return true; | |
3809 | |
3810 // Deoptimize if it is a non-array. | |
3811 Node* non_array = generate_non_array_guard(load_object_klass(array), NULL); | |
3812 | |
3813 if (non_array != NULL) { | |
3814 PreserveJVMState pjvms(this); | |
3815 set_control(non_array); | |
3816 uncommon_trap(Deoptimization::Reason_intrinsic, | |
3817 Deoptimization::Action_maybe_recompile); | |
3818 } | |
3819 | |
3820 // If control is dead, only non-array-path is taken. | |
3821 if (stopped()) return true; | |
3822 | |
3823 // The works fine even if the array type is polymorphic. | |
3824 // It could be a dynamic mix of int[], boolean[], Object[], etc. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3825 Node* result = load_array_length(array); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3826 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3827 C->set_has_split_ifs(true); // Has chance for split-if optimization |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3828 set_result(result); |
0 | 3829 return true; |
3830 } | |
3831 | |
3832 //------------------------inline_array_copyOf---------------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3833 // public static <T,U> T[] java.util.Arrays.copyOf( U[] original, int newLength, Class<? extends T[]> newType); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3834 // public static <T,U> T[] java.util.Arrays.copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType); |
0 | 3835 bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { |
3836 if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; | |
3837 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3838 // Get the arguments. |
0 | 3839 Node* original = argument(0); |
3840 Node* start = is_copyOfRange? argument(1): intcon(0); | |
3841 Node* end = is_copyOfRange? argument(2): argument(1); | |
3842 Node* array_type_mirror = is_copyOfRange? argument(3): argument(2); | |
3843 | |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3844 Node* newcopy; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3845 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3846 // Set the original stack and the reexecute bit for the interpreter to reexecute |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3847 // the bytecode that invokes Arrays.copyOf if deoptimization happens. |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3848 { PreserveReexecuteState preexecs(this); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3849 jvms()->set_should_reexecute(true); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3850 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3851 array_type_mirror = null_check(array_type_mirror); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3852 original = null_check(original); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3853 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3854 // Check if a null path was taken unconditionally. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3855 if (stopped()) return true; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3856 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3857 Node* orig_length = load_array_length(original); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3858 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3859 Node* klass_node = load_klass_from_mirror(array_type_mirror, false, NULL, 0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3860 klass_node = null_check(klass_node); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3861 |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3862 RegionNode* bailout = new (C) RegionNode(1); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3863 record_for_igvn(bailout); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3864 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3865 // 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
|
3866 // Bail out if that is so. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3867 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
|
3868 if (not_objArray != NULL) { |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3869 // 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
|
3870 ciKlass* ak = ciArrayKlass::make(env()->Object_klass()); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3871 const Type* akls = TypeKlassPtr::make(TypePtr::NotNull, ak, 0/*offset*/); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3872 Node* cast = new (C) CastPPNode(klass_node, akls); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3873 cast->init_req(0, control()); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3874 klass_node = _gvn.transform(cast); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3875 } |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3876 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3877 // 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
|
3878 generate_negative_guard(start, bailout, &start); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3879 generate_negative_guard(end, bailout, &end); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3880 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3881 Node* length = end; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3882 if (_gvn.type(start) != TypeInt::ZERO) { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3883 length = _gvn.transform(new (C) SubINode(end, start)); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3884 } |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3885 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3886 // Bail out if length is negative. |
6180
eeb819cf36e5
7174363: Arrays.copyOfRange leads to VM crash with -Xcomp -server if executed by testing framework
roland
parents:
6143
diff
changeset
|
3887 // Without this the new_array would throw |
eeb819cf36e5
7174363: Arrays.copyOfRange leads to VM crash with -Xcomp -server if executed by testing framework
roland
parents:
6143
diff
changeset
|
3888 // NegativeArraySizeException but IllegalArgumentException is what |
eeb819cf36e5
7174363: Arrays.copyOfRange leads to VM crash with -Xcomp -server if executed by testing framework
roland
parents:
6143
diff
changeset
|
3889 // should be thrown |
eeb819cf36e5
7174363: Arrays.copyOfRange leads to VM crash with -Xcomp -server if executed by testing framework
roland
parents:
6143
diff
changeset
|
3890 generate_negative_guard(length, bailout, &length); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3891 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3892 if (bailout->req() > 1) { |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3893 PreserveJVMState pjvms(this); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3894 set_control(_gvn.transform(bailout)); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3895 uncommon_trap(Deoptimization::Reason_intrinsic, |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3896 Deoptimization::Action_maybe_recompile); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3897 } |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3898 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3899 if (!stopped()) { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3900 // 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
|
3901 // The answer is MinI(orig_length - start, length). |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3902 Node* orig_tail = _gvn.transform(new (C) SubINode(orig_length, start)); |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3903 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
|
3904 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3905 newcopy = new_array(klass_node, length, 0); // no argments to push |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3906 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3907 // 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
|
3908 // 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
|
3909 // oop stores need checking. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3910 // 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
|
3911 // 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
|
3912 bool disjoint_bases = true; |
6180
eeb819cf36e5
7174363: Arrays.copyOfRange leads to VM crash with -Xcomp -server if executed by testing framework
roland
parents:
6143
diff
changeset
|
3913 // if start > orig_length then the length of the copy may be |
eeb819cf36e5
7174363: Arrays.copyOfRange leads to VM crash with -Xcomp -server if executed by testing framework
roland
parents:
6143
diff
changeset
|
3914 // negative. |
eeb819cf36e5
7174363: Arrays.copyOfRange leads to VM crash with -Xcomp -server if executed by testing framework
roland
parents:
6143
diff
changeset
|
3915 bool length_never_negative = !is_copyOfRange; |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3916 generate_arraycopy(TypeAryPtr::OOPS, T_OBJECT, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3917 original, start, newcopy, intcon(0), moved, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3918 disjoint_bases, length_never_negative); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3919 } |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3920 } // original reexecute is set back here |
0 | 3921 |
3922 C->set_has_split_ifs(true); // Has chance for split-if optimization | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3923 if (!stopped()) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3924 set_result(newcopy); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3925 } |
0 | 3926 return true; |
3927 } | |
3928 | |
3929 | |
3930 //----------------------generate_virtual_guard--------------------------- | |
3931 // Helper for hashCode and clone. Peeks inside the vtable to avoid a call. | |
3932 Node* LibraryCallKit::generate_virtual_guard(Node* obj_klass, | |
3933 RegionNode* slow_region) { | |
3934 ciMethod* method = callee(); | |
3935 int vtable_index = method->vtable_index(); | |
12264
b2e698d2276c
8014013: CallInfo structure no longer accurately reports the result of a LinkResolver operation
drchase
parents:
12190
diff
changeset
|
3936 assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index, |
b2e698d2276c
8014013: CallInfo structure no longer accurately reports the result of a LinkResolver operation
drchase
parents:
12190
diff
changeset
|
3937 err_msg_res("bad index %d", vtable_index)); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6615
diff
changeset
|
3938 // Get the Method* out of the appropriate vtable entry. |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6615
diff
changeset
|
3939 int entry_offset = (InstanceKlass::vtable_start_offset() + |
0 | 3940 vtable_index*vtableEntry::size()) * wordSize + |
3941 vtableEntry::method_offset_in_bytes(); | |
3942 Node* entry_addr = basic_plus_adr(obj_klass, entry_offset); | |
6888
cfe522e6461c
8000623: tools/javac/Diagnostics/6769027/T6769027.java crashes in PSPromotionManager::copy_to_survivor_space
kvn
parents:
6853
diff
changeset
|
3943 Node* target_call = make_load(NULL, entry_addr, TypePtr::NOTNULL, T_ADDRESS); |
0 | 3944 |
3945 // Compare the target method with the expected method (e.g., Object.hashCode). | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6615
diff
changeset
|
3946 const TypePtr* native_call_addr = TypeMetadataPtr::make(method); |
0 | 3947 |
3948 Node* native_call = makecon(native_call_addr); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3949 Node* chk_native = _gvn.transform(new(C) CmpPNode(target_call, native_call)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3950 Node* test_native = _gvn.transform(new(C) BoolNode(chk_native, BoolTest::ne)); |
0 | 3951 |
3952 return generate_slow_guard(test_native, slow_region); | |
3953 } | |
3954 | |
3955 //-----------------------generate_method_call---------------------------- | |
3956 // Use generate_method_call to make a slow-call to the real | |
3957 // method if the fast path fails. An alternative would be to | |
3958 // use a stub like OptoRuntime::slow_arraycopy_Java. | |
3959 // This only works for expanding the current library call, | |
3960 // not another intrinsic. (E.g., don't use this for making an | |
3961 // arraycopy call inside of the copyOf intrinsic.) | |
3962 CallJavaNode* | |
3963 LibraryCallKit::generate_method_call(vmIntrinsics::ID method_id, bool is_virtual, bool is_static) { | |
3964 // When compiling the intrinsic method itself, do not use this technique. | |
3965 guarantee(callee() != C->method(), "cannot make slow-call to self"); | |
3966 | |
3967 ciMethod* method = callee(); | |
3968 // ensure the JVMS we have will be correct for this call | |
3969 guarantee(method_id == method->intrinsic_id(), "must match"); | |
3970 | |
3971 const TypeFunc* tf = TypeFunc::make(method); | |
3972 CallJavaNode* slow_call; | |
3973 if (is_static) { | |
3974 assert(!is_virtual, ""); | |
10278 | 3975 slow_call = new(C) CallStaticJavaNode(C, tf, |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3976 SharedRuntime::get_resolve_static_call_stub(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3977 method, bci()); |
0 | 3978 } else if (is_virtual) { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3979 null_check_receiver(); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6615
diff
changeset
|
3980 int vtable_index = Method::invalid_vtable_index; |
0 | 3981 if (UseInlineCaches) { |
3982 // Suppress the vtable call | |
3983 } else { | |
3984 // hashCode and clone are not a miranda methods, | |
3985 // so the vtable index is fixed. | |
3986 // No need to use the linkResolver to get it. | |
3987 vtable_index = method->vtable_index(); | |
12264
b2e698d2276c
8014013: CallInfo structure no longer accurately reports the result of a LinkResolver operation
drchase
parents:
12190
diff
changeset
|
3988 assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index, |
b2e698d2276c
8014013: CallInfo structure no longer accurately reports the result of a LinkResolver operation
drchase
parents:
12190
diff
changeset
|
3989 err_msg_res("bad index %d", vtable_index)); |
0 | 3990 } |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3991 slow_call = new(C) CallDynamicJavaNode(tf, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3992 SharedRuntime::get_resolve_virtual_call_stub(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3993 method, vtable_index, bci()); |
0 | 3994 } else { // neither virtual nor static: opt_virtual |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3995 null_check_receiver(); |
10278 | 3996 slow_call = new(C) CallStaticJavaNode(C, tf, |
0 | 3997 SharedRuntime::get_resolve_opt_virtual_call_stub(), |
3998 method, bci()); | |
3999 slow_call->set_optimized_virtual(true); | |
4000 } | |
4001 set_arguments_for_java_call(slow_call); | |
4002 set_edges_for_java_call(slow_call); | |
4003 return slow_call; | |
4004 } | |
4005 | |
4006 | |
4007 //------------------------------inline_native_hashcode-------------------- | |
4008 // Build special case code for calls to hashCode on an object. | |
4009 bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) { | |
4010 assert(is_static == callee()->is_static(), "correct intrinsic selection"); | |
4011 assert(!(is_virtual && is_static), "either virtual, special, or static"); | |
4012 | |
4013 enum { _slow_path = 1, _fast_path, _null_path, PATH_LIMIT }; | |
4014 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4015 RegionNode* result_reg = new(C) RegionNode(PATH_LIMIT); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4016 PhiNode* result_val = new(C) PhiNode(result_reg, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4017 TypeInt::INT); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4018 PhiNode* result_io = new(C) PhiNode(result_reg, Type::ABIO); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4019 PhiNode* result_mem = new(C) PhiNode(result_reg, Type::MEMORY, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4020 TypePtr::BOTTOM); |
0 | 4021 Node* obj = NULL; |
4022 if (!is_static) { | |
4023 // Check for hashing null object | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4024 obj = null_check_receiver(); |
0 | 4025 if (stopped()) return true; // unconditionally null |
4026 result_reg->init_req(_null_path, top()); | |
4027 result_val->init_req(_null_path, top()); | |
4028 } else { | |
4029 // Do a null check, and return zero if null. | |
4030 // System.identityHashCode(null) == 0 | |
4031 obj = argument(0); | |
4032 Node* null_ctl = top(); | |
4033 obj = null_check_oop(obj, &null_ctl); | |
4034 result_reg->init_req(_null_path, null_ctl); | |
4035 result_val->init_req(_null_path, _gvn.intcon(0)); | |
4036 } | |
4037 | |
4038 // Unconditionally null? Then return right away. | |
4039 if (stopped()) { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4040 set_control( result_reg->in(_null_path)); |
0 | 4041 if (!stopped()) |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4042 set_result(result_val->in(_null_path)); |
0 | 4043 return true; |
4044 } | |
4045 | |
4046 // After null check, get the object's klass. | |
4047 Node* obj_klass = load_object_klass(obj); | |
4048 | |
4049 // This call may be virtual (invokevirtual) or bound (invokespecial). | |
4050 // For each case we generate slightly different code. | |
4051 | |
4052 // We only go to the fast case code if we pass a number of guards. The | |
4053 // paths which do not pass are accumulated in the slow_region. | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4054 RegionNode* slow_region = new (C) RegionNode(1); |
0 | 4055 record_for_igvn(slow_region); |
4056 | |
4057 // If this is a virtual call, we generate a funny guard. We pull out | |
4058 // the vtable entry corresponding to hashCode() from the target object. | |
4059 // If the target method which we are calling happens to be the native | |
4060 // Object hashCode() method, we pass the guard. We do not need this | |
4061 // guard for non-virtual calls -- the caller is known to be the native | |
4062 // Object hashCode(). | |
4063 if (is_virtual) { | |
4064 generate_virtual_guard(obj_klass, slow_region); | |
4065 } | |
4066 | |
4067 // Get the header out of the object, use LoadMarkNode when available | |
4068 Node* header_addr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes()); | |
1609 | 4069 Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type()); |
0 | 4070 |
4071 // Test the header to see if it is unlocked. | |
4072 Node *lock_mask = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4073 Node *lmasked_header = _gvn.transform(new (C) AndXNode(header, lock_mask)); |
0 | 4074 Node *unlocked_val = _gvn.MakeConX(markOopDesc::unlocked_value); |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4075 Node *chk_unlocked = _gvn.transform(new (C) CmpXNode( lmasked_header, unlocked_val)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4076 Node *test_unlocked = _gvn.transform(new (C) BoolNode( chk_unlocked, BoolTest::ne)); |
0 | 4077 |
4078 generate_slow_guard(test_unlocked, slow_region); | |
4079 | |
4080 // Get the hash value and check to see that it has been properly assigned. | |
4081 // We depend on hash_mask being at most 32 bits and avoid the use of | |
4082 // hash_mask_in_place because it could be larger than 32 bits in a 64-bit | |
4083 // vm: see markOop.hpp. | |
4084 Node *hash_mask = _gvn.intcon(markOopDesc::hash_mask); | |
4085 Node *hash_shift = _gvn.intcon(markOopDesc::hash_shift); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4086 Node *hshifted_header= _gvn.transform(new (C) URShiftXNode(header, hash_shift)); |
0 | 4087 // This hack lets the hash bits live anywhere in the mark object now, as long |
605 | 4088 // as the shift drops the relevant bits into the low 32 bits. Note that |
0 | 4089 // Java spec says that HashCode is an int so there's no point in capturing |
4090 // an 'X'-sized hashcode (32 in 32-bit build or 64 in 64-bit build). | |
4091 hshifted_header = ConvX2I(hshifted_header); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4092 Node *hash_val = _gvn.transform(new (C) AndINode(hshifted_header, hash_mask)); |
0 | 4093 |
4094 Node *no_hash_val = _gvn.intcon(markOopDesc::no_hash); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4095 Node *chk_assigned = _gvn.transform(new (C) CmpINode( hash_val, no_hash_val)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4096 Node *test_assigned = _gvn.transform(new (C) BoolNode( chk_assigned, BoolTest::eq)); |
0 | 4097 |
4098 generate_slow_guard(test_assigned, slow_region); | |
4099 | |
4100 Node* init_mem = reset_memory(); | |
4101 // fill in the rest of the null path: | |
4102 result_io ->init_req(_null_path, i_o()); | |
4103 result_mem->init_req(_null_path, init_mem); | |
4104 | |
4105 result_val->init_req(_fast_path, hash_val); | |
4106 result_reg->init_req(_fast_path, control()); | |
4107 result_io ->init_req(_fast_path, i_o()); | |
4108 result_mem->init_req(_fast_path, init_mem); | |
4109 | |
4110 // Generate code for the slow case. We make a call to hashCode(). | |
4111 set_control(_gvn.transform(slow_region)); | |
4112 if (!stopped()) { | |
4113 // No need for PreserveJVMState, because we're using up the present state. | |
4114 set_all_memory(init_mem); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4115 vmIntrinsics::ID hashCode_id = is_static ? vmIntrinsics::_identityHashCode : vmIntrinsics::_hashCode; |
0 | 4116 CallJavaNode* slow_call = generate_method_call(hashCode_id, is_virtual, is_static); |
4117 Node* slow_result = set_results_for_java_call(slow_call); | |
4118 // this->control() comes from set_results_for_java_call | |
4119 result_reg->init_req(_slow_path, control()); | |
4120 result_val->init_req(_slow_path, slow_result); | |
4121 result_io ->set_req(_slow_path, i_o()); | |
4122 result_mem ->set_req(_slow_path, reset_memory()); | |
4123 } | |
4124 | |
4125 // Return the combined state. | |
4126 set_i_o( _gvn.transform(result_io) ); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4127 set_all_memory( _gvn.transform(result_mem)); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4128 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4129 set_result(result_reg, result_val); |
0 | 4130 return true; |
4131 } | |
4132 | |
4133 //---------------------------inline_native_getClass---------------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4134 // public final native Class<?> java.lang.Object.getClass(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4135 // |
605 | 4136 // Build special case code for calls to getClass on an object. |
0 | 4137 bool LibraryCallKit::inline_native_getClass() { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4138 Node* obj = null_check_receiver(); |
0 | 4139 if (stopped()) return true; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4140 set_result(load_mirror_from_klass(load_object_klass(obj))); |
0 | 4141 return true; |
4142 } | |
4143 | |
4144 //-----------------inline_native_Reflection_getCallerClass--------------------- | |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4145 // public static native Class<?> sun.reflect.Reflection.getCallerClass(); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4146 // |
0 | 4147 // In the presence of deep enough inlining, getCallerClass() becomes a no-op. |
4148 // | |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4149 // NOTE: This code must perform the same logic as JVM_GetCallerClass |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4150 // in that it must skip particular security frames and checks for |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4151 // caller sensitive methods. |
0 | 4152 bool LibraryCallKit::inline_native_Reflection_getCallerClass() { |
4153 #ifndef PRODUCT | |
12295 | 4154 if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { |
0 | 4155 tty->print_cr("Attempting to inline sun.reflect.Reflection.getCallerClass"); |
4156 } | |
4157 #endif | |
4158 | |
4159 if (!jvms()->has_method()) { | |
4160 #ifndef PRODUCT | |
12295 | 4161 if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { |
0 | 4162 tty->print_cr(" Bailing out because intrinsic was inlined at top level"); |
4163 } | |
4164 #endif | |
4165 return false; | |
4166 } | |
4167 | |
4168 // Walk back up the JVM state to find the caller at the required | |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4169 // depth. |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4170 JVMState* caller_jvms = jvms(); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4171 |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4172 // Cf. JVM_GetCallerClass |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4173 // NOTE: Start the loop at depth 1 because the current JVM state does |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4174 // not include the Reflection.getCallerClass() frame. |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4175 for (int n = 1; caller_jvms != NULL; caller_jvms = caller_jvms->caller(), n++) { |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4176 ciMethod* m = caller_jvms->method(); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4177 switch (n) { |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4178 case 0: |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4179 fatal("current JVM state does not include the Reflection.getCallerClass frame"); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4180 break; |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4181 case 1: |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4182 // Frame 0 and 1 must be caller sensitive (see JVM_GetCallerClass). |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4183 if (!m->caller_sensitive()) { |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4184 #ifndef PRODUCT |
12295 | 4185 if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4186 tty->print_cr(" Bailing out: CallerSensitive annotation expected at frame %d", n); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4187 } |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4188 #endif |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4189 return false; // bail-out; let JVM_GetCallerClass do the work |
0 | 4190 } |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4191 break; |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4192 default: |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4193 if (!m->is_ignored_by_security_stack_walk()) { |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4194 // We have reached the desired frame; return the holder class. |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4195 // Acquire method holder as java.lang.Class and push as constant. |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4196 ciInstanceKlass* caller_klass = caller_jvms->method()->holder(); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4197 ciInstance* caller_mirror = caller_klass->java_mirror(); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4198 set_result(makecon(TypeInstPtr::make(caller_mirror))); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4199 |
0 | 4200 #ifndef PRODUCT |
12295 | 4201 if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4202 tty->print_cr(" Succeeded: caller = %d) %s.%s, JVMS depth = %d", n, caller_klass->name()->as_utf8(), caller_jvms->method()->name()->as_utf8(), jvms()->depth()); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4203 tty->print_cr(" JVM state at this point:"); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4204 for (int i = jvms()->depth(), n = 1; i >= 1; i--, n++) { |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4205 ciMethod* m = jvms()->of_depth(i)->method(); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4206 tty->print_cr(" %d) %s.%s", n, m->holder()->name()->as_utf8(), m->name()->as_utf8()); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4207 } |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4208 } |
0 | 4209 #endif |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4210 return true; |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4211 } |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4212 break; |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4213 } |
0 | 4214 } |
4215 | |
4216 #ifndef PRODUCT | |
12295 | 4217 if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4218 tty->print_cr(" Bailing out because caller depth exceeded inlining depth = %d", jvms()->depth()); |
0 | 4219 tty->print_cr(" JVM state at this point:"); |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4220 for (int i = jvms()->depth(), n = 1; i >= 1; i--, n++) { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4221 ciMethod* m = jvms()->of_depth(i)->method(); |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4222 tty->print_cr(" %d) %s.%s", n, m->holder()->name()->as_utf8(), m->name()->as_utf8()); |
0 | 4223 } |
4224 } | |
4225 #endif | |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4226 |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4227 return false; // bail-out; let JVM_GetCallerClass do the work |
0 | 4228 } |
4229 | |
4230 bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4231 Node* arg = argument(0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4232 Node* result; |
0 | 4233 |
4234 switch (id) { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4235 case vmIntrinsics::_floatToRawIntBits: result = new (C) MoveF2INode(arg); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4236 case vmIntrinsics::_intBitsToFloat: result = new (C) MoveI2FNode(arg); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4237 case vmIntrinsics::_doubleToRawLongBits: result = new (C) MoveD2LNode(arg); break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4238 case vmIntrinsics::_longBitsToDouble: result = new (C) MoveL2DNode(arg); break; |
0 | 4239 |
4240 case vmIntrinsics::_doubleToLongBits: { | |
4241 // two paths (plus control) merge in a wood | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4242 RegionNode *r = new (C) RegionNode(3); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4243 Node *phi = new (C) PhiNode(r, TypeLong::LONG); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4244 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4245 Node *cmpisnan = _gvn.transform(new (C) CmpDNode(arg, arg)); |
0 | 4246 // Build the boolean node |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4247 Node *bolisnan = _gvn.transform(new (C) BoolNode(cmpisnan, BoolTest::ne)); |
0 | 4248 |
4249 // Branch either way. | |
4250 // NaN case is less traveled, which makes all the difference. | |
4251 IfNode *ifisnan = create_and_xform_if(control(), bolisnan, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); | |
4252 Node *opt_isnan = _gvn.transform(ifisnan); | |
4253 assert( opt_isnan->is_If(), "Expect an IfNode"); | |
4254 IfNode *opt_ifisnan = (IfNode*)opt_isnan; | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4255 Node *iftrue = _gvn.transform(new (C) IfTrueNode(opt_ifisnan)); |
0 | 4256 |
4257 set_control(iftrue); | |
4258 | |
4259 static const jlong nan_bits = CONST64(0x7ff8000000000000); | |
4260 Node *slow_result = longcon(nan_bits); // return NaN | |
4261 phi->init_req(1, _gvn.transform( slow_result )); | |
4262 r->init_req(1, iftrue); | |
4263 | |
4264 // Else fall through | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4265 Node *iffalse = _gvn.transform(new (C) IfFalseNode(opt_ifisnan)); |
0 | 4266 set_control(iffalse); |
4267 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4268 phi->init_req(2, _gvn.transform(new (C) MoveD2LNode(arg))); |
0 | 4269 r->init_req(2, iffalse); |
4270 | |
4271 // Post merge | |
4272 set_control(_gvn.transform(r)); | |
4273 record_for_igvn(r); | |
4274 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4275 C->set_has_split_ifs(true); // Has chance for split-if optimization |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4276 result = phi; |
0 | 4277 assert(result->bottom_type()->isa_long(), "must be"); |
4278 break; | |
4279 } | |
4280 | |
4281 case vmIntrinsics::_floatToIntBits: { | |
4282 // two paths (plus control) merge in a wood | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4283 RegionNode *r = new (C) RegionNode(3); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4284 Node *phi = new (C) PhiNode(r, TypeInt::INT); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4285 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4286 Node *cmpisnan = _gvn.transform(new (C) CmpFNode(arg, arg)); |
0 | 4287 // Build the boolean node |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4288 Node *bolisnan = _gvn.transform(new (C) BoolNode(cmpisnan, BoolTest::ne)); |
0 | 4289 |
4290 // Branch either way. | |
4291 // NaN case is less traveled, which makes all the difference. | |
4292 IfNode *ifisnan = create_and_xform_if(control(), bolisnan, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); | |
4293 Node *opt_isnan = _gvn.transform(ifisnan); | |
4294 assert( opt_isnan->is_If(), "Expect an IfNode"); | |
4295 IfNode *opt_ifisnan = (IfNode*)opt_isnan; | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4296 Node *iftrue = _gvn.transform(new (C) IfTrueNode(opt_ifisnan)); |
0 | 4297 |
4298 set_control(iftrue); | |
4299 | |
4300 static const jint nan_bits = 0x7fc00000; | |
4301 Node *slow_result = makecon(TypeInt::make(nan_bits)); // return NaN | |
4302 phi->init_req(1, _gvn.transform( slow_result )); | |
4303 r->init_req(1, iftrue); | |
4304 | |
4305 // Else fall through | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4306 Node *iffalse = _gvn.transform(new (C) IfFalseNode(opt_ifisnan)); |
0 | 4307 set_control(iffalse); |
4308 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4309 phi->init_req(2, _gvn.transform(new (C) MoveF2INode(arg))); |
0 | 4310 r->init_req(2, iffalse); |
4311 | |
4312 // Post merge | |
4313 set_control(_gvn.transform(r)); | |
4314 record_for_igvn(r); | |
4315 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4316 C->set_has_split_ifs(true); // Has chance for split-if optimization |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4317 result = phi; |
0 | 4318 assert(result->bottom_type()->isa_int(), "must be"); |
4319 break; | |
4320 } | |
4321 | |
4322 default: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4323 fatal_unexpected_iid(id); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4324 break; |
0 | 4325 } |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4326 set_result(_gvn.transform(result)); |
0 | 4327 return true; |
4328 } | |
4329 | |
4330 #ifdef _LP64 | |
4331 #define XTOP ,top() /*additional argument*/ | |
4332 #else //_LP64 | |
4333 #define XTOP /*no additional argument*/ | |
4334 #endif //_LP64 | |
4335 | |
4336 //----------------------inline_unsafe_copyMemory------------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4337 // public native void sun.misc.Unsafe.copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes); |
0 | 4338 bool LibraryCallKit::inline_unsafe_copyMemory() { |
4339 if (callee()->is_static()) return false; // caller must have the capability! | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4340 null_check_receiver(); // null-check receiver |
0 | 4341 if (stopped()) return true; |
4342 | |
4343 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
4344 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4345 Node* src_ptr = argument(1); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4346 Node* src_off = ConvL2X(argument(2)); // type: long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4347 Node* dst_ptr = argument(4); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4348 Node* dst_off = ConvL2X(argument(5)); // type: long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4349 Node* size = ConvL2X(argument(7)); // type: long |
0 | 4350 |
4351 assert(Unsafe_field_offset_to_byte_offset(11) == 11, | |
4352 "fieldOffset must be byte-scaled"); | |
4353 | |
4354 Node* src = make_unsafe_address(src_ptr, src_off); | |
4355 Node* dst = make_unsafe_address(dst_ptr, dst_off); | |
4356 | |
4357 // Conservatively insert a memory barrier on all memory slices. | |
4358 // Do not let writes of the copy source or destination float below the copy. | |
4359 insert_mem_bar(Op_MemBarCPUOrder); | |
4360 | |
4361 // Call it. Note that the length argument is not scaled. | |
4362 make_runtime_call(RC_LEAF|RC_NO_FP, | |
4363 OptoRuntime::fast_arraycopy_Type(), | |
4364 StubRoutines::unsafe_arraycopy(), | |
4365 "unsafe_arraycopy", | |
4366 TypeRawPtr::BOTTOM, | |
4367 src, dst, size XTOP); | |
4368 | |
4369 // Do not let reads of the copy destination float above the copy. | |
4370 insert_mem_bar(Op_MemBarCPUOrder); | |
4371 | |
4372 return true; | |
4373 } | |
4374 | |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4375 //------------------------clone_coping----------------------------------- |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4376 // 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
|
4377 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
|
4378 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
|
4379 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
|
4380 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
|
4381 |
4763
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4382 AllocateNode* alloc = NULL; |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4383 if (ReduceBulkZeroing) { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4384 // 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
|
4385 // mark Initialize node as complete. |
4763
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4386 alloc = AllocateNode::Ideal_allocation(alloc_obj, &_gvn); |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4387 // 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
|
4388 guarantee(alloc != NULL && alloc->maybe_set_complete(&_gvn), ""); |
4763
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4389 // Mark as complete_with_arraycopy so that on AllocateNode |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4390 // expansion, we know this AllocateNode is initialized by an array |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4391 // copy and a StoreStore barrier exists after the array copy. |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4392 alloc->initialization()->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
|
4393 } |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4394 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4395 // 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
|
4396 // 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
|
4397 Node* src = obj; |
958
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
4398 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
|
4399 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
|
4400 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4401 // 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
|
4402 // 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
|
4403 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
|
4404 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
|
4405 // base_off: |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4406 // 8 - 32-bit VM |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6615
diff
changeset
|
4407 // 12 - 64-bit VM, compressed klass |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6615
diff
changeset
|
4408 // 16 - 64-bit VM, normal klass |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4409 if (base_off % BytesPerLong != 0) { |
12226
7944aba7ba41
8015107: NPG: Use consistent naming for metaspace concepts
ehelin
parents:
12169
diff
changeset
|
4410 assert(UseCompressedClassPointers, ""); |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4411 if (is_array) { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4412 // 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
|
4413 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
|
4414 } else { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4415 // 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
|
4416 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
|
4417 } |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4418 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
|
4419 } |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4420 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
|
4421 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
|
4422 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4423 // 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
|
4424 Node* countx = size; |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4425 countx = _gvn.transform(new (C) SubXNode(countx, MakeConX(base_off))); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4426 countx = _gvn.transform(new (C) URShiftXNode(countx, intcon(LogBytesPerLong) )); |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4427 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4428 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
|
4429 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
|
4430 generate_unchecked_arraycopy(raw_adr_type, T_LONG, disjoint_bases, |
2324 | 4431 src, NULL, dest, NULL, countx, |
4432 /*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
|
4433 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4434 // 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
|
4435 if (card_mark) { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4436 assert(!is_array, ""); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4437 // 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
|
4438 // 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
|
4439 // 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
|
4440 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
|
4441 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
|
4442 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
|
4443 post_barrier(control(), |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4444 memory(raw_adr_type), |
958
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
4445 alloc_obj, |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4446 no_particular_field, |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4447 raw_adr_idx, |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4448 no_particular_value, |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4449 T_OBJECT, |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4450 false); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4451 } |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4452 |
958
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
4453 // Do not let reads from the cloned object float above the arraycopy. |
4763
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4454 if (alloc != NULL) { |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4455 // Do not let stores that initialize this object be reordered with |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4456 // a subsequent store that would make this object accessible by |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4457 // other threads. |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4458 // Record what AllocateNode this StoreStore protects so that |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4459 // escape analysis can go from the MemBarStoreStoreNode to the |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4460 // AllocateNode and eliminate the MemBarStoreStoreNode if possible |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4461 // based on the escape status of the AllocateNode. |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4462 insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress)); |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4463 } else { |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4464 insert_mem_bar(Op_MemBarCPUOrder); |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4465 } |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4466 } |
0 | 4467 |
4468 //------------------------inline_native_clone---------------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4469 // protected native Object java.lang.Object.clone(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4470 // |
0 | 4471 // Here are the simple edge cases: |
4472 // null receiver => normal trap | |
4473 // virtual and clone was overridden => slow path to out-of-line clone | |
4474 // not cloneable or finalizer => slow path to out-of-line Object.clone | |
4475 // | |
4476 // The general case has two steps, allocation and copying. | |
4477 // Allocation has two cases, and uses GraphKit::new_instance or new_array. | |
4478 // | |
4479 // Copying also has two cases, oop arrays and everything else. | |
4480 // Oop arrays use arrayof_oop_arraycopy (same as System.arraycopy). | |
4481 // Everything else uses the tight inline loop supplied by CopyArrayNode. | |
4482 // | |
4483 // These steps fold up nicely if and when the cloned object's klass | |
4484 // can be sharply typed as an object array, a type array, or an instance. | |
4485 // | |
4486 bool LibraryCallKit::inline_native_clone(bool is_virtual) { | |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4487 PhiNode* result_val; |
0 | 4488 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4489 // Set the reexecute bit for the interpreter to reexecute |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4490 // the bytecode that invokes Object.clone if deoptimization happens. |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4491 { PreserveReexecuteState preexecs(this); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4492 jvms()->set_should_reexecute(true); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4493 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4494 Node* obj = null_check_receiver(); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4495 if (stopped()) return true; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4496 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4497 Node* obj_klass = load_object_klass(obj); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4498 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
|
4499 const TypeOopPtr* toop = ((tklass != NULL) |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4500 ? tklass->as_instance_type() |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4501 : TypeInstPtr::NOTNULL); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4502 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4503 // 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
|
4504 // 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
|
4505 insert_mem_bar(Op_MemBarCPUOrder); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4506 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4507 // paths into result_reg: |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4508 enum { |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4509 _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
|
4510 _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
|
4511 _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
|
4512 _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
|
4513 PATH_LIMIT |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4514 }; |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4515 RegionNode* result_reg = new(C) RegionNode(PATH_LIMIT); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4516 result_val = new(C) PhiNode(result_reg, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4517 TypeInstPtr::NOTNULL); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4518 PhiNode* result_i_o = new(C) PhiNode(result_reg, Type::ABIO); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4519 PhiNode* result_mem = new(C) PhiNode(result_reg, Type::MEMORY, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4520 TypePtr::BOTTOM); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4521 record_for_igvn(result_reg); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4522 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4523 const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4524 int raw_adr_idx = Compile::AliasIdxRaw; |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4525 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4526 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
|
4527 if (array_ctl != NULL) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4528 // It's an array. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4529 PreserveJVMState pjvms(this); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4530 set_control(array_ctl); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4531 Node* obj_length = load_array_length(obj); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4532 Node* obj_size = NULL; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4533 Node* alloc_obj = new_array(obj_klass, obj_length, 0, &obj_size); // no arguments to push |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4534 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4535 if (!use_ReduceInitialCardMarks()) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4536 // 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
|
4537 // 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
|
4538 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
|
4539 if (is_obja != NULL) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4540 PreserveJVMState pjvms2(this); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4541 set_control(is_obja); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4542 // 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
|
4543 bool disjoint_bases = true; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4544 bool length_never_negative = true; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4545 generate_arraycopy(TypeAryPtr::OOPS, T_OBJECT, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4546 obj, intcon(0), alloc_obj, intcon(0), |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4547 obj_length, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4548 disjoint_bases, length_never_negative); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4549 result_reg->init_req(_objArray_path, control()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4550 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
|
4551 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
|
4552 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
|
4553 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4554 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4555 // 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
|
4556 // (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
|
4557 // comes out of eden (TLAB)... In fact, ReduceInitialCardMarks |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
986
diff
changeset
|
4558 // 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
|
4559 // simulate a fresh allocation, so that no further |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
986
diff
changeset
|
4560 // 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
|
4561 // the object.) |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4562 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4563 if (!stopped()) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4564 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
|
4565 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4566 // Present the results of the copy. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4567 result_reg->init_req(_array_path, control()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4568 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
|
4569 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
|
4570 result_mem ->set_req(_array_path, reset_memory()); |
0 | 4571 } |
4572 } | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4573 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4574 // 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
|
4575 // The paths which do not pass are accumulated in the slow_region. |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4576 RegionNode* slow_region = new (C) RegionNode(1); |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4577 record_for_igvn(slow_region); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4578 if (!stopped()) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4579 // 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
|
4580 // 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
|
4581 // 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
|
4582 // 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
|
4583 // 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
|
4584 // 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
|
4585 // Object clone(). |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4586 if (is_virtual) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4587 generate_virtual_guard(obj_klass, slow_region); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4588 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4589 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4590 // 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
|
4591 // 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
|
4592 // 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
|
4593 generate_access_flags_guard(obj_klass, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4594 // Test both conditions: |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4595 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
|
4596 // Must be cloneable but not finalizer: |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4597 JVM_ACC_IS_CLONEABLE, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4598 slow_region); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4599 } |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4600 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4601 if (!stopped()) { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4602 // 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
|
4603 PreserveJVMState pjvms(this); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4604 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
|
4605 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
|
4606 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4607 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
|
4608 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4609 // Present the results of the slow call. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4610 result_reg->init_req(_instance_path, control()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4611 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
|
4612 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
|
4613 result_mem ->set_req(_instance_path, reset_memory()); |
0 | 4614 } |
4615 | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4616 // 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
|
4617 set_control(_gvn.transform(slow_region)); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4618 if (!stopped()) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4619 PreserveJVMState pjvms(this); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4620 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
|
4621 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
|
4622 // 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
|
4623 result_reg->init_req(_slow_path, control()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4624 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
|
4625 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
|
4626 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
|
4627 } |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4628 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4629 // Return the combined state. |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4630 set_control( _gvn.transform(result_reg)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4631 set_i_o( _gvn.transform(result_i_o)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4632 set_all_memory( _gvn.transform(result_mem)); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4633 } // original reexecute is set back here |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4634 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4635 set_result(_gvn.transform(result_val)); |
0 | 4636 return true; |
4637 } | |
4638 | |
4639 //------------------------------basictype2arraycopy---------------------------- | |
4640 address LibraryCallKit::basictype2arraycopy(BasicType t, | |
4641 Node* src_offset, | |
4642 Node* dest_offset, | |
4643 bool disjoint_bases, | |
2324 | 4644 const char* &name, |
4645 bool dest_uninitialized) { | |
0 | 4646 const TypeInt* src_offset_inttype = gvn().find_int_type(src_offset);; |
4647 const TypeInt* dest_offset_inttype = gvn().find_int_type(dest_offset);; | |
4648 | |
4649 bool aligned = false; | |
4650 bool disjoint = disjoint_bases; | |
4651 | |
4652 // if the offsets are the same, we can treat the memory regions as | |
4653 // disjoint, because either the memory regions are in different arrays, | |
4654 // or they are identical (which we can treat as disjoint.) We can also | |
4655 // treat a copy with a destination index less that the source index | |
4656 // as disjoint since a low->high copy will work correctly in this case. | |
4657 if (src_offset_inttype != NULL && src_offset_inttype->is_con() && | |
4658 dest_offset_inttype != NULL && dest_offset_inttype->is_con()) { | |
4659 // both indices are constants | |
4660 int s_offs = src_offset_inttype->get_con(); | |
4661 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
|
4662 int element_size = type2aelembytes(t); |
0 | 4663 aligned = ((arrayOopDesc::base_offset_in_bytes(t) + s_offs * element_size) % HeapWordSize == 0) && |
4664 ((arrayOopDesc::base_offset_in_bytes(t) + d_offs * element_size) % HeapWordSize == 0); | |
4665 if (s_offs >= d_offs) disjoint = true; | |
4666 } else if (src_offset == dest_offset && src_offset != NULL) { | |
4667 // This can occur if the offsets are identical non-constants. | |
4668 disjoint = true; | |
4669 } | |
4670 | |
2446 | 4671 return StubRoutines::select_arraycopy_function(t, aligned, disjoint, name, dest_uninitialized); |
0 | 4672 } |
4673 | |
4674 | |
4675 //------------------------------inline_arraycopy----------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4676 // public static native void java.lang.System.arraycopy(Object src, int srcPos, |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4677 // Object dest, int destPos, |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4678 // int length); |
0 | 4679 bool LibraryCallKit::inline_arraycopy() { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4680 // Get the arguments. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4681 Node* src = argument(0); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4682 Node* src_offset = argument(1); // type: int |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4683 Node* dest = argument(2); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4684 Node* dest_offset = argument(3); // type: int |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4685 Node* length = argument(4); // type: int |
0 | 4686 |
4687 // Compile time checks. If any of these checks cannot be verified at compile time, | |
4688 // we do not make a fast path for this call. Instead, we let the call remain as it | |
4689 // is. The checks we choose to mandate at compile time are: | |
4690 // | |
4691 // (1) src and dest are arrays. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4692 const Type* src_type = src->Value(&_gvn); |
0 | 4693 const Type* dest_type = dest->Value(&_gvn); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4694 const TypeAryPtr* top_src = src_type->isa_aryptr(); |
0 | 4695 const TypeAryPtr* top_dest = dest_type->isa_aryptr(); |
12966 | 4696 |
4697 // Do we have the type of src? | |
4698 bool has_src = (top_src != NULL && top_src->klass() != NULL); | |
4699 // Do we have the type of dest? | |
4700 bool has_dest = (top_dest != NULL && top_dest->klass() != NULL); | |
4701 // Is the type for src from speculation? | |
4702 bool src_spec = false; | |
4703 // Is the type for dest from speculation? | |
4704 bool dest_spec = false; | |
4705 | |
4706 if (!has_src || !has_dest) { | |
4707 // We don't have sufficient type information, let's see if | |
4708 // speculative types can help. We need to have types for both src | |
4709 // and dest so that it pays off. | |
4710 | |
4711 // Do we already have or could we have type information for src | |
4712 bool could_have_src = has_src; | |
4713 // Do we already have or could we have type information for dest | |
4714 bool could_have_dest = has_dest; | |
4715 | |
4716 ciKlass* src_k = NULL; | |
4717 if (!has_src) { | |
4718 src_k = src_type->speculative_type(); | |
4719 if (src_k != NULL && src_k->is_array_klass()) { | |
4720 could_have_src = true; | |
4721 } | |
4722 } | |
4723 | |
4724 ciKlass* dest_k = NULL; | |
4725 if (!has_dest) { | |
4726 dest_k = dest_type->speculative_type(); | |
4727 if (dest_k != NULL && dest_k->is_array_klass()) { | |
4728 could_have_dest = true; | |
4729 } | |
4730 } | |
4731 | |
4732 if (could_have_src && could_have_dest) { | |
4733 // This is going to pay off so emit the required guards | |
4734 if (!has_src) { | |
4735 src = maybe_cast_profiled_obj(src, src_k); | |
4736 src_type = _gvn.type(src); | |
4737 top_src = src_type->isa_aryptr(); | |
4738 has_src = (top_src != NULL && top_src->klass() != NULL); | |
4739 src_spec = true; | |
4740 } | |
4741 if (!has_dest) { | |
4742 dest = maybe_cast_profiled_obj(dest, dest_k); | |
4743 dest_type = _gvn.type(dest); | |
4744 top_dest = dest_type->isa_aryptr(); | |
4745 has_dest = (top_dest != NULL && top_dest->klass() != NULL); | |
4746 dest_spec = true; | |
4747 } | |
4748 } | |
4749 } | |
4750 | |
4751 if (!has_src || !has_dest) { | |
0 | 4752 // Conservatively insert a memory barrier on all memory slices. |
4753 // Do not let writes into the source float below the arraycopy. | |
4754 insert_mem_bar(Op_MemBarCPUOrder); | |
4755 | |
4756 // Call StubRoutines::generic_arraycopy stub. | |
4757 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
|
4758 src, src_offset, dest, dest_offset, length); |
0 | 4759 |
4760 // Do not let reads from the destination float above the arraycopy. | |
4761 // Since we cannot type the arrays, we don't know which slices | |
4762 // might be affected. We could restrict this barrier only to those | |
4763 // memory slices which pertain to array elements--but don't bother. | |
4764 if (!InsertMemBarAfterArraycopy) | |
4765 // (If InsertMemBarAfterArraycopy, there is already one in place.) | |
4766 insert_mem_bar(Op_MemBarCPUOrder); | |
4767 return true; | |
4768 } | |
4769 | |
4770 // (2) src and dest arrays must have elements of the same BasicType | |
4771 // Figure out the size and type of the elements we will be copying. | |
4772 BasicType src_elem = top_src->klass()->as_array_klass()->element_type()->basic_type(); | |
4773 BasicType dest_elem = top_dest->klass()->as_array_klass()->element_type()->basic_type(); | |
4774 if (src_elem == T_ARRAY) src_elem = T_OBJECT; | |
4775 if (dest_elem == T_ARRAY) dest_elem = T_OBJECT; | |
4776 | |
4777 if (src_elem != dest_elem || dest_elem == T_VOID) { | |
4778 // The component types are not the same or are not recognized. Punt. | |
4779 // (But, avoid the native method wrapper to JVM_ArrayCopy.) | |
4780 generate_slow_arraycopy(TypePtr::BOTTOM, | |
2324 | 4781 src, src_offset, dest, dest_offset, length, |
4782 /*dest_uninitialized*/false); | |
0 | 4783 return true; |
4784 } | |
4785 | |
12966 | 4786 if (src_elem == T_OBJECT) { |
4787 // If both arrays are object arrays then having the exact types | |
4788 // for both will remove the need for a subtype check at runtime | |
4789 // before the call and may make it possible to pick a faster copy | |
4790 // routine (without a subtype check on every element) | |
4791 // Do we have the exact type of src? | |
4792 bool could_have_src = src_spec; | |
4793 // Do we have the exact type of dest? | |
4794 bool could_have_dest = dest_spec; | |
4795 ciKlass* src_k = top_src->klass(); | |
4796 ciKlass* dest_k = top_dest->klass(); | |
4797 if (!src_spec) { | |
4798 src_k = src_type->speculative_type(); | |
4799 if (src_k != NULL && src_k->is_array_klass()) { | |
4800 could_have_src = true; | |
4801 } | |
4802 } | |
4803 if (!dest_spec) { | |
4804 dest_k = dest_type->speculative_type(); | |
4805 if (dest_k != NULL && dest_k->is_array_klass()) { | |
4806 could_have_dest = true; | |
4807 } | |
4808 } | |
4809 if (could_have_src && could_have_dest) { | |
4810 // If we can have both exact types, emit the missing guards | |
4811 if (could_have_src && !src_spec) { | |
4812 src = maybe_cast_profiled_obj(src, src_k); | |
4813 } | |
4814 if (could_have_dest && !dest_spec) { | |
4815 dest = maybe_cast_profiled_obj(dest, dest_k); | |
4816 } | |
4817 } | |
4818 } | |
4819 | |
0 | 4820 //--------------------------------------------------------------------------- |
4821 // We will make a fast path for this call to arraycopy. | |
4822 | |
4823 // We have the following tests left to perform: | |
4824 // | |
4825 // (3) src and dest must not be null. | |
4826 // (4) src_offset must not be negative. | |
4827 // (5) dest_offset must not be negative. | |
4828 // (6) length must not be negative. | |
4829 // (7) src_offset + length must not exceed length of src. | |
4830 // (8) dest_offset + length must not exceed length of dest. | |
4831 // (9) each element of an oop array must be assignable | |
4832 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4833 RegionNode* slow_region = new (C) RegionNode(1); |
0 | 4834 record_for_igvn(slow_region); |
4835 | |
4836 // (3) operands must not be null | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4837 // We currently perform our null checks with the null_check routine. |
0 | 4838 // This means that the null exceptions will be reported in the caller |
4839 // rather than (correctly) reported inside of the native arraycopy call. | |
4840 // This should be corrected, given time. We do our null check with the | |
4841 // stack pointer restored. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4842 src = null_check(src, T_ARRAY); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4843 dest = null_check(dest, T_ARRAY); |
0 | 4844 |
4845 // (4) src_offset must not be negative. | |
4846 generate_negative_guard(src_offset, slow_region); | |
4847 | |
4848 // (5) dest_offset must not be negative. | |
4849 generate_negative_guard(dest_offset, slow_region); | |
4850 | |
4851 // (6) length must not be negative (moved to generate_arraycopy()). | |
4852 // generate_negative_guard(length, slow_region); | |
4853 | |
4854 // (7) src_offset + length must not exceed length of src. | |
4855 generate_limit_guard(src_offset, length, | |
4856 load_array_length(src), | |
4857 slow_region); | |
4858 | |
4859 // (8) dest_offset + length must not exceed length of dest. | |
4860 generate_limit_guard(dest_offset, length, | |
4861 load_array_length(dest), | |
4862 slow_region); | |
4863 | |
4864 // (9) each element of an oop array must be assignable | |
4865 // The generate_arraycopy subroutine checks this. | |
4866 | |
4867 // This is where the memory effects are placed: | |
4868 const TypePtr* adr_type = TypeAryPtr::get_array_body_type(dest_elem); | |
4869 generate_arraycopy(adr_type, dest_elem, | |
4870 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
|
4871 false, false, slow_region); |
0 | 4872 |
4873 return true; | |
4874 } | |
4875 | |
4876 //-----------------------------generate_arraycopy---------------------- | |
4877 // Generate an optimized call to arraycopy. | |
4878 // Caller must guard against non-arrays. | |
4879 // Caller must determine a common array basic-type for both arrays. | |
4880 // Caller must validate offsets against array bounds. | |
4881 // The slow_region has already collected guard failure paths | |
4882 // (such as out of bounds length or non-conformable array types). | |
4883 // The generated code has this shape, in general: | |
4884 // | |
4885 // if (length == 0) return // via zero_path | |
4886 // slowval = -1 | |
4887 // if (types unknown) { | |
4888 // slowval = call generic copy loop | |
4889 // if (slowval == 0) return // via checked_path | |
4890 // } else if (indexes in bounds) { | |
4891 // if ((is object array) && !(array type check)) { | |
4892 // slowval = call checked copy loop | |
4893 // if (slowval == 0) return // via checked_path | |
4894 // } else { | |
4895 // call bulk copy loop | |
4896 // return // via fast_path | |
4897 // } | |
4898 // } | |
4899 // // adjust params for remaining work: | |
4900 // if (slowval != -1) { | |
4901 // n = -1^slowval; src_offset += n; dest_offset += n; length -= n | |
4902 // } | |
4903 // slow_region: | |
4904 // call slow arraycopy(src, src_offset, dest, dest_offset, length) | |
4905 // return // via slow_call_path | |
4906 // | |
4907 // This routine is used from several intrinsics: System.arraycopy, | |
4908 // Object.clone (the array subcase), and Arrays.copyOf[Range]. | |
4909 // | |
4910 void | |
4911 LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, | |
4912 BasicType basic_elem_type, | |
4913 Node* src, Node* src_offset, | |
4914 Node* dest, Node* dest_offset, | |
4915 Node* copy_length, | |
4916 bool disjoint_bases, | |
4917 bool length_never_negative, | |
4918 RegionNode* slow_region) { | |
4919 | |
4920 if (slow_region == NULL) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4921 slow_region = new(C) RegionNode(1); |
0 | 4922 record_for_igvn(slow_region); |
4923 } | |
4924 | |
4925 Node* original_dest = dest; | |
4926 AllocateArrayNode* alloc = NULL; // used for zeroing, if needed | |
2324 | 4927 bool dest_uninitialized = false; |
0 | 4928 |
4929 // See if this is the initialization of a newly-allocated array. | |
4930 // If so, we will take responsibility here for initializing it to zero. | |
4931 // (Note: Because tightly_coupled_allocation performs checks on the | |
4932 // out-edges of the dest, we need to avoid making derived pointers | |
4933 // from it until we have checked its uses.) | |
4934 if (ReduceBulkZeroing | |
4935 && !ZeroTLAB // pointless if already zeroed | |
4936 && basic_elem_type != T_CONFLICT // avoid corner case | |
4778 | 4937 && !src->eqv_uncast(dest) |
0 | 4938 && ((alloc = tightly_coupled_allocation(dest, slow_region)) |
4939 != NULL) | |
34
545c277a3ecf
6667581: Don't generate initialization (by 0) code for arrays with size 0
kvn
parents:
29
diff
changeset
|
4940 && _gvn.find_int_con(alloc->in(AllocateNode::ALength), 1) > 0 |
0 | 4941 && alloc->maybe_set_complete(&_gvn)) { |
4942 // "You break it, you buy it." | |
4943 InitializeNode* init = alloc->initialization(); | |
4944 assert(init->is_complete(), "we just did this"); | |
3961
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3742
diff
changeset
|
4945 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
|
4946 assert(dest->is_CheckCastPP(), "sanity"); |
0 | 4947 assert(dest->in(0)->in(0) == init, "dest pinned"); |
4948 adr_type = TypeRawPtr::BOTTOM; // all initializations are into raw memory | |
4949 // From this point on, every exit path is responsible for | |
4950 // initializing any non-copied parts of the object to zero. | |
2324 | 4951 // Also, if this flag is set we make sure that arraycopy interacts properly |
4952 // with G1, eliding pre-barriers. See CR 6627983. | |
4953 dest_uninitialized = true; | |
0 | 4954 } else { |
4955 // No zeroing elimination here. | |
4956 alloc = NULL; | |
4957 //original_dest = dest; | |
2324 | 4958 //dest_uninitialized = false; |
0 | 4959 } |
4960 | |
4961 // Results are placed here: | |
4962 enum { fast_path = 1, // normal void-returning assembly stub | |
4963 checked_path = 2, // special assembly stub with cleanup | |
4964 slow_call_path = 3, // something went wrong; call the VM | |
4965 zero_path = 4, // bypass when length of copy is zero | |
4966 bcopy_path = 5, // copy primitive array by 64-bit blocks | |
4967 PATH_LIMIT = 6 | |
4968 }; | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4969 RegionNode* result_region = new(C) RegionNode(PATH_LIMIT); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4970 PhiNode* result_i_o = new(C) PhiNode(result_region, Type::ABIO); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4971 PhiNode* result_memory = new(C) PhiNode(result_region, Type::MEMORY, adr_type); |
0 | 4972 record_for_igvn(result_region); |
4973 _gvn.set_type_bottom(result_i_o); | |
4974 _gvn.set_type_bottom(result_memory); | |
4975 assert(adr_type != TypePtr::BOTTOM, "must be RawMem or a T[] slice"); | |
4976 | |
4977 // The slow_control path: | |
4978 Node* slow_control; | |
4979 Node* slow_i_o = i_o(); | |
4980 Node* slow_mem = memory(adr_type); | |
4981 debug_only(slow_control = (Node*) badAddress); | |
4982 | |
4983 // Checked control path: | |
4984 Node* checked_control = top(); | |
4985 Node* checked_mem = NULL; | |
4986 Node* checked_i_o = NULL; | |
4987 Node* checked_value = NULL; | |
4988 | |
4989 if (basic_elem_type == T_CONFLICT) { | |
2324 | 4990 assert(!dest_uninitialized, ""); |
0 | 4991 Node* cv = generate_generic_arraycopy(adr_type, |
4992 src, src_offset, dest, dest_offset, | |
2324 | 4993 copy_length, dest_uninitialized); |
0 | 4994 if (cv == NULL) cv = intcon(-1); // failure (no stub available) |
4995 checked_control = control(); | |
4996 checked_i_o = i_o(); | |
4997 checked_mem = memory(adr_type); | |
4998 checked_value = cv; | |
4999 set_control(top()); // no fast path | |
5000 } | |
5001 | |
5002 Node* not_pos = generate_nonpositive_guard(copy_length, length_never_negative); | |
5003 if (not_pos != NULL) { | |
5004 PreserveJVMState pjvms(this); | |
5005 set_control(not_pos); | |
5006 | |
5007 // (6) length must not be negative. | |
5008 if (!length_never_negative) { | |
5009 generate_negative_guard(copy_length, slow_region); | |
5010 } | |
5011 | |
836
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
5012 // copy_length is 0. |
2324 | 5013 if (!stopped() && dest_uninitialized) { |
0 | 5014 Node* dest_length = alloc->in(AllocateNode::ALength); |
4778 | 5015 if (copy_length->eqv_uncast(dest_length) |
0 | 5016 || _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
|
5017 // There is no zeroing to do. No need for a secondary raw memory barrier. |
0 | 5018 } else { |
5019 // Clear the whole thing since there are no source elements to copy. | |
5020 generate_clear_array(adr_type, dest, basic_elem_type, | |
5021 intcon(0), NULL, | |
5022 alloc->in(AllocateNode::AllocSize)); | |
836
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
5023 // 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
|
5024 // 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
|
5025 // 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
|
5026 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
|
5027 Compile::AliasIdxRaw, |
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
5028 top())->as_Initialize(); |
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
5029 init->set_complete(&_gvn); // (there is no corresponding AllocateNode) |
0 | 5030 } |
5031 } | |
5032 | |
5033 // Present the results of the fast call. | |
5034 result_region->init_req(zero_path, control()); | |
5035 result_i_o ->init_req(zero_path, i_o()); | |
5036 result_memory->init_req(zero_path, memory(adr_type)); | |
5037 } | |
5038 | |
2324 | 5039 if (!stopped() && dest_uninitialized) { |
0 | 5040 // We have to initialize the *uncopied* part of the array to zero. |
5041 // The copy destination is the slice dest[off..off+len]. The other slices | |
5042 // are dest_head = dest[0..off] and dest_tail = dest[off+len..dest.length]. | |
5043 Node* dest_size = alloc->in(AllocateNode::AllocSize); | |
5044 Node* dest_length = alloc->in(AllocateNode::ALength); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5045 Node* dest_tail = _gvn.transform(new(C) AddINode(dest_offset, |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5046 copy_length)); |
0 | 5047 |
5048 // If there is a head section that needs zeroing, do it now. | |
5049 if (find_int_con(dest_offset, -1) != 0) { | |
5050 generate_clear_array(adr_type, dest, basic_elem_type, | |
5051 intcon(0), dest_offset, | |
5052 NULL); | |
5053 } | |
5054 | |
5055 // Next, perform a dynamic check on the tail length. | |
5056 // It is often zero, and we can win big if we prove this. | |
5057 // There are two wins: Avoid generating the ClearArray | |
5058 // with its attendant messy index arithmetic, and upgrade | |
5059 // the copy to a more hardware-friendly word size of 64 bits. | |
5060 Node* tail_ctl = NULL; | |
4778 | 5061 if (!stopped() && !dest_tail->eqv_uncast(dest_length)) { |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5062 Node* cmp_lt = _gvn.transform(new(C) CmpINode(dest_tail, dest_length)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5063 Node* bol_lt = _gvn.transform(new(C) BoolNode(cmp_lt, BoolTest::lt)); |
0 | 5064 tail_ctl = generate_slow_guard(bol_lt, NULL); |
5065 assert(tail_ctl != NULL || !stopped(), "must be an outcome"); | |
5066 } | |
5067 | |
5068 // At this point, let's assume there is no tail. | |
5069 if (!stopped() && alloc != NULL && basic_elem_type != T_OBJECT) { | |
5070 // There is no tail. Try an upgrade to a 64-bit copy. | |
5071 bool didit = false; | |
5072 { PreserveJVMState pjvms(this); | |
5073 didit = generate_block_arraycopy(adr_type, basic_elem_type, alloc, | |
5074 src, src_offset, dest, dest_offset, | |
2324 | 5075 dest_size, dest_uninitialized); |
0 | 5076 if (didit) { |
5077 // Present the results of the block-copying fast call. | |
5078 result_region->init_req(bcopy_path, control()); | |
5079 result_i_o ->init_req(bcopy_path, i_o()); | |
5080 result_memory->init_req(bcopy_path, memory(adr_type)); | |
5081 } | |
5082 } | |
5083 if (didit) | |
5084 set_control(top()); // no regular fast path | |
5085 } | |
5086 | |
5087 // Clear the tail, if any. | |
5088 if (tail_ctl != NULL) { | |
5089 Node* notail_ctl = stopped() ? NULL : control(); | |
5090 set_control(tail_ctl); | |
5091 if (notail_ctl == NULL) { | |
5092 generate_clear_array(adr_type, dest, basic_elem_type, | |
5093 dest_tail, NULL, | |
5094 dest_size); | |
5095 } else { | |
5096 // Make a local merge. | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
5097 Node* done_ctl = new(C) RegionNode(3); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
5098 Node* done_mem = new(C) PhiNode(done_ctl, Type::MEMORY, adr_type); |
0 | 5099 done_ctl->init_req(1, notail_ctl); |
5100 done_mem->init_req(1, memory(adr_type)); | |
5101 generate_clear_array(adr_type, dest, basic_elem_type, | |
5102 dest_tail, NULL, | |
5103 dest_size); | |
5104 done_ctl->init_req(2, control()); | |
5105 done_mem->init_req(2, memory(adr_type)); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5106 set_control( _gvn.transform(done_ctl)); |
0 | 5107 set_memory( _gvn.transform(done_mem), adr_type ); |
5108 } | |
5109 } | |
5110 } | |
5111 | |
5112 BasicType copy_type = basic_elem_type; | |
5113 assert(basic_elem_type != T_ARRAY, "caller must fix this"); | |
5114 if (!stopped() && copy_type == T_OBJECT) { | |
5115 // If src and dest have compatible element types, we can copy bits. | |
5116 // Types S[] and D[] are compatible if D is a supertype of S. | |
5117 // | |
5118 // If they are not, we will use checked_oop_disjoint_arraycopy, | |
5119 // which performs a fast optimistic per-oop check, and backs off | |
5120 // further to JVM_ArrayCopy on the first per-oop check that fails. | |
5121 // (Actually, we don't move raw bits only; the GC requires card marks.) | |
5122 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6615
diff
changeset
|
5123 // Get the Klass* for both src and dest |
0 | 5124 Node* src_klass = load_object_klass(src); |
5125 Node* dest_klass = load_object_klass(dest); | |
5126 | |
5127 // Generate the subtype check. | |
5128 // This might fold up statically, or then again it might not. | |
5129 // | |
5130 // Non-static example: Copying List<String>.elements to a new String[]. | |
5131 // The backing store for a List<String> is always an Object[], | |
5132 // but its elements are always type String, if the generic types | |
5133 // are correct at the source level. | |
5134 // | |
5135 // Test S[] against D[], not S against D, because (probably) | |
5136 // the secondary supertype cache is less busy for S[] than S. | |
5137 // This usually only matters when D is an interface. | |
5138 Node* not_subtype_ctrl = gen_subtype_check(src_klass, dest_klass); | |
5139 // Plug failing path into checked_oop_disjoint_arraycopy | |
5140 if (not_subtype_ctrl != top()) { | |
5141 PreserveJVMState pjvms(this); | |
5142 set_control(not_subtype_ctrl); | |
5143 // (At this point we can assume disjoint_bases, since types differ.) | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6804
diff
changeset
|
5144 int ek_offset = in_bytes(ObjArrayKlass::element_klass_offset()); |
0 | 5145 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
|
5146 Node* n1 = LoadKlassNode::make(_gvn, immutable_memory(), p1, TypeRawPtr::BOTTOM); |
0 | 5147 Node* dest_elem_klass = _gvn.transform(n1); |
5148 Node* cv = generate_checkcast_arraycopy(adr_type, | |
5149 dest_elem_klass, | |
5150 src, src_offset, dest, dest_offset, | |
2324 | 5151 ConvI2X(copy_length), dest_uninitialized); |
0 | 5152 if (cv == NULL) cv = intcon(-1); // failure (no stub available) |
5153 checked_control = control(); | |
5154 checked_i_o = i_o(); | |
5155 checked_mem = memory(adr_type); | |
5156 checked_value = cv; | |
5157 } | |
5158 // At this point we know we do not need type checks on oop stores. | |
5159 | |
5160 // Let's see if we need card marks: | |
5161 if (alloc != NULL && use_ReduceInitialCardMarks()) { | |
5162 // 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
|
5163 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
|
5164 assert(type2aelembytes(basic_elem_type) == type2aelembytes(copy_type), |
0 | 5165 "sizes agree"); |
5166 } | |
5167 } | |
5168 | |
5169 if (!stopped()) { | |
5170 // Generate the fast path, if possible. | |
5171 PreserveJVMState pjvms(this); | |
5172 generate_unchecked_arraycopy(adr_type, copy_type, disjoint_bases, | |
5173 src, src_offset, dest, dest_offset, | |
2324 | 5174 ConvI2X(copy_length), dest_uninitialized); |
0 | 5175 |
5176 // Present the results of the fast call. | |
5177 result_region->init_req(fast_path, control()); | |
5178 result_i_o ->init_req(fast_path, i_o()); | |
5179 result_memory->init_req(fast_path, memory(adr_type)); | |
5180 } | |
5181 | |
5182 // Here are all the slow paths up to this point, in one bundle: | |
5183 slow_control = top(); | |
5184 if (slow_region != NULL) | |
5185 slow_control = _gvn.transform(slow_region); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5186 DEBUG_ONLY(slow_region = (RegionNode*)badAddress); |
0 | 5187 |
5188 set_control(checked_control); | |
5189 if (!stopped()) { | |
5190 // Clean up after the checked call. | |
5191 // The returned value is either 0 or -1^K, | |
5192 // where K = number of partially transferred array elements. | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5193 Node* cmp = _gvn.transform(new(C) CmpINode(checked_value, intcon(0))); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5194 Node* bol = _gvn.transform(new(C) BoolNode(cmp, BoolTest::eq)); |
0 | 5195 IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN); |
5196 | |
5197 // If it is 0, we are done, so transfer to the end. | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5198 Node* checks_done = _gvn.transform(new(C) IfTrueNode(iff)); |
0 | 5199 result_region->init_req(checked_path, checks_done); |
5200 result_i_o ->init_req(checked_path, checked_i_o); | |
5201 result_memory->init_req(checked_path, checked_mem); | |
5202 | |
5203 // If it is not zero, merge into the slow call. | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5204 set_control( _gvn.transform(new(C) IfFalseNode(iff) )); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
5205 RegionNode* slow_reg2 = new(C) RegionNode(3); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
5206 PhiNode* slow_i_o2 = new(C) PhiNode(slow_reg2, Type::ABIO); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
5207 PhiNode* slow_mem2 = new(C) PhiNode(slow_reg2, Type::MEMORY, adr_type); |
0 | 5208 record_for_igvn(slow_reg2); |
5209 slow_reg2 ->init_req(1, slow_control); | |
5210 slow_i_o2 ->init_req(1, slow_i_o); | |
5211 slow_mem2 ->init_req(1, slow_mem); | |
5212 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
|
5213 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
|
5214 slow_mem2 ->init_req(2, checked_mem); |
0 | 5215 |
5216 slow_control = _gvn.transform(slow_reg2); | |
5217 slow_i_o = _gvn.transform(slow_i_o2); | |
5218 slow_mem = _gvn.transform(slow_mem2); | |
5219 | |
5220 if (alloc != NULL) { | |
5221 // We'll restart from the very beginning, after zeroing the whole thing. | |
5222 // This can cause double writes, but that's OK since dest is brand new. | |
5223 // So we ignore the low 31 bits of the value returned from the stub. | |
5224 } else { | |
5225 // We must continue the copy exactly where it failed, or else | |
5226 // another thread might see the wrong number of writes to dest. | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5227 Node* checked_offset = _gvn.transform(new(C) XorINode(checked_value, intcon(-1))); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
5228 Node* slow_offset = new(C) PhiNode(slow_reg2, TypeInt::INT); |
0 | 5229 slow_offset->init_req(1, intcon(0)); |
5230 slow_offset->init_req(2, checked_offset); | |
5231 slow_offset = _gvn.transform(slow_offset); | |
5232 | |
5233 // Adjust the arguments by the conditionally incoming offset. | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5234 Node* src_off_plus = _gvn.transform(new(C) AddINode(src_offset, slow_offset)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5235 Node* dest_off_plus = _gvn.transform(new(C) AddINode(dest_offset, slow_offset)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5236 Node* length_minus = _gvn.transform(new(C) SubINode(copy_length, slow_offset)); |
0 | 5237 |
5238 // Tweak the node variables to adjust the code produced below: | |
5239 src_offset = src_off_plus; | |
5240 dest_offset = dest_off_plus; | |
5241 copy_length = length_minus; | |
5242 } | |
5243 } | |
5244 | |
5245 set_control(slow_control); | |
5246 if (!stopped()) { | |
5247 // Generate the slow path, if needed. | |
5248 PreserveJVMState pjvms(this); // replace_in_map may trash the map | |
5249 | |
5250 set_memory(slow_mem, adr_type); | |
5251 set_i_o(slow_i_o); | |
5252 | |
2324 | 5253 if (dest_uninitialized) { |
0 | 5254 generate_clear_array(adr_type, dest, basic_elem_type, |
5255 intcon(0), NULL, | |
5256 alloc->in(AllocateNode::AllocSize)); | |
5257 } | |
5258 | |
5259 generate_slow_arraycopy(adr_type, | |
5260 src, src_offset, dest, dest_offset, | |
2324 | 5261 copy_length, /*dest_uninitialized*/false); |
0 | 5262 |
5263 result_region->init_req(slow_call_path, control()); | |
5264 result_i_o ->init_req(slow_call_path, i_o()); | |
5265 result_memory->init_req(slow_call_path, memory(adr_type)); | |
5266 } | |
5267 | |
5268 // Remove unused edges. | |
5269 for (uint i = 1; i < result_region->req(); i++) { | |
5270 if (result_region->in(i) == NULL) | |
5271 result_region->init_req(i, top()); | |
5272 } | |
5273 | |
5274 // Finished; return the combined state. | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5275 set_control( _gvn.transform(result_region)); |
0 | 5276 set_i_o( _gvn.transform(result_i_o) ); |
5277 set_memory( _gvn.transform(result_memory), adr_type ); | |
5278 | |
5279 // The memory edges above are precise in order to model effects around | |
605 | 5280 // array copies accurately to allow value numbering of field loads around |
0 | 5281 // arraycopy. Such field loads, both before and after, are common in Java |
5282 // collections and similar classes involving header/array data structures. | |
5283 // | |
5284 // But with low number of register or when some registers are used or killed | |
5285 // by arraycopy calls it causes registers spilling on stack. See 6544710. | |
5286 // The next memory barrier is added to avoid it. If the arraycopy can be | |
5287 // optimized away (which it can, sometimes) then we can manually remove | |
5288 // the membar also. | |
958
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
5289 // |
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
5290 // Do not let reads from the cloned object float above the arraycopy. |
4763
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
5291 if (alloc != NULL) { |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
5292 // Do not let stores that initialize this object be reordered with |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
5293 // a subsequent store that would make this object accessible by |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
5294 // other threads. |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
5295 // Record what AllocateNode this StoreStore protects so that |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
5296 // escape analysis can go from the MemBarStoreStoreNode to the |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
5297 // AllocateNode and eliminate the MemBarStoreStoreNode if possible |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
5298 // based on the escape status of the AllocateNode. |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
5299 insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress)); |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
5300 } else if (InsertMemBarAfterArraycopy) |
0 | 5301 insert_mem_bar(Op_MemBarCPUOrder); |
5302 } | |
5303 | |
5304 | |
5305 // Helper function which determines if an arraycopy immediately follows | |
5306 // an allocation, with no intervening tests or other escapes for the object. | |
5307 AllocateArrayNode* | |
5308 LibraryCallKit::tightly_coupled_allocation(Node* ptr, | |
5309 RegionNode* slow_region) { | |
5310 if (stopped()) return NULL; // no fast path | |
5311 if (C->AliasLevel() == 0) return NULL; // no MergeMems around | |
5312 | |
5313 AllocateArrayNode* alloc = AllocateArrayNode::Ideal_array_allocation(ptr, &_gvn); | |
5314 if (alloc == NULL) return NULL; | |
5315 | |
5316 Node* rawmem = memory(Compile::AliasIdxRaw); | |
5317 // Is the allocation's memory state untouched? | |
5318 if (!(rawmem->is_Proj() && rawmem->in(0)->is_Initialize())) { | |
5319 // Bail out if there have been raw-memory effects since the allocation. | |
5320 // (Example: There might have been a call or safepoint.) | |
5321 return NULL; | |
5322 } | |
5323 rawmem = rawmem->in(0)->as_Initialize()->memory(Compile::AliasIdxRaw); | |
5324 if (!(rawmem->is_Proj() && rawmem->in(0) == alloc)) { | |
5325 return NULL; | |
5326 } | |
5327 | |
5328 // There must be no unexpected observers of this allocation. | |
5329 for (DUIterator_Fast imax, i = ptr->fast_outs(imax); i < imax; i++) { | |
5330 Node* obs = ptr->fast_out(i); | |
5331 if (obs != this->map()) { | |
5332 return NULL; | |
5333 } | |
5334 } | |
5335 | |
5336 // This arraycopy must unconditionally follow the allocation of the ptr. | |
5337 Node* alloc_ctl = ptr->in(0); | |
5338 assert(just_allocated_object(alloc_ctl) == ptr, "most recent allo"); | |
5339 | |
5340 Node* ctl = control(); | |
5341 while (ctl != alloc_ctl) { | |
5342 // There may be guards which feed into the slow_region. | |
5343 // Any other control flow means that we might not get a chance | |
5344 // to finish initializing the allocated object. | |
5345 if ((ctl->is_IfFalse() || ctl->is_IfTrue()) && ctl->in(0)->is_If()) { | |
5346 IfNode* iff = ctl->in(0)->as_If(); | |
5347 Node* not_ctl = iff->proj_out(1 - ctl->as_Proj()->_con); | |
5348 assert(not_ctl != NULL && not_ctl != ctl, "found alternate"); | |
5349 if (slow_region != NULL && slow_region->find_edge(not_ctl) >= 1) { | |
5350 ctl = iff->in(0); // This test feeds the known slow_region. | |
5351 continue; | |
5352 } | |
5353 // One more try: Various low-level checks bottom out in | |
5354 // uncommon traps. If the debug-info of the trap omits | |
5355 // any reference to the allocation, as we've already | |
5356 // observed, then there can be no objection to the trap. | |
5357 bool found_trap = false; | |
5358 for (DUIterator_Fast jmax, j = not_ctl->fast_outs(jmax); j < jmax; j++) { | |
5359 Node* obs = not_ctl->fast_out(j); | |
5360 if (obs->in(0) == not_ctl && obs->is_Call() && | |
1748 | 5361 (obs->as_Call()->entry_point() == SharedRuntime::uncommon_trap_blob()->entry_point())) { |
0 | 5362 found_trap = true; break; |
5363 } | |
5364 } | |
5365 if (found_trap) { | |
5366 ctl = iff->in(0); // This test feeds a harmless uncommon trap. | |
5367 continue; | |
5368 } | |
5369 } | |
5370 return NULL; | |
5371 } | |
5372 | |
5373 // If we get this far, we have an allocation which immediately | |
5374 // precedes the arraycopy, and we can take over zeroing the new object. | |
5375 // The arraycopy will finish the initialization, and provide | |
5376 // a new control state to which we will anchor the destination pointer. | |
5377 | |
5378 return alloc; | |
5379 } | |
5380 | |
5381 // Helper for initialization of arrays, creating a ClearArray. | |
5382 // It writes zero bits in [start..end), within the body of an array object. | |
5383 // The memory effects are all chained onto the 'adr_type' alias category. | |
5384 // | |
5385 // Since the object is otherwise uninitialized, we are free | |
5386 // to put a little "slop" around the edges of the cleared area, | |
5387 // as long as it does not go back into the array's header, | |
5388 // or beyond the array end within the heap. | |
5389 // | |
5390 // The lower edge can be rounded down to the nearest jint and the | |
5391 // upper edge can be rounded up to the nearest MinObjAlignmentInBytes. | |
5392 // | |
5393 // Arguments: | |
5394 // adr_type memory slice where writes are generated | |
5395 // dest oop of the destination array | |
5396 // basic_elem_type element type of the destination | |
5397 // slice_idx array index of first element to store | |
5398 // slice_len number of elements to store (or NULL) | |
5399 // dest_size total size in bytes of the array object | |
5400 // | |
5401 // Exactly one of slice_len or dest_size must be non-NULL. | |
5402 // If dest_size is non-NULL, zeroing extends to the end of the object. | |
5403 // If slice_len is non-NULL, the slice_idx value must be a constant. | |
5404 void | |
5405 LibraryCallKit::generate_clear_array(const TypePtr* adr_type, | |
5406 Node* dest, | |
5407 BasicType basic_elem_type, | |
5408 Node* slice_idx, | |
5409 Node* slice_len, | |
5410 Node* dest_size) { | |
5411 // one or the other but not both of slice_len and dest_size: | |
5412 assert((slice_len != NULL? 1: 0) + (dest_size != NULL? 1: 0) == 1, ""); | |
5413 if (slice_len == NULL) slice_len = top(); | |
5414 if (dest_size == NULL) dest_size = top(); | |
5415 | |
5416 // operate on this memory slice: | |
5417 Node* mem = memory(adr_type); // memory slice to operate on | |
5418 | |
5419 // scaling and rounding of indexes: | |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
0
diff
changeset
|
5420 int scale = exact_log2(type2aelembytes(basic_elem_type)); |
0 | 5421 int abase = arrayOopDesc::base_offset_in_bytes(basic_elem_type); |
5422 int clear_low = (-1 << scale) & (BytesPerInt - 1); | |
5423 int bump_bit = (-1 << scale) & BytesPerInt; | |
5424 | |
5425 // determine constant starts and ends | |
5426 const intptr_t BIG_NEG = -128; | |
5427 assert(BIG_NEG + 2*abase < 0, "neg enough"); | |
5428 intptr_t slice_idx_con = (intptr_t) find_int_con(slice_idx, BIG_NEG); | |
5429 intptr_t slice_len_con = (intptr_t) find_int_con(slice_len, BIG_NEG); | |
5430 if (slice_len_con == 0) { | |
5431 return; // nothing to do here | |
5432 } | |
5433 intptr_t start_con = (abase + (slice_idx_con << scale)) & ~clear_low; | |
5434 intptr_t end_con = find_intptr_t_con(dest_size, -1); | |
5435 if (slice_idx_con >= 0 && slice_len_con >= 0) { | |
5436 assert(end_con < 0, "not two cons"); | |
5437 end_con = round_to(abase + ((slice_idx_con + slice_len_con) << scale), | |
5438 BytesPerLong); | |
5439 } | |
5440 | |
5441 if (start_con >= 0 && end_con >= 0) { | |
5442 // Constant start and end. Simple. | |
5443 mem = ClearArrayNode::clear_memory(control(), mem, dest, | |
5444 start_con, end_con, &_gvn); | |
5445 } else if (start_con >= 0 && dest_size != top()) { | |
5446 // Constant start, pre-rounded end after the tail of the array. | |
5447 Node* end = dest_size; | |
5448 mem = ClearArrayNode::clear_memory(control(), mem, dest, | |
5449 start_con, end, &_gvn); | |
5450 } else if (start_con >= 0 && slice_len != top()) { | |
5451 // Constant start, non-constant end. End needs rounding up. | |
5452 // End offset = round_up(abase + ((slice_idx_con + slice_len) << scale), 8) | |
5453 intptr_t end_base = abase + (slice_idx_con << scale); | |
5454 int end_round = (-1 << scale) & (BytesPerLong - 1); | |
5455 Node* end = ConvI2X(slice_len); | |
5456 if (scale != 0) | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5457 end = _gvn.transform(new(C) LShiftXNode(end, intcon(scale) )); |
0 | 5458 end_base += end_round; |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5459 end = _gvn.transform(new(C) AddXNode(end, MakeConX(end_base))); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5460 end = _gvn.transform(new(C) AndXNode(end, MakeConX(~end_round))); |
0 | 5461 mem = ClearArrayNode::clear_memory(control(), mem, dest, |
5462 start_con, end, &_gvn); | |
5463 } else if (start_con < 0 && dest_size != top()) { | |
5464 // Non-constant start, pre-rounded end after the tail of the array. | |
5465 // This is almost certainly a "round-to-end" operation. | |
5466 Node* start = slice_idx; | |
5467 start = ConvI2X(start); | |
5468 if (scale != 0) | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5469 start = _gvn.transform(new(C) LShiftXNode( start, intcon(scale) )); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5470 start = _gvn.transform(new(C) AddXNode(start, MakeConX(abase))); |
0 | 5471 if ((bump_bit | clear_low) != 0) { |
5472 int to_clear = (bump_bit | clear_low); | |
5473 // Align up mod 8, then store a jint zero unconditionally | |
5474 // 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
|
5475 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
|
5476 < 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
|
5477 bump_bit = 0; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5478 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
|
5479 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5480 // Bump 'start' up to (or past) the next jint boundary: |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5481 start = _gvn.transform(new(C) AddXNode(start, MakeConX(bump_bit))); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5482 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
|
5483 } |
0 | 5484 // Round bumped 'start' down to jlong boundary in body of array. |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5485 start = _gvn.transform(new(C) 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
|
5486 if (bump_bit != 0) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5487 // Store a zero to the immediately preceding jint: |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5488 Node* x1 = _gvn.transform(new(C) AddXNode(start, MakeConX(-bump_bit))); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5489 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
|
5490 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
|
5491 mem = _gvn.transform(mem); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5492 } |
0 | 5493 } |
5494 Node* end = dest_size; // pre-rounded | |
5495 mem = ClearArrayNode::clear_memory(control(), mem, dest, | |
5496 start, end, &_gvn); | |
5497 } else { | |
5498 // Non-constant start, unrounded non-constant end. | |
5499 // (Nobody zeroes a random midsection of an array using this routine.) | |
5500 ShouldNotReachHere(); // fix caller | |
5501 } | |
5502 | |
5503 // Done. | |
5504 set_memory(mem, adr_type); | |
5505 } | |
5506 | |
5507 | |
5508 bool | |
5509 LibraryCallKit::generate_block_arraycopy(const TypePtr* adr_type, | |
5510 BasicType basic_elem_type, | |
5511 AllocateNode* alloc, | |
5512 Node* src, Node* src_offset, | |
5513 Node* dest, Node* dest_offset, | |
2324 | 5514 Node* dest_size, bool dest_uninitialized) { |
0 | 5515 // 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
|
5516 int scale = exact_log2(type2aelembytes(basic_elem_type)); |
0 | 5517 if (scale >= LogBytesPerLong) |
5518 return false; // it is already a block transfer | |
5519 | |
5520 // Look at the alignment of the starting offsets. | |
5521 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
|
5522 |
b2cb497dec28
7047069: Array can dynamically change size when assigned to an object field
kvn
parents:
3337
diff
changeset
|
5523 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
|
5524 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
|
5525 if (src_off_con < 0 || dest_off_con < 0) |
0 | 5526 // At present, we can only understand constants. |
5527 return false; | |
5528 | |
3742
b2cb497dec28
7047069: Array can dynamically change size when assigned to an object field
kvn
parents:
3337
diff
changeset
|
5529 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
|
5530 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
|
5531 |
0 | 5532 if (((src_off | dest_off) & (BytesPerLong-1)) != 0) { |
5533 // Non-aligned; too bad. | |
5534 // One more chance: Pick off an initial 32-bit word. | |
5535 // This is a common case, since abase can be odd mod 8. | |
5536 if (((src_off | dest_off) & (BytesPerLong-1)) == BytesPerInt && | |
5537 ((src_off ^ dest_off) & (BytesPerLong-1)) == 0) { | |
5538 Node* sptr = basic_plus_adr(src, src_off); | |
5539 Node* dptr = basic_plus_adr(dest, dest_off); | |
5540 Node* sval = make_load(control(), sptr, TypeInt::INT, T_INT, adr_type); | |
5541 store_to_memory(control(), dptr, sval, T_INT, adr_type); | |
5542 src_off += BytesPerInt; | |
5543 dest_off += BytesPerInt; | |
5544 } else { | |
5545 return false; | |
5546 } | |
5547 } | |
5548 assert(src_off % BytesPerLong == 0, ""); | |
5549 assert(dest_off % BytesPerLong == 0, ""); | |
5550 | |
5551 // Do this copy by giant steps. | |
5552 Node* sptr = basic_plus_adr(src, src_off); | |
5553 Node* dptr = basic_plus_adr(dest, dest_off); | |
5554 Node* countx = dest_size; | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5555 countx = _gvn.transform(new (C) SubXNode(countx, MakeConX(dest_off))); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5556 countx = _gvn.transform(new (C) URShiftXNode(countx, intcon(LogBytesPerLong))); |
0 | 5557 |
5558 bool disjoint_bases = true; // since alloc != NULL | |
5559 generate_unchecked_arraycopy(adr_type, T_LONG, disjoint_bases, | |
2324 | 5560 sptr, NULL, dptr, NULL, countx, dest_uninitialized); |
0 | 5561 |
5562 return true; | |
5563 } | |
5564 | |
5565 | |
5566 // Helper function; generates code for the slow case. | |
5567 // We make a call to a runtime method which emulates the native method, | |
5568 // but without the native wrapper overhead. | |
5569 void | |
5570 LibraryCallKit::generate_slow_arraycopy(const TypePtr* adr_type, | |
5571 Node* src, Node* src_offset, | |
5572 Node* dest, Node* dest_offset, | |
2324 | 5573 Node* copy_length, bool dest_uninitialized) { |
5574 assert(!dest_uninitialized, "Invariant"); | |
0 | 5575 Node* call = make_runtime_call(RC_NO_LEAF | RC_UNCOMMON, |
5576 OptoRuntime::slow_arraycopy_Type(), | |
5577 OptoRuntime::slow_arraycopy_Java(), | |
5578 "slow_arraycopy", adr_type, | |
5579 src, src_offset, dest, dest_offset, | |
5580 copy_length); | |
5581 | |
5582 // Handle exceptions thrown by this fellow: | |
5583 make_slow_call_ex(call, env()->Throwable_klass(), false); | |
5584 } | |
5585 | |
5586 // Helper function; generates code for cases requiring runtime checks. | |
5587 Node* | |
5588 LibraryCallKit::generate_checkcast_arraycopy(const TypePtr* adr_type, | |
5589 Node* dest_elem_klass, | |
5590 Node* src, Node* src_offset, | |
5591 Node* dest, Node* dest_offset, | |
2324 | 5592 Node* copy_length, bool dest_uninitialized) { |
0 | 5593 if (stopped()) return NULL; |
5594 | |
2324 | 5595 address copyfunc_addr = StubRoutines::checkcast_arraycopy(dest_uninitialized); |
0 | 5596 if (copyfunc_addr == NULL) { // Stub was not generated, go slow path. |
5597 return NULL; | |
5598 } | |
5599 | |
5600 // Pick out the parameters required to perform a store-check | |
5601 // for the target array. This is an optimistic check. It will | |
5602 // look in each non-null element's class, at the desired klass's | |
5603 // super_check_offset, for the desired klass. | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3961
diff
changeset
|
5604 int sco_offset = in_bytes(Klass::super_check_offset_offset()); |
0 | 5605 Node* p3 = basic_plus_adr(dest_elem_klass, sco_offset); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
5606 Node* n3 = new(C) 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
|
5607 Node* check_offset = ConvI2X(_gvn.transform(n3)); |
0 | 5608 Node* check_value = dest_elem_klass; |
5609 | |
5610 Node* src_start = array_element_address(src, src_offset, T_OBJECT); | |
5611 Node* dest_start = array_element_address(dest, dest_offset, T_OBJECT); | |
5612 | |
5613 // (We know the arrays are never conjoint, because their types differ.) | |
5614 Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, | |
5615 OptoRuntime::checkcast_arraycopy_Type(), | |
5616 copyfunc_addr, "checkcast_arraycopy", adr_type, | |
5617 // five arguments, of which two are | |
5618 // intptr_t (jlong in LP64) | |
5619 src_start, dest_start, | |
5620 copy_length XTOP, | |
5621 check_offset XTOP, | |
5622 check_value); | |
5623 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
5624 return _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms)); |
0 | 5625 } |
5626 | |
5627 | |
5628 // Helper function; generates code for cases requiring runtime checks. | |
5629 Node* | |
5630 LibraryCallKit::generate_generic_arraycopy(const TypePtr* adr_type, | |
5631 Node* src, Node* src_offset, | |
5632 Node* dest, Node* dest_offset, | |
2324 | 5633 Node* copy_length, bool dest_uninitialized) { |
5634 assert(!dest_uninitialized, "Invariant"); | |
0 | 5635 if (stopped()) return NULL; |
5636 address copyfunc_addr = StubRoutines::generic_arraycopy(); | |
5637 if (copyfunc_addr == NULL) { // Stub was not generated, go slow path. | |
5638 return NULL; | |
5639 } | |
5640 | |
5641 Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, | |
5642 OptoRuntime::generic_arraycopy_Type(), | |
5643 copyfunc_addr, "generic_arraycopy", adr_type, | |
5644 src, src_offset, dest, dest_offset, copy_length); | |
5645 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
5646 return _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms)); |
0 | 5647 } |
5648 | |
5649 // Helper function; generates the fast out-of-line call to an arraycopy stub. | |
5650 void | |
5651 LibraryCallKit::generate_unchecked_arraycopy(const TypePtr* adr_type, | |
5652 BasicType basic_elem_type, | |
5653 bool disjoint_bases, | |
5654 Node* src, Node* src_offset, | |
5655 Node* dest, Node* dest_offset, | |
2324 | 5656 Node* copy_length, bool dest_uninitialized) { |
0 | 5657 if (stopped()) return; // nothing to do |
5658 | |
5659 Node* src_start = src; | |
5660 Node* dest_start = dest; | |
5661 if (src_offset != NULL || dest_offset != NULL) { | |
5662 assert(src_offset != NULL && dest_offset != NULL, ""); | |
5663 src_start = array_element_address(src, src_offset, basic_elem_type); | |
5664 dest_start = array_element_address(dest, dest_offset, basic_elem_type); | |
5665 } | |
5666 | |
5667 // Figure out which arraycopy runtime method to call. | |
5668 const char* copyfunc_name = "arraycopy"; | |
5669 address copyfunc_addr = | |
5670 basictype2arraycopy(basic_elem_type, src_offset, dest_offset, | |
2324 | 5671 disjoint_bases, copyfunc_name, dest_uninitialized); |
0 | 5672 |
5673 // Call it. Note that the count_ix value is not scaled to a byte-size. | |
5674 make_runtime_call(RC_LEAF|RC_NO_FP, | |
5675 OptoRuntime::fast_arraycopy_Type(), | |
5676 copyfunc_addr, copyfunc_name, adr_type, | |
5677 src_start, dest_start, copy_length XTOP); | |
5678 } | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5679 |
7637
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5680 //-------------inline_encodeISOArray----------------------------------- |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5681 // encode char[] to byte[] in ISO_8859_1 |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5682 bool LibraryCallKit::inline_encodeISOArray() { |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5683 assert(callee()->signature()->size() == 5, "encodeISOArray has 5 parameters"); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5684 // no receiver since it is static method |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5685 Node *src = argument(0); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5686 Node *src_offset = argument(1); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5687 Node *dst = argument(2); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5688 Node *dst_offset = argument(3); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5689 Node *length = argument(4); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5690 |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5691 const Type* src_type = src->Value(&_gvn); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5692 const Type* dst_type = dst->Value(&_gvn); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5693 const TypeAryPtr* top_src = src_type->isa_aryptr(); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5694 const TypeAryPtr* top_dest = dst_type->isa_aryptr(); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5695 if (top_src == NULL || top_src->klass() == NULL || |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5696 top_dest == NULL || top_dest->klass() == NULL) { |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5697 // failed array check |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5698 return false; |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5699 } |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5700 |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5701 // Figure out the size and type of the elements we will be copying. |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5702 BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5703 BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5704 if (src_elem != T_CHAR || dst_elem != T_BYTE) { |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5705 return false; |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5706 } |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5707 Node* src_start = array_element_address(src, src_offset, src_elem); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5708 Node* dst_start = array_element_address(dst, dst_offset, dst_elem); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5709 // 'src_start' points to src array + scaled offset |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5710 // 'dst_start' points to dst array + scaled offset |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5711 |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5712 const TypeAryPtr* mtype = TypeAryPtr::BYTES; |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5713 Node* enc = new (C) EncodeISOArrayNode(control(), memory(mtype), src_start, dst_start, length); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5714 enc = _gvn.transform(enc); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5715 Node* res_mem = _gvn.transform(new (C) SCMemProjNode(enc)); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5716 set_memory(res_mem, mtype); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5717 set_result(enc); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5718 return true; |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5719 } |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5720 |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5721 /** |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5722 * Calculate CRC32 for byte. |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5723 * int java.util.zip.CRC32.update(int crc, int b) |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5724 */ |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5725 bool LibraryCallKit::inline_updateCRC32() { |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5726 assert(UseCRC32Intrinsics, "need AVX and LCMUL instructions support"); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5727 assert(callee()->signature()->size() == 2, "update has 2 parameters"); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5728 // no receiver since it is static method |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5729 Node* crc = argument(0); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5730 Node* b = argument(1); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5731 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5732 /* |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5733 * int c = ~ crc; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5734 * b = timesXtoThe32[(b ^ c) & 0xFF]; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5735 * b = b ^ (c >>> 8); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5736 * crc = ~b; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5737 */ |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5738 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5739 Node* M1 = intcon(-1); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5740 crc = _gvn.transform(new (C) XorINode(crc, M1)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5741 Node* result = _gvn.transform(new (C) XorINode(crc, b)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5742 result = _gvn.transform(new (C) AndINode(result, intcon(0xFF))); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5743 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5744 Node* base = makecon(TypeRawPtr::make(StubRoutines::crc_table_addr())); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5745 Node* offset = _gvn.transform(new (C) LShiftINode(result, intcon(0x2))); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5746 Node* adr = basic_plus_adr(top(), base, ConvI2X(offset)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5747 result = make_load(control(), adr, TypeInt::INT, T_INT); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5748 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5749 crc = _gvn.transform(new (C) URShiftINode(crc, intcon(8))); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5750 result = _gvn.transform(new (C) XorINode(crc, result)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5751 result = _gvn.transform(new (C) XorINode(result, M1)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5752 set_result(result); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5753 return true; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5754 } |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5755 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5756 /** |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5757 * Calculate CRC32 for byte[] array. |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5758 * int java.util.zip.CRC32.updateBytes(int crc, byte[] buf, int off, int len) |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5759 */ |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5760 bool LibraryCallKit::inline_updateBytesCRC32() { |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5761 assert(UseCRC32Intrinsics, "need AVX and LCMUL instructions support"); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5762 assert(callee()->signature()->size() == 4, "updateBytes has 4 parameters"); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5763 // no receiver since it is static method |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5764 Node* crc = argument(0); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5765 Node* src = argument(1); // type: oop |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5766 Node* offset = argument(2); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5767 Node* length = argument(3); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5768 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5769 const Type* src_type = src->Value(&_gvn); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5770 const TypeAryPtr* top_src = src_type->isa_aryptr(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5771 if (top_src == NULL || top_src->klass() == NULL) { |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5772 // failed array check |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5773 return false; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5774 } |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5775 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5776 // Figure out the size and type of the elements we will be copying. |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5777 BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5778 if (src_elem != T_BYTE) { |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5779 return false; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5780 } |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5781 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5782 // 'src_start' points to src array + scaled offset |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5783 Node* src_start = array_element_address(src, offset, src_elem); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5784 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5785 // We assume that range check is done by caller. |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5786 // TODO: generate range check (offset+length < src.length) in debug VM. |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5787 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5788 // Call the stub. |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5789 address stubAddr = StubRoutines::updateBytesCRC32(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5790 const char *stubName = "updateBytesCRC32"; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5791 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5792 Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::updateBytesCRC32_Type(), |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5793 stubAddr, stubName, TypePtr::BOTTOM, |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5794 crc, src_start, length); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5795 Node* result = _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5796 set_result(result); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5797 return true; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5798 } |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5799 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5800 /** |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5801 * Calculate CRC32 for ByteBuffer. |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5802 * int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len) |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5803 */ |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5804 bool LibraryCallKit::inline_updateByteBufferCRC32() { |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5805 assert(UseCRC32Intrinsics, "need AVX and LCMUL instructions support"); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5806 assert(callee()->signature()->size() == 5, "updateByteBuffer has 4 parameters and one is long"); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5807 // no receiver since it is static method |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5808 Node* crc = argument(0); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5809 Node* src = argument(1); // type: long |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5810 Node* offset = argument(3); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5811 Node* length = argument(4); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5812 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5813 src = ConvL2X(src); // adjust Java long to machine word |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5814 Node* base = _gvn.transform(new (C) CastX2PNode(src)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5815 offset = ConvI2X(offset); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5816 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5817 // 'src_start' points to src array + scaled offset |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5818 Node* src_start = basic_plus_adr(top(), base, offset); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5819 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5820 // Call the stub. |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5821 address stubAddr = StubRoutines::updateBytesCRC32(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5822 const char *stubName = "updateBytesCRC32"; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5823 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5824 Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::updateBytesCRC32_Type(), |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5825 stubAddr, stubName, TypePtr::BOTTOM, |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5826 crc, src_start, length); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5827 Node* result = _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5828 set_result(result); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5829 return true; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5830 } |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5831 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5832 //----------------------------inline_reference_get---------------------------- |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5833 // public T java.lang.ref.Reference.get(); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5834 bool LibraryCallKit::inline_reference_get() { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5835 const int referent_offset = java_lang_ref_Reference::referent_offset; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5836 guarantee(referent_offset > 0, "should have already been set"); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5837 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5838 // Get the argument: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5839 Node* reference_obj = null_check_receiver(); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5840 if (stopped()) return true; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5841 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5842 Node* adr = basic_plus_adr(reference_obj, reference_obj, referent_offset); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5843 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5844 ciInstanceKlass* klass = env()->Object_klass(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5845 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
|
5846 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5847 Node* no_ctrl = NULL; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5848 Node* result = make_load(no_ctrl, adr, object_type, T_OBJECT); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5849 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5850 // 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
|
5851 pre_barrier(false /* do_load */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5852 control(), |
3258
edd9b016deb6
7036021: G1: build failure on win64 and linux with hs21 in jdk6 build environment
johnc
parents:
3255
diff
changeset
|
5853 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
|
5854 result /* pre_val */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5855 T_OBJECT); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5856 |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
5857 // Add memory barrier to prevent commoning reads from this field |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
5858 // across safepoint since GC can change its value. |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
5859 insert_mem_bar(Op_MemBarCPUOrder); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
5860 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5861 set_result(result); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5862 return true; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5863 } |
6894 | 5864 |
5865 | |
5866 Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, | |
5867 bool is_exact=true, bool is_static=false) { | |
5868 | |
5869 const TypeInstPtr* tinst = _gvn.type(fromObj)->isa_instptr(); | |
5870 assert(tinst != NULL, "obj is null"); | |
5871 assert(tinst->klass()->is_loaded(), "obj is not loaded"); | |
5872 assert(!is_exact || tinst->klass_is_exact(), "klass not exact"); | |
5873 | |
5874 ciField* field = tinst->klass()->as_instance_klass()->get_field_by_name(ciSymbol::make(fieldName), | |
5875 ciSymbol::make(fieldTypeString), | |
5876 is_static); | |
5877 if (field == NULL) return (Node *) NULL; | |
5878 assert (field != NULL, "undefined field"); | |
5879 | |
5880 // Next code copied from Parse::do_get_xxx(): | |
5881 | |
5882 // Compute address and memory type. | |
5883 int offset = field->offset_in_bytes(); | |
5884 bool is_vol = field->is_volatile(); | |
5885 ciType* field_klass = field->type(); | |
5886 assert(field_klass->is_loaded(), "should be loaded"); | |
5887 const TypePtr* adr_type = C->alias_type(field)->adr_type(); | |
5888 Node *adr = basic_plus_adr(fromObj, fromObj, offset); | |
5889 BasicType bt = field->layout_type(); | |
5890 | |
5891 // Build the resultant type of the load | |
5892 const Type *type = TypeOopPtr::make_from_klass(field_klass->as_klass()); | |
5893 | |
5894 // Build the load. | |
5895 Node* loadedField = make_load(NULL, adr, type, bt, adr_type, is_vol); | |
5896 return loadedField; | |
5897 } | |
5898 | |
5899 | |
5900 //------------------------------inline_aescrypt_Block----------------------- | |
5901 bool LibraryCallKit::inline_aescrypt_Block(vmIntrinsics::ID id) { | |
5902 address stubAddr; | |
5903 const char *stubName; | |
5904 assert(UseAES, "need AES instruction support"); | |
5905 | |
5906 switch(id) { | |
5907 case vmIntrinsics::_aescrypt_encryptBlock: | |
5908 stubAddr = StubRoutines::aescrypt_encryptBlock(); | |
5909 stubName = "aescrypt_encryptBlock"; | |
5910 break; | |
5911 case vmIntrinsics::_aescrypt_decryptBlock: | |
5912 stubAddr = StubRoutines::aescrypt_decryptBlock(); | |
5913 stubName = "aescrypt_decryptBlock"; | |
5914 break; | |
5915 } | |
5916 if (stubAddr == NULL) return false; | |
5917 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5918 Node* aescrypt_object = argument(0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5919 Node* src = argument(1); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5920 Node* src_offset = argument(2); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5921 Node* dest = argument(3); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5922 Node* dest_offset = argument(4); |
6894 | 5923 |
5924 // (1) src and dest are arrays. | |
5925 const Type* src_type = src->Value(&_gvn); | |
5926 const Type* dest_type = dest->Value(&_gvn); | |
5927 const TypeAryPtr* top_src = src_type->isa_aryptr(); | |
5928 const TypeAryPtr* top_dest = dest_type->isa_aryptr(); | |
5929 assert (top_src != NULL && top_src->klass() != NULL && top_dest != NULL && top_dest->klass() != NULL, "args are strange"); | |
5930 | |
5931 // for the quick and dirty code we will skip all the checks. | |
5932 // we are just trying to get the call to be generated. | |
5933 Node* src_start = src; | |
5934 Node* dest_start = dest; | |
5935 if (src_offset != NULL || dest_offset != NULL) { | |
5936 assert(src_offset != NULL && dest_offset != NULL, ""); | |
5937 src_start = array_element_address(src, src_offset, T_BYTE); | |
5938 dest_start = array_element_address(dest, dest_offset, T_BYTE); | |
5939 } | |
5940 | |
5941 // now need to get the start of its expanded key array | |
5942 // this requires a newer class file that has this array as littleEndian ints, otherwise we revert to java | |
5943 Node* k_start = get_key_start_from_aescrypt_object(aescrypt_object); | |
5944 if (k_start == NULL) return false; | |
5945 | |
17670 | 5946 if (Matcher::pass_original_key_for_aes()) { |
5947 // on SPARC we need to pass the original key since key expansion needs to happen in intrinsics due to | |
5948 // compatibility issues between Java key expansion and SPARC crypto instructions | |
5949 Node* original_k_start = get_original_key_start_from_aescrypt_object(aescrypt_object); | |
5950 if (original_k_start == NULL) return false; | |
5951 | |
5952 // Call the stub. | |
5953 make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::aescrypt_block_Type(), | |
5954 stubAddr, stubName, TypePtr::BOTTOM, | |
5955 src_start, dest_start, k_start, original_k_start); | |
5956 } else { | |
5957 // Call the stub. | |
5958 make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::aescrypt_block_Type(), | |
5959 stubAddr, stubName, TypePtr::BOTTOM, | |
5960 src_start, dest_start, k_start); | |
5961 } | |
6894 | 5962 |
5963 return true; | |
5964 } | |
5965 | |
5966 //------------------------------inline_cipherBlockChaining_AESCrypt----------------------- | |
5967 bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) { | |
5968 address stubAddr; | |
5969 const char *stubName; | |
5970 | |
5971 assert(UseAES, "need AES instruction support"); | |
5972 | |
5973 switch(id) { | |
5974 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: | |
5975 stubAddr = StubRoutines::cipherBlockChaining_encryptAESCrypt(); | |
5976 stubName = "cipherBlockChaining_encryptAESCrypt"; | |
5977 break; | |
5978 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: | |
5979 stubAddr = StubRoutines::cipherBlockChaining_decryptAESCrypt(); | |
5980 stubName = "cipherBlockChaining_decryptAESCrypt"; | |
5981 break; | |
5982 } | |
5983 if (stubAddr == NULL) return false; | |
5984 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5985 Node* cipherBlockChaining_object = argument(0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5986 Node* src = argument(1); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5987 Node* src_offset = argument(2); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5988 Node* len = argument(3); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5989 Node* dest = argument(4); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5990 Node* dest_offset = argument(5); |
6894 | 5991 |
5992 // (1) src and dest are arrays. | |
5993 const Type* src_type = src->Value(&_gvn); | |
5994 const Type* dest_type = dest->Value(&_gvn); | |
5995 const TypeAryPtr* top_src = src_type->isa_aryptr(); | |
5996 const TypeAryPtr* top_dest = dest_type->isa_aryptr(); | |
5997 assert (top_src != NULL && top_src->klass() != NULL | |
5998 && top_dest != NULL && top_dest->klass() != NULL, "args are strange"); | |
5999 | |
6000 // checks are the responsibility of the caller | |
6001 Node* src_start = src; | |
6002 Node* dest_start = dest; | |
6003 if (src_offset != NULL || dest_offset != NULL) { | |
6004 assert(src_offset != NULL && dest_offset != NULL, ""); | |
6005 src_start = array_element_address(src, src_offset, T_BYTE); | |
6006 dest_start = array_element_address(dest, dest_offset, T_BYTE); | |
6007 } | |
6008 | |
6009 // if we are in this set of code, we "know" the embeddedCipher is an AESCrypt object | |
6010 // (because of the predicated logic executed earlier). | |
6011 // so we cast it here safely. | |
6012 // this requires a newer class file that has this array as littleEndian ints, otherwise we revert to java | |
6013 | |
6014 Node* embeddedCipherObj = load_field_from_object(cipherBlockChaining_object, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false); | |
6015 if (embeddedCipherObj == NULL) return false; | |
6016 | |
6017 // cast it to what we know it will be at runtime | |
6018 const TypeInstPtr* tinst = _gvn.type(cipherBlockChaining_object)->isa_instptr(); | |
6019 assert(tinst != NULL, "CBC obj is null"); | |
6020 assert(tinst->klass()->is_loaded(), "CBC obj is not loaded"); | |
6021 ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); | |
6022 if (!klass_AESCrypt->is_loaded()) return false; | |
6023 | |
6024 ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); | |
6025 const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt); | |
6026 const TypeOopPtr* xtype = aklass->as_instance_type(); | |
6027 Node* aescrypt_object = new(C) CheckCastPPNode(control(), embeddedCipherObj, xtype); | |
6028 aescrypt_object = _gvn.transform(aescrypt_object); | |
6029 | |
6030 // we need to get the start of the aescrypt_object's expanded key array | |
6031 Node* k_start = get_key_start_from_aescrypt_object(aescrypt_object); | |
6032 if (k_start == NULL) return false; | |
6033 | |
6034 // similarly, get the start address of the r vector | |
6035 Node* objRvec = load_field_from_object(cipherBlockChaining_object, "r", "[B", /*is_exact*/ false); | |
6036 if (objRvec == NULL) return false; | |
6037 Node* r_start = array_element_address(objRvec, intcon(0), T_BYTE); | |
6038 | |
17670 | 6039 Node* cbcCrypt; |
6040 if (Matcher::pass_original_key_for_aes()) { | |
6041 // on SPARC we need to pass the original key since key expansion needs to happen in intrinsics due to | |
6042 // compatibility issues between Java key expansion and SPARC crypto instructions | |
6043 Node* original_k_start = get_original_key_start_from_aescrypt_object(aescrypt_object); | |
6044 if (original_k_start == NULL) return false; | |
6045 | |
6046 // Call the stub, passing src_start, dest_start, k_start, r_start, src_len and original_k_start | |
6047 cbcCrypt = make_runtime_call(RC_LEAF|RC_NO_FP, | |
6048 OptoRuntime::cipherBlockChaining_aescrypt_Type(), | |
6049 stubAddr, stubName, TypePtr::BOTTOM, | |
6050 src_start, dest_start, k_start, r_start, len, original_k_start); | |
6051 } else { | |
6052 // Call the stub, passing src_start, dest_start, k_start, r_start and src_len | |
6053 cbcCrypt = make_runtime_call(RC_LEAF|RC_NO_FP, | |
6054 OptoRuntime::cipherBlockChaining_aescrypt_Type(), | |
6055 stubAddr, stubName, TypePtr::BOTTOM, | |
6056 src_start, dest_start, k_start, r_start, len); | |
6057 } | |
6058 | |
6059 // return cipher length (int) | |
6060 Node* retvalue = _gvn.transform(new (C) ProjNode(cbcCrypt, TypeFunc::Parms)); | |
6061 set_result(retvalue); | |
6894 | 6062 return true; |
6063 } | |
6064 | |
6065 //------------------------------get_key_start_from_aescrypt_object----------------------- | |
6066 Node * LibraryCallKit::get_key_start_from_aescrypt_object(Node *aescrypt_object) { | |
6067 Node* objAESCryptKey = load_field_from_object(aescrypt_object, "K", "[I", /*is_exact*/ false); | |
6068 assert (objAESCryptKey != NULL, "wrong version of com.sun.crypto.provider.AESCrypt"); | |
6069 if (objAESCryptKey == NULL) return (Node *) NULL; | |
6070 | |
6071 // now have the array, need to get the start address of the K array | |
6072 Node* k_start = array_element_address(objAESCryptKey, intcon(0), T_INT); | |
6073 return k_start; | |
6074 } | |
6075 | |
17670 | 6076 //------------------------------get_original_key_start_from_aescrypt_object----------------------- |
6077 Node * LibraryCallKit::get_original_key_start_from_aescrypt_object(Node *aescrypt_object) { | |
6078 Node* objAESCryptKey = load_field_from_object(aescrypt_object, "lastKey", "[B", /*is_exact*/ false); | |
6079 assert (objAESCryptKey != NULL, "wrong version of com.sun.crypto.provider.AESCrypt"); | |
6080 if (objAESCryptKey == NULL) return (Node *) NULL; | |
6081 | |
6082 // now have the array, need to get the start address of the lastKey array | |
6083 Node* original_k_start = array_element_address(objAESCryptKey, intcon(0), T_BYTE); | |
6084 return original_k_start; | |
6085 } | |
6086 | |
6894 | 6087 //----------------------------inline_cipherBlockChaining_AESCrypt_predicate---------------------------- |
6088 // Return node representing slow path of predicate check. | |
6089 // the pseudo code we want to emulate with this predicate is: | |
6090 // for encryption: | |
6091 // if (embeddedCipherObj instanceof AESCrypt) do_intrinsic, else do_javapath | |
6092 // for decryption: | |
6093 // if ((embeddedCipherObj instanceof AESCrypt) && (cipher!=plain)) do_intrinsic, else do_javapath | |
6094 // note cipher==plain is more conservative than the original java code but that's OK | |
6095 // | |
6096 Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting) { | |
6097 // First, check receiver for NULL since it is virtual method. | |
6098 Node* objCBC = argument(0); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
6099 objCBC = null_check(objCBC); |
6894 | 6100 |
6101 if (stopped()) return NULL; // Always NULL | |
6102 | |
6103 // Load embeddedCipher field of CipherBlockChaining object. | |
6104 Node* embeddedCipherObj = load_field_from_object(objCBC, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false); | |
6105 | |
6106 // get AESCrypt klass for instanceOf check | |
6107 // AESCrypt might not be loaded yet if some other SymmetricCipher got us to this compile point | |
6108 // will have same classloader as CipherBlockChaining object | |
6109 const TypeInstPtr* tinst = _gvn.type(objCBC)->isa_instptr(); | |
6110 assert(tinst != NULL, "CBCobj is null"); | |
6111 assert(tinst->klass()->is_loaded(), "CBCobj is not loaded"); | |
6112 | |
6113 // we want to do an instanceof comparison against the AESCrypt class | |
6114 ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); | |
6115 if (!klass_AESCrypt->is_loaded()) { | |
6116 // if AESCrypt is not even loaded, we never take the intrinsic fast path | |
6117 Node* ctrl = control(); | |
6118 set_control(top()); // no regular fast path | |
6119 return ctrl; | |
6120 } | |
6121 ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); | |
6122 | |
6123 Node* instof = gen_instanceof(embeddedCipherObj, makecon(TypeKlassPtr::make(instklass_AESCrypt))); | |
6124 Node* cmp_instof = _gvn.transform(new (C) CmpINode(instof, intcon(1))); | |
6125 Node* bool_instof = _gvn.transform(new (C) BoolNode(cmp_instof, BoolTest::ne)); | |
6126 | |
6127 Node* instof_false = generate_guard(bool_instof, NULL, PROB_MIN); | |
6128 | |
6129 // for encryption, we are done | |
6130 if (!decrypting) | |
6131 return instof_false; // even if it is NULL | |
6132 | |
6133 // for decryption, we need to add a further check to avoid | |
6134 // taking the intrinsic path when cipher and plain are the same | |
6135 // see the original java code for why. | |
6136 RegionNode* region = new(C) RegionNode(3); | |
6137 region->init_req(1, instof_false); | |
6138 Node* src = argument(1); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
6139 Node* dest = argument(4); |
6894 | 6140 Node* cmp_src_dest = _gvn.transform(new (C) CmpPNode(src, dest)); |
6141 Node* bool_src_dest = _gvn.transform(new (C) BoolNode(cmp_src_dest, BoolTest::eq)); | |
6142 Node* src_dest_conjoint = generate_guard(bool_src_dest, NULL, PROB_MIN); | |
6143 region->init_req(2, src_dest_conjoint); | |
6144 | |
6145 record_for_igvn(region); | |
6146 return _gvn.transform(region); | |
6147 } |