Mercurial > hg > truffle
comparison src/share/vm/opto/library_call.cpp @ 3255:5d046bf49ce7
Merge
author | johnc |
---|---|
date | Thu, 14 Apr 2011 13:45:41 -0700 |
parents | 13bc79b5c9c8 59766fd005ff |
children | edd9b016deb6 |
comparison
equal
deleted
inserted
replaced
2468:6c97c830fb6f | 3255:5d046bf49ce7 |
---|---|
164 bool inline_min_max(vmIntrinsics::ID id); | 164 bool inline_min_max(vmIntrinsics::ID id); |
165 Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y); | 165 Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y); |
166 // This returns Type::AnyPtr, RawPtr, or OopPtr. | 166 // This returns Type::AnyPtr, RawPtr, or OopPtr. |
167 int classify_unsafe_addr(Node* &base, Node* &offset); | 167 int classify_unsafe_addr(Node* &base, Node* &offset); |
168 Node* make_unsafe_address(Node* base, Node* offset); | 168 Node* make_unsafe_address(Node* base, Node* offset); |
169 // Helper for inline_unsafe_access. | |
170 // Generates the guards that check whether the result of | |
171 // Unsafe.getObject should be recorded in an SATB log buffer. | |
172 void insert_g1_pre_barrier(Node* base_oop, Node* offset, Node* pre_val); | |
169 bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile); | 173 bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile); |
170 bool inline_unsafe_prefetch(bool is_native_ptr, bool is_store, bool is_static); | 174 bool inline_unsafe_prefetch(bool is_native_ptr, bool is_store, bool is_static); |
171 bool inline_unsafe_allocate(); | 175 bool inline_unsafe_allocate(); |
172 bool inline_unsafe_copyMemory(); | 176 bool inline_unsafe_copyMemory(); |
173 bool inline_native_currentThread(); | 177 bool inline_native_currentThread(); |
238 bool inline_fp_conversions(vmIntrinsics::ID id); | 242 bool inline_fp_conversions(vmIntrinsics::ID id); |
239 bool inline_numberOfLeadingZeros(vmIntrinsics::ID id); | 243 bool inline_numberOfLeadingZeros(vmIntrinsics::ID id); |
240 bool inline_numberOfTrailingZeros(vmIntrinsics::ID id); | 244 bool inline_numberOfTrailingZeros(vmIntrinsics::ID id); |
241 bool inline_bitCount(vmIntrinsics::ID id); | 245 bool inline_bitCount(vmIntrinsics::ID id); |
242 bool inline_reverseBytes(vmIntrinsics::ID id); | 246 bool inline_reverseBytes(vmIntrinsics::ID id); |
247 | |
248 bool inline_reference_get(); | |
243 }; | 249 }; |
244 | 250 |
245 | 251 |
246 //---------------------------make_vm_intrinsic---------------------------- | 252 //---------------------------make_vm_intrinsic---------------------------- |
247 CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { | 253 CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { |
334 case vmIntrinsics::_bitCount_i: | 340 case vmIntrinsics::_bitCount_i: |
335 case vmIntrinsics::_bitCount_l: | 341 case vmIntrinsics::_bitCount_l: |
336 if (!UsePopCountInstruction) return NULL; | 342 if (!UsePopCountInstruction) return NULL; |
337 break; | 343 break; |
338 | 344 |
345 case vmIntrinsics::_Reference_get: | |
346 // It is only when G1 is enabled that we absolutely | |
347 // need to use the intrinsic version of Reference.get() | |
348 // so that the value in the referent field, if necessary, | |
349 // can be registered by the pre-barrier code. | |
350 if (!UseG1GC) return NULL; | |
351 break; | |
352 | |
339 default: | 353 default: |
340 assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility"); | 354 assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility"); |
341 assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?"); | 355 assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?"); |
342 break; | 356 break; |
343 } | 357 } |
385 char buf[1000]; | 399 char buf[1000]; |
386 const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf)); | 400 const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf)); |
387 tty->print_cr("Intrinsic %s", str); | 401 tty->print_cr("Intrinsic %s", str); |
388 } | 402 } |
389 #endif | 403 #endif |
404 | |
390 if (kit.try_to_inline()) { | 405 if (kit.try_to_inline()) { |
391 if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) { | 406 if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) { |
392 CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, kit.bci(), is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); | 407 CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, kit.bci(), is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); |
393 } | 408 } |
394 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); | 409 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); |
400 } | 415 } |
401 return kit.transfer_exceptions_into_jvms(); | 416 return kit.transfer_exceptions_into_jvms(); |
402 } | 417 } |
403 | 418 |
404 if (PrintIntrinsics) { | 419 if (PrintIntrinsics) { |
405 tty->print("Did not inline intrinsic %s%s at bci:%d in", | 420 if (jvms->has_method()) { |
421 // Not a root compile. | |
422 tty->print("Did not inline intrinsic %s%s at bci:%d in", | |
423 vmIntrinsics::name_at(intrinsic_id()), | |
424 (is_virtual() ? " (virtual)" : ""), kit.bci()); | |
425 kit.caller()->print_short_name(tty); | |
426 tty->print_cr(" (%d bytes)", kit.caller()->code_size()); | |
427 } else { | |
428 // Root compile | |
429 tty->print("Did not generate intrinsic %s%s at bci:%d in", | |
406 vmIntrinsics::name_at(intrinsic_id()), | 430 vmIntrinsics::name_at(intrinsic_id()), |
407 (is_virtual() ? " (virtual)" : ""), kit.bci()); | 431 (is_virtual() ? " (virtual)" : ""), kit.bci()); |
408 kit.caller()->print_short_name(tty); | 432 } |
409 tty->print_cr(" (%d bytes)", kit.caller()->code_size()); | |
410 } | 433 } |
411 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); | 434 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); |
412 return NULL; | 435 return NULL; |
413 } | 436 } |
414 | 437 |
415 bool LibraryCallKit::try_to_inline() { | 438 bool LibraryCallKit::try_to_inline() { |
416 // Handle symbolic names for otherwise undistinguished boolean switches: | 439 // Handle symbolic names for otherwise undistinguished boolean switches: |
417 const bool is_store = true; | 440 const bool is_store = true; |
418 const bool is_native_ptr = true; | 441 const bool is_native_ptr = true; |
419 const bool is_static = true; | 442 const bool is_static = true; |
443 | |
444 if (!jvms()->has_method()) { | |
445 // Root JVMState has a null method. | |
446 assert(map()->memory()->Opcode() == Op_Parm, ""); | |
447 // Insert the memory aliasing node | |
448 set_all_memory(reset_memory()); | |
449 } | |
450 assert(merged_memory(), ""); | |
420 | 451 |
421 switch (intrinsic_id()) { | 452 switch (intrinsic_id()) { |
422 case vmIntrinsics::_hashCode: | 453 case vmIntrinsics::_hashCode: |
423 return inline_native_hashcode(intrinsic()->is_virtual(), !is_static); | 454 return inline_native_hashcode(intrinsic()->is_virtual(), !is_static); |
424 case vmIntrinsics::_identityHashCode: | 455 case vmIntrinsics::_identityHashCode: |
655 case vmIntrinsics::_attemptUpdate: | 686 case vmIntrinsics::_attemptUpdate: |
656 return inline_native_AtomicLong_attemptUpdate(); | 687 return inline_native_AtomicLong_attemptUpdate(); |
657 | 688 |
658 case vmIntrinsics::_getCallerClass: | 689 case vmIntrinsics::_getCallerClass: |
659 return inline_native_Reflection_getCallerClass(); | 690 return inline_native_Reflection_getCallerClass(); |
691 | |
692 case vmIntrinsics::_Reference_get: | |
693 return inline_reference_get(); | |
660 | 694 |
661 default: | 695 default: |
662 // If you get here, it may be that someone has added a new intrinsic | 696 // If you get here, it may be that someone has added a new intrinsic |
663 // to the list in vmSymbols.hpp without implementing it here. | 697 // to the list in vmSymbols.hpp without implementing it here. |
664 #ifndef PRODUCT | 698 #ifndef PRODUCT |
2074 | 2108 |
2075 //----------------------------inline_unsafe_access---------------------------- | 2109 //----------------------------inline_unsafe_access---------------------------- |
2076 | 2110 |
2077 const static BasicType T_ADDRESS_HOLDER = T_LONG; | 2111 const static BasicType T_ADDRESS_HOLDER = T_LONG; |
2078 | 2112 |
2113 // Helper that guards and inserts a G1 pre-barrier. | |
2114 void LibraryCallKit::insert_g1_pre_barrier(Node* base_oop, Node* offset, Node* pre_val) { | |
2115 assert(UseG1GC, "should not call this otherwise"); | |
2116 | |
2117 // We could be accessing the referent field of a reference object. If so, when G1 | |
2118 // is enabled, we need to log the value in the referent field in an SATB buffer. | |
2119 // This routine performs some compile time filters and generates suitable | |
2120 // runtime filters that guard the pre-barrier code. | |
2121 | |
2122 // Some compile time checks. | |
2123 | |
2124 // If offset is a constant, is it java_lang_ref_Reference::_reference_offset? | |
2125 const TypeX* otype = offset->find_intptr_t_type(); | |
2126 if (otype != NULL && otype->is_con() && | |
2127 otype->get_con() != java_lang_ref_Reference::referent_offset) { | |
2128 // Constant offset but not the reference_offset so just return | |
2129 return; | |
2130 } | |
2131 | |
2132 // We only need to generate the runtime guards for instances. | |
2133 const TypeOopPtr* btype = base_oop->bottom_type()->isa_oopptr(); | |
2134 if (btype != NULL) { | |
2135 if (btype->isa_aryptr()) { | |
2136 // Array type so nothing to do | |
2137 return; | |
2138 } | |
2139 | |
2140 const TypeInstPtr* itype = btype->isa_instptr(); | |
2141 if (itype != NULL) { | |
2142 // Can the klass of base_oop be statically determined | |
2143 // to be _not_ a sub-class of Reference? | |
2144 ciKlass* klass = itype->klass(); | |
2145 if (klass->is_subtype_of(env()->Reference_klass()) && | |
2146 !env()->Reference_klass()->is_subtype_of(klass)) { | |
2147 return; | |
2148 } | |
2149 } | |
2150 } | |
2151 | |
2152 // The compile time filters did not reject base_oop/offset so | |
2153 // we need to generate the following runtime filters | |
2154 // | |
2155 // if (offset == java_lang_ref_Reference::_reference_offset) { | |
2156 // if (base != null) { | |
2157 // if (klass(base)->reference_type() != REF_NONE)) { | |
2158 // pre_barrier(_, pre_val, ...); | |
2159 // } | |
2160 // } | |
2161 // } | |
2162 | |
2163 float likely = PROB_LIKELY(0.999); | |
2164 float unlikely = PROB_UNLIKELY(0.999); | |
2165 | |
2166 IdealKit ideal(this); | |
2167 #define __ ideal. | |
2168 | |
2169 const int reference_type_offset = instanceKlass::reference_type_offset_in_bytes() + | |
2170 sizeof(oopDesc); | |
2171 | |
2172 Node* referent_off = __ ConX(java_lang_ref_Reference::referent_offset); | |
2173 | |
2174 __ if_then(offset, BoolTest::eq, referent_off, unlikely); { | |
2175 __ if_then(base_oop, BoolTest::ne, null(), likely); { | |
2176 | |
2177 // Update graphKit memory and control from IdealKit. | |
2178 sync_kit(ideal); | |
2179 | |
2180 Node* ref_klass_con = makecon(TypeKlassPtr::make(env()->Reference_klass())); | |
2181 Node* is_instof = gen_instanceof(base_oop, ref_klass_con); | |
2182 | |
2183 // Update IdealKit memory and control from graphKit. | |
2184 __ sync_kit(this); | |
2185 | |
2186 Node* one = __ ConI(1); | |
2187 | |
2188 __ if_then(is_instof, BoolTest::eq, one, unlikely); { | |
2189 | |
2190 // Update graphKit from IdeakKit. | |
2191 sync_kit(ideal); | |
2192 | |
2193 // Use the pre-barrier to record the value in the referent field | |
2194 pre_barrier(false /* do_load */, | |
2195 __ ctrl(), | |
2196 NULL /* obj */, NULL /* adr */, -1 /* alias_idx */, NULL /* val */, NULL /* val_type */, | |
2197 pre_val /* pre_val */, | |
2198 T_OBJECT); | |
2199 | |
2200 // Update IdealKit from graphKit. | |
2201 __ sync_kit(this); | |
2202 | |
2203 } __ end_if(); // _ref_type != ref_none | |
2204 } __ end_if(); // base != NULL | |
2205 } __ end_if(); // offset == referent_offset | |
2206 | |
2207 // Final sync IdealKit and GraphKit. | |
2208 final_sync(ideal); | |
2209 #undef __ | |
2210 } | |
2211 | |
2212 | |
2079 // Interpret Unsafe.fieldOffset cookies correctly: | 2213 // Interpret Unsafe.fieldOffset cookies correctly: |
2080 extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset); | 2214 extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset); |
2081 | 2215 |
2082 bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile) { | 2216 bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile) { |
2083 if (callee()->is_static()) return false; // caller must have the capability! | 2217 if (callee()->is_static()) return false; // caller must have the capability! |
2150 } | 2284 } |
2151 | 2285 |
2152 // Build address expression. See the code in inline_unsafe_prefetch. | 2286 // Build address expression. See the code in inline_unsafe_prefetch. |
2153 Node *adr; | 2287 Node *adr; |
2154 Node *heap_base_oop = top(); | 2288 Node *heap_base_oop = top(); |
2289 Node* offset = top(); | |
2290 | |
2155 if (!is_native_ptr) { | 2291 if (!is_native_ptr) { |
2156 // The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset | 2292 // The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset |
2157 Node* offset = pop_pair(); | 2293 offset = pop_pair(); |
2158 // The base is either a Java object or a value produced by Unsafe.staticFieldBase | 2294 // The base is either a Java object or a value produced by Unsafe.staticFieldBase |
2159 Node* base = pop(); | 2295 Node* base = pop(); |
2160 // We currently rely on the cookies produced by Unsafe.xxxFieldOffset | 2296 // We currently rely on the cookies produced by Unsafe.xxxFieldOffset |
2161 // to be plain byte offsets, which are also the same as those accepted | 2297 // to be plain byte offsets, which are also the same as those accepted |
2162 // by oopDesc::field_base. | 2298 // by oopDesc::field_base. |
2193 // the barriers get omitted and the unsafe reference begins to "pollute" | 2329 // the barriers get omitted and the unsafe reference begins to "pollute" |
2194 // the alias analysis of the rest of the graph, either Compile::can_alias | 2330 // the alias analysis of the rest of the graph, either Compile::can_alias |
2195 // or Compile::must_alias will throw a diagnostic assert.) | 2331 // or Compile::must_alias will throw a diagnostic assert.) |
2196 bool need_mem_bar = (alias_type->adr_type() == TypeOopPtr::BOTTOM); | 2332 bool need_mem_bar = (alias_type->adr_type() == TypeOopPtr::BOTTOM); |
2197 | 2333 |
2334 // If we are reading the value of the referent field of a Reference | |
2335 // object (either by using Unsafe directly or through reflection) | |
2336 // then, if G1 is enabled, we need to record the referent in an | |
2337 // SATB log buffer using the pre-barrier mechanism. | |
2338 bool need_read_barrier = UseG1GC && !is_native_ptr && !is_store && | |
2339 offset != top() && heap_base_oop != top(); | |
2340 | |
2198 if (!is_store && type == T_OBJECT) { | 2341 if (!is_store && type == T_OBJECT) { |
2199 // Attempt to infer a sharper value type from the offset and base type. | 2342 // Attempt to infer a sharper value type from the offset and base type. |
2200 ciKlass* sharpened_klass = NULL; | 2343 ciKlass* sharpened_klass = NULL; |
2201 | 2344 |
2202 // See if it is an instance field, with an object type. | 2345 // See if it is an instance field, with an object type. |
2276 case T_CHAR: | 2419 case T_CHAR: |
2277 case T_BYTE: | 2420 case T_BYTE: |
2278 case T_SHORT: | 2421 case T_SHORT: |
2279 case T_INT: | 2422 case T_INT: |
2280 case T_FLOAT: | 2423 case T_FLOAT: |
2424 push(p); | |
2425 break; | |
2281 case T_OBJECT: | 2426 case T_OBJECT: |
2282 push( p ); | 2427 if (need_read_barrier) { |
2428 insert_g1_pre_barrier(heap_base_oop, offset, p); | |
2429 } | |
2430 push(p); | |
2283 break; | 2431 break; |
2284 case T_ADDRESS: | 2432 case T_ADDRESS: |
2285 // Cast to an int type. | 2433 // Cast to an int type. |
2286 p = _gvn.transform( new (C, 2) CastP2XNode(NULL,p) ); | 2434 p = _gvn.transform( new (C, 2) CastP2XNode(NULL,p) ); |
2287 p = ConvX2L(p); | 2435 p = ConvX2L(p); |
2532 cas = _gvn.transform(new (C, 5) CompareAndSwapLNode(control(), mem, adr, newval, oldval)); | 2680 cas = _gvn.transform(new (C, 5) CompareAndSwapLNode(control(), mem, adr, newval, oldval)); |
2533 break; | 2681 break; |
2534 case T_OBJECT: | 2682 case T_OBJECT: |
2535 // reference stores need a store barrier. | 2683 // reference stores need a store barrier. |
2536 // (They don't if CAS fails, but it isn't worth checking.) | 2684 // (They don't if CAS fails, but it isn't worth checking.) |
2537 pre_barrier(control(), base, adr, alias_idx, newval, value_type->make_oopptr(), T_OBJECT); | 2685 pre_barrier(true /* do_load*/, |
2686 control(), base, adr, alias_idx, newval, value_type->make_oopptr(), | |
2687 NULL /* pre_val*/, | |
2688 T_OBJECT); | |
2538 #ifdef _LP64 | 2689 #ifdef _LP64 |
2539 if (adr->bottom_type()->is_ptr_to_narrowoop()) { | 2690 if (adr->bottom_type()->is_ptr_to_narrowoop()) { |
2540 Node *newval_enc = _gvn.transform(new (C, 2) EncodePNode(newval, newval->bottom_type()->make_narrowoop())); | 2691 Node *newval_enc = _gvn.transform(new (C, 2) EncodePNode(newval, newval->bottom_type()->make_narrowoop())); |
2541 Node *oldval_enc = _gvn.transform(new (C, 2) EncodePNode(oldval, oldval->bottom_type()->make_narrowoop())); | 2692 Node *oldval_enc = _gvn.transform(new (C, 2) EncodePNode(oldval, oldval->bottom_type()->make_narrowoop())); |
2542 cas = _gvn.transform(new (C, 5) CompareAndSwapNNode(control(), mem, adr, | 2693 cas = _gvn.transform(new (C, 5) CompareAndSwapNNode(control(), mem, adr, |
5233 make_runtime_call(RC_LEAF|RC_NO_FP, | 5384 make_runtime_call(RC_LEAF|RC_NO_FP, |
5234 OptoRuntime::fast_arraycopy_Type(), | 5385 OptoRuntime::fast_arraycopy_Type(), |
5235 copyfunc_addr, copyfunc_name, adr_type, | 5386 copyfunc_addr, copyfunc_name, adr_type, |
5236 src_start, dest_start, copy_length XTOP); | 5387 src_start, dest_start, copy_length XTOP); |
5237 } | 5388 } |
5389 | |
5390 //----------------------------inline_reference_get---------------------------- | |
5391 | |
5392 bool LibraryCallKit::inline_reference_get() { | |
5393 const int nargs = 1; // self | |
5394 | |
5395 guarantee(java_lang_ref_Reference::referent_offset > 0, | |
5396 "should have already been set"); | |
5397 | |
5398 int referent_offset = java_lang_ref_Reference::referent_offset; | |
5399 | |
5400 // Restore the stack and pop off the argument | |
5401 _sp += nargs; | |
5402 Node *reference_obj = pop(); | |
5403 | |
5404 // Null check on self without removing any arguments. | |
5405 _sp += nargs; | |
5406 reference_obj = do_null_check(reference_obj, T_OBJECT); | |
5407 _sp -= nargs;; | |
5408 | |
5409 if (stopped()) return true; | |
5410 | |
5411 Node *adr = basic_plus_adr(reference_obj, reference_obj, referent_offset); | |
5412 | |
5413 ciInstanceKlass* klass = env()->Object_klass(); | |
5414 const TypeOopPtr* object_type = TypeOopPtr::make_from_klass(klass); | |
5415 | |
5416 Node* no_ctrl = NULL; | |
5417 Node *result = make_load(no_ctrl, adr, object_type, T_OBJECT); | |
5418 | |
5419 // Use the pre-barrier to record the value in the referent field | |
5420 pre_barrier(false /* do_load */, | |
5421 control(), | |
5422 NULL /* obj */, NULL /* adr */, -1 /* alias_idx */, NULL /* val */, NULL /* val_type */, | |
5423 result /* pre_val */, | |
5424 T_OBJECT); | |
5425 | |
5426 push(result); | |
5427 return true; | |
5428 } | |
5429 |