Mercurial > hg > graal-compiler
annotate src/share/vm/opto/library_call.cpp @ 14649:f6301b007a16
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 | 0f19095fd8c1 |
children | ef7328717719 |
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); | |
14261 | 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())); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
1061 Node* threadObj = make_load(NULL, p, thread_type, T_OBJECT, MemNode::unordered); |
0 | 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 | |
14463
0f19095fd8c1
8035394: PPC64: Make usage of intrinsic dsqrt depend on processor recognition.
goetz
parents:
14456
diff
changeset
|
1940 case vmIntrinsics::_dsqrt: return Matcher::match_rule_supported(Op_SqrtD) ? inline_math(id) : false; |
7194
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. | |
14452
c6d7e7406136
8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes
goetz
parents:
14439
diff
changeset
|
2631 if (is_store) { |
0 | 2632 insert_mem_bar(Op_MemBarRelease); |
14452
c6d7e7406136
8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes
goetz
parents:
14439
diff
changeset
|
2633 } else { |
c6d7e7406136
8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes
goetz
parents:
14439
diff
changeset
|
2634 if (support_IRIW_for_not_multiple_copy_atomic_cpu) { |
c6d7e7406136
8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes
goetz
parents:
14439
diff
changeset
|
2635 insert_mem_bar(Op_MemBarVolatile); |
c6d7e7406136
8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes
goetz
parents:
14439
diff
changeset
|
2636 } |
c6d7e7406136
8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes
goetz
parents:
14439
diff
changeset
|
2637 } |
0 | 2638 } |
2639 | |
2640 // Memory barrier to prevent normal and 'unsafe' accesses from | |
2641 // bypassing each other. Happens after null checks, so the | |
2642 // exception paths do not take memory state from the memory barrier, | |
2643 // so there's no problems making a strong assert about mixing users | |
2644 // of safe & unsafe memory. Otherwise fails in a CTW of rt.jar | |
2645 // around 5701, class sun/reflect/UnsafeBooleanFieldAccessorImpl. | |
2646 if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder); | |
2647 | |
2648 if (!is_store) { | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
2649 Node* p = make_load(control(), adr, value_type, type, adr_type, MemNode::unordered, is_volatile); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2650 // load value |
0 | 2651 switch (type) { |
2652 case T_BOOLEAN: | |
2653 case T_CHAR: | |
2654 case T_BYTE: | |
2655 case T_SHORT: | |
2656 case T_INT: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2657 case T_LONG: |
0 | 2658 case T_FLOAT: |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2659 case T_DOUBLE: |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2660 break; |
0 | 2661 case T_OBJECT: |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
2662 if (need_read_barrier) { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2663 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
|
2664 } |
0 | 2665 break; |
2666 case T_ADDRESS: | |
2667 // Cast to an int type. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2668 p = _gvn.transform(new (C) CastP2XNode(NULL, p)); |
0 | 2669 p = ConvX2L(p); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2670 break; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2671 default: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2672 fatal(err_msg_res("unexpected type %d: %s", type, type2name(type))); |
0 | 2673 break; |
2674 } | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2675 // 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
|
2676 // 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
|
2677 // 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
|
2678 // point is fine. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2679 set_result(p); |
0 | 2680 } else { |
2681 // place effect of store into memory | |
2682 switch (type) { | |
2683 case T_DOUBLE: | |
2684 val = dstore_rounding(val); | |
2685 break; | |
2686 case T_ADDRESS: | |
2687 // Repackage the long as a pointer. | |
2688 val = ConvL2X(val); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
2689 val = _gvn.transform(new (C) CastX2PNode(val)); |
0 | 2690 break; |
2691 } | |
2692 | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
2693 MemNode::MemOrd mo = is_volatile ? MemNode::release : MemNode::unordered; |
0 | 2694 if (type != T_OBJECT ) { |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
2695 (void) store_to_memory(control(), adr, val, type, adr_type, mo, is_volatile); |
0 | 2696 } else { |
2697 // Possibly an oop being stored to Java heap or native memory | |
2698 if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) { | |
2699 // oop to Java heap. | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
2700 (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo); |
0 | 2701 } else { |
2702 // We can't tell at compile time if we are storing in the Java heap or outside | |
2703 // of it. So we need to emit code to conditionally do the proper type of | |
2704 // store. | |
2705 | |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
2706 IdealKit ideal(this); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2707 #define __ ideal. |
0 | 2708 // QQQ who knows what probability is here?? |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2709 __ 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
|
2710 // Sync IdealKit and graphKit. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
2711 sync_kit(ideal); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
2712 Node* st = store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2713 // Update IdealKit memory. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
2714 __ sync_kit(this); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2715 } __ else_(); { |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
2716 __ store(__ ctrl(), adr, val, type, alias_type->index(), mo, is_volatile); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2717 } __ end_if(); |
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2718 // Final sync IdealKit and GraphKit. |
2444
07acc51c1d2a
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
2405
diff
changeset
|
2719 final_sync(ideal); |
851
fc4be448891f
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
836
diff
changeset
|
2720 #undef __ |
0 | 2721 } |
2722 } | |
2723 } | |
2724 | |
2725 if (is_volatile) { | |
14452
c6d7e7406136
8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes
goetz
parents:
14439
diff
changeset
|
2726 if (!is_store) { |
0 | 2727 insert_mem_bar(Op_MemBarAcquire); |
14452
c6d7e7406136
8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes
goetz
parents:
14439
diff
changeset
|
2728 } else { |
c6d7e7406136
8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes
goetz
parents:
14439
diff
changeset
|
2729 if (!support_IRIW_for_not_multiple_copy_atomic_cpu) { |
c6d7e7406136
8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes
goetz
parents:
14439
diff
changeset
|
2730 insert_mem_bar(Op_MemBarVolatile); |
c6d7e7406136
8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes
goetz
parents:
14439
diff
changeset
|
2731 } |
c6d7e7406136
8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes
goetz
parents:
14439
diff
changeset
|
2732 } |
0 | 2733 } |
2734 | |
2735 if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder); | |
2736 | |
2737 return true; | |
2738 } | |
2739 | |
2740 //----------------------------inline_unsafe_prefetch---------------------------- | |
2741 | |
2742 bool LibraryCallKit::inline_unsafe_prefetch(bool is_native_ptr, bool is_store, bool is_static) { | |
2743 #ifndef PRODUCT | |
2744 { | |
2745 ResourceMark rm; | |
2746 // Check the signatures. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2747 ciSignature* sig = callee()->signature(); |
0 | 2748 #ifdef ASSERT |
2749 // Object getObject(Object base, int/long offset), etc. | |
2750 BasicType rtype = sig->return_type()->basic_type(); | |
2751 if (!is_native_ptr) { | |
2752 assert(sig->count() == 2, "oop prefetch has 2 arguments"); | |
2753 assert(sig->type_at(0)->basic_type() == T_OBJECT, "prefetch base is object"); | |
2754 assert(sig->type_at(1)->basic_type() == T_LONG, "prefetcha offset is correct"); | |
2755 } else { | |
2756 assert(sig->count() == 1, "native prefetch has 1 argument"); | |
2757 assert(sig->type_at(0)->basic_type() == T_LONG, "prefetch base is long"); | |
2758 } | |
2759 #endif // ASSERT | |
2760 } | |
2761 #endif // !PRODUCT | |
2762 | |
2763 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
2764 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2765 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
|
2766 if (!is_static) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2767 null_check_receiver(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2768 if (stopped()) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2769 return true; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2770 } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2771 } |
0 | 2772 |
2773 // Build address expression. See the code in inline_unsafe_access. | |
2774 Node *adr; | |
2775 if (!is_native_ptr) { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2776 // 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
|
2777 Node* base = argument(idx + 0); // type: oop |
0 | 2778 // 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
|
2779 Node* offset = argument(idx + 1); // type: long |
0 | 2780 // We currently rely on the cookies produced by Unsafe.xxxFieldOffset |
2781 // to be plain byte offsets, which are also the same as those accepted | |
2782 // by oopDesc::field_base. | |
2783 assert(Unsafe_field_offset_to_byte_offset(11) == 11, | |
2784 "fieldOffset must be byte-scaled"); | |
2785 // 32-bit machines ignore the high half! | |
2786 offset = ConvL2X(offset); | |
2787 adr = make_unsafe_address(base, offset); | |
2788 } else { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2789 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
|
2790 ptr = ConvL2X(ptr); // adjust Java long to machine word |
0 | 2791 adr = make_unsafe_address(NULL, ptr); |
2792 } | |
2793 | |
2794 // Generate the read or write prefetch | |
2795 Node *prefetch; | |
2796 if (is_store) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2797 prefetch = new (C) PrefetchWriteNode(i_o(), adr); |
0 | 2798 } else { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2799 prefetch = new (C) PrefetchReadNode(i_o(), adr); |
0 | 2800 } |
2801 prefetch->init_req(0, control()); | |
2802 set_i_o(_gvn.transform(prefetch)); | |
2803 | |
2804 return true; | |
2805 } | |
2806 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2807 //----------------------------inline_unsafe_load_store---------------------------- |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2808 // 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
|
2809 // |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2810 // LS_cmpxchg: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2811 // 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
|
2812 // 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
|
2813 // 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
|
2814 // |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2815 // LS_xadd: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2816 // 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
|
2817 // 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
|
2818 // |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2819 // LS_xchg: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2820 // 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
|
2821 // 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
|
2822 // 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
|
2823 // |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2824 bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind) { |
0 | 2825 // This basic scheme here is the same as inline_unsafe_access, but |
2826 // differs in enough details that combining them would make the code | |
2827 // overly confusing. (This is a true fact! I originally combined | |
2828 // them, but even I was confused by it!) As much code/comments as | |
2829 // possible are retained from inline_unsafe_access though to make | |
605 | 2830 // the correspondences clearer. - dl |
0 | 2831 |
2832 if (callee()->is_static()) return false; // caller must have the capability! | |
2833 | |
2834 #ifndef PRODUCT | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2835 BasicType rtype; |
0 | 2836 { |
2837 ResourceMark rm; | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2838 // Check the signatures. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2839 ciSignature* sig = callee()->signature(); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2840 rtype = sig->return_type()->basic_type(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2841 if (kind == LS_xadd || kind == LS_xchg) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2842 // Check the signatures. |
0 | 2843 #ifdef ASSERT |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2844 assert(rtype == type, "get and set must return the expected type"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2845 assert(sig->count() == 3, "get and set has 3 arguments"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2846 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
|
2847 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
|
2848 assert(sig->type_at(2)->basic_type() == type, "get and set must take expected type as new value/delta"); |
0 | 2849 #endif // ASSERT |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2850 } else if (kind == LS_cmpxchg) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2851 // Check the signatures. |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2852 #ifdef ASSERT |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2853 assert(rtype == T_BOOLEAN, "CAS must return boolean"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2854 assert(sig->count() == 4, "CAS has 4 arguments"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2855 assert(sig->type_at(0)->basic_type() == T_OBJECT, "CAS base is object"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2856 assert(sig->type_at(1)->basic_type() == T_LONG, "CAS offset is long"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2857 #endif // ASSERT |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2858 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2859 ShouldNotReachHere(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2860 } |
0 | 2861 } |
2862 #endif //PRODUCT | |
2863 | |
2864 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
2865 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2866 // Get arguments: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2867 Node* receiver = NULL; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2868 Node* base = NULL; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2869 Node* offset = NULL; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2870 Node* oldval = NULL; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2871 Node* newval = NULL; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2872 if (kind == LS_cmpxchg) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2873 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
|
2874 receiver = argument(0); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2875 base = argument(1); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2876 offset = argument(2); // type: long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2877 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
|
2878 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
|
2879 } 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
|
2880 receiver = argument(0); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2881 base = argument(1); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2882 offset = argument(2); // type: long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2883 oldval = NULL; |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2884 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
|
2885 } |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2886 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2887 // Null check receiver. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
2888 receiver = null_check(receiver); |
0 | 2889 if (stopped()) { |
2890 return true; | |
2891 } | |
2892 | |
2893 // Build field offset expression. | |
2894 // We currently rely on the cookies produced by Unsafe.xxxFieldOffset | |
2895 // to be plain byte offsets, which are also the same as those accepted | |
2896 // by oopDesc::field_base. | |
2897 assert(Unsafe_field_offset_to_byte_offset(11) == 11, "fieldOffset must be byte-scaled"); | |
2898 // 32-bit machines ignore the high half of long offsets | |
2899 offset = ConvL2X(offset); | |
2900 Node* adr = make_unsafe_address(base, offset); | |
2901 const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); | |
2902 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2903 // For CAS, unlike inline_unsafe_access, there seems no point in |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2904 // trying to refine types. Just use the coarse types here. |
0 | 2905 const Type *value_type = Type::get_const_basic_type(type); |
2906 Compile::AliasType* alias_type = C->alias_type(adr_type); | |
2907 assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here"); | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2908 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2909 if (kind == LS_xchg && type == T_OBJECT) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2910 const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2911 if (tjp != NULL) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2912 value_type = tjp; |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2913 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2914 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2915 |
0 | 2916 int alias_idx = C->get_alias_index(adr_type); |
2917 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2918 // Memory-model-wise, a LoadStore acts like a little synchronized |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2919 // block, so needs barriers on each side. These don't translate |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2920 // into actual barriers on most machines, but we still need rest of |
0 | 2921 // compiler to respect ordering. |
2922 | |
2923 insert_mem_bar(Op_MemBarRelease); | |
2924 insert_mem_bar(Op_MemBarCPUOrder); | |
2925 | |
2926 // 4984716: MemBars must be inserted before this | |
2927 // memory node in order to avoid a false | |
2928 // dependency which will confuse the scheduler. | |
2929 Node *mem = memory(alias_idx); | |
2930 | |
2931 // For now, we handle only those cases that actually exist: ints, | |
2932 // longs, and Object. Adding others should be straightforward. | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2933 Node* load_store; |
0 | 2934 switch(type) { |
2935 case T_INT: | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2936 if (kind == LS_xadd) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2937 load_store = _gvn.transform(new (C) GetAndAddINode(control(), mem, adr, newval, adr_type)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2938 } else if (kind == LS_xchg) { |
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) GetAndSetINode(control(), mem, adr, newval, adr_type)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2940 } else if (kind == LS_cmpxchg) { |
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) CompareAndSwapINode(control(), mem, adr, newval, oldval)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2942 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2943 ShouldNotReachHere(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2944 } |
0 | 2945 break; |
2946 case T_LONG: | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2947 if (kind == LS_xadd) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2948 load_store = _gvn.transform(new (C) GetAndAddLNode(control(), mem, adr, newval, adr_type)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2949 } else if (kind == LS_xchg) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2950 load_store = _gvn.transform(new (C) GetAndSetLNode(control(), mem, adr, newval, adr_type)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2951 } else if (kind == LS_cmpxchg) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2952 load_store = _gvn.transform(new (C) CompareAndSwapLNode(control(), mem, adr, newval, oldval)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2953 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2954 ShouldNotReachHere(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2955 } |
0 | 2956 break; |
2957 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
|
2958 // 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
|
2959 // 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
|
2960 // 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
|
2961 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
|
2962 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
|
2963 |
b9bc6cae88f2
7143491: G1 C2 CTW: assert(p2x->outcnt() == 2) failed: expects 2 users: Xor and URShift nodes
kvn
parents:
4778
diff
changeset
|
2964 // Reference stores need a store barrier. |
12169
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2965 if (kind == LS_xchg) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2966 // 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
|
2967 if (!can_move_pre_barrier()) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2968 pre_barrier(true /* do_load*/, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2969 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
|
2970 NULL /* pre_val*/, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2971 T_OBJECT); |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2972 } // 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
|
2973 } else if (kind == LS_cmpxchg) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2974 // Same as for newval above: |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2975 if (_gvn.type(oldval) == TypePtr::NULL_PTR) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2976 oldval = _gvn.makecon(TypePtr::NULL_PTR); |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2977 } |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2978 // 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
|
2979 pre_barrier(false /* do_load */, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2980 control(), NULL, NULL, max_juint, NULL, NULL, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2981 oldval /* pre_val */, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2982 T_OBJECT); |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2983 } else { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2984 ShouldNotReachHere(); |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2985 } |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
2986 |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
2987 #ifdef _LP64 |
163 | 2988 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
|
2989 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
|
2990 if (kind == LS_xchg) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
2991 load_store = _gvn.transform(new (C) GetAndSetNNode(control(), mem, adr, |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
2992 newval_enc, adr_type, value_type->make_narrowoop())); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2993 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2994 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
|
2995 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
|
2996 load_store = _gvn.transform(new (C) CompareAndSwapNNode(control(), mem, adr, |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
2997 newval_enc, oldval_enc)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
2998 } |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
2999 } else |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
3000 #endif |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
174
diff
changeset
|
3001 { |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3002 if (kind == LS_xchg) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3003 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
|
3004 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3005 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
|
3006 load_store = _gvn.transform(new (C) CompareAndSwapPNode(control(), mem, adr, newval, oldval)); |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3007 } |
221
1e026f8da827
6710487: More than half of JDI Regression tests hang with COOPs in -Xcomp mode
kvn
parents:
174
diff
changeset
|
3008 } |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3009 post_barrier(control(), load_store, base, adr, alias_idx, newval, T_OBJECT, true); |
0 | 3010 break; |
3011 default: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3012 fatal(err_msg_res("unexpected type %d: %s", type, type2name(type))); |
0 | 3013 break; |
3014 } | |
3015 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3016 // SCMemProjNodes represent the memory state of a LoadStore. Their |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3017 // main role is to prevent LoadStore nodes from being optimized away |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3018 // when their results aren't used. |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3019 Node* proj = _gvn.transform(new (C) SCMemProjNode(load_store)); |
0 | 3020 set_memory(proj, alias_idx); |
3021 | |
12169
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3022 if (type == T_OBJECT && kind == LS_xchg) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3023 #ifdef _LP64 |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3024 if (adr->bottom_type()->is_ptr_to_narrowoop()) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3025 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
|
3026 } |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3027 #endif |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3028 if (can_move_pre_barrier()) { |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3029 // 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
|
3030 // 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
|
3031 // gets inserted between them. |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3032 pre_barrier(false /* do_load */, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3033 control(), NULL, NULL, max_juint, NULL, NULL, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3034 load_store /* pre_val */, |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3035 T_OBJECT); |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3036 } |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3037 } |
29aa8936f03c
8023597: Optimize G1 barriers code for unsafe load_store
kvn
parents:
12078
diff
changeset
|
3038 |
0 | 3039 // Add the trailing membar surrounding the access |
3040 insert_mem_bar(Op_MemBarCPUOrder); | |
3041 insert_mem_bar(Op_MemBarAcquire); | |
3042 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6725
diff
changeset
|
3043 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
|
3044 set_result(load_store); |
0 | 3045 return true; |
3046 } | |
3047 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3048 //----------------------------inline_unsafe_ordered_store---------------------- |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3049 // 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
|
3050 // 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
|
3051 // public native void sun.misc.Unsafe.putOrderedLong(Object o, long offset, long x); |
0 | 3052 bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) { |
3053 // This is another variant of inline_unsafe_access, differing in | |
3054 // that it always issues store-store ("release") barrier and ensures | |
3055 // store-atomicity (which only matters for "long"). | |
3056 | |
3057 if (callee()->is_static()) return false; // caller must have the capability! | |
3058 | |
3059 #ifndef PRODUCT | |
3060 { | |
3061 ResourceMark rm; | |
3062 // Check the signatures. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3063 ciSignature* sig = callee()->signature(); |
0 | 3064 #ifdef ASSERT |
3065 BasicType rtype = sig->return_type()->basic_type(); | |
3066 assert(rtype == T_VOID, "must return void"); | |
3067 assert(sig->count() == 3, "has 3 arguments"); | |
3068 assert(sig->type_at(0)->basic_type() == T_OBJECT, "base is object"); | |
3069 assert(sig->type_at(1)->basic_type() == T_LONG, "offset is long"); | |
3070 #endif // ASSERT | |
3071 } | |
3072 #endif //PRODUCT | |
3073 | |
3074 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
3075 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3076 // Get arguments: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3077 Node* receiver = argument(0); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3078 Node* base = argument(1); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3079 Node* offset = argument(2); // type: long |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3080 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
|
3081 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3082 // Null check receiver. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3083 receiver = null_check(receiver); |
0 | 3084 if (stopped()) { |
3085 return true; | |
3086 } | |
3087 | |
3088 // Build field offset expression. | |
3089 assert(Unsafe_field_offset_to_byte_offset(11) == 11, "fieldOffset must be byte-scaled"); | |
3090 // 32-bit machines ignore the high half of long offsets | |
3091 offset = ConvL2X(offset); | |
3092 Node* adr = make_unsafe_address(base, offset); | |
3093 const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); | |
3094 const Type *value_type = Type::get_const_basic_type(type); | |
3095 Compile::AliasType* alias_type = C->alias_type(adr_type); | |
3096 | |
3097 insert_mem_bar(Op_MemBarRelease); | |
3098 insert_mem_bar(Op_MemBarCPUOrder); | |
3099 // 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
|
3100 const bool require_atomic_access = true; |
0 | 3101 Node* store; |
3102 if (type == T_OBJECT) // reference stores need a store barrier. | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3103 store = store_oop_to_unknown(control(), base, adr, adr_type, val, type, MemNode::release); |
0 | 3104 else { |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3105 store = store_to_memory(control(), adr, val, type, adr_type, MemNode::release, require_atomic_access); |
0 | 3106 } |
3107 insert_mem_bar(Op_MemBarCPUOrder); | |
3108 return true; | |
3109 } | |
3110 | |
7425 | 3111 bool LibraryCallKit::inline_unsafe_fence(vmIntrinsics::ID id) { |
3112 // Regardless of form, don't allow previous ld/st to move down, | |
3113 // then issue acquire, release, or volatile mem_bar. | |
3114 insert_mem_bar(Op_MemBarCPUOrder); | |
3115 switch(id) { | |
3116 case vmIntrinsics::_loadFence: | |
14439
50fdb38839eb
8028515: PPPC64 (part 113.2): opto: Introduce LoadFence/StoreFence.
goetz
parents:
14429
diff
changeset
|
3117 insert_mem_bar(Op_LoadFence); |
7425 | 3118 return true; |
3119 case vmIntrinsics::_storeFence: | |
14439
50fdb38839eb
8028515: PPPC64 (part 113.2): opto: Introduce LoadFence/StoreFence.
goetz
parents:
14429
diff
changeset
|
3120 insert_mem_bar(Op_StoreFence); |
7425 | 3121 return true; |
3122 case vmIntrinsics::_fullFence: | |
3123 insert_mem_bar(Op_MemBarVolatile); | |
3124 return true; | |
3125 default: | |
3126 fatal_unexpected_iid(id); | |
3127 return false; | |
3128 } | |
3129 } | |
3130 | |
12078 | 3131 bool LibraryCallKit::klass_needs_init_guard(Node* kls) { |
3132 if (!kls->is_Con()) { | |
3133 return true; | |
3134 } | |
3135 const TypeKlassPtr* klsptr = kls->bottom_type()->isa_klassptr(); | |
3136 if (klsptr == NULL) { | |
3137 return true; | |
3138 } | |
3139 ciInstanceKlass* ik = klsptr->klass()->as_instance_klass(); | |
3140 // don't need a guard for a klass that is already initialized | |
3141 return !ik->is_initialized(); | |
3142 } | |
3143 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3144 //----------------------------inline_unsafe_allocate--------------------------- |
12078 | 3145 // public native Object sun.misc.Unsafe.allocateInstance(Class<?> cls); |
0 | 3146 bool LibraryCallKit::inline_unsafe_allocate() { |
3147 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
|
3148 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3149 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
|
3150 Node* cls = null_check(argument(1)); |
0 | 3151 if (stopped()) return true; |
3152 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3153 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
|
3154 kls = null_check(kls); |
0 | 3155 if (stopped()) return true; // argument was like int.class |
3156 | |
12078 | 3157 Node* test = NULL; |
3158 if (LibraryCallKit::klass_needs_init_guard(kls)) { | |
3159 // Note: The argument might still be an illegal value like | |
3160 // Serializable.class or Object[].class. The runtime will handle it. | |
3161 // But we must make an explicit check for initialization. | |
3162 Node* insp = basic_plus_adr(kls, in_bytes(InstanceKlass::init_state_offset())); | |
3163 // Use T_BOOLEAN for InstanceKlass::_init_state so the compiler | |
3164 // can generate code to load it as unsigned byte. | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3165 Node* inst = make_load(NULL, insp, TypeInt::UBYTE, T_BOOLEAN, MemNode::unordered); |
12078 | 3166 Node* bits = intcon(InstanceKlass::fully_initialized); |
3167 test = _gvn.transform(new (C) SubINode(inst, bits)); | |
3168 // The 'test' is non-zero if we need to take a slow path. | |
3169 } | |
0 | 3170 |
3171 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
|
3172 set_result(obj); |
0 | 3173 return true; |
3174 } | |
3175 | |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3176 #ifdef TRACE_HAVE_INTRINSICS |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3177 /* |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3178 * oop -> myklass |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3179 * myklass->trace_id |= USED |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3180 * return myklass->trace_id & ~0x3 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3181 */ |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3182 bool LibraryCallKit::inline_native_classID() { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3183 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
|
3184 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
|
3185 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
|
3186 kls = null_check(kls, T_OBJECT); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3187 ByteSize offset = TRACE_ID_OFFSET; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3188 Node* insp = basic_plus_adr(kls, in_bytes(offset)); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3189 Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG, MemNode::unordered); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3190 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
|
3191 Node* andl = _gvn.transform(new (C) AndLNode(tvalue, bits)); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3192 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
|
3193 Node* orl = _gvn.transform(new (C) OrLNode(tvalue, clsused)); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3194 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3195 const TypePtr *adr_type = _gvn.type(insp)->isa_ptr(); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3196 store_to_memory(control(), insp, orl, T_LONG, adr_type, MemNode::unordered); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3197 set_result(andl); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3198 return true; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3199 } |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3200 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3201 bool LibraryCallKit::inline_native_threadID() { |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3202 Node* tls_ptr = NULL; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3203 Node* cur_thr = generate_current_thread(tls_ptr); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3204 Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3205 Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3206 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
|
3207 |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3208 Node* threadid = NULL; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3209 size_t thread_id_size = OSThread::thread_id_size(); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3210 if (thread_id_size == (size_t) BytesPerLong) { |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3211 threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG, MemNode::unordered)); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3212 } else if (thread_id_size == (size_t) BytesPerInt) { |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3213 threadid = make_load(control(), p, TypeInt::INT, T_INT, MemNode::unordered); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3214 } else { |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3215 ShouldNotReachHere(); |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3216 } |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3217 set_result(threadid); |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3218 return true; |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3219 } |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3220 #endif |
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3221 |
0 | 3222 //------------------------inline_native_time_funcs-------------- |
3223 // inline code for System.currentTimeMillis() and System.nanoTime() | |
3224 // these have the same type and signature | |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
5934
diff
changeset
|
3225 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
|
3226 const TypeFunc* tf = OptoRuntime::void_long_Type(); |
0 | 3227 const TypePtr* no_memory_effects = NULL; |
3228 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
|
3229 Node* value = _gvn.transform(new (C) ProjNode(time, TypeFunc::Parms+0)); |
0 | 3230 #ifdef ASSERT |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3231 Node* value_top = _gvn.transform(new (C) ProjNode(time, TypeFunc::Parms+1)); |
0 | 3232 assert(value_top == top(), "second value must be top"); |
3233 #endif | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3234 set_result(value); |
0 | 3235 return true; |
3236 } | |
3237 | |
3238 //------------------------inline_native_currentThread------------------ | |
3239 bool LibraryCallKit::inline_native_currentThread() { | |
3240 Node* junk = NULL; | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3241 set_result(generate_current_thread(junk)); |
0 | 3242 return true; |
3243 } | |
3244 | |
3245 //------------------------inline_native_isInterrupted------------------ | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3246 // private native boolean java.lang.Thread.isInterrupted(boolean ClearInterrupted); |
0 | 3247 bool LibraryCallKit::inline_native_isInterrupted() { |
3248 // Add a fast path to t.isInterrupted(clear_int): | |
14649
f6301b007a16
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
14463
diff
changeset
|
3249 // (t == Thread.current() && |
f6301b007a16
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
14463
diff
changeset
|
3250 // (!TLS._osthread._interrupted || WINDOWS_ONLY(false) NOT_WINDOWS(!clear_int))) |
0 | 3251 // ? TLS._osthread._interrupted : /*slow path:*/ t.isInterrupted(clear_int) |
3252 // So, in the common case that the interrupt bit is false, | |
3253 // we avoid making a call into the VM. Even if the interrupt bit | |
3254 // is true, if the clear_int argument is false, we avoid the VM call. | |
3255 // However, if the receiver is not currentThread, we must call the VM, | |
3256 // because there must be some locking done around the operation. | |
3257 | |
3258 // We only go to the fast case code if we pass two guards. | |
3259 // 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
|
3260 |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3261 enum { |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3262 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
|
3263 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
|
3264 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
|
3265 PATH_LIMIT |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3266 }; |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3267 |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3268 // 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
|
3269 // out of the function. |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3270 insert_mem_bar(Op_MemBarCPUOrder); |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3271 |
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3272 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
|
3273 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
|
3274 |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3275 RegionNode* slow_region = new (C) RegionNode(1); |
0 | 3276 record_for_igvn(slow_region); |
3277 | |
3278 // (a) Receiving thread must be the current thread. | |
3279 Node* rec_thr = argument(0); | |
3280 Node* tls_ptr = NULL; | |
3281 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
|
3282 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
|
3283 Node* bol_thr = _gvn.transform(new (C) BoolNode(cmp_thr, BoolTest::ne)); |
0 | 3284 |
7422
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3285 generate_slow_guard(bol_thr, slow_region); |
0 | 3286 |
3287 // (b) Interrupt bit on TLS must be false. | |
3288 Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3289 Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered); |
0 | 3290 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
|
3291 |
787
aabd393cf1ee
6772683: Thread.isInterrupted() fails to return true on multiprocessor PC
kvn
parents:
775
diff
changeset
|
3292 // Set the control input on the field _interrupted read to prevent it floating up. |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3293 Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT, MemNode::unordered); |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3294 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
|
3295 Node* bol_bit = _gvn.transform(new (C) BoolNode(cmp_bit, BoolTest::ne)); |
0 | 3296 |
3297 IfNode* iff_bit = create_and_map_if(control(), bol_bit, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN); | |
3298 | |
3299 // 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
|
3300 Node* false_bit = _gvn.transform(new (C) IfFalseNode(iff_bit)); |
0 | 3301 result_rgn->init_req(no_int_result_path, false_bit); |
3302 result_val->init_req(no_int_result_path, intcon(0)); | |
3303 | |
3304 // drop through to next case | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3305 set_control( _gvn.transform(new (C) IfTrueNode(iff_bit))); |
0 | 3306 |
14649
f6301b007a16
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
14463
diff
changeset
|
3307 #ifndef TARGET_OS_FAMILY_windows |
0 | 3308 // (c) Or, if interrupt bit is set and clear_int is false, use 2nd fast path. |
3309 Node* clr_arg = argument(1); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3310 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
|
3311 Node* bol_arg = _gvn.transform(new (C) BoolNode(cmp_arg, BoolTest::ne)); |
0 | 3312 IfNode* iff_arg = create_and_map_if(control(), bol_arg, PROB_FAIR, COUNT_UNKNOWN); |
3313 | |
3314 // 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
|
3315 Node* false_arg = _gvn.transform(new (C) IfFalseNode(iff_arg)); |
0 | 3316 result_rgn->init_req(no_clear_result_path, false_arg); |
3317 result_val->init_req(no_clear_result_path, intcon(1)); | |
3318 | |
3319 // drop through to next case | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3320 set_control( _gvn.transform(new (C) IfTrueNode(iff_arg))); |
14649
f6301b007a16
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
14463
diff
changeset
|
3321 #else |
f6301b007a16
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
14463
diff
changeset
|
3322 // To return true on Windows you must read the _interrupted field |
f6301b007a16
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
14463
diff
changeset
|
3323 // and check the the event state i.e. take the slow path. |
f6301b007a16
6498581: ThreadInterruptTest3 produces wrong output on Windows
minqi
parents:
14463
diff
changeset
|
3324 #endif // TARGET_OS_FAMILY_windows |
0 | 3325 |
3326 // (d) Otherwise, go to the slow path. | |
3327 slow_region->add_req(control()); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3328 set_control( _gvn.transform(slow_region)); |
0 | 3329 |
3330 if (stopped()) { | |
3331 // There is no slow path. | |
3332 result_rgn->init_req(slow_result_path, top()); | |
3333 result_val->init_req(slow_result_path, top()); | |
3334 } else { | |
3335 // non-virtual because it is a private non-static | |
3336 CallJavaNode* slow_call = generate_method_call(vmIntrinsics::_isInterrupted); | |
3337 | |
3338 Node* slow_val = set_results_for_java_call(slow_call); | |
3339 // this->control() comes from set_results_for_java_call | |
3340 | |
3341 Node* fast_io = slow_call->in(TypeFunc::I_O); | |
3342 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
|
3343 |
0 | 3344 // 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
|
3345 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
|
3346 PhiNode* result_io = PhiNode::make(result_rgn, fast_io, Type::ABIO); |
0 | 3347 |
3348 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
|
3349 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
|
3350 result_mem->init_req(slow_result_path, reset_memory()); |
0 | 3351 result_val->init_req(slow_result_path, slow_val); |
3352 | |
7422
eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
vlivanov
parents:
7200
diff
changeset
|
3353 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
|
3354 set_i_o( _gvn.transform(result_io)); |
0 | 3355 } |
3356 | |
3357 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
|
3358 set_result(result_rgn, result_val); |
0 | 3359 return true; |
3360 } | |
3361 | |
3362 //---------------------------load_mirror_from_klass---------------------------- | |
3363 // Given a klass oop, load its java mirror (a java.lang.Class oop). | |
3364 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
|
3365 Node* p = basic_plus_adr(klass, in_bytes(Klass::java_mirror_offset())); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3366 return make_load(NULL, p, TypeInstPtr::MIRROR, T_OBJECT, MemNode::unordered); |
0 | 3367 } |
3368 | |
3369 //-----------------------load_klass_from_mirror_common------------------------- | |
3370 // Given a java mirror (a java.lang.Class oop), load its corresponding klass oop. | |
3371 // Test the klass oop for null (signifying a primitive Class like Integer.TYPE), | |
3372 // and branch to the given path on the region. | |
3373 // If never_see_null, take an uncommon trap on null, so we can optimistically | |
3374 // compile for the non-null case. | |
3375 // If the region is NULL, force never_see_null = true. | |
3376 Node* LibraryCallKit::load_klass_from_mirror_common(Node* mirror, | |
3377 bool never_see_null, | |
3378 RegionNode* region, | |
3379 int null_path, | |
3380 int offset) { | |
3381 if (region == NULL) never_see_null = true; | |
3382 Node* p = basic_plus_adr(mirror, offset); | |
3383 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
|
3384 Node* kls = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeRawPtr::BOTTOM, kls_type)); |
0 | 3385 Node* null_ctl = top(); |
3386 kls = null_check_oop(kls, &null_ctl, never_see_null); | |
3387 if (region != NULL) { | |
3388 // Set region->in(null_path) if the mirror is a primitive (e.g, int.class). | |
3389 region->init_req(null_path, null_ctl); | |
3390 } else { | |
3391 assert(null_ctl == top(), "no loose ends"); | |
3392 } | |
3393 return kls; | |
3394 } | |
3395 | |
3396 //--------------------(inline_native_Class_query helpers)--------------------- | |
3397 // Use this for JVM_ACC_INTERFACE, JVM_ACC_IS_CLONEABLE, JVM_ACC_HAS_FINALIZER. | |
3398 // Fall through if (mods & mask) == bits, take the guard otherwise. | |
3399 Node* LibraryCallKit::generate_access_flags_guard(Node* kls, int modifier_mask, int modifier_bits, RegionNode* region) { | |
3400 // Branch around if the given klass has the given modifier bit set. | |
3401 // 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
|
3402 Node* modp = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset())); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3403 Node* mods = make_load(NULL, modp, TypeInt::INT, T_INT, MemNode::unordered); |
0 | 3404 Node* mask = intcon(modifier_mask); |
3405 Node* bits = intcon(modifier_bits); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3406 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
|
3407 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
|
3408 Node* bol = _gvn.transform(new (C) BoolNode(cmp, BoolTest::ne)); |
0 | 3409 return generate_fair_guard(bol, region); |
3410 } | |
3411 Node* LibraryCallKit::generate_interface_guard(Node* kls, RegionNode* region) { | |
3412 return generate_access_flags_guard(kls, JVM_ACC_INTERFACE, 0, region); | |
3413 } | |
3414 | |
3415 //-------------------------inline_native_Class_query------------------- | |
3416 bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { | |
3417 const Type* return_type = TypeInt::BOOL; | |
3418 Node* prim_return_value = top(); // what happens if it's a primitive class? | |
3419 bool never_see_null = !too_many_traps(Deoptimization::Reason_null_check); | |
3420 bool expect_prim = false; // most of these guys expect to work on refs | |
3421 | |
3422 enum { _normal_path = 1, _prim_path = 2, PATH_LIMIT }; | |
3423 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3424 Node* mirror = argument(0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3425 Node* obj = top(); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3426 |
0 | 3427 switch (id) { |
3428 case vmIntrinsics::_isInstance: | |
3429 // nothing is an instance of a primitive type | |
3430 prim_return_value = intcon(0); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3431 obj = argument(1); |
0 | 3432 break; |
3433 case vmIntrinsics::_getModifiers: | |
3434 prim_return_value = intcon(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC); | |
3435 assert(is_power_of_2((int)JVM_ACC_WRITTEN_FLAGS+1), "change next line"); | |
3436 return_type = TypeInt::make(0, JVM_ACC_WRITTEN_FLAGS, Type::WidenMin); | |
3437 break; | |
3438 case vmIntrinsics::_isInterface: | |
3439 prim_return_value = intcon(0); | |
3440 break; | |
3441 case vmIntrinsics::_isArray: | |
3442 prim_return_value = intcon(0); | |
3443 expect_prim = true; // cf. ObjectStreamClass.getClassSignature | |
3444 break; | |
3445 case vmIntrinsics::_isPrimitive: | |
3446 prim_return_value = intcon(1); | |
3447 expect_prim = true; // obviously | |
3448 break; | |
3449 case vmIntrinsics::_getSuperclass: | |
3450 prim_return_value = null(); | |
3451 return_type = TypeInstPtr::MIRROR->cast_to_ptr_type(TypePtr::BotPTR); | |
3452 break; | |
3453 case vmIntrinsics::_getComponentType: | |
3454 prim_return_value = null(); | |
3455 return_type = TypeInstPtr::MIRROR->cast_to_ptr_type(TypePtr::BotPTR); | |
3456 break; | |
3457 case vmIntrinsics::_getClassAccessFlags: | |
3458 prim_return_value = intcon(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC); | |
3459 return_type = TypeInt::INT; // not bool! 6297094 | |
3460 break; | |
3461 default: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3462 fatal_unexpected_iid(id); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3463 break; |
0 | 3464 } |
3465 | |
3466 const TypeInstPtr* mirror_con = _gvn.type(mirror)->isa_instptr(); | |
3467 if (mirror_con == NULL) return false; // cannot happen? | |
3468 | |
3469 #ifndef PRODUCT | |
12295 | 3470 if (C->print_intrinsics() || C->print_inlining()) { |
0 | 3471 ciType* k = mirror_con->java_mirror_type(); |
3472 if (k) { | |
3473 tty->print("Inlining %s on constant Class ", vmIntrinsics::name_at(intrinsic_id())); | |
3474 k->print_name(); | |
3475 tty->cr(); | |
3476 } | |
3477 } | |
3478 #endif | |
3479 | |
3480 // 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
|
3481 RegionNode* region = new (C) RegionNode(PATH_LIMIT); |
0 | 3482 record_for_igvn(region); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3483 PhiNode* phi = new (C) PhiNode(region, return_type); |
0 | 3484 |
3485 // The mirror will never be null of Reflection.getClassAccessFlags, however | |
3486 // it may be null for Class.isInstance or Class.getModifiers. Throw a NPE | |
3487 // if it is. See bug 4774291. | |
3488 | |
3489 // For Reflection.getClassAccessFlags(), the null check occurs in | |
3490 // the wrong place; see inline_unsafe_access(), above, for a similar | |
3491 // situation. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3492 mirror = null_check(mirror); |
0 | 3493 // If mirror or obj is dead, only null-path is taken. |
3494 if (stopped()) return true; | |
3495 | |
3496 if (expect_prim) never_see_null = false; // expect nulls (meaning prims) | |
3497 | |
3498 // Now load the mirror's klass metaobject, and null-check it. | |
3499 // 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
|
3500 Node* kls = load_klass_from_mirror(mirror, never_see_null, region, _prim_path); |
0 | 3501 // If kls is null, we have a primitive mirror. |
3502 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
|
3503 if (stopped()) { set_result(region, phi); return true; } |
12966 | 3504 bool safe_for_replace = (region->in(_prim_path) == top()); |
0 | 3505 |
3506 Node* p; // handy temp | |
3507 Node* null_ctl; | |
3508 | |
3509 // Now that we have the non-null klass, we can perform the real query. | |
3510 // For constant classes, the query will constant-fold in LoadNode::Value. | |
3511 Node* query_value = top(); | |
3512 switch (id) { | |
3513 case vmIntrinsics::_isInstance: | |
3514 // nothing is an instance of a primitive type | |
12966 | 3515 query_value = gen_instanceof(obj, kls, safe_for_replace); |
0 | 3516 break; |
3517 | |
3518 case vmIntrinsics::_getModifiers: | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3961
diff
changeset
|
3519 p = basic_plus_adr(kls, in_bytes(Klass::modifier_flags_offset())); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3520 query_value = make_load(NULL, p, TypeInt::INT, T_INT, MemNode::unordered); |
0 | 3521 break; |
3522 | |
3523 case vmIntrinsics::_isInterface: | |
3524 // (To verify this code sequence, check the asserts in JVM_IsInterface.) | |
3525 if (generate_interface_guard(kls, region) != NULL) | |
3526 // A guard was added. If the guard is taken, it was an interface. | |
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::_isArray: | |
3533 // (To verify this code sequence, check the asserts in JVM_IsArrayClass.) | |
3534 if (generate_array_guard(kls, region) != NULL) | |
3535 // A guard was added. If the guard is taken, it was an array. | |
3536 phi->add_req(intcon(1)); | |
3537 // If we fall through, it's a plain class. | |
3538 query_value = intcon(0); | |
3539 break; | |
3540 | |
3541 case vmIntrinsics::_isPrimitive: | |
3542 query_value = intcon(0); // "normal" path produces false | |
3543 break; | |
3544 | |
3545 case vmIntrinsics::_getSuperclass: | |
3546 // The rules here are somewhat unfortunate, but we can still do better | |
3547 // with random logic than with a JNI call. | |
3548 // Interfaces store null or Object as _super, but must report null. | |
3549 // Arrays store an intermediate super as _super, but must report Object. | |
3550 // Other types can report the actual _super. | |
3551 // (To verify this code sequence, check the asserts in JVM_IsInterface.) | |
3552 if (generate_interface_guard(kls, region) != NULL) | |
3553 // A guard was added. If the guard is taken, it was an interface. | |
3554 phi->add_req(null()); | |
3555 if (generate_array_guard(kls, region) != NULL) | |
3556 // A guard was added. If the guard is taken, it was an array. | |
3557 phi->add_req(makecon(TypeInstPtr::make(env()->Object_klass()->java_mirror()))); | |
3558 // 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
|
3559 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
|
3560 kls = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeRawPtr::BOTTOM, TypeKlassPtr::OBJECT_OR_NULL)); |
0 | 3561 null_ctl = top(); |
3562 kls = null_check_oop(kls, &null_ctl); | |
3563 if (null_ctl != top()) { | |
3564 // If the guard is taken, Object.superClass is null (both klass and mirror). | |
3565 region->add_req(null_ctl); | |
3566 phi ->add_req(null()); | |
3567 } | |
3568 if (!stopped()) { | |
3569 query_value = load_mirror_from_klass(kls); | |
3570 } | |
3571 break; | |
3572 | |
3573 case vmIntrinsics::_getComponentType: | |
3574 if (generate_array_guard(kls, region) != NULL) { | |
3575 // Be sure to pin the oop load to the guard edge just created: | |
3576 Node* is_array_ctrl = region->in(region->req()-1); | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6804
diff
changeset
|
3577 Node* cma = basic_plus_adr(kls, in_bytes(ArrayKlass::component_mirror_offset())); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3578 Node* cmo = make_load(is_array_ctrl, cma, TypeInstPtr::MIRROR, T_OBJECT, MemNode::unordered); |
0 | 3579 phi->add_req(cmo); |
3580 } | |
3581 query_value = null(); // non-array case is null | |
3582 break; | |
3583 | |
3584 case vmIntrinsics::_getClassAccessFlags: | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3961
diff
changeset
|
3585 p = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset())); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3586 query_value = make_load(NULL, p, TypeInt::INT, T_INT, MemNode::unordered); |
0 | 3587 break; |
3588 | |
3589 default: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3590 fatal_unexpected_iid(id); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3591 break; |
0 | 3592 } |
3593 | |
3594 // Fall-through is the normal case of a query to a real class. | |
3595 phi->init_req(1, query_value); | |
3596 region->init_req(1, control()); | |
3597 | |
3598 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
|
3599 set_result(region, phi); |
0 | 3600 return true; |
3601 } | |
3602 | |
3603 //--------------------------inline_native_subtype_check------------------------ | |
3604 // This intrinsic takes the JNI calls out of the heart of | |
3605 // UnsafeFieldAccessorImpl.set, which improves Field.set, readObject, etc. | |
3606 bool LibraryCallKit::inline_native_subtype_check() { | |
3607 // Pull both arguments off the stack. | |
3608 Node* args[2]; // two java.lang.Class mirrors: superc, subc | |
3609 args[0] = argument(0); | |
3610 args[1] = argument(1); | |
3611 Node* klasses[2]; // corresponding Klasses: superk, subk | |
3612 klasses[0] = klasses[1] = top(); | |
3613 | |
3614 enum { | |
3615 // A full decision tree on {superc is prim, subc is prim}: | |
3616 _prim_0_path = 1, // {P,N} => false | |
3617 // {P,P} & superc!=subc => false | |
3618 _prim_same_path, // {P,P} & superc==subc => true | |
3619 _prim_1_path, // {N,P} => false | |
3620 _ref_subtype_path, // {N,N} & subtype check wins => true | |
3621 _both_ref_path, // {N,N} & subtype check loses => false | |
3622 PATH_LIMIT | |
3623 }; | |
3624 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3625 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
|
3626 Node* phi = new (C) PhiNode(region, TypeInt::BOOL); |
0 | 3627 record_for_igvn(region); |
3628 | |
3629 const TypePtr* adr_type = TypeRawPtr::BOTTOM; // memory type of loads | |
3630 const TypeKlassPtr* kls_type = TypeKlassPtr::OBJECT_OR_NULL; | |
3631 int class_klass_offset = java_lang_Class::klass_offset_in_bytes(); | |
3632 | |
3633 // First null-check both mirrors and load each mirror's klass metaobject. | |
3634 int which_arg; | |
3635 for (which_arg = 0; which_arg <= 1; which_arg++) { | |
3636 Node* arg = args[which_arg]; | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3637 arg = null_check(arg); |
0 | 3638 if (stopped()) break; |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7200
diff
changeset
|
3639 args[which_arg] = arg; |
0 | 3640 |
3641 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
|
3642 Node* kls = LoadKlassNode::make(_gvn, immutable_memory(), p, adr_type, kls_type); |
0 | 3643 klasses[which_arg] = _gvn.transform(kls); |
3644 } | |
3645 | |
3646 // Having loaded both klasses, test each for null. | |
3647 bool never_see_null = !too_many_traps(Deoptimization::Reason_null_check); | |
3648 for (which_arg = 0; which_arg <= 1; which_arg++) { | |
3649 Node* kls = klasses[which_arg]; | |
3650 Node* null_ctl = top(); | |
3651 kls = null_check_oop(kls, &null_ctl, never_see_null); | |
3652 int prim_path = (which_arg == 0 ? _prim_0_path : _prim_1_path); | |
3653 region->init_req(prim_path, null_ctl); | |
3654 if (stopped()) break; | |
3655 klasses[which_arg] = kls; | |
3656 } | |
3657 | |
3658 if (!stopped()) { | |
3659 // now we have two reference types, in klasses[0..1] | |
3660 Node* subk = klasses[1]; // the argument to isAssignableFrom | |
3661 Node* superk = klasses[0]; // the receiver | |
3662 region->set_req(_both_ref_path, gen_subtype_check(subk, superk)); | |
3663 // now we have a successful reference subtype check | |
3664 region->set_req(_ref_subtype_path, control()); | |
3665 } | |
3666 | |
3667 // If both operands are primitive (both klasses null), then | |
3668 // we must return true when they are identical primitives. | |
3669 // It is convenient to test this after the first null klass check. | |
3670 set_control(region->in(_prim_0_path)); // go back to first null check | |
3671 if (!stopped()) { | |
3672 // 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
|
3673 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
|
3674 Node* bol_eq = _gvn.transform(new (C) BoolNode(cmp_eq, BoolTest::eq)); |
0 | 3675 generate_guard(bol_eq, region, PROB_FAIR); |
3676 if (region->req() == PATH_LIMIT+1) { | |
3677 // A guard was added. If the added guard is taken, superc==subc. | |
3678 region->swap_edges(PATH_LIMIT, _prim_same_path); | |
3679 region->del_req(PATH_LIMIT); | |
3680 } | |
3681 region->set_req(_prim_0_path, control()); // Not equal after all. | |
3682 } | |
3683 | |
3684 // these are the only paths that produce 'true': | |
3685 phi->set_req(_prim_same_path, intcon(1)); | |
3686 phi->set_req(_ref_subtype_path, intcon(1)); | |
3687 | |
3688 // pull together the cases: | |
3689 assert(region->req() == PATH_LIMIT, "sane region"); | |
3690 for (uint i = 1; i < region->req(); i++) { | |
3691 Node* ctl = region->in(i); | |
3692 if (ctl == NULL || ctl == top()) { | |
3693 region->set_req(i, top()); | |
3694 phi ->set_req(i, top()); | |
3695 } else if (phi->in(i) == NULL) { | |
3696 phi->set_req(i, intcon(0)); // all other paths produce 'false' | |
3697 } | |
3698 } | |
3699 | |
3700 set_control(_gvn.transform(region)); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3701 set_result(_gvn.transform(phi)); |
0 | 3702 return true; |
3703 } | |
3704 | |
3705 //---------------------generate_array_guard_common------------------------ | |
3706 Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region, | |
3707 bool obj_array, bool not_array) { | |
3708 // If obj_array/non_array==false/false: | |
3709 // Branch around if the given klass is in fact an array (either obj or prim). | |
3710 // If obj_array/non_array==false/true: | |
3711 // Branch around if the given klass is not an array klass of any kind. | |
3712 // If obj_array/non_array==true/true: | |
3713 // Branch around if the kls is not an oop array (kls is int[], String, etc.) | |
3714 // If obj_array/non_array==true/false: | |
3715 // Branch around if the kls is an oop array (Object[] or subtype) | |
3716 // | |
3717 // Like generate_guard, adds a new path onto the region. | |
3718 jint layout_con = 0; | |
3719 Node* layout_val = get_layout_helper(kls, layout_con); | |
3720 if (layout_val == NULL) { | |
3721 bool query = (obj_array | |
3722 ? Klass::layout_helper_is_objArray(layout_con) | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6615
diff
changeset
|
3723 : Klass::layout_helper_is_array(layout_con)); |
0 | 3724 if (query == not_array) { |
3725 return NULL; // never a branch | |
3726 } else { // always a branch | |
3727 Node* always_branch = control(); | |
3728 if (region != NULL) | |
3729 region->add_req(always_branch); | |
3730 set_control(top()); | |
3731 return always_branch; | |
3732 } | |
3733 } | |
3734 // Now test the correct condition. | |
3735 jint nval = (obj_array | |
3736 ? ((jint)Klass::_lh_array_tag_type_value | |
3737 << Klass::_lh_array_tag_shift) | |
3738 : Klass::_lh_neutral_value); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
3739 Node* cmp = _gvn.transform(new(C) CmpINode(layout_val, intcon(nval))); |
0 | 3740 BoolTest::mask btest = BoolTest::lt; // correct for testing is_[obj]array |
3741 // invert the test if we are looking for a non-array | |
3742 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
|
3743 Node* bol = _gvn.transform(new(C) BoolNode(cmp, btest)); |
0 | 3744 return generate_fair_guard(bol, region); |
3745 } | |
3746 | |
3747 | |
3748 //-----------------------inline_native_newArray-------------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3749 // private static native Object java.lang.reflect.newArray(Class<?> componentType, int length); |
0 | 3750 bool LibraryCallKit::inline_native_newArray() { |
3751 Node* mirror = argument(0); | |
3752 Node* count_val = argument(1); | |
3753 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3754 mirror = null_check(mirror); |
163 | 3755 // If mirror or obj is dead, only null-path is taken. |
3756 if (stopped()) return true; | |
0 | 3757 |
3758 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
|
3759 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
|
3760 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
|
3761 TypeInstPtr::NOTNULL); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3762 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
|
3763 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
|
3764 TypePtr::BOTTOM); |
0 | 3765 |
3766 bool never_see_null = !too_many_traps(Deoptimization::Reason_null_check); | |
3767 Node* klass_node = load_array_klass_from_mirror(mirror, never_see_null, | |
3768 result_reg, _slow_path); | |
3769 Node* normal_ctl = control(); | |
3770 Node* no_array_ctl = result_reg->in(_slow_path); | |
3771 | |
3772 // Generate code for the slow case. We make a call to newArray(). | |
3773 set_control(no_array_ctl); | |
3774 if (!stopped()) { | |
3775 // Either the input type is void.class, or else the | |
3776 // array klass has not yet been cached. Either the | |
3777 // ensuing call will throw an exception, or else it | |
3778 // will cache the array klass for next time. | |
3779 PreserveJVMState pjvms(this); | |
3780 CallJavaNode* slow_call = generate_method_call_static(vmIntrinsics::_newArray); | |
3781 Node* slow_result = set_results_for_java_call(slow_call); | |
3782 // this->control() comes from set_results_for_java_call | |
3783 result_reg->set_req(_slow_path, control()); | |
3784 result_val->set_req(_slow_path, slow_result); | |
3785 result_io ->set_req(_slow_path, i_o()); | |
3786 result_mem->set_req(_slow_path, reset_memory()); | |
3787 } | |
3788 | |
3789 set_control(normal_ctl); | |
3790 if (!stopped()) { | |
3791 // Normal case: The array type has been cached in the java.lang.Class. | |
3792 // The following call works fine even if the array type is polymorphic. | |
3793 // 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
|
3794 Node* obj = new_array(klass_node, count_val, 0); // no arguments to push |
0 | 3795 result_reg->init_req(_normal_path, control()); |
3796 result_val->init_req(_normal_path, obj); | |
3797 result_io ->init_req(_normal_path, i_o()); | |
3798 result_mem->init_req(_normal_path, reset_memory()); | |
3799 } | |
3800 | |
3801 // Return the combined state. | |
3802 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
|
3803 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
|
3804 |
0 | 3805 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
|
3806 set_result(result_reg, result_val); |
0 | 3807 return true; |
3808 } | |
3809 | |
3810 //----------------------inline_native_getLength-------------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3811 // public static native int java.lang.reflect.Array.getLength(Object array); |
0 | 3812 bool LibraryCallKit::inline_native_getLength() { |
3813 if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; | |
3814 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3815 Node* array = null_check(argument(0)); |
0 | 3816 // If array is dead, only null-path is taken. |
3817 if (stopped()) return true; | |
3818 | |
3819 // Deoptimize if it is a non-array. | |
3820 Node* non_array = generate_non_array_guard(load_object_klass(array), NULL); | |
3821 | |
3822 if (non_array != NULL) { | |
3823 PreserveJVMState pjvms(this); | |
3824 set_control(non_array); | |
3825 uncommon_trap(Deoptimization::Reason_intrinsic, | |
3826 Deoptimization::Action_maybe_recompile); | |
3827 } | |
3828 | |
3829 // If control is dead, only non-array-path is taken. | |
3830 if (stopped()) return true; | |
3831 | |
3832 // The works fine even if the array type is polymorphic. | |
3833 // 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
|
3834 Node* result = load_array_length(array); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3835 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3836 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
|
3837 set_result(result); |
0 | 3838 return true; |
3839 } | |
3840 | |
3841 //------------------------inline_array_copyOf---------------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3842 // 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
|
3843 // public static <T,U> T[] java.util.Arrays.copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType); |
0 | 3844 bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { |
3845 if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; | |
3846 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3847 // Get the arguments. |
0 | 3848 Node* original = argument(0); |
3849 Node* start = is_copyOfRange? argument(1): intcon(0); | |
3850 Node* end = is_copyOfRange? argument(2): argument(1); | |
3851 Node* array_type_mirror = is_copyOfRange? argument(3): argument(2); | |
3852 | |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3853 Node* newcopy; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3854 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3855 // 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
|
3856 // 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
|
3857 { PreserveReexecuteState preexecs(this); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3858 jvms()->set_should_reexecute(true); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3859 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3860 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
|
3861 original = null_check(original); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3862 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3863 // Check if a null path was taken unconditionally. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3864 if (stopped()) return true; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3865 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3866 Node* orig_length = load_array_length(original); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3867 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3868 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
|
3869 klass_node = null_check(klass_node); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3870 |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3871 RegionNode* bailout = new (C) RegionNode(1); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3872 record_for_igvn(bailout); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3873 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3874 // 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
|
3875 // Bail out if that is so. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3876 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
|
3877 if (not_objArray != NULL) { |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3878 // 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
|
3879 ciKlass* ak = ciArrayKlass::make(env()->Object_klass()); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3880 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
|
3881 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
|
3882 cast->init_req(0, control()); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3883 klass_node = _gvn.transform(cast); |
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 either start or end is negative. |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3887 generate_negative_guard(start, bailout, &start); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3888 generate_negative_guard(end, bailout, &end); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3889 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3890 Node* length = end; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3891 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
|
3892 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
|
3893 } |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3894 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3895 // 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
|
3896 // 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
|
3897 // 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
|
3898 // should be thrown |
eeb819cf36e5
7174363: Arrays.copyOfRange leads to VM crash with -Xcomp -server if executed by testing framework
roland
parents:
6143
diff
changeset
|
3899 generate_negative_guard(length, bailout, &length); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3900 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3901 if (bailout->req() > 1) { |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3902 PreserveJVMState pjvms(this); |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3903 set_control(_gvn.transform(bailout)); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3904 uncommon_trap(Deoptimization::Reason_intrinsic, |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3905 Deoptimization::Action_maybe_recompile); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3906 } |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3907 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3908 if (!stopped()) { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3909 // 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
|
3910 // 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
|
3911 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
|
3912 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
|
3913 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3914 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
|
3915 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3916 // 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
|
3917 // 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
|
3918 // oop stores need checking. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3919 // 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
|
3920 // 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
|
3921 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
|
3922 // 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
|
3923 // negative. |
eeb819cf36e5
7174363: Arrays.copyOfRange leads to VM crash with -Xcomp -server if executed by testing framework
roland
parents:
6143
diff
changeset
|
3924 bool length_never_negative = !is_copyOfRange; |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3925 generate_arraycopy(TypeAryPtr::OOPS, T_OBJECT, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3926 original, start, newcopy, intcon(0), moved, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
3927 disjoint_bases, length_never_negative); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
3928 } |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3929 } // original reexecute is set back here |
0 | 3930 |
3931 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
|
3932 if (!stopped()) { |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3933 set_result(newcopy); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3934 } |
0 | 3935 return true; |
3936 } | |
3937 | |
3938 | |
3939 //----------------------generate_virtual_guard--------------------------- | |
3940 // Helper for hashCode and clone. Peeks inside the vtable to avoid a call. | |
3941 Node* LibraryCallKit::generate_virtual_guard(Node* obj_klass, | |
3942 RegionNode* slow_region) { | |
3943 ciMethod* method = callee(); | |
3944 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
|
3945 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
|
3946 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
|
3947 // 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
|
3948 int entry_offset = (InstanceKlass::vtable_start_offset() + |
0 | 3949 vtable_index*vtableEntry::size()) * wordSize + |
3950 vtableEntry::method_offset_in_bytes(); | |
3951 Node* entry_addr = basic_plus_adr(obj_klass, entry_offset); | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
3952 Node* target_call = make_load(NULL, entry_addr, TypePtr::NOTNULL, T_ADDRESS, MemNode::unordered); |
0 | 3953 |
3954 // 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
|
3955 const TypePtr* native_call_addr = TypeMetadataPtr::make(method); |
0 | 3956 |
3957 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
|
3958 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
|
3959 Node* test_native = _gvn.transform(new(C) BoolNode(chk_native, BoolTest::ne)); |
0 | 3960 |
3961 return generate_slow_guard(test_native, slow_region); | |
3962 } | |
3963 | |
3964 //-----------------------generate_method_call---------------------------- | |
3965 // Use generate_method_call to make a slow-call to the real | |
3966 // method if the fast path fails. An alternative would be to | |
3967 // use a stub like OptoRuntime::slow_arraycopy_Java. | |
3968 // This only works for expanding the current library call, | |
3969 // not another intrinsic. (E.g., don't use this for making an | |
3970 // arraycopy call inside of the copyOf intrinsic.) | |
3971 CallJavaNode* | |
3972 LibraryCallKit::generate_method_call(vmIntrinsics::ID method_id, bool is_virtual, bool is_static) { | |
3973 // When compiling the intrinsic method itself, do not use this technique. | |
3974 guarantee(callee() != C->method(), "cannot make slow-call to self"); | |
3975 | |
3976 ciMethod* method = callee(); | |
3977 // ensure the JVMS we have will be correct for this call | |
3978 guarantee(method_id == method->intrinsic_id(), "must match"); | |
3979 | |
3980 const TypeFunc* tf = TypeFunc::make(method); | |
3981 CallJavaNode* slow_call; | |
3982 if (is_static) { | |
3983 assert(!is_virtual, ""); | |
10278 | 3984 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
|
3985 SharedRuntime::get_resolve_static_call_stub(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
3986 method, bci()); |
0 | 3987 } else if (is_virtual) { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
3988 null_check_receiver(); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6615
diff
changeset
|
3989 int vtable_index = Method::invalid_vtable_index; |
0 | 3990 if (UseInlineCaches) { |
3991 // Suppress the vtable call | |
3992 } else { | |
3993 // hashCode and clone are not a miranda methods, | |
3994 // so the vtable index is fixed. | |
3995 // No need to use the linkResolver to get it. | |
3996 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
|
3997 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
|
3998 err_msg_res("bad index %d", vtable_index)); |
0 | 3999 } |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4000 slow_call = new(C) CallDynamicJavaNode(tf, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4001 SharedRuntime::get_resolve_virtual_call_stub(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4002 method, vtable_index, bci()); |
0 | 4003 } 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
|
4004 null_check_receiver(); |
10278 | 4005 slow_call = new(C) CallStaticJavaNode(C, tf, |
0 | 4006 SharedRuntime::get_resolve_opt_virtual_call_stub(), |
4007 method, bci()); | |
4008 slow_call->set_optimized_virtual(true); | |
4009 } | |
4010 set_arguments_for_java_call(slow_call); | |
4011 set_edges_for_java_call(slow_call); | |
4012 return slow_call; | |
4013 } | |
4014 | |
4015 | |
4016 //------------------------------inline_native_hashcode-------------------- | |
4017 // Build special case code for calls to hashCode on an object. | |
4018 bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) { | |
4019 assert(is_static == callee()->is_static(), "correct intrinsic selection"); | |
4020 assert(!(is_virtual && is_static), "either virtual, special, or static"); | |
4021 | |
4022 enum { _slow_path = 1, _fast_path, _null_path, PATH_LIMIT }; | |
4023 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4024 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
|
4025 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
|
4026 TypeInt::INT); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4027 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
|
4028 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
|
4029 TypePtr::BOTTOM); |
0 | 4030 Node* obj = NULL; |
4031 if (!is_static) { | |
4032 // Check for hashing null object | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4033 obj = null_check_receiver(); |
0 | 4034 if (stopped()) return true; // unconditionally null |
4035 result_reg->init_req(_null_path, top()); | |
4036 result_val->init_req(_null_path, top()); | |
4037 } else { | |
4038 // Do a null check, and return zero if null. | |
4039 // System.identityHashCode(null) == 0 | |
4040 obj = argument(0); | |
4041 Node* null_ctl = top(); | |
4042 obj = null_check_oop(obj, &null_ctl); | |
4043 result_reg->init_req(_null_path, null_ctl); | |
4044 result_val->init_req(_null_path, _gvn.intcon(0)); | |
4045 } | |
4046 | |
4047 // Unconditionally null? Then return right away. | |
4048 if (stopped()) { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4049 set_control( result_reg->in(_null_path)); |
0 | 4050 if (!stopped()) |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4051 set_result(result_val->in(_null_path)); |
0 | 4052 return true; |
4053 } | |
4054 | |
4055 // After null check, get the object's klass. | |
4056 Node* obj_klass = load_object_klass(obj); | |
4057 | |
4058 // This call may be virtual (invokevirtual) or bound (invokespecial). | |
4059 // For each case we generate slightly different code. | |
4060 | |
4061 // We only go to the fast case code if we pass a number of guards. The | |
4062 // 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
|
4063 RegionNode* slow_region = new (C) RegionNode(1); |
0 | 4064 record_for_igvn(slow_region); |
4065 | |
4066 // If this is a virtual call, we generate a funny guard. We pull out | |
4067 // the vtable entry corresponding to hashCode() from the target object. | |
4068 // If the target method which we are calling happens to be the native | |
4069 // Object hashCode() method, we pass the guard. We do not need this | |
4070 // guard for non-virtual calls -- the caller is known to be the native | |
4071 // Object hashCode(). | |
4072 if (is_virtual) { | |
4073 generate_virtual_guard(obj_klass, slow_region); | |
4074 } | |
4075 | |
4076 // Get the header out of the object, use LoadMarkNode when available | |
4077 Node* header_addr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes()); | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
4078 Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type(), MemNode::unordered); |
0 | 4079 |
4080 // Test the header to see if it is unlocked. | |
4081 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
|
4082 Node *lmasked_header = _gvn.transform(new (C) AndXNode(header, lock_mask)); |
0 | 4083 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
|
4084 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
|
4085 Node *test_unlocked = _gvn.transform(new (C) BoolNode( chk_unlocked, BoolTest::ne)); |
0 | 4086 |
4087 generate_slow_guard(test_unlocked, slow_region); | |
4088 | |
4089 // Get the hash value and check to see that it has been properly assigned. | |
4090 // We depend on hash_mask being at most 32 bits and avoid the use of | |
4091 // hash_mask_in_place because it could be larger than 32 bits in a 64-bit | |
4092 // vm: see markOop.hpp. | |
4093 Node *hash_mask = _gvn.intcon(markOopDesc::hash_mask); | |
4094 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
|
4095 Node *hshifted_header= _gvn.transform(new (C) URShiftXNode(header, hash_shift)); |
0 | 4096 // This hack lets the hash bits live anywhere in the mark object now, as long |
605 | 4097 // as the shift drops the relevant bits into the low 32 bits. Note that |
0 | 4098 // Java spec says that HashCode is an int so there's no point in capturing |
4099 // an 'X'-sized hashcode (32 in 32-bit build or 64 in 64-bit build). | |
4100 hshifted_header = ConvX2I(hshifted_header); | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4101 Node *hash_val = _gvn.transform(new (C) AndINode(hshifted_header, hash_mask)); |
0 | 4102 |
4103 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
|
4104 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
|
4105 Node *test_assigned = _gvn.transform(new (C) BoolNode( chk_assigned, BoolTest::eq)); |
0 | 4106 |
4107 generate_slow_guard(test_assigned, slow_region); | |
4108 | |
4109 Node* init_mem = reset_memory(); | |
4110 // fill in the rest of the null path: | |
4111 result_io ->init_req(_null_path, i_o()); | |
4112 result_mem->init_req(_null_path, init_mem); | |
4113 | |
4114 result_val->init_req(_fast_path, hash_val); | |
4115 result_reg->init_req(_fast_path, control()); | |
4116 result_io ->init_req(_fast_path, i_o()); | |
4117 result_mem->init_req(_fast_path, init_mem); | |
4118 | |
4119 // Generate code for the slow case. We make a call to hashCode(). | |
4120 set_control(_gvn.transform(slow_region)); | |
4121 if (!stopped()) { | |
4122 // No need for PreserveJVMState, because we're using up the present state. | |
4123 set_all_memory(init_mem); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4124 vmIntrinsics::ID hashCode_id = is_static ? vmIntrinsics::_identityHashCode : vmIntrinsics::_hashCode; |
0 | 4125 CallJavaNode* slow_call = generate_method_call(hashCode_id, is_virtual, is_static); |
4126 Node* slow_result = set_results_for_java_call(slow_call); | |
4127 // this->control() comes from set_results_for_java_call | |
4128 result_reg->init_req(_slow_path, control()); | |
4129 result_val->init_req(_slow_path, slow_result); | |
4130 result_io ->set_req(_slow_path, i_o()); | |
4131 result_mem ->set_req(_slow_path, reset_memory()); | |
4132 } | |
4133 | |
4134 // Return the combined state. | |
4135 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
|
4136 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
|
4137 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4138 set_result(result_reg, result_val); |
0 | 4139 return true; |
4140 } | |
4141 | |
4142 //---------------------------inline_native_getClass---------------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4143 // 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
|
4144 // |
605 | 4145 // Build special case code for calls to getClass on an object. |
0 | 4146 bool LibraryCallKit::inline_native_getClass() { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4147 Node* obj = null_check_receiver(); |
0 | 4148 if (stopped()) return true; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4149 set_result(load_mirror_from_klass(load_object_klass(obj))); |
0 | 4150 return true; |
4151 } | |
4152 | |
4153 //-----------------inline_native_Reflection_getCallerClass--------------------- | |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4154 // 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
|
4155 // |
0 | 4156 // In the presence of deep enough inlining, getCallerClass() becomes a no-op. |
4157 // | |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4158 // 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
|
4159 // 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
|
4160 // caller sensitive methods. |
0 | 4161 bool LibraryCallKit::inline_native_Reflection_getCallerClass() { |
4162 #ifndef PRODUCT | |
12295 | 4163 if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { |
0 | 4164 tty->print_cr("Attempting to inline sun.reflect.Reflection.getCallerClass"); |
4165 } | |
4166 #endif | |
4167 | |
4168 if (!jvms()->has_method()) { | |
4169 #ifndef PRODUCT | |
12295 | 4170 if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { |
0 | 4171 tty->print_cr(" Bailing out because intrinsic was inlined at top level"); |
4172 } | |
4173 #endif | |
4174 return false; | |
4175 } | |
4176 | |
4177 // 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
|
4178 // depth. |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4179 JVMState* caller_jvms = jvms(); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4180 |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4181 // Cf. JVM_GetCallerClass |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4182 // 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
|
4183 // not include the Reflection.getCallerClass() frame. |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4184 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
|
4185 ciMethod* m = caller_jvms->method(); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4186 switch (n) { |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4187 case 0: |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4188 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
|
4189 break; |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4190 case 1: |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4191 // 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
|
4192 if (!m->caller_sensitive()) { |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4193 #ifndef PRODUCT |
12295 | 4194 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
|
4195 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
|
4196 } |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4197 #endif |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4198 return false; // bail-out; let JVM_GetCallerClass do the work |
0 | 4199 } |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4200 break; |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4201 default: |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4202 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
|
4203 // 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
|
4204 // 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
|
4205 ciInstanceKlass* caller_klass = caller_jvms->method()->holder(); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4206 ciInstance* caller_mirror = caller_klass->java_mirror(); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4207 set_result(makecon(TypeInstPtr::make(caller_mirror))); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4208 |
0 | 4209 #ifndef PRODUCT |
12295 | 4210 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
|
4211 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
|
4212 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
|
4213 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
|
4214 ciMethod* m = jvms()->of_depth(i)->method(); |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4215 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
|
4216 } |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4217 } |
0 | 4218 #endif |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4219 return true; |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4220 } |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4221 break; |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4222 } |
0 | 4223 } |
4224 | |
4225 #ifndef PRODUCT | |
12295 | 4226 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
|
4227 tty->print_cr(" Bailing out because caller depth exceeded inlining depth = %d", jvms()->depth()); |
0 | 4228 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
|
4229 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
|
4230 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
|
4231 tty->print_cr(" %d) %s.%s", n, m->holder()->name()->as_utf8(), m->name()->as_utf8()); |
0 | 4232 } |
4233 } | |
4234 #endif | |
8866
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4235 |
16885e702c88
7198429: need checked categorization of caller-sensitive methods in the JDK
twisti
parents:
8076
diff
changeset
|
4236 return false; // bail-out; let JVM_GetCallerClass do the work |
0 | 4237 } |
4238 | |
4239 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
|
4240 Node* arg = argument(0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4241 Node* result; |
0 | 4242 |
4243 switch (id) { | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4244 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
|
4245 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
|
4246 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
|
4247 case vmIntrinsics::_longBitsToDouble: result = new (C) MoveL2DNode(arg); break; |
0 | 4248 |
4249 case vmIntrinsics::_doubleToLongBits: { | |
4250 // 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
|
4251 RegionNode *r = new (C) RegionNode(3); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4252 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
|
4253 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4254 Node *cmpisnan = _gvn.transform(new (C) CmpDNode(arg, arg)); |
0 | 4255 // Build the boolean node |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4256 Node *bolisnan = _gvn.transform(new (C) BoolNode(cmpisnan, BoolTest::ne)); |
0 | 4257 |
4258 // Branch either way. | |
4259 // NaN case is less traveled, which makes all the difference. | |
4260 IfNode *ifisnan = create_and_xform_if(control(), bolisnan, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); | |
4261 Node *opt_isnan = _gvn.transform(ifisnan); | |
4262 assert( opt_isnan->is_If(), "Expect an IfNode"); | |
4263 IfNode *opt_ifisnan = (IfNode*)opt_isnan; | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4264 Node *iftrue = _gvn.transform(new (C) IfTrueNode(opt_ifisnan)); |
0 | 4265 |
4266 set_control(iftrue); | |
4267 | |
4268 static const jlong nan_bits = CONST64(0x7ff8000000000000); | |
4269 Node *slow_result = longcon(nan_bits); // return NaN | |
4270 phi->init_req(1, _gvn.transform( slow_result )); | |
4271 r->init_req(1, iftrue); | |
4272 | |
4273 // Else fall through | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4274 Node *iffalse = _gvn.transform(new (C) IfFalseNode(opt_ifisnan)); |
0 | 4275 set_control(iffalse); |
4276 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4277 phi->init_req(2, _gvn.transform(new (C) MoveD2LNode(arg))); |
0 | 4278 r->init_req(2, iffalse); |
4279 | |
4280 // Post merge | |
4281 set_control(_gvn.transform(r)); | |
4282 record_for_igvn(r); | |
4283 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4284 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
|
4285 result = phi; |
0 | 4286 assert(result->bottom_type()->isa_long(), "must be"); |
4287 break; | |
4288 } | |
4289 | |
4290 case vmIntrinsics::_floatToIntBits: { | |
4291 // 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
|
4292 RegionNode *r = new (C) RegionNode(3); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4293 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
|
4294 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4295 Node *cmpisnan = _gvn.transform(new (C) CmpFNode(arg, arg)); |
0 | 4296 // Build the boolean node |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4297 Node *bolisnan = _gvn.transform(new (C) BoolNode(cmpisnan, BoolTest::ne)); |
0 | 4298 |
4299 // Branch either way. | |
4300 // NaN case is less traveled, which makes all the difference. | |
4301 IfNode *ifisnan = create_and_xform_if(control(), bolisnan, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); | |
4302 Node *opt_isnan = _gvn.transform(ifisnan); | |
4303 assert( opt_isnan->is_If(), "Expect an IfNode"); | |
4304 IfNode *opt_ifisnan = (IfNode*)opt_isnan; | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4305 Node *iftrue = _gvn.transform(new (C) IfTrueNode(opt_ifisnan)); |
0 | 4306 |
4307 set_control(iftrue); | |
4308 | |
4309 static const jint nan_bits = 0x7fc00000; | |
4310 Node *slow_result = makecon(TypeInt::make(nan_bits)); // return NaN | |
4311 phi->init_req(1, _gvn.transform( slow_result )); | |
4312 r->init_req(1, iftrue); | |
4313 | |
4314 // Else fall through | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4315 Node *iffalse = _gvn.transform(new (C) IfFalseNode(opt_ifisnan)); |
0 | 4316 set_control(iffalse); |
4317 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4318 phi->init_req(2, _gvn.transform(new (C) MoveF2INode(arg))); |
0 | 4319 r->init_req(2, iffalse); |
4320 | |
4321 // Post merge | |
4322 set_control(_gvn.transform(r)); | |
4323 record_for_igvn(r); | |
4324 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4325 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
|
4326 result = phi; |
0 | 4327 assert(result->bottom_type()->isa_int(), "must be"); |
4328 break; | |
4329 } | |
4330 | |
4331 default: | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4332 fatal_unexpected_iid(id); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4333 break; |
0 | 4334 } |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4335 set_result(_gvn.transform(result)); |
0 | 4336 return true; |
4337 } | |
4338 | |
4339 #ifdef _LP64 | |
4340 #define XTOP ,top() /*additional argument*/ | |
4341 #else //_LP64 | |
4342 #define XTOP /*no additional argument*/ | |
4343 #endif //_LP64 | |
4344 | |
4345 //----------------------inline_unsafe_copyMemory------------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4346 // public native void sun.misc.Unsafe.copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes); |
0 | 4347 bool LibraryCallKit::inline_unsafe_copyMemory() { |
4348 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
|
4349 null_check_receiver(); // null-check receiver |
0 | 4350 if (stopped()) return true; |
4351 | |
4352 C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". | |
4353 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4354 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
|
4355 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
|
4356 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
|
4357 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
|
4358 Node* size = ConvL2X(argument(7)); // type: long |
0 | 4359 |
4360 assert(Unsafe_field_offset_to_byte_offset(11) == 11, | |
4361 "fieldOffset must be byte-scaled"); | |
4362 | |
4363 Node* src = make_unsafe_address(src_ptr, src_off); | |
4364 Node* dst = make_unsafe_address(dst_ptr, dst_off); | |
4365 | |
4366 // Conservatively insert a memory barrier on all memory slices. | |
4367 // Do not let writes of the copy source or destination float below the copy. | |
4368 insert_mem_bar(Op_MemBarCPUOrder); | |
4369 | |
4370 // Call it. Note that the length argument is not scaled. | |
4371 make_runtime_call(RC_LEAF|RC_NO_FP, | |
4372 OptoRuntime::fast_arraycopy_Type(), | |
4373 StubRoutines::unsafe_arraycopy(), | |
4374 "unsafe_arraycopy", | |
4375 TypeRawPtr::BOTTOM, | |
4376 src, dst, size XTOP); | |
4377 | |
4378 // Do not let reads of the copy destination float above the copy. | |
4379 insert_mem_bar(Op_MemBarCPUOrder); | |
4380 | |
4381 return true; | |
4382 } | |
4383 | |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4384 //------------------------clone_coping----------------------------------- |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4385 // 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
|
4386 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
|
4387 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
|
4388 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
|
4389 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
|
4390 |
4763
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4391 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
|
4392 if (ReduceBulkZeroing) { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4393 // 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
|
4394 // mark Initialize node as complete. |
4763
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4395 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
|
4396 // 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
|
4397 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
|
4398 // 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
|
4399 // 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
|
4400 // 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
|
4401 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
|
4402 } |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4403 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4404 // 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
|
4405 // 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
|
4406 Node* src = obj; |
958
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
4407 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
|
4408 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
|
4409 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4410 // 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
|
4411 // 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
|
4412 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
|
4413 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
|
4414 // base_off: |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4415 // 8 - 32-bit VM |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6615
diff
changeset
|
4416 // 12 - 64-bit VM, compressed klass |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6615
diff
changeset
|
4417 // 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
|
4418 if (base_off % BytesPerLong != 0) { |
12226
7944aba7ba41
8015107: NPG: Use consistent naming for metaspace concepts
ehelin
parents:
12169
diff
changeset
|
4419 assert(UseCompressedClassPointers, ""); |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4420 if (is_array) { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4421 // 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
|
4422 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
|
4423 } else { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4424 // 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
|
4425 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
|
4426 } |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4427 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
|
4428 } |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4429 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
|
4430 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
|
4431 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4432 // 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
|
4433 Node* countx = size; |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4434 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
|
4435 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
|
4436 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4437 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
|
4438 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
|
4439 generate_unchecked_arraycopy(raw_adr_type, T_LONG, disjoint_bases, |
2324 | 4440 src, NULL, dest, NULL, countx, |
4441 /*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
|
4442 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4443 // 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
|
4444 if (card_mark) { |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4445 assert(!is_array, ""); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4446 // 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
|
4447 // 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
|
4448 // 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
|
4449 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
|
4450 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
|
4451 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
|
4452 post_barrier(control(), |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4453 memory(raw_adr_type), |
958
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
4454 alloc_obj, |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4455 no_particular_field, |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4456 raw_adr_idx, |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4457 no_particular_value, |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4458 T_OBJECT, |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4459 false); |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4460 } |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4461 |
958
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
4462 // 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
|
4463 if (alloc != NULL) { |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4464 // 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
|
4465 // 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
|
4466 // other threads. |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4467 // 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
|
4468 // 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
|
4469 // AllocateNode and eliminate the MemBarStoreStoreNode if possible |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4470 // 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
|
4471 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
|
4472 } else { |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4473 insert_mem_bar(Op_MemBarCPUOrder); |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
4474 } |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4475 } |
0 | 4476 |
4477 //------------------------inline_native_clone---------------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4478 // 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
|
4479 // |
0 | 4480 // Here are the simple edge cases: |
4481 // null receiver => normal trap | |
4482 // virtual and clone was overridden => slow path to out-of-line clone | |
4483 // not cloneable or finalizer => slow path to out-of-line Object.clone | |
4484 // | |
4485 // The general case has two steps, allocation and copying. | |
4486 // Allocation has two cases, and uses GraphKit::new_instance or new_array. | |
4487 // | |
4488 // Copying also has two cases, oop arrays and everything else. | |
4489 // Oop arrays use arrayof_oop_arraycopy (same as System.arraycopy). | |
4490 // Everything else uses the tight inline loop supplied by CopyArrayNode. | |
4491 // | |
4492 // These steps fold up nicely if and when the cloned object's klass | |
4493 // can be sharply typed as an object array, a type array, or an instance. | |
4494 // | |
4495 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
|
4496 PhiNode* result_val; |
0 | 4497 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4498 // 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
|
4499 // 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
|
4500 { PreserveReexecuteState preexecs(this); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4501 jvms()->set_should_reexecute(true); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4502 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4503 Node* obj = null_check_receiver(); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4504 if (stopped()) return true; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4505 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4506 Node* obj_klass = load_object_klass(obj); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4507 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
|
4508 const TypeOopPtr* toop = ((tklass != NULL) |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4509 ? tklass->as_instance_type() |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4510 : TypeInstPtr::NOTNULL); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4511 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4512 // 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
|
4513 // 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
|
4514 insert_mem_bar(Op_MemBarCPUOrder); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4515 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4516 // paths into result_reg: |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4517 enum { |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4518 _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
|
4519 _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
|
4520 _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
|
4521 _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
|
4522 PATH_LIMIT |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4523 }; |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4524 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
|
4525 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
|
4526 TypeInstPtr::NOTNULL); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4527 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
|
4528 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
|
4529 TypePtr::BOTTOM); |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4530 record_for_igvn(result_reg); |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4531 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4532 const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4533 int raw_adr_idx = Compile::AliasIdxRaw; |
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 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
|
4536 if (array_ctl != NULL) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4537 // It's an array. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4538 PreserveJVMState pjvms(this); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4539 set_control(array_ctl); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4540 Node* obj_length = load_array_length(obj); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4541 Node* obj_size = NULL; |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4542 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
|
4543 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4544 if (!use_ReduceInitialCardMarks()) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4545 // 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
|
4546 // 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
|
4547 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
|
4548 if (is_obja != NULL) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4549 PreserveJVMState pjvms2(this); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4550 set_control(is_obja); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4551 // 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
|
4552 bool disjoint_bases = true; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4553 bool length_never_negative = true; |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4554 generate_arraycopy(TypeAryPtr::OOPS, T_OBJECT, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4555 obj, intcon(0), alloc_obj, intcon(0), |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4556 obj_length, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4557 disjoint_bases, length_never_negative); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4558 result_reg->init_req(_objArray_path, control()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4559 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
|
4560 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
|
4561 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
|
4562 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4563 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4564 // 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
|
4565 // (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
|
4566 // comes out of eden (TLAB)... In fact, ReduceInitialCardMarks |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
986
diff
changeset
|
4567 // 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
|
4568 // simulate a fresh allocation, so that no further |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
986
diff
changeset
|
4569 // 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
|
4570 // the object.) |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4571 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4572 if (!stopped()) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4573 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
|
4574 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4575 // Present the results of the copy. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4576 result_reg->init_req(_array_path, control()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4577 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
|
4578 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
|
4579 result_mem ->set_req(_array_path, reset_memory()); |
0 | 4580 } |
4581 } | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4582 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4583 // 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
|
4584 // 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
|
4585 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
|
4586 record_for_igvn(slow_region); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4587 if (!stopped()) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4588 // 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
|
4589 // 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
|
4590 // 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
|
4591 // 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
|
4592 // 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
|
4593 // 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
|
4594 // Object clone(). |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4595 if (is_virtual) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4596 generate_virtual_guard(obj_klass, slow_region); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4597 } |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4598 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4599 // 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
|
4600 // 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
|
4601 // 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
|
4602 generate_access_flags_guard(obj_klass, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4603 // Test both conditions: |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4604 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
|
4605 // Must be cloneable but not finalizer: |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4606 JVM_ACC_IS_CLONEABLE, |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4607 slow_region); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4608 } |
833
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4609 |
acba6af809c8
6840775: Multiple JVM crashes seen with 1.6.0_10 through 1.6.0_14
kvn
parents:
827
diff
changeset
|
4610 if (!stopped()) { |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4611 // 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
|
4612 PreserveJVMState pjvms(this); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4613 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
|
4614 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
|
4615 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4616 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
|
4617 |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4618 // Present the results of the slow call. |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4619 result_reg->init_req(_instance_path, control()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4620 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
|
4621 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
|
4622 result_mem ->set_req(_instance_path, reset_memory()); |
0 | 4623 } |
4624 | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4625 // 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
|
4626 set_control(_gvn.transform(slow_region)); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4627 if (!stopped()) { |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4628 PreserveJVMState pjvms(this); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4629 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
|
4630 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
|
4631 // 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
|
4632 result_reg->init_req(_slow_path, control()); |
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
896
diff
changeset
|
4633 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
|
4634 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
|
4635 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
|
4636 } |
902
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4637 |
fc2281ddce3c
6868269: CompileTheWorld assertion failure introduced by the reexecute bit implementation
cfang
parents:
900
diff
changeset
|
4638 // Return the combined state. |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4639 set_control( _gvn.transform(result_reg)); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
4640 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
|
4641 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
|
4642 } // original reexecute is set back here |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4643 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4644 set_result(_gvn.transform(result_val)); |
0 | 4645 return true; |
4646 } | |
4647 | |
4648 //------------------------------basictype2arraycopy---------------------------- | |
4649 address LibraryCallKit::basictype2arraycopy(BasicType t, | |
4650 Node* src_offset, | |
4651 Node* dest_offset, | |
4652 bool disjoint_bases, | |
2324 | 4653 const char* &name, |
4654 bool dest_uninitialized) { | |
0 | 4655 const TypeInt* src_offset_inttype = gvn().find_int_type(src_offset);; |
4656 const TypeInt* dest_offset_inttype = gvn().find_int_type(dest_offset);; | |
4657 | |
4658 bool aligned = false; | |
4659 bool disjoint = disjoint_bases; | |
4660 | |
4661 // if the offsets are the same, we can treat the memory regions as | |
4662 // disjoint, because either the memory regions are in different arrays, | |
4663 // or they are identical (which we can treat as disjoint.) We can also | |
4664 // treat a copy with a destination index less that the source index | |
4665 // as disjoint since a low->high copy will work correctly in this case. | |
4666 if (src_offset_inttype != NULL && src_offset_inttype->is_con() && | |
4667 dest_offset_inttype != NULL && dest_offset_inttype->is_con()) { | |
4668 // both indices are constants | |
4669 int s_offs = src_offset_inttype->get_con(); | |
4670 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
|
4671 int element_size = type2aelembytes(t); |
0 | 4672 aligned = ((arrayOopDesc::base_offset_in_bytes(t) + s_offs * element_size) % HeapWordSize == 0) && |
4673 ((arrayOopDesc::base_offset_in_bytes(t) + d_offs * element_size) % HeapWordSize == 0); | |
4674 if (s_offs >= d_offs) disjoint = true; | |
4675 } else if (src_offset == dest_offset && src_offset != NULL) { | |
4676 // This can occur if the offsets are identical non-constants. | |
4677 disjoint = true; | |
4678 } | |
4679 | |
2446 | 4680 return StubRoutines::select_arraycopy_function(t, aligned, disjoint, name, dest_uninitialized); |
0 | 4681 } |
4682 | |
4683 | |
4684 //------------------------------inline_arraycopy----------------------- | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4685 // 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
|
4686 // Object dest, int destPos, |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4687 // int length); |
0 | 4688 bool LibraryCallKit::inline_arraycopy() { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4689 // Get the arguments. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4690 Node* src = argument(0); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4691 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
|
4692 Node* dest = argument(2); // type: oop |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4693 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
|
4694 Node* length = argument(4); // type: int |
0 | 4695 |
4696 // Compile time checks. If any of these checks cannot be verified at compile time, | |
4697 // we do not make a fast path for this call. Instead, we let the call remain as it | |
4698 // is. The checks we choose to mandate at compile time are: | |
4699 // | |
4700 // (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
|
4701 const Type* src_type = src->Value(&_gvn); |
0 | 4702 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
|
4703 const TypeAryPtr* top_src = src_type->isa_aryptr(); |
0 | 4704 const TypeAryPtr* top_dest = dest_type->isa_aryptr(); |
12966 | 4705 |
4706 // Do we have the type of src? | |
4707 bool has_src = (top_src != NULL && top_src->klass() != NULL); | |
4708 // Do we have the type of dest? | |
4709 bool has_dest = (top_dest != NULL && top_dest->klass() != NULL); | |
4710 // Is the type for src from speculation? | |
4711 bool src_spec = false; | |
4712 // Is the type for dest from speculation? | |
4713 bool dest_spec = false; | |
4714 | |
4715 if (!has_src || !has_dest) { | |
4716 // We don't have sufficient type information, let's see if | |
4717 // speculative types can help. We need to have types for both src | |
4718 // and dest so that it pays off. | |
4719 | |
4720 // Do we already have or could we have type information for src | |
4721 bool could_have_src = has_src; | |
4722 // Do we already have or could we have type information for dest | |
4723 bool could_have_dest = has_dest; | |
4724 | |
4725 ciKlass* src_k = NULL; | |
4726 if (!has_src) { | |
4727 src_k = src_type->speculative_type(); | |
4728 if (src_k != NULL && src_k->is_array_klass()) { | |
4729 could_have_src = true; | |
4730 } | |
4731 } | |
4732 | |
4733 ciKlass* dest_k = NULL; | |
4734 if (!has_dest) { | |
4735 dest_k = dest_type->speculative_type(); | |
4736 if (dest_k != NULL && dest_k->is_array_klass()) { | |
4737 could_have_dest = true; | |
4738 } | |
4739 } | |
4740 | |
4741 if (could_have_src && could_have_dest) { | |
4742 // This is going to pay off so emit the required guards | |
4743 if (!has_src) { | |
4744 src = maybe_cast_profiled_obj(src, src_k); | |
4745 src_type = _gvn.type(src); | |
4746 top_src = src_type->isa_aryptr(); | |
4747 has_src = (top_src != NULL && top_src->klass() != NULL); | |
4748 src_spec = true; | |
4749 } | |
4750 if (!has_dest) { | |
4751 dest = maybe_cast_profiled_obj(dest, dest_k); | |
4752 dest_type = _gvn.type(dest); | |
4753 top_dest = dest_type->isa_aryptr(); | |
4754 has_dest = (top_dest != NULL && top_dest->klass() != NULL); | |
4755 dest_spec = true; | |
4756 } | |
4757 } | |
4758 } | |
4759 | |
4760 if (!has_src || !has_dest) { | |
0 | 4761 // Conservatively insert a memory barrier on all memory slices. |
4762 // Do not let writes into the source float below the arraycopy. | |
4763 insert_mem_bar(Op_MemBarCPUOrder); | |
4764 | |
4765 // Call StubRoutines::generic_arraycopy stub. | |
4766 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
|
4767 src, src_offset, dest, dest_offset, length); |
0 | 4768 |
4769 // Do not let reads from the destination float above the arraycopy. | |
4770 // Since we cannot type the arrays, we don't know which slices | |
4771 // might be affected. We could restrict this barrier only to those | |
4772 // memory slices which pertain to array elements--but don't bother. | |
4773 if (!InsertMemBarAfterArraycopy) | |
4774 // (If InsertMemBarAfterArraycopy, there is already one in place.) | |
4775 insert_mem_bar(Op_MemBarCPUOrder); | |
4776 return true; | |
4777 } | |
4778 | |
4779 // (2) src and dest arrays must have elements of the same BasicType | |
4780 // Figure out the size and type of the elements we will be copying. | |
4781 BasicType src_elem = top_src->klass()->as_array_klass()->element_type()->basic_type(); | |
4782 BasicType dest_elem = top_dest->klass()->as_array_klass()->element_type()->basic_type(); | |
4783 if (src_elem == T_ARRAY) src_elem = T_OBJECT; | |
4784 if (dest_elem == T_ARRAY) dest_elem = T_OBJECT; | |
4785 | |
4786 if (src_elem != dest_elem || dest_elem == T_VOID) { | |
4787 // The component types are not the same or are not recognized. Punt. | |
4788 // (But, avoid the native method wrapper to JVM_ArrayCopy.) | |
4789 generate_slow_arraycopy(TypePtr::BOTTOM, | |
2324 | 4790 src, src_offset, dest, dest_offset, length, |
4791 /*dest_uninitialized*/false); | |
0 | 4792 return true; |
4793 } | |
4794 | |
12966 | 4795 if (src_elem == T_OBJECT) { |
4796 // If both arrays are object arrays then having the exact types | |
4797 // for both will remove the need for a subtype check at runtime | |
4798 // before the call and may make it possible to pick a faster copy | |
4799 // routine (without a subtype check on every element) | |
4800 // Do we have the exact type of src? | |
4801 bool could_have_src = src_spec; | |
4802 // Do we have the exact type of dest? | |
4803 bool could_have_dest = dest_spec; | |
4804 ciKlass* src_k = top_src->klass(); | |
4805 ciKlass* dest_k = top_dest->klass(); | |
4806 if (!src_spec) { | |
4807 src_k = src_type->speculative_type(); | |
4808 if (src_k != NULL && src_k->is_array_klass()) { | |
4809 could_have_src = true; | |
4810 } | |
4811 } | |
4812 if (!dest_spec) { | |
4813 dest_k = dest_type->speculative_type(); | |
4814 if (dest_k != NULL && dest_k->is_array_klass()) { | |
4815 could_have_dest = true; | |
4816 } | |
4817 } | |
4818 if (could_have_src && could_have_dest) { | |
4819 // If we can have both exact types, emit the missing guards | |
4820 if (could_have_src && !src_spec) { | |
4821 src = maybe_cast_profiled_obj(src, src_k); | |
4822 } | |
4823 if (could_have_dest && !dest_spec) { | |
4824 dest = maybe_cast_profiled_obj(dest, dest_k); | |
4825 } | |
4826 } | |
4827 } | |
4828 | |
0 | 4829 //--------------------------------------------------------------------------- |
4830 // We will make a fast path for this call to arraycopy. | |
4831 | |
4832 // We have the following tests left to perform: | |
4833 // | |
4834 // (3) src and dest must not be null. | |
4835 // (4) src_offset must not be negative. | |
4836 // (5) dest_offset must not be negative. | |
4837 // (6) length must not be negative. | |
4838 // (7) src_offset + length must not exceed length of src. | |
4839 // (8) dest_offset + length must not exceed length of dest. | |
4840 // (9) each element of an oop array must be assignable | |
4841 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4842 RegionNode* slow_region = new (C) RegionNode(1); |
0 | 4843 record_for_igvn(slow_region); |
4844 | |
4845 // (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
|
4846 // We currently perform our null checks with the null_check routine. |
0 | 4847 // This means that the null exceptions will be reported in the caller |
4848 // rather than (correctly) reported inside of the native arraycopy call. | |
4849 // This should be corrected, given time. We do our null check with the | |
4850 // stack pointer restored. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4851 src = null_check(src, T_ARRAY); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
4852 dest = null_check(dest, T_ARRAY); |
0 | 4853 |
4854 // (4) src_offset must not be negative. | |
4855 generate_negative_guard(src_offset, slow_region); | |
4856 | |
4857 // (5) dest_offset must not be negative. | |
4858 generate_negative_guard(dest_offset, slow_region); | |
4859 | |
4860 // (6) length must not be negative (moved to generate_arraycopy()). | |
4861 // generate_negative_guard(length, slow_region); | |
4862 | |
4863 // (7) src_offset + length must not exceed length of src. | |
4864 generate_limit_guard(src_offset, length, | |
4865 load_array_length(src), | |
4866 slow_region); | |
4867 | |
4868 // (8) dest_offset + length must not exceed length of dest. | |
4869 generate_limit_guard(dest_offset, length, | |
4870 load_array_length(dest), | |
4871 slow_region); | |
4872 | |
4873 // (9) each element of an oop array must be assignable | |
4874 // The generate_arraycopy subroutine checks this. | |
4875 | |
4876 // This is where the memory effects are placed: | |
4877 const TypePtr* adr_type = TypeAryPtr::get_array_body_type(dest_elem); | |
4878 generate_arraycopy(adr_type, dest_elem, | |
4879 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
|
4880 false, false, slow_region); |
0 | 4881 |
4882 return true; | |
4883 } | |
4884 | |
4885 //-----------------------------generate_arraycopy---------------------- | |
4886 // Generate an optimized call to arraycopy. | |
4887 // Caller must guard against non-arrays. | |
4888 // Caller must determine a common array basic-type for both arrays. | |
4889 // Caller must validate offsets against array bounds. | |
4890 // The slow_region has already collected guard failure paths | |
4891 // (such as out of bounds length or non-conformable array types). | |
4892 // The generated code has this shape, in general: | |
4893 // | |
4894 // if (length == 0) return // via zero_path | |
4895 // slowval = -1 | |
4896 // if (types unknown) { | |
4897 // slowval = call generic copy loop | |
4898 // if (slowval == 0) return // via checked_path | |
4899 // } else if (indexes in bounds) { | |
4900 // if ((is object array) && !(array type check)) { | |
4901 // slowval = call checked copy loop | |
4902 // if (slowval == 0) return // via checked_path | |
4903 // } else { | |
4904 // call bulk copy loop | |
4905 // return // via fast_path | |
4906 // } | |
4907 // } | |
4908 // // adjust params for remaining work: | |
4909 // if (slowval != -1) { | |
4910 // n = -1^slowval; src_offset += n; dest_offset += n; length -= n | |
4911 // } | |
4912 // slow_region: | |
4913 // call slow arraycopy(src, src_offset, dest, dest_offset, length) | |
4914 // return // via slow_call_path | |
4915 // | |
4916 // This routine is used from several intrinsics: System.arraycopy, | |
4917 // Object.clone (the array subcase), and Arrays.copyOf[Range]. | |
4918 // | |
4919 void | |
4920 LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, | |
4921 BasicType basic_elem_type, | |
4922 Node* src, Node* src_offset, | |
4923 Node* dest, Node* dest_offset, | |
4924 Node* copy_length, | |
4925 bool disjoint_bases, | |
4926 bool length_never_negative, | |
4927 RegionNode* slow_region) { | |
4928 | |
4929 if (slow_region == NULL) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4930 slow_region = new(C) RegionNode(1); |
0 | 4931 record_for_igvn(slow_region); |
4932 } | |
4933 | |
4934 Node* original_dest = dest; | |
4935 AllocateArrayNode* alloc = NULL; // used for zeroing, if needed | |
2324 | 4936 bool dest_uninitialized = false; |
0 | 4937 |
4938 // See if this is the initialization of a newly-allocated array. | |
4939 // If so, we will take responsibility here for initializing it to zero. | |
4940 // (Note: Because tightly_coupled_allocation performs checks on the | |
4941 // out-edges of the dest, we need to avoid making derived pointers | |
4942 // from it until we have checked its uses.) | |
4943 if (ReduceBulkZeroing | |
4944 && !ZeroTLAB // pointless if already zeroed | |
4945 && basic_elem_type != T_CONFLICT // avoid corner case | |
4778 | 4946 && !src->eqv_uncast(dest) |
0 | 4947 && ((alloc = tightly_coupled_allocation(dest, slow_region)) |
4948 != NULL) | |
34
545c277a3ecf
6667581: Don't generate initialization (by 0) code for arrays with size 0
kvn
parents:
29
diff
changeset
|
4949 && _gvn.find_int_con(alloc->in(AllocateNode::ALength), 1) > 0 |
0 | 4950 && alloc->maybe_set_complete(&_gvn)) { |
4951 // "You break it, you buy it." | |
4952 InitializeNode* init = alloc->initialization(); | |
4953 assert(init->is_complete(), "we just did this"); | |
3961
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3742
diff
changeset
|
4954 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
|
4955 assert(dest->is_CheckCastPP(), "sanity"); |
0 | 4956 assert(dest->in(0)->in(0) == init, "dest pinned"); |
4957 adr_type = TypeRawPtr::BOTTOM; // all initializations are into raw memory | |
4958 // From this point on, every exit path is responsible for | |
4959 // initializing any non-copied parts of the object to zero. | |
2324 | 4960 // Also, if this flag is set we make sure that arraycopy interacts properly |
4961 // with G1, eliding pre-barriers. See CR 6627983. | |
4962 dest_uninitialized = true; | |
0 | 4963 } else { |
4964 // No zeroing elimination here. | |
4965 alloc = NULL; | |
4966 //original_dest = dest; | |
2324 | 4967 //dest_uninitialized = false; |
0 | 4968 } |
4969 | |
4970 // Results are placed here: | |
4971 enum { fast_path = 1, // normal void-returning assembly stub | |
4972 checked_path = 2, // special assembly stub with cleanup | |
4973 slow_call_path = 3, // something went wrong; call the VM | |
4974 zero_path = 4, // bypass when length of copy is zero | |
4975 bcopy_path = 5, // copy primitive array by 64-bit blocks | |
4976 PATH_LIMIT = 6 | |
4977 }; | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
4978 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
|
4979 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
|
4980 PhiNode* result_memory = new(C) PhiNode(result_region, Type::MEMORY, adr_type); |
0 | 4981 record_for_igvn(result_region); |
4982 _gvn.set_type_bottom(result_i_o); | |
4983 _gvn.set_type_bottom(result_memory); | |
4984 assert(adr_type != TypePtr::BOTTOM, "must be RawMem or a T[] slice"); | |
4985 | |
4986 // The slow_control path: | |
4987 Node* slow_control; | |
4988 Node* slow_i_o = i_o(); | |
4989 Node* slow_mem = memory(adr_type); | |
4990 debug_only(slow_control = (Node*) badAddress); | |
4991 | |
4992 // Checked control path: | |
4993 Node* checked_control = top(); | |
4994 Node* checked_mem = NULL; | |
4995 Node* checked_i_o = NULL; | |
4996 Node* checked_value = NULL; | |
4997 | |
4998 if (basic_elem_type == T_CONFLICT) { | |
2324 | 4999 assert(!dest_uninitialized, ""); |
0 | 5000 Node* cv = generate_generic_arraycopy(adr_type, |
5001 src, src_offset, dest, dest_offset, | |
2324 | 5002 copy_length, dest_uninitialized); |
0 | 5003 if (cv == NULL) cv = intcon(-1); // failure (no stub available) |
5004 checked_control = control(); | |
5005 checked_i_o = i_o(); | |
5006 checked_mem = memory(adr_type); | |
5007 checked_value = cv; | |
5008 set_control(top()); // no fast path | |
5009 } | |
5010 | |
5011 Node* not_pos = generate_nonpositive_guard(copy_length, length_never_negative); | |
5012 if (not_pos != NULL) { | |
5013 PreserveJVMState pjvms(this); | |
5014 set_control(not_pos); | |
5015 | |
5016 // (6) length must not be negative. | |
5017 if (!length_never_negative) { | |
5018 generate_negative_guard(copy_length, slow_region); | |
5019 } | |
5020 | |
836
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
5021 // copy_length is 0. |
2324 | 5022 if (!stopped() && dest_uninitialized) { |
0 | 5023 Node* dest_length = alloc->in(AllocateNode::ALength); |
4778 | 5024 if (copy_length->eqv_uncast(dest_length) |
0 | 5025 || _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
|
5026 // There is no zeroing to do. No need for a secondary raw memory barrier. |
0 | 5027 } else { |
5028 // Clear the whole thing since there are no source elements to copy. | |
5029 generate_clear_array(adr_type, dest, basic_elem_type, | |
5030 intcon(0), NULL, | |
5031 alloc->in(AllocateNode::AllocSize)); | |
836
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
5032 // 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
|
5033 // 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
|
5034 // 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
|
5035 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
|
5036 Compile::AliasIdxRaw, |
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
5037 top())->as_Initialize(); |
4325cdaa78ad
6857661: 64-bit server VM: assert(is_Initialize(),"invalid node class")
kvn
parents:
833
diff
changeset
|
5038 init->set_complete(&_gvn); // (there is no corresponding AllocateNode) |
0 | 5039 } |
5040 } | |
5041 | |
5042 // Present the results of the fast call. | |
5043 result_region->init_req(zero_path, control()); | |
5044 result_i_o ->init_req(zero_path, i_o()); | |
5045 result_memory->init_req(zero_path, memory(adr_type)); | |
5046 } | |
5047 | |
2324 | 5048 if (!stopped() && dest_uninitialized) { |
0 | 5049 // We have to initialize the *uncopied* part of the array to zero. |
5050 // The copy destination is the slice dest[off..off+len]. The other slices | |
5051 // are dest_head = dest[0..off] and dest_tail = dest[off+len..dest.length]. | |
5052 Node* dest_size = alloc->in(AllocateNode::AllocSize); | |
5053 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
|
5054 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
|
5055 copy_length)); |
0 | 5056 |
5057 // If there is a head section that needs zeroing, do it now. | |
5058 if (find_int_con(dest_offset, -1) != 0) { | |
5059 generate_clear_array(adr_type, dest, basic_elem_type, | |
5060 intcon(0), dest_offset, | |
5061 NULL); | |
5062 } | |
5063 | |
5064 // Next, perform a dynamic check on the tail length. | |
5065 // It is often zero, and we can win big if we prove this. | |
5066 // There are two wins: Avoid generating the ClearArray | |
5067 // with its attendant messy index arithmetic, and upgrade | |
5068 // the copy to a more hardware-friendly word size of 64 bits. | |
5069 Node* tail_ctl = NULL; | |
4778 | 5070 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
|
5071 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
|
5072 Node* bol_lt = _gvn.transform(new(C) BoolNode(cmp_lt, BoolTest::lt)); |
0 | 5073 tail_ctl = generate_slow_guard(bol_lt, NULL); |
5074 assert(tail_ctl != NULL || !stopped(), "must be an outcome"); | |
5075 } | |
5076 | |
5077 // At this point, let's assume there is no tail. | |
5078 if (!stopped() && alloc != NULL && basic_elem_type != T_OBJECT) { | |
5079 // There is no tail. Try an upgrade to a 64-bit copy. | |
5080 bool didit = false; | |
5081 { PreserveJVMState pjvms(this); | |
5082 didit = generate_block_arraycopy(adr_type, basic_elem_type, alloc, | |
5083 src, src_offset, dest, dest_offset, | |
2324 | 5084 dest_size, dest_uninitialized); |
0 | 5085 if (didit) { |
5086 // Present the results of the block-copying fast call. | |
5087 result_region->init_req(bcopy_path, control()); | |
5088 result_i_o ->init_req(bcopy_path, i_o()); | |
5089 result_memory->init_req(bcopy_path, memory(adr_type)); | |
5090 } | |
5091 } | |
5092 if (didit) | |
5093 set_control(top()); // no regular fast path | |
5094 } | |
5095 | |
5096 // Clear the tail, if any. | |
5097 if (tail_ctl != NULL) { | |
5098 Node* notail_ctl = stopped() ? NULL : control(); | |
5099 set_control(tail_ctl); | |
5100 if (notail_ctl == NULL) { | |
5101 generate_clear_array(adr_type, dest, basic_elem_type, | |
5102 dest_tail, NULL, | |
5103 dest_size); | |
5104 } else { | |
5105 // Make a local merge. | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
5106 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
|
5107 Node* done_mem = new(C) PhiNode(done_ctl, Type::MEMORY, adr_type); |
0 | 5108 done_ctl->init_req(1, notail_ctl); |
5109 done_mem->init_req(1, memory(adr_type)); | |
5110 generate_clear_array(adr_type, dest, basic_elem_type, | |
5111 dest_tail, NULL, | |
5112 dest_size); | |
5113 done_ctl->init_req(2, control()); | |
5114 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
|
5115 set_control( _gvn.transform(done_ctl)); |
0 | 5116 set_memory( _gvn.transform(done_mem), adr_type ); |
5117 } | |
5118 } | |
5119 } | |
5120 | |
5121 BasicType copy_type = basic_elem_type; | |
5122 assert(basic_elem_type != T_ARRAY, "caller must fix this"); | |
5123 if (!stopped() && copy_type == T_OBJECT) { | |
5124 // If src and dest have compatible element types, we can copy bits. | |
5125 // Types S[] and D[] are compatible if D is a supertype of S. | |
5126 // | |
5127 // If they are not, we will use checked_oop_disjoint_arraycopy, | |
5128 // which performs a fast optimistic per-oop check, and backs off | |
5129 // further to JVM_ArrayCopy on the first per-oop check that fails. | |
5130 // (Actually, we don't move raw bits only; the GC requires card marks.) | |
5131 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6615
diff
changeset
|
5132 // Get the Klass* for both src and dest |
0 | 5133 Node* src_klass = load_object_klass(src); |
5134 Node* dest_klass = load_object_klass(dest); | |
5135 | |
5136 // Generate the subtype check. | |
5137 // This might fold up statically, or then again it might not. | |
5138 // | |
5139 // Non-static example: Copying List<String>.elements to a new String[]. | |
5140 // The backing store for a List<String> is always an Object[], | |
5141 // but its elements are always type String, if the generic types | |
5142 // are correct at the source level. | |
5143 // | |
5144 // Test S[] against D[], not S against D, because (probably) | |
5145 // the secondary supertype cache is less busy for S[] than S. | |
5146 // This usually only matters when D is an interface. | |
5147 Node* not_subtype_ctrl = gen_subtype_check(src_klass, dest_klass); | |
5148 // Plug failing path into checked_oop_disjoint_arraycopy | |
5149 if (not_subtype_ctrl != top()) { | |
5150 PreserveJVMState pjvms(this); | |
5151 set_control(not_subtype_ctrl); | |
5152 // (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
|
5153 int ek_offset = in_bytes(ObjArrayKlass::element_klass_offset()); |
0 | 5154 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
|
5155 Node* n1 = LoadKlassNode::make(_gvn, immutable_memory(), p1, TypeRawPtr::BOTTOM); |
0 | 5156 Node* dest_elem_klass = _gvn.transform(n1); |
5157 Node* cv = generate_checkcast_arraycopy(adr_type, | |
5158 dest_elem_klass, | |
5159 src, src_offset, dest, dest_offset, | |
2324 | 5160 ConvI2X(copy_length), dest_uninitialized); |
0 | 5161 if (cv == NULL) cv = intcon(-1); // failure (no stub available) |
5162 checked_control = control(); | |
5163 checked_i_o = i_o(); | |
5164 checked_mem = memory(adr_type); | |
5165 checked_value = cv; | |
5166 } | |
5167 // At this point we know we do not need type checks on oop stores. | |
5168 | |
5169 // Let's see if we need card marks: | |
5170 if (alloc != NULL && use_ReduceInitialCardMarks()) { | |
5171 // 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
|
5172 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
|
5173 assert(type2aelembytes(basic_elem_type) == type2aelembytes(copy_type), |
0 | 5174 "sizes agree"); |
5175 } | |
5176 } | |
5177 | |
5178 if (!stopped()) { | |
5179 // Generate the fast path, if possible. | |
5180 PreserveJVMState pjvms(this); | |
5181 generate_unchecked_arraycopy(adr_type, copy_type, disjoint_bases, | |
5182 src, src_offset, dest, dest_offset, | |
2324 | 5183 ConvI2X(copy_length), dest_uninitialized); |
0 | 5184 |
5185 // Present the results of the fast call. | |
5186 result_region->init_req(fast_path, control()); | |
5187 result_i_o ->init_req(fast_path, i_o()); | |
5188 result_memory->init_req(fast_path, memory(adr_type)); | |
5189 } | |
5190 | |
5191 // Here are all the slow paths up to this point, in one bundle: | |
5192 slow_control = top(); | |
5193 if (slow_region != NULL) | |
5194 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
|
5195 DEBUG_ONLY(slow_region = (RegionNode*)badAddress); |
0 | 5196 |
5197 set_control(checked_control); | |
5198 if (!stopped()) { | |
5199 // Clean up after the checked call. | |
5200 // The returned value is either 0 or -1^K, | |
5201 // 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
|
5202 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
|
5203 Node* bol = _gvn.transform(new(C) BoolNode(cmp, BoolTest::eq)); |
0 | 5204 IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN); |
5205 | |
5206 // 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
|
5207 Node* checks_done = _gvn.transform(new(C) IfTrueNode(iff)); |
0 | 5208 result_region->init_req(checked_path, checks_done); |
5209 result_i_o ->init_req(checked_path, checked_i_o); | |
5210 result_memory->init_req(checked_path, checked_mem); | |
5211 | |
5212 // 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
|
5213 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
|
5214 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
|
5215 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
|
5216 PhiNode* slow_mem2 = new(C) PhiNode(slow_reg2, Type::MEMORY, adr_type); |
0 | 5217 record_for_igvn(slow_reg2); |
5218 slow_reg2 ->init_req(1, slow_control); | |
5219 slow_i_o2 ->init_req(1, slow_i_o); | |
5220 slow_mem2 ->init_req(1, slow_mem); | |
5221 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
|
5222 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
|
5223 slow_mem2 ->init_req(2, checked_mem); |
0 | 5224 |
5225 slow_control = _gvn.transform(slow_reg2); | |
5226 slow_i_o = _gvn.transform(slow_i_o2); | |
5227 slow_mem = _gvn.transform(slow_mem2); | |
5228 | |
5229 if (alloc != NULL) { | |
5230 // We'll restart from the very beginning, after zeroing the whole thing. | |
5231 // This can cause double writes, but that's OK since dest is brand new. | |
5232 // So we ignore the low 31 bits of the value returned from the stub. | |
5233 } else { | |
5234 // We must continue the copy exactly where it failed, or else | |
5235 // 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
|
5236 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
|
5237 Node* slow_offset = new(C) PhiNode(slow_reg2, TypeInt::INT); |
0 | 5238 slow_offset->init_req(1, intcon(0)); |
5239 slow_offset->init_req(2, checked_offset); | |
5240 slow_offset = _gvn.transform(slow_offset); | |
5241 | |
5242 // 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
|
5243 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
|
5244 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
|
5245 Node* length_minus = _gvn.transform(new(C) SubINode(copy_length, slow_offset)); |
0 | 5246 |
5247 // Tweak the node variables to adjust the code produced below: | |
5248 src_offset = src_off_plus; | |
5249 dest_offset = dest_off_plus; | |
5250 copy_length = length_minus; | |
5251 } | |
5252 } | |
5253 | |
5254 set_control(slow_control); | |
5255 if (!stopped()) { | |
5256 // Generate the slow path, if needed. | |
5257 PreserveJVMState pjvms(this); // replace_in_map may trash the map | |
5258 | |
5259 set_memory(slow_mem, adr_type); | |
5260 set_i_o(slow_i_o); | |
5261 | |
2324 | 5262 if (dest_uninitialized) { |
0 | 5263 generate_clear_array(adr_type, dest, basic_elem_type, |
5264 intcon(0), NULL, | |
5265 alloc->in(AllocateNode::AllocSize)); | |
5266 } | |
5267 | |
5268 generate_slow_arraycopy(adr_type, | |
5269 src, src_offset, dest, dest_offset, | |
2324 | 5270 copy_length, /*dest_uninitialized*/false); |
0 | 5271 |
5272 result_region->init_req(slow_call_path, control()); | |
5273 result_i_o ->init_req(slow_call_path, i_o()); | |
5274 result_memory->init_req(slow_call_path, memory(adr_type)); | |
5275 } | |
5276 | |
5277 // Remove unused edges. | |
5278 for (uint i = 1; i < result_region->req(); i++) { | |
5279 if (result_region->in(i) == NULL) | |
5280 result_region->init_req(i, top()); | |
5281 } | |
5282 | |
5283 // Finished; return the combined state. | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5284 set_control( _gvn.transform(result_region)); |
0 | 5285 set_i_o( _gvn.transform(result_i_o) ); |
5286 set_memory( _gvn.transform(result_memory), adr_type ); | |
5287 | |
5288 // The memory edges above are precise in order to model effects around | |
605 | 5289 // array copies accurately to allow value numbering of field loads around |
0 | 5290 // arraycopy. Such field loads, both before and after, are common in Java |
5291 // collections and similar classes involving header/array data structures. | |
5292 // | |
5293 // But with low number of register or when some registers are used or killed | |
5294 // by arraycopy calls it causes registers spilling on stack. See 6544710. | |
5295 // The next memory barrier is added to avoid it. If the arraycopy can be | |
5296 // optimized away (which it can, sometimes) then we can manually remove | |
5297 // the membar also. | |
958
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
5298 // |
c7e94e8fff43
6880053: assert(alloc_obj->as_CheckCastPP()->type() != TypeInstPtr::NOTNULL)
kvn
parents:
950
diff
changeset
|
5299 // 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
|
5300 if (alloc != NULL) { |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
5301 // 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
|
5302 // 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
|
5303 // other threads. |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
5304 // 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
|
5305 // 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
|
5306 // AllocateNode and eliminate the MemBarStoreStoreNode if possible |
1dc233a8c7fe
7121140: Allocation paths require explicit memory synchronization operations for RMO systems
roland
parents:
4762
diff
changeset
|
5307 // 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
|
5308 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
|
5309 } else if (InsertMemBarAfterArraycopy) |
0 | 5310 insert_mem_bar(Op_MemBarCPUOrder); |
5311 } | |
5312 | |
5313 | |
5314 // Helper function which determines if an arraycopy immediately follows | |
5315 // an allocation, with no intervening tests or other escapes for the object. | |
5316 AllocateArrayNode* | |
5317 LibraryCallKit::tightly_coupled_allocation(Node* ptr, | |
5318 RegionNode* slow_region) { | |
5319 if (stopped()) return NULL; // no fast path | |
5320 if (C->AliasLevel() == 0) return NULL; // no MergeMems around | |
5321 | |
5322 AllocateArrayNode* alloc = AllocateArrayNode::Ideal_array_allocation(ptr, &_gvn); | |
5323 if (alloc == NULL) return NULL; | |
5324 | |
5325 Node* rawmem = memory(Compile::AliasIdxRaw); | |
5326 // Is the allocation's memory state untouched? | |
5327 if (!(rawmem->is_Proj() && rawmem->in(0)->is_Initialize())) { | |
5328 // Bail out if there have been raw-memory effects since the allocation. | |
5329 // (Example: There might have been a call or safepoint.) | |
5330 return NULL; | |
5331 } | |
5332 rawmem = rawmem->in(0)->as_Initialize()->memory(Compile::AliasIdxRaw); | |
5333 if (!(rawmem->is_Proj() && rawmem->in(0) == alloc)) { | |
5334 return NULL; | |
5335 } | |
5336 | |
5337 // There must be no unexpected observers of this allocation. | |
5338 for (DUIterator_Fast imax, i = ptr->fast_outs(imax); i < imax; i++) { | |
5339 Node* obs = ptr->fast_out(i); | |
5340 if (obs != this->map()) { | |
5341 return NULL; | |
5342 } | |
5343 } | |
5344 | |
5345 // This arraycopy must unconditionally follow the allocation of the ptr. | |
5346 Node* alloc_ctl = ptr->in(0); | |
5347 assert(just_allocated_object(alloc_ctl) == ptr, "most recent allo"); | |
5348 | |
5349 Node* ctl = control(); | |
5350 while (ctl != alloc_ctl) { | |
5351 // There may be guards which feed into the slow_region. | |
5352 // Any other control flow means that we might not get a chance | |
5353 // to finish initializing the allocated object. | |
5354 if ((ctl->is_IfFalse() || ctl->is_IfTrue()) && ctl->in(0)->is_If()) { | |
5355 IfNode* iff = ctl->in(0)->as_If(); | |
5356 Node* not_ctl = iff->proj_out(1 - ctl->as_Proj()->_con); | |
5357 assert(not_ctl != NULL && not_ctl != ctl, "found alternate"); | |
5358 if (slow_region != NULL && slow_region->find_edge(not_ctl) >= 1) { | |
5359 ctl = iff->in(0); // This test feeds the known slow_region. | |
5360 continue; | |
5361 } | |
5362 // One more try: Various low-level checks bottom out in | |
5363 // uncommon traps. If the debug-info of the trap omits | |
5364 // any reference to the allocation, as we've already | |
5365 // observed, then there can be no objection to the trap. | |
5366 bool found_trap = false; | |
5367 for (DUIterator_Fast jmax, j = not_ctl->fast_outs(jmax); j < jmax; j++) { | |
5368 Node* obs = not_ctl->fast_out(j); | |
5369 if (obs->in(0) == not_ctl && obs->is_Call() && | |
1748 | 5370 (obs->as_Call()->entry_point() == SharedRuntime::uncommon_trap_blob()->entry_point())) { |
0 | 5371 found_trap = true; break; |
5372 } | |
5373 } | |
5374 if (found_trap) { | |
5375 ctl = iff->in(0); // This test feeds a harmless uncommon trap. | |
5376 continue; | |
5377 } | |
5378 } | |
5379 return NULL; | |
5380 } | |
5381 | |
5382 // If we get this far, we have an allocation which immediately | |
5383 // precedes the arraycopy, and we can take over zeroing the new object. | |
5384 // The arraycopy will finish the initialization, and provide | |
5385 // a new control state to which we will anchor the destination pointer. | |
5386 | |
5387 return alloc; | |
5388 } | |
5389 | |
5390 // Helper for initialization of arrays, creating a ClearArray. | |
5391 // It writes zero bits in [start..end), within the body of an array object. | |
5392 // The memory effects are all chained onto the 'adr_type' alias category. | |
5393 // | |
5394 // Since the object is otherwise uninitialized, we are free | |
5395 // to put a little "slop" around the edges of the cleared area, | |
5396 // as long as it does not go back into the array's header, | |
5397 // or beyond the array end within the heap. | |
5398 // | |
5399 // The lower edge can be rounded down to the nearest jint and the | |
5400 // upper edge can be rounded up to the nearest MinObjAlignmentInBytes. | |
5401 // | |
5402 // Arguments: | |
5403 // adr_type memory slice where writes are generated | |
5404 // dest oop of the destination array | |
5405 // basic_elem_type element type of the destination | |
5406 // slice_idx array index of first element to store | |
5407 // slice_len number of elements to store (or NULL) | |
5408 // dest_size total size in bytes of the array object | |
5409 // | |
5410 // Exactly one of slice_len or dest_size must be non-NULL. | |
5411 // If dest_size is non-NULL, zeroing extends to the end of the object. | |
5412 // If slice_len is non-NULL, the slice_idx value must be a constant. | |
5413 void | |
5414 LibraryCallKit::generate_clear_array(const TypePtr* adr_type, | |
5415 Node* dest, | |
5416 BasicType basic_elem_type, | |
5417 Node* slice_idx, | |
5418 Node* slice_len, | |
5419 Node* dest_size) { | |
5420 // one or the other but not both of slice_len and dest_size: | |
5421 assert((slice_len != NULL? 1: 0) + (dest_size != NULL? 1: 0) == 1, ""); | |
5422 if (slice_len == NULL) slice_len = top(); | |
5423 if (dest_size == NULL) dest_size = top(); | |
5424 | |
5425 // operate on this memory slice: | |
5426 Node* mem = memory(adr_type); // memory slice to operate on | |
5427 | |
5428 // scaling and rounding of indexes: | |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
0
diff
changeset
|
5429 int scale = exact_log2(type2aelembytes(basic_elem_type)); |
0 | 5430 int abase = arrayOopDesc::base_offset_in_bytes(basic_elem_type); |
5431 int clear_low = (-1 << scale) & (BytesPerInt - 1); | |
5432 int bump_bit = (-1 << scale) & BytesPerInt; | |
5433 | |
5434 // determine constant starts and ends | |
5435 const intptr_t BIG_NEG = -128; | |
5436 assert(BIG_NEG + 2*abase < 0, "neg enough"); | |
5437 intptr_t slice_idx_con = (intptr_t) find_int_con(slice_idx, BIG_NEG); | |
5438 intptr_t slice_len_con = (intptr_t) find_int_con(slice_len, BIG_NEG); | |
5439 if (slice_len_con == 0) { | |
5440 return; // nothing to do here | |
5441 } | |
5442 intptr_t start_con = (abase + (slice_idx_con << scale)) & ~clear_low; | |
5443 intptr_t end_con = find_intptr_t_con(dest_size, -1); | |
5444 if (slice_idx_con >= 0 && slice_len_con >= 0) { | |
5445 assert(end_con < 0, "not two cons"); | |
5446 end_con = round_to(abase + ((slice_idx_con + slice_len_con) << scale), | |
5447 BytesPerLong); | |
5448 } | |
5449 | |
5450 if (start_con >= 0 && end_con >= 0) { | |
5451 // Constant start and end. Simple. | |
5452 mem = ClearArrayNode::clear_memory(control(), mem, dest, | |
5453 start_con, end_con, &_gvn); | |
5454 } else if (start_con >= 0 && dest_size != top()) { | |
5455 // Constant start, pre-rounded end after the tail of the array. | |
5456 Node* end = dest_size; | |
5457 mem = ClearArrayNode::clear_memory(control(), mem, dest, | |
5458 start_con, end, &_gvn); | |
5459 } else if (start_con >= 0 && slice_len != top()) { | |
5460 // Constant start, non-constant end. End needs rounding up. | |
5461 // End offset = round_up(abase + ((slice_idx_con + slice_len) << scale), 8) | |
5462 intptr_t end_base = abase + (slice_idx_con << scale); | |
5463 int end_round = (-1 << scale) & (BytesPerLong - 1); | |
5464 Node* end = ConvI2X(slice_len); | |
5465 if (scale != 0) | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5466 end = _gvn.transform(new(C) LShiftXNode(end, intcon(scale) )); |
0 | 5467 end_base += end_round; |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5468 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
|
5469 end = _gvn.transform(new(C) AndXNode(end, MakeConX(~end_round))); |
0 | 5470 mem = ClearArrayNode::clear_memory(control(), mem, dest, |
5471 start_con, end, &_gvn); | |
5472 } else if (start_con < 0 && dest_size != top()) { | |
5473 // Non-constant start, pre-rounded end after the tail of the array. | |
5474 // This is almost certainly a "round-to-end" operation. | |
5475 Node* start = slice_idx; | |
5476 start = ConvI2X(start); | |
5477 if (scale != 0) | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5478 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
|
5479 start = _gvn.transform(new(C) AddXNode(start, MakeConX(abase))); |
0 | 5480 if ((bump_bit | clear_low) != 0) { |
5481 int to_clear = (bump_bit | clear_low); | |
5482 // Align up mod 8, then store a jint zero unconditionally | |
5483 // 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
|
5484 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
|
5485 < 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
|
5486 bump_bit = 0; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5487 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
|
5488 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5489 // 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
|
5490 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
|
5491 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
|
5492 } |
0 | 5493 // 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
|
5494 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
|
5495 if (bump_bit != 0) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5496 // 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
|
5497 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
|
5498 Node* p1 = basic_plus_adr(dest, x1); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
5499 mem = StoreNode::make(_gvn, control(), mem, p1, adr_type, intcon(0), T_INT, MemNode::unordered); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5500 mem = _gvn.transform(mem); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
34
diff
changeset
|
5501 } |
0 | 5502 } |
5503 Node* end = dest_size; // pre-rounded | |
5504 mem = ClearArrayNode::clear_memory(control(), mem, dest, | |
5505 start, end, &_gvn); | |
5506 } else { | |
5507 // Non-constant start, unrounded non-constant end. | |
5508 // (Nobody zeroes a random midsection of an array using this routine.) | |
5509 ShouldNotReachHere(); // fix caller | |
5510 } | |
5511 | |
5512 // Done. | |
5513 set_memory(mem, adr_type); | |
5514 } | |
5515 | |
5516 | |
5517 bool | |
5518 LibraryCallKit::generate_block_arraycopy(const TypePtr* adr_type, | |
5519 BasicType basic_elem_type, | |
5520 AllocateNode* alloc, | |
5521 Node* src, Node* src_offset, | |
5522 Node* dest, Node* dest_offset, | |
2324 | 5523 Node* dest_size, bool dest_uninitialized) { |
0 | 5524 // 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
|
5525 int scale = exact_log2(type2aelembytes(basic_elem_type)); |
0 | 5526 if (scale >= LogBytesPerLong) |
5527 return false; // it is already a block transfer | |
5528 | |
5529 // Look at the alignment of the starting offsets. | |
5530 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
|
5531 |
b2cb497dec28
7047069: Array can dynamically change size when assigned to an object field
kvn
parents:
3337
diff
changeset
|
5532 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
|
5533 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
|
5534 if (src_off_con < 0 || dest_off_con < 0) |
0 | 5535 // At present, we can only understand constants. |
5536 return false; | |
5537 | |
3742
b2cb497dec28
7047069: Array can dynamically change size when assigned to an object field
kvn
parents:
3337
diff
changeset
|
5538 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
|
5539 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
|
5540 |
0 | 5541 if (((src_off | dest_off) & (BytesPerLong-1)) != 0) { |
5542 // Non-aligned; too bad. | |
5543 // One more chance: Pick off an initial 32-bit word. | |
5544 // This is a common case, since abase can be odd mod 8. | |
5545 if (((src_off | dest_off) & (BytesPerLong-1)) == BytesPerInt && | |
5546 ((src_off ^ dest_off) & (BytesPerLong-1)) == 0) { | |
5547 Node* sptr = basic_plus_adr(src, src_off); | |
5548 Node* dptr = basic_plus_adr(dest, dest_off); | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
5549 Node* sval = make_load(control(), sptr, TypeInt::INT, T_INT, adr_type, MemNode::unordered); |
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
5550 store_to_memory(control(), dptr, sval, T_INT, adr_type, MemNode::unordered); |
0 | 5551 src_off += BytesPerInt; |
5552 dest_off += BytesPerInt; | |
5553 } else { | |
5554 return false; | |
5555 } | |
5556 } | |
5557 assert(src_off % BytesPerLong == 0, ""); | |
5558 assert(dest_off % BytesPerLong == 0, ""); | |
5559 | |
5560 // Do this copy by giant steps. | |
5561 Node* sptr = basic_plus_adr(src, src_off); | |
5562 Node* dptr = basic_plus_adr(dest, dest_off); | |
5563 Node* countx = dest_size; | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5564 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
|
5565 countx = _gvn.transform(new (C) URShiftXNode(countx, intcon(LogBytesPerLong))); |
0 | 5566 |
5567 bool disjoint_bases = true; // since alloc != NULL | |
5568 generate_unchecked_arraycopy(adr_type, T_LONG, disjoint_bases, | |
2324 | 5569 sptr, NULL, dptr, NULL, countx, dest_uninitialized); |
0 | 5570 |
5571 return true; | |
5572 } | |
5573 | |
5574 | |
5575 // Helper function; generates code for the slow case. | |
5576 // We make a call to a runtime method which emulates the native method, | |
5577 // but without the native wrapper overhead. | |
5578 void | |
5579 LibraryCallKit::generate_slow_arraycopy(const TypePtr* adr_type, | |
5580 Node* src, Node* src_offset, | |
5581 Node* dest, Node* dest_offset, | |
2324 | 5582 Node* copy_length, bool dest_uninitialized) { |
5583 assert(!dest_uninitialized, "Invariant"); | |
0 | 5584 Node* call = make_runtime_call(RC_NO_LEAF | RC_UNCOMMON, |
5585 OptoRuntime::slow_arraycopy_Type(), | |
5586 OptoRuntime::slow_arraycopy_Java(), | |
5587 "slow_arraycopy", adr_type, | |
5588 src, src_offset, dest, dest_offset, | |
5589 copy_length); | |
5590 | |
5591 // Handle exceptions thrown by this fellow: | |
5592 make_slow_call_ex(call, env()->Throwable_klass(), false); | |
5593 } | |
5594 | |
5595 // Helper function; generates code for cases requiring runtime checks. | |
5596 Node* | |
5597 LibraryCallKit::generate_checkcast_arraycopy(const TypePtr* adr_type, | |
5598 Node* dest_elem_klass, | |
5599 Node* src, Node* src_offset, | |
5600 Node* dest, Node* dest_offset, | |
2324 | 5601 Node* copy_length, bool dest_uninitialized) { |
0 | 5602 if (stopped()) return NULL; |
5603 | |
2324 | 5604 address copyfunc_addr = StubRoutines::checkcast_arraycopy(dest_uninitialized); |
0 | 5605 if (copyfunc_addr == NULL) { // Stub was not generated, go slow path. |
5606 return NULL; | |
5607 } | |
5608 | |
5609 // Pick out the parameters required to perform a store-check | |
5610 // for the target array. This is an optimistic check. It will | |
5611 // look in each non-null element's class, at the desired klass's | |
5612 // 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
|
5613 int sco_offset = in_bytes(Klass::super_check_offset_offset()); |
0 | 5614 Node* p3 = basic_plus_adr(dest_elem_klass, sco_offset); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
5615 Node* n3 = new(C) LoadINode(NULL, memory(p3), p3, _gvn.type(p3)->is_ptr(), TypeInt::INT, MemNode::unordered); |
1844
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1748
diff
changeset
|
5616 Node* check_offset = ConvI2X(_gvn.transform(n3)); |
0 | 5617 Node* check_value = dest_elem_klass; |
5618 | |
5619 Node* src_start = array_element_address(src, src_offset, T_OBJECT); | |
5620 Node* dest_start = array_element_address(dest, dest_offset, T_OBJECT); | |
5621 | |
5622 // (We know the arrays are never conjoint, because their types differ.) | |
5623 Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, | |
5624 OptoRuntime::checkcast_arraycopy_Type(), | |
5625 copyfunc_addr, "checkcast_arraycopy", adr_type, | |
5626 // five arguments, of which two are | |
5627 // intptr_t (jlong in LP64) | |
5628 src_start, dest_start, | |
5629 copy_length XTOP, | |
5630 check_offset XTOP, | |
5631 check_value); | |
5632 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
5633 return _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms)); |
0 | 5634 } |
5635 | |
5636 | |
5637 // Helper function; generates code for cases requiring runtime checks. | |
5638 Node* | |
5639 LibraryCallKit::generate_generic_arraycopy(const TypePtr* adr_type, | |
5640 Node* src, Node* src_offset, | |
5641 Node* dest, Node* dest_offset, | |
2324 | 5642 Node* copy_length, bool dest_uninitialized) { |
5643 assert(!dest_uninitialized, "Invariant"); | |
0 | 5644 if (stopped()) return NULL; |
5645 address copyfunc_addr = StubRoutines::generic_arraycopy(); | |
5646 if (copyfunc_addr == NULL) { // Stub was not generated, go slow path. | |
5647 return NULL; | |
5648 } | |
5649 | |
5650 Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, | |
5651 OptoRuntime::generic_arraycopy_Type(), | |
5652 copyfunc_addr, "generic_arraycopy", adr_type, | |
5653 src, src_offset, dest, dest_offset, copy_length); | |
5654 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6795
diff
changeset
|
5655 return _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms)); |
0 | 5656 } |
5657 | |
5658 // Helper function; generates the fast out-of-line call to an arraycopy stub. | |
5659 void | |
5660 LibraryCallKit::generate_unchecked_arraycopy(const TypePtr* adr_type, | |
5661 BasicType basic_elem_type, | |
5662 bool disjoint_bases, | |
5663 Node* src, Node* src_offset, | |
5664 Node* dest, Node* dest_offset, | |
2324 | 5665 Node* copy_length, bool dest_uninitialized) { |
0 | 5666 if (stopped()) return; // nothing to do |
5667 | |
5668 Node* src_start = src; | |
5669 Node* dest_start = dest; | |
5670 if (src_offset != NULL || dest_offset != NULL) { | |
5671 assert(src_offset != NULL && dest_offset != NULL, ""); | |
5672 src_start = array_element_address(src, src_offset, basic_elem_type); | |
5673 dest_start = array_element_address(dest, dest_offset, basic_elem_type); | |
5674 } | |
5675 | |
5676 // Figure out which arraycopy runtime method to call. | |
5677 const char* copyfunc_name = "arraycopy"; | |
5678 address copyfunc_addr = | |
5679 basictype2arraycopy(basic_elem_type, src_offset, dest_offset, | |
2324 | 5680 disjoint_bases, copyfunc_name, dest_uninitialized); |
0 | 5681 |
5682 // Call it. Note that the count_ix value is not scaled to a byte-size. | |
5683 make_runtime_call(RC_LEAF|RC_NO_FP, | |
5684 OptoRuntime::fast_arraycopy_Type(), | |
5685 copyfunc_addr, copyfunc_name, adr_type, | |
5686 src_start, dest_start, copy_length XTOP); | |
5687 } | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5688 |
7637
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5689 //-------------inline_encodeISOArray----------------------------------- |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5690 // 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
|
5691 bool LibraryCallKit::inline_encodeISOArray() { |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5692 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
|
5693 // 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
|
5694 Node *src = argument(0); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5695 Node *src_offset = argument(1); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5696 Node *dst = argument(2); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5697 Node *dst_offset = argument(3); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5698 Node *length = argument(4); |
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 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
|
5701 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
|
5702 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
|
5703 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
|
5704 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
|
5705 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
|
5706 // failed array check |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5707 return false; |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5708 } |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5709 |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5710 // 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
|
5711 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
|
5712 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
|
5713 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
|
5714 return false; |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5715 } |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5716 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
|
5717 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
|
5718 // '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
|
5719 // '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
|
5720 |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5721 const TypeAryPtr* mtype = TypeAryPtr::BYTES; |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5722 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
|
5723 enc = _gvn.transform(enc); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5724 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
|
5725 set_memory(res_mem, mtype); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5726 set_result(enc); |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5727 return true; |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5728 } |
b30b3c2a0cf2
6896617: Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() on x86
kvn
parents:
7602
diff
changeset
|
5729 |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5730 /** |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5731 * Calculate CRC32 for byte. |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5732 * 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
|
5733 */ |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5734 bool LibraryCallKit::inline_updateCRC32() { |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5735 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
|
5736 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
|
5737 // no receiver since it is static method |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5738 Node* crc = argument(0); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5739 Node* b = argument(1); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5740 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5741 /* |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5742 * int c = ~ crc; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5743 * b = timesXtoThe32[(b ^ c) & 0xFF]; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5744 * b = b ^ (c >>> 8); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5745 * crc = ~b; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5746 */ |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5747 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5748 Node* M1 = intcon(-1); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5749 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
|
5750 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
|
5751 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
|
5752 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5753 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
|
5754 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
|
5755 Node* adr = basic_plus_adr(top(), base, ConvI2X(offset)); |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
5756 result = make_load(control(), adr, TypeInt::INT, T_INT, MemNode::unordered); |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5757 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5758 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
|
5759 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
|
5760 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
|
5761 set_result(result); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5762 return true; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5763 } |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5764 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5765 /** |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5766 * Calculate CRC32 for byte[] array. |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5767 * 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
|
5768 */ |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5769 bool LibraryCallKit::inline_updateBytesCRC32() { |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5770 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
|
5771 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
|
5772 // no receiver since it is static method |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5773 Node* crc = argument(0); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5774 Node* src = argument(1); // type: oop |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5775 Node* offset = argument(2); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5776 Node* length = argument(3); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5777 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5778 const Type* src_type = src->Value(&_gvn); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5779 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
|
5780 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
|
5781 // failed array check |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5782 return false; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5783 } |
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 // 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
|
5786 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
|
5787 if (src_elem != T_BYTE) { |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5788 return false; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5789 } |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5790 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5791 // '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
|
5792 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
|
5793 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5794 // 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
|
5795 // 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
|
5796 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5797 // Call the stub. |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5798 address stubAddr = StubRoutines::updateBytesCRC32(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5799 const char *stubName = "updateBytesCRC32"; |
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 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
|
5802 stubAddr, stubName, TypePtr::BOTTOM, |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5803 crc, src_start, length); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5804 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
|
5805 set_result(result); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5806 return true; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5807 } |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5808 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5809 /** |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5810 * Calculate CRC32 for ByteBuffer. |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5811 * 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
|
5812 */ |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5813 bool LibraryCallKit::inline_updateByteBufferCRC32() { |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5814 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
|
5815 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
|
5816 // no receiver since it is static method |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5817 Node* crc = argument(0); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5818 Node* src = argument(1); // type: long |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5819 Node* offset = argument(3); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5820 Node* length = argument(4); // type: int |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5821 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5822 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
|
5823 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
|
5824 offset = ConvI2X(offset); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5825 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5826 // '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
|
5827 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
|
5828 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5829 // Call the stub. |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5830 address stubAddr = StubRoutines::updateBytesCRC32(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5831 const char *stubName = "updateBytesCRC32"; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5832 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5833 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
|
5834 stubAddr, stubName, TypePtr::BOTTOM, |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5835 crc, src_start, length); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5836 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
|
5837 set_result(result); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5838 return true; |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5839 } |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
10405
diff
changeset
|
5840 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5841 //----------------------------inline_reference_get---------------------------- |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5842 // 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
|
5843 bool LibraryCallKit::inline_reference_get() { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5844 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
|
5845 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
|
5846 |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5847 // Get the argument: |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5848 Node* reference_obj = null_check_receiver(); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5849 if (stopped()) return true; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5850 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5851 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
|
5852 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5853 ciInstanceKlass* klass = env()->Object_klass(); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5854 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
|
5855 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5856 Node* no_ctrl = NULL; |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
5857 Node* result = make_load(no_ctrl, adr, object_type, T_OBJECT, MemNode::unordered); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5858 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5859 // 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
|
5860 pre_barrier(false /* do_load */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5861 control(), |
3258
edd9b016deb6
7036021: G1: build failure on win64 and linux with hs21 in jdk6 build environment
johnc
parents:
3255
diff
changeset
|
5862 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
|
5863 result /* pre_val */, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5864 T_OBJECT); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5865 |
6615
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
5866 // 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
|
5867 // 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
|
5868 insert_mem_bar(Op_MemBarCPUOrder); |
09aad8452938
7190310: Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
kvn
parents:
6266
diff
changeset
|
5869 |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5870 set_result(result); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5871 return true; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2385
diff
changeset
|
5872 } |
6894 | 5873 |
5874 | |
5875 Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, | |
5876 bool is_exact=true, bool is_static=false) { | |
5877 | |
5878 const TypeInstPtr* tinst = _gvn.type(fromObj)->isa_instptr(); | |
5879 assert(tinst != NULL, "obj is null"); | |
5880 assert(tinst->klass()->is_loaded(), "obj is not loaded"); | |
5881 assert(!is_exact || tinst->klass_is_exact(), "klass not exact"); | |
5882 | |
5883 ciField* field = tinst->klass()->as_instance_klass()->get_field_by_name(ciSymbol::make(fieldName), | |
5884 ciSymbol::make(fieldTypeString), | |
5885 is_static); | |
5886 if (field == NULL) return (Node *) NULL; | |
5887 assert (field != NULL, "undefined field"); | |
5888 | |
5889 // Next code copied from Parse::do_get_xxx(): | |
5890 | |
5891 // Compute address and memory type. | |
5892 int offset = field->offset_in_bytes(); | |
5893 bool is_vol = field->is_volatile(); | |
5894 ciType* field_klass = field->type(); | |
5895 assert(field_klass->is_loaded(), "should be loaded"); | |
5896 const TypePtr* adr_type = C->alias_type(field)->adr_type(); | |
5897 Node *adr = basic_plus_adr(fromObj, fromObj, offset); | |
5898 BasicType bt = field->layout_type(); | |
5899 | |
5900 // Build the resultant type of the load | |
5901 const Type *type = TypeOopPtr::make_from_klass(field_klass->as_klass()); | |
5902 | |
5903 // Build the load. | |
14429
2113136690bc
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
13019
diff
changeset
|
5904 Node* loadedField = make_load(NULL, adr, type, bt, adr_type, MemNode::unordered, is_vol); |
6894 | 5905 return loadedField; |
5906 } | |
5907 | |
5908 | |
5909 //------------------------------inline_aescrypt_Block----------------------- | |
5910 bool LibraryCallKit::inline_aescrypt_Block(vmIntrinsics::ID id) { | |
5911 address stubAddr; | |
5912 const char *stubName; | |
5913 assert(UseAES, "need AES instruction support"); | |
5914 | |
5915 switch(id) { | |
5916 case vmIntrinsics::_aescrypt_encryptBlock: | |
5917 stubAddr = StubRoutines::aescrypt_encryptBlock(); | |
5918 stubName = "aescrypt_encryptBlock"; | |
5919 break; | |
5920 case vmIntrinsics::_aescrypt_decryptBlock: | |
5921 stubAddr = StubRoutines::aescrypt_decryptBlock(); | |
5922 stubName = "aescrypt_decryptBlock"; | |
5923 break; | |
5924 } | |
5925 if (stubAddr == NULL) return false; | |
5926 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5927 Node* aescrypt_object = argument(0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5928 Node* src = argument(1); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5929 Node* src_offset = argument(2); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5930 Node* dest = argument(3); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5931 Node* dest_offset = argument(4); |
6894 | 5932 |
5933 // (1) src and dest are arrays. | |
5934 const Type* src_type = src->Value(&_gvn); | |
5935 const Type* dest_type = dest->Value(&_gvn); | |
5936 const TypeAryPtr* top_src = src_type->isa_aryptr(); | |
5937 const TypeAryPtr* top_dest = dest_type->isa_aryptr(); | |
5938 assert (top_src != NULL && top_src->klass() != NULL && top_dest != NULL && top_dest->klass() != NULL, "args are strange"); | |
5939 | |
5940 // for the quick and dirty code we will skip all the checks. | |
5941 // we are just trying to get the call to be generated. | |
5942 Node* src_start = src; | |
5943 Node* dest_start = dest; | |
5944 if (src_offset != NULL || dest_offset != NULL) { | |
5945 assert(src_offset != NULL && dest_offset != NULL, ""); | |
5946 src_start = array_element_address(src, src_offset, T_BYTE); | |
5947 dest_start = array_element_address(dest, dest_offset, T_BYTE); | |
5948 } | |
5949 | |
5950 // now need to get the start of its expanded key array | |
5951 // this requires a newer class file that has this array as littleEndian ints, otherwise we revert to java | |
5952 Node* k_start = get_key_start_from_aescrypt_object(aescrypt_object); | |
5953 if (k_start == NULL) return false; | |
5954 | |
14261 | 5955 if (Matcher::pass_original_key_for_aes()) { |
5956 // on SPARC we need to pass the original key since key expansion needs to happen in intrinsics due to | |
5957 // compatibility issues between Java key expansion and SPARC crypto instructions | |
5958 Node* original_k_start = get_original_key_start_from_aescrypt_object(aescrypt_object); | |
5959 if (original_k_start == NULL) return false; | |
5960 | |
5961 // Call the stub. | |
5962 make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::aescrypt_block_Type(), | |
5963 stubAddr, stubName, TypePtr::BOTTOM, | |
5964 src_start, dest_start, k_start, original_k_start); | |
5965 } else { | |
5966 // Call the stub. | |
5967 make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::aescrypt_block_Type(), | |
5968 stubAddr, stubName, TypePtr::BOTTOM, | |
5969 src_start, dest_start, k_start); | |
5970 } | |
6894 | 5971 |
5972 return true; | |
5973 } | |
5974 | |
5975 //------------------------------inline_cipherBlockChaining_AESCrypt----------------------- | |
5976 bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) { | |
5977 address stubAddr; | |
5978 const char *stubName; | |
5979 | |
5980 assert(UseAES, "need AES instruction support"); | |
5981 | |
5982 switch(id) { | |
5983 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: | |
5984 stubAddr = StubRoutines::cipherBlockChaining_encryptAESCrypt(); | |
5985 stubName = "cipherBlockChaining_encryptAESCrypt"; | |
5986 break; | |
5987 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: | |
5988 stubAddr = StubRoutines::cipherBlockChaining_decryptAESCrypt(); | |
5989 stubName = "cipherBlockChaining_decryptAESCrypt"; | |
5990 break; | |
5991 } | |
5992 if (stubAddr == NULL) return false; | |
5993 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5994 Node* cipherBlockChaining_object = argument(0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5995 Node* src = argument(1); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5996 Node* src_offset = argument(2); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5997 Node* len = argument(3); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5998 Node* dest = argument(4); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
5999 Node* dest_offset = argument(5); |
6894 | 6000 |
6001 // (1) src and dest are arrays. | |
6002 const Type* src_type = src->Value(&_gvn); | |
6003 const Type* dest_type = dest->Value(&_gvn); | |
6004 const TypeAryPtr* top_src = src_type->isa_aryptr(); | |
6005 const TypeAryPtr* top_dest = dest_type->isa_aryptr(); | |
6006 assert (top_src != NULL && top_src->klass() != NULL | |
6007 && top_dest != NULL && top_dest->klass() != NULL, "args are strange"); | |
6008 | |
6009 // checks are the responsibility of the caller | |
6010 Node* src_start = src; | |
6011 Node* dest_start = dest; | |
6012 if (src_offset != NULL || dest_offset != NULL) { | |
6013 assert(src_offset != NULL && dest_offset != NULL, ""); | |
6014 src_start = array_element_address(src, src_offset, T_BYTE); | |
6015 dest_start = array_element_address(dest, dest_offset, T_BYTE); | |
6016 } | |
6017 | |
6018 // if we are in this set of code, we "know" the embeddedCipher is an AESCrypt object | |
6019 // (because of the predicated logic executed earlier). | |
6020 // so we cast it here safely. | |
6021 // this requires a newer class file that has this array as littleEndian ints, otherwise we revert to java | |
6022 | |
6023 Node* embeddedCipherObj = load_field_from_object(cipherBlockChaining_object, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false); | |
6024 if (embeddedCipherObj == NULL) return false; | |
6025 | |
6026 // cast it to what we know it will be at runtime | |
6027 const TypeInstPtr* tinst = _gvn.type(cipherBlockChaining_object)->isa_instptr(); | |
6028 assert(tinst != NULL, "CBC obj is null"); | |
6029 assert(tinst->klass()->is_loaded(), "CBC obj is not loaded"); | |
6030 ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); | |
6031 if (!klass_AESCrypt->is_loaded()) return false; | |
6032 | |
6033 ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); | |
6034 const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt); | |
6035 const TypeOopPtr* xtype = aklass->as_instance_type(); | |
6036 Node* aescrypt_object = new(C) CheckCastPPNode(control(), embeddedCipherObj, xtype); | |
6037 aescrypt_object = _gvn.transform(aescrypt_object); | |
6038 | |
6039 // we need to get the start of the aescrypt_object's expanded key array | |
6040 Node* k_start = get_key_start_from_aescrypt_object(aescrypt_object); | |
6041 if (k_start == NULL) return false; | |
6042 | |
6043 // similarly, get the start address of the r vector | |
6044 Node* objRvec = load_field_from_object(cipherBlockChaining_object, "r", "[B", /*is_exact*/ false); | |
6045 if (objRvec == NULL) return false; | |
6046 Node* r_start = array_element_address(objRvec, intcon(0), T_BYTE); | |
6047 | |
14261 | 6048 Node* cbcCrypt; |
6049 if (Matcher::pass_original_key_for_aes()) { | |
6050 // on SPARC we need to pass the original key since key expansion needs to happen in intrinsics due to | |
6051 // compatibility issues between Java key expansion and SPARC crypto instructions | |
6052 Node* original_k_start = get_original_key_start_from_aescrypt_object(aescrypt_object); | |
6053 if (original_k_start == NULL) return false; | |
6054 | |
6055 // Call the stub, passing src_start, dest_start, k_start, r_start, src_len and original_k_start | |
6056 cbcCrypt = make_runtime_call(RC_LEAF|RC_NO_FP, | |
6057 OptoRuntime::cipherBlockChaining_aescrypt_Type(), | |
6058 stubAddr, stubName, TypePtr::BOTTOM, | |
6059 src_start, dest_start, k_start, r_start, len, original_k_start); | |
6060 } else { | |
6061 // Call the stub, passing src_start, dest_start, k_start, r_start and src_len | |
6062 cbcCrypt = make_runtime_call(RC_LEAF|RC_NO_FP, | |
6063 OptoRuntime::cipherBlockChaining_aescrypt_Type(), | |
6064 stubAddr, stubName, TypePtr::BOTTOM, | |
6065 src_start, dest_start, k_start, r_start, len); | |
6066 } | |
6067 | |
6068 // return cipher length (int) | |
6069 Node* retvalue = _gvn.transform(new (C) ProjNode(cbcCrypt, TypeFunc::Parms)); | |
6070 set_result(retvalue); | |
6894 | 6071 return true; |
6072 } | |
6073 | |
6074 //------------------------------get_key_start_from_aescrypt_object----------------------- | |
6075 Node * LibraryCallKit::get_key_start_from_aescrypt_object(Node *aescrypt_object) { | |
6076 Node* objAESCryptKey = load_field_from_object(aescrypt_object, "K", "[I", /*is_exact*/ false); | |
6077 assert (objAESCryptKey != NULL, "wrong version of com.sun.crypto.provider.AESCrypt"); | |
6078 if (objAESCryptKey == NULL) return (Node *) NULL; | |
6079 | |
6080 // now have the array, need to get the start address of the K array | |
6081 Node* k_start = array_element_address(objAESCryptKey, intcon(0), T_INT); | |
6082 return k_start; | |
6083 } | |
6084 | |
14261 | 6085 //------------------------------get_original_key_start_from_aescrypt_object----------------------- |
6086 Node * LibraryCallKit::get_original_key_start_from_aescrypt_object(Node *aescrypt_object) { | |
6087 Node* objAESCryptKey = load_field_from_object(aescrypt_object, "lastKey", "[B", /*is_exact*/ false); | |
6088 assert (objAESCryptKey != NULL, "wrong version of com.sun.crypto.provider.AESCrypt"); | |
6089 if (objAESCryptKey == NULL) return (Node *) NULL; | |
6090 | |
6091 // now have the array, need to get the start address of the lastKey array | |
6092 Node* original_k_start = array_element_address(objAESCryptKey, intcon(0), T_BYTE); | |
6093 return original_k_start; | |
6094 } | |
6095 | |
6894 | 6096 //----------------------------inline_cipherBlockChaining_AESCrypt_predicate---------------------------- |
6097 // Return node representing slow path of predicate check. | |
6098 // the pseudo code we want to emulate with this predicate is: | |
6099 // for encryption: | |
6100 // if (embeddedCipherObj instanceof AESCrypt) do_intrinsic, else do_javapath | |
6101 // for decryption: | |
6102 // if ((embeddedCipherObj instanceof AESCrypt) && (cipher!=plain)) do_intrinsic, else do_javapath | |
6103 // note cipher==plain is more conservative than the original java code but that's OK | |
6104 // | |
6105 Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting) { | |
6106 // First, check receiver for NULL since it is virtual method. | |
6107 Node* objCBC = argument(0); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
6108 objCBC = null_check(objCBC); |
6894 | 6109 |
6110 if (stopped()) return NULL; // Always NULL | |
6111 | |
6112 // Load embeddedCipher field of CipherBlockChaining object. | |
6113 Node* embeddedCipherObj = load_field_from_object(objCBC, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false); | |
6114 | |
6115 // get AESCrypt klass for instanceOf check | |
6116 // AESCrypt might not be loaded yet if some other SymmetricCipher got us to this compile point | |
6117 // will have same classloader as CipherBlockChaining object | |
6118 const TypeInstPtr* tinst = _gvn.type(objCBC)->isa_instptr(); | |
6119 assert(tinst != NULL, "CBCobj is null"); | |
6120 assert(tinst->klass()->is_loaded(), "CBCobj is not loaded"); | |
6121 | |
6122 // we want to do an instanceof comparison against the AESCrypt class | |
6123 ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); | |
6124 if (!klass_AESCrypt->is_loaded()) { | |
6125 // if AESCrypt is not even loaded, we never take the intrinsic fast path | |
6126 Node* ctrl = control(); | |
6127 set_control(top()); // no regular fast path | |
6128 return ctrl; | |
6129 } | |
6130 ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); | |
6131 | |
6132 Node* instof = gen_instanceof(embeddedCipherObj, makecon(TypeKlassPtr::make(instklass_AESCrypt))); | |
6133 Node* cmp_instof = _gvn.transform(new (C) CmpINode(instof, intcon(1))); | |
6134 Node* bool_instof = _gvn.transform(new (C) BoolNode(cmp_instof, BoolTest::ne)); | |
6135 | |
6136 Node* instof_false = generate_guard(bool_instof, NULL, PROB_MIN); | |
6137 | |
6138 // for encryption, we are done | |
6139 if (!decrypting) | |
6140 return instof_false; // even if it is NULL | |
6141 | |
6142 // for decryption, we need to add a further check to avoid | |
6143 // taking the intrinsic path when cipher and plain are the same | |
6144 // see the original java code for why. | |
6145 RegionNode* region = new(C) RegionNode(3); | |
6146 region->init_req(1, instof_false); | |
6147 Node* src = argument(1); | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
6148 Node* dest = argument(4); |
6894 | 6149 Node* cmp_src_dest = _gvn.transform(new (C) CmpPNode(src, dest)); |
6150 Node* bool_src_dest = _gvn.transform(new (C) BoolNode(cmp_src_dest, BoolTest::eq)); | |
6151 Node* src_dest_conjoint = generate_guard(bool_src_dest, NULL, PROB_MIN); | |
6152 region->init_req(2, src_dest_conjoint); | |
6153 | |
6154 record_for_igvn(region); | |
6155 return _gvn.transform(region); | |
6156 } |