27 #include "code/codeCache.hpp"
28 #include "code/compiledIC.hpp"
29 #include "code/nmethod.hpp"
30 #include "code/pcDesc.hpp"
31 #include "code/scopeDesc.hpp"
32 #include "code/vtableStubs.hpp"
33 #include "compiler/compilationMemoryStatistic.hpp"
34 #include "compiler/compileBroker.hpp"
35 #include "compiler/oopMap.hpp"
36 #include "gc/g1/g1HeapRegion.hpp"
37 #include "gc/shared/barrierSet.hpp"
38 #include "gc/shared/collectedHeap.hpp"
39 #include "gc/shared/gcLocker.hpp"
40 #include "interpreter/bytecode.hpp"
41 #include "interpreter/interpreter.hpp"
42 #include "interpreter/linkResolver.hpp"
43 #include "logging/log.hpp"
44 #include "logging/logStream.hpp"
45 #include "memory/oopFactory.hpp"
46 #include "memory/resourceArea.hpp"
47 #include "oops/objArrayKlass.hpp"
48 #include "oops/klass.inline.hpp"
49 #include "oops/oop.inline.hpp"
50 #include "oops/typeArrayOop.inline.hpp"
51 #include "opto/ad.hpp"
52 #include "opto/addnode.hpp"
53 #include "opto/callnode.hpp"
54 #include "opto/cfgnode.hpp"
55 #include "opto/graphKit.hpp"
56 #include "opto/machnode.hpp"
57 #include "opto/matcher.hpp"
58 #include "opto/memnode.hpp"
59 #include "opto/mulnode.hpp"
60 #include "opto/output.hpp"
61 #include "opto/runtime.hpp"
62 #include "opto/subnode.hpp"
63 #include "prims/jvmtiExport.hpp"
64 #include "runtime/atomic.hpp"
65 #include "runtime/frame.inline.hpp"
66 #include "runtime/handles.inline.hpp"
179
180 C2_STUBS_DO(GEN_C2_BLOB, GEN_C2_STUB, GEN_C2_JVMTI_STUB)
181
182 return true;
183 }
184
185 #undef GEN_C2_BLOB
186
187 #undef C2_STUB_FIELD_NAME
188 #undef C2_STUB_TYPEFUNC
189 #undef C2_STUB_C_FUNC
190 #undef C2_STUB_NAME
191 #undef GEN_C2_STUB
192
193 #undef C2_JVMTI_STUB_C_FUNC
194 #undef GEN_C2_JVMTI_STUB
195 // #undef gen
196
197 const TypeFunc* OptoRuntime::_new_instance_Type = nullptr;
198 const TypeFunc* OptoRuntime::_new_array_Type = nullptr;
199 const TypeFunc* OptoRuntime::_multianewarray2_Type = nullptr;
200 const TypeFunc* OptoRuntime::_multianewarray3_Type = nullptr;
201 const TypeFunc* OptoRuntime::_multianewarray4_Type = nullptr;
202 const TypeFunc* OptoRuntime::_multianewarray5_Type = nullptr;
203 const TypeFunc* OptoRuntime::_multianewarrayN_Type = nullptr;
204 const TypeFunc* OptoRuntime::_complete_monitor_enter_Type = nullptr;
205 const TypeFunc* OptoRuntime::_complete_monitor_exit_Type = nullptr;
206 const TypeFunc* OptoRuntime::_monitor_notify_Type = nullptr;
207 const TypeFunc* OptoRuntime::_uncommon_trap_Type = nullptr;
208 const TypeFunc* OptoRuntime::_athrow_Type = nullptr;
209 const TypeFunc* OptoRuntime::_rethrow_Type = nullptr;
210 const TypeFunc* OptoRuntime::_Math_D_D_Type = nullptr;
211 const TypeFunc* OptoRuntime::_Math_DD_D_Type = nullptr;
212 const TypeFunc* OptoRuntime::_modf_Type = nullptr;
213 const TypeFunc* OptoRuntime::_l2f_Type = nullptr;
214 const TypeFunc* OptoRuntime::_void_long_Type = nullptr;
215 const TypeFunc* OptoRuntime::_void_void_Type = nullptr;
216 const TypeFunc* OptoRuntime::_jfr_write_checkpoint_Type = nullptr;
217 const TypeFunc* OptoRuntime::_flush_windows_Type = nullptr;
218 const TypeFunc* OptoRuntime::_fast_arraycopy_Type = nullptr;
304 oopDesc* dest, jint dest_pos,
305 jint length, JavaThread* thread) {
306 SharedRuntime::slow_arraycopy_C(src, src_pos, dest, dest_pos, length, thread);
307 }
308
309 void OptoRuntime::complete_monitor_locking_C(oopDesc* obj, BasicLock* lock, JavaThread* current) {
310 SharedRuntime::complete_monitor_locking_C(obj, lock, current);
311 }
312
313
314 //=============================================================================
315 // Opto compiler runtime routines
316 //=============================================================================
317
318
319 //=============================allocation======================================
320 // We failed the fast-path allocation. Now we need to do a scavenge or GC
321 // and try allocation again.
322
323 // object allocation
324 JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(Klass* klass, JavaThread* current))
325 JRT_BLOCK;
326 #ifndef PRODUCT
327 SharedRuntime::_new_instance_ctr++; // new instance requires GC
328 #endif
329 assert(check_compiled_frame(current), "incorrect caller");
330
331 // These checks are cheap to make and support reflective allocation.
332 int lh = klass->layout_helper();
333 if (Klass::layout_helper_needs_slow_path(lh) || !InstanceKlass::cast(klass)->is_initialized()) {
334 Handle holder(current, klass->klass_holder()); // keep the klass alive
335 klass->check_valid_for_instantiation(false, THREAD);
336 if (!HAS_PENDING_EXCEPTION) {
337 InstanceKlass::cast(klass)->initialize(THREAD);
338 }
339 }
340
341 if (!HAS_PENDING_EXCEPTION) {
342 // Scavenge and allocate an instance.
343 Handle holder(current, klass->klass_holder()); // keep the klass alive
344 oop result = InstanceKlass::cast(klass)->allocate_instance(THREAD);
345 current->set_vm_result(result);
346
347 // Pass oops back through thread local storage. Our apparent type to Java
348 // is that we return an oop, but we can block on exit from this routine and
349 // a GC can trash the oop in C's return register. The generated stub will
350 // fetch the oop from TLS after any possible GC.
351 }
352
353 deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION);
354 JRT_BLOCK_END;
355
356 // inform GC that we won't do card marks for initializing writes.
357 SharedRuntime::on_slowpath_allocation_exit(current);
358 JRT_END
359
360
361 // array allocation
362 JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(Klass* array_type, int len, JavaThread* current))
363 JRT_BLOCK;
364 #ifndef PRODUCT
365 SharedRuntime::_new_array_ctr++; // new array requires GC
366 #endif
367 assert(check_compiled_frame(current), "incorrect caller");
368
369 // Scavenge and allocate an instance.
370 oop result;
371
372 if (array_type->is_typeArray_klass()) {
373 // The oopFactory likes to work with the element type.
374 // (We could bypass the oopFactory, since it doesn't add much value.)
375 BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type();
376 result = oopFactory::new_typeArray(elem_type, len, THREAD);
377 } else {
378 // Although the oopFactory likes to work with the elem_type,
379 // the compiler prefers the array_type, since it must already have
380 // that latter value in hand for the fast path.
381 Handle holder(current, array_type->klass_holder()); // keep the array klass alive
382 Klass* elem_type = ObjArrayKlass::cast(array_type)->element_klass();
383 result = oopFactory::new_objArray(elem_type, len, THREAD);
384 }
385
386 // Pass oops back through thread local storage. Our apparent type to Java
387 // is that we return an oop, but we can block on exit from this routine and
388 // a GC can trash the oop in C's return register. The generated stub will
389 // fetch the oop from TLS after any possible GC.
390 deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION);
391 current->set_vm_result(result);
392 JRT_BLOCK_END;
393
394 // inform GC that we won't do card marks for initializing writes.
395 SharedRuntime::on_slowpath_allocation_exit(current);
396 JRT_END
397
398 // array allocation without zeroing
399 JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_nozero_C(Klass* array_type, int len, JavaThread* current))
400 JRT_BLOCK;
401 #ifndef PRODUCT
402 SharedRuntime::_new_array_ctr++; // new array requires GC
403 #endif
560 JRT_BLOCK_ENTRY(void, OptoRuntime::monitor_notifyAll_C(oopDesc* obj, JavaThread* current))
561
562 if (!SafepointSynchronize::is_synchronizing() ) {
563 if (ObjectSynchronizer::quick_notify(obj, current, true)) {
564 return;
565 }
566 }
567
568 // This is the case the fast-path above isn't provisioned to handle.
569 // The fast-path is designed to handle frequently arising cases in an efficient manner.
570 // (The fast-path is just a degenerate variant of the slow-path).
571 // Perform the dreaded state transition and pass control into the slow-path.
572 JRT_BLOCK;
573 Handle h_obj(current, obj);
574 ObjectSynchronizer::notifyall(h_obj, CHECK);
575 JRT_BLOCK_END;
576 JRT_END
577
578 static const TypeFunc* make_new_instance_Type() {
579 // create input type (domain)
580 const Type **fields = TypeTuple::fields(1);
581 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Klass to be allocated
582 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields);
583
584 // create result type (range)
585 fields = TypeTuple::fields(1);
586 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop
587
588 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields);
589
590 return TypeFunc::make(domain, range);
591 }
592
593 #if INCLUDE_JVMTI
594 static const TypeFunc* make_notify_jvmti_vthread_Type() {
595 // create input type (domain)
596 const Type **fields = TypeTuple::fields(2);
597 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // VirtualThread oop
598 fields[TypeFunc::Parms+1] = TypeInt::BOOL; // jboolean
599 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields);
600
601 // no result type needed
602 fields = TypeTuple::fields(1);
605
606 return TypeFunc::make(domain,range);
607 }
608 #endif
609
610 static const TypeFunc* make_athrow_Type() {
611 // create input type (domain)
612 const Type **fields = TypeTuple::fields(1);
613 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Klass to be allocated
614 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields);
615
616 // create result type (range)
617 fields = TypeTuple::fields(0);
618
619 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
620
621 return TypeFunc::make(domain, range);
622 }
623
624 static const TypeFunc* make_new_array_Type() {
625 // create input type (domain)
626 const Type **fields = TypeTuple::fields(2);
627 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // element klass
628 fields[TypeFunc::Parms+1] = TypeInt::INT; // array size
629 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields);
630
631 // create result type (range)
632 fields = TypeTuple::fields(1);
633 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop
634
635 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields);
636
637 return TypeFunc::make(domain, range);
638 }
639
640 const TypeFunc* OptoRuntime::multianewarray_Type(int ndim) {
641 // create input type (domain)
642 const int nargs = ndim + 1;
643 const Type **fields = TypeTuple::fields(nargs);
644 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // element klass
680 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
681
682 return TypeFunc::make(domain, range);
683 }
684
685 //-----------------------------------------------------------------------------
686 // Monitor Handling
687
688 static const TypeFunc* make_complete_monitor_enter_Type() {
689 // create input type (domain)
690 const Type **fields = TypeTuple::fields(2);
691 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Object to be Locked
692 fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // Address of stack location for lock
693 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields);
694
695 // create result type (range)
696 fields = TypeTuple::fields(0);
697
698 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields);
699
700 return TypeFunc::make(domain,range);
701 }
702
703 //-----------------------------------------------------------------------------
704
705 static const TypeFunc* make_complete_monitor_exit_Type() {
706 // create input type (domain)
707 const Type **fields = TypeTuple::fields(3);
708 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Object to be Locked
709 fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // Address of stack location for lock - BasicLock
710 fields[TypeFunc::Parms+2] = TypeRawPtr::BOTTOM; // Thread pointer (Self)
711 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+3, fields);
712
713 // create result type (range)
714 fields = TypeTuple::fields(0);
715
716 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
717
718 return TypeFunc::make(domain, range);
719 }
720
1918 RegisterMap::WalkContinuation::skip);
1919 frame stub_frame = thread->last_frame();
1920 assert(stub_frame.is_runtime_frame() || exception_blob()->contains(stub_frame.pc()), "sanity check");
1921 frame caller_frame = stub_frame.sender(®_map);
1922 return caller_frame.is_deoptimized_frame();
1923 }
1924
1925 static const TypeFunc* make_register_finalizer_Type() {
1926 // create input type (domain)
1927 const Type **fields = TypeTuple::fields(1);
1928 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // oop; Receiver
1929 // // The JavaThread* is passed to each routine as the last argument
1930 // fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL; // JavaThread *; Executing thread
1931 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1,fields);
1932
1933 // create result type (range)
1934 fields = TypeTuple::fields(0);
1935
1936 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields);
1937
1938 return TypeFunc::make(domain,range);
1939 }
1940
1941 #if INCLUDE_JFR
1942 static const TypeFunc* make_class_id_load_barrier_Type() {
1943 // create input type (domain)
1944 const Type **fields = TypeTuple::fields(1);
1945 fields[TypeFunc::Parms+0] = TypeInstPtr::KLASS;
1946 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms + 1, fields);
1947
1948 // create result type (range)
1949 fields = TypeTuple::fields(0);
1950
1951 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms + 0, fields);
1952
1953 return TypeFunc::make(domain,range);
1954 }
1955 #endif // INCLUDE_JFR
1956
1957 //-----------------------------------------------------------------------------
1958 static const TypeFunc* make_dtrace_method_entry_exit_Type() {
1959 // create input type (domain)
1960 const Type **fields = TypeTuple::fields(2);
1961 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // Thread-local storage
1962 fields[TypeFunc::Parms+1] = TypeMetadataPtr::BOTTOM; // Method*; Method we are entering
1963 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields);
1964
1965 // create result type (range)
1966 fields = TypeTuple::fields(0);
1967
1968 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields);
1969
1970 return TypeFunc::make(domain,range);
1971 }
1972
1973 static const TypeFunc* make_dtrace_object_alloc_Type() {
1974 // create input type (domain)
1975 const Type **fields = TypeTuple::fields(2);
1976 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // Thread-local storage
1977 fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // oop; newly allocated object
1978
1979 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields);
1980
1981 // create result type (range)
1982 fields = TypeTuple::fields(0);
1983
1984 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields);
1985
1986 return TypeFunc::make(domain,range);
1987 }
1988
1989 JRT_ENTRY_NO_ASYNC(void, OptoRuntime::register_finalizer_C(oopDesc* obj, JavaThread* current))
1990 assert(oopDesc::is_oop(obj), "must be a valid oop");
1991 assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
1992 InstanceKlass::register_finalizer(instanceOop(obj), CHECK);
1993 JRT_END
1994
1995 //-----------------------------------------------------------------------------
1996
1997 NamedCounter * volatile OptoRuntime::_named_counters = nullptr;
1998
1999 //
2000 // dump the collected NamedCounters.
2001 //
2002 void OptoRuntime::print_named_counters() {
2003 int total_lock_count = 0;
2004 int eliminated_lock_count = 0;
2005
2006 NamedCounter* c = _named_counters;
2057 }
2058 st.print("@%d", bci);
2059 // To print linenumbers instead of bci use: m->line_number_from_bci(bci)
2060 }
2061 NamedCounter* c = new NamedCounter(st.freeze(), tag);
2062
2063 // atomically add the new counter to the head of the list. We only
2064 // add counters so this is safe.
2065 NamedCounter* head;
2066 do {
2067 c->set_next(nullptr);
2068 head = _named_counters;
2069 c->set_next(head);
2070 } while (Atomic::cmpxchg(&_named_counters, head, c) != head);
2071 return c;
2072 }
2073
2074 void OptoRuntime::initialize_types() {
2075 _new_instance_Type = make_new_instance_Type();
2076 _new_array_Type = make_new_array_Type();
2077 _multianewarray2_Type = multianewarray_Type(2);
2078 _multianewarray3_Type = multianewarray_Type(3);
2079 _multianewarray4_Type = multianewarray_Type(4);
2080 _multianewarray5_Type = multianewarray_Type(5);
2081 _multianewarrayN_Type = make_multianewarrayN_Type();
2082 _complete_monitor_enter_Type = make_complete_monitor_enter_Type();
2083 _complete_monitor_exit_Type = make_complete_monitor_exit_Type();
2084 _monitor_notify_Type = make_monitor_notify_Type();
2085 _uncommon_trap_Type = make_uncommon_trap_Type();
2086 _athrow_Type = make_athrow_Type();
2087 _rethrow_Type = make_rethrow_Type();
2088 _Math_D_D_Type = make_Math_D_D_Type();
2089 _Math_DD_D_Type = make_Math_DD_D_Type();
2090 _modf_Type = make_modf_Type();
2091 _l2f_Type = make_l2f_Type();
2092 _void_long_Type = make_void_long_Type();
2093 _void_void_Type = make_void_void_Type();
2094 _jfr_write_checkpoint_Type = make_jfr_write_checkpoint_Type();
2095 _flush_windows_Type = make_flush_windows_Type();
2096 _fast_arraycopy_Type = make_arraycopy_Type(ac_fast);
2152 static void trace_exception(outputStream* st, oop exception_oop, address exception_pc, const char* msg) {
2153 trace_exception_counter++;
2154 stringStream tempst;
2155
2156 tempst.print("%d [Exception (%s): ", trace_exception_counter, msg);
2157 exception_oop->print_value_on(&tempst);
2158 tempst.print(" in ");
2159 CodeBlob* blob = CodeCache::find_blob(exception_pc);
2160 if (blob->is_nmethod()) {
2161 blob->as_nmethod()->method()->print_value_on(&tempst);
2162 } else if (blob->is_runtime_stub()) {
2163 tempst.print("<runtime-stub>");
2164 } else {
2165 tempst.print("<unknown>");
2166 }
2167 tempst.print(" at " INTPTR_FORMAT, p2i(exception_pc));
2168 tempst.print("]");
2169
2170 st->print_raw_cr(tempst.freeze());
2171 }
|
27 #include "code/codeCache.hpp"
28 #include "code/compiledIC.hpp"
29 #include "code/nmethod.hpp"
30 #include "code/pcDesc.hpp"
31 #include "code/scopeDesc.hpp"
32 #include "code/vtableStubs.hpp"
33 #include "compiler/compilationMemoryStatistic.hpp"
34 #include "compiler/compileBroker.hpp"
35 #include "compiler/oopMap.hpp"
36 #include "gc/g1/g1HeapRegion.hpp"
37 #include "gc/shared/barrierSet.hpp"
38 #include "gc/shared/collectedHeap.hpp"
39 #include "gc/shared/gcLocker.hpp"
40 #include "interpreter/bytecode.hpp"
41 #include "interpreter/interpreter.hpp"
42 #include "interpreter/linkResolver.hpp"
43 #include "logging/log.hpp"
44 #include "logging/logStream.hpp"
45 #include "memory/oopFactory.hpp"
46 #include "memory/resourceArea.hpp"
47 #include "oops/flatArrayKlass.hpp"
48 #include "oops/flatArrayOop.inline.hpp"
49 #include "oops/objArrayKlass.hpp"
50 #include "oops/klass.inline.hpp"
51 #include "oops/oop.inline.hpp"
52 #include "oops/typeArrayOop.inline.hpp"
53 #include "opto/ad.hpp"
54 #include "opto/addnode.hpp"
55 #include "opto/callnode.hpp"
56 #include "opto/cfgnode.hpp"
57 #include "opto/graphKit.hpp"
58 #include "opto/machnode.hpp"
59 #include "opto/matcher.hpp"
60 #include "opto/memnode.hpp"
61 #include "opto/mulnode.hpp"
62 #include "opto/output.hpp"
63 #include "opto/runtime.hpp"
64 #include "opto/subnode.hpp"
65 #include "prims/jvmtiExport.hpp"
66 #include "runtime/atomic.hpp"
67 #include "runtime/frame.inline.hpp"
68 #include "runtime/handles.inline.hpp"
181
182 C2_STUBS_DO(GEN_C2_BLOB, GEN_C2_STUB, GEN_C2_JVMTI_STUB)
183
184 return true;
185 }
186
187 #undef GEN_C2_BLOB
188
189 #undef C2_STUB_FIELD_NAME
190 #undef C2_STUB_TYPEFUNC
191 #undef C2_STUB_C_FUNC
192 #undef C2_STUB_NAME
193 #undef GEN_C2_STUB
194
195 #undef C2_JVMTI_STUB_C_FUNC
196 #undef GEN_C2_JVMTI_STUB
197 // #undef gen
198
199 const TypeFunc* OptoRuntime::_new_instance_Type = nullptr;
200 const TypeFunc* OptoRuntime::_new_array_Type = nullptr;
201 const TypeFunc* OptoRuntime::_new_array_nozero_Type = nullptr;
202 const TypeFunc* OptoRuntime::_multianewarray2_Type = nullptr;
203 const TypeFunc* OptoRuntime::_multianewarray3_Type = nullptr;
204 const TypeFunc* OptoRuntime::_multianewarray4_Type = nullptr;
205 const TypeFunc* OptoRuntime::_multianewarray5_Type = nullptr;
206 const TypeFunc* OptoRuntime::_multianewarrayN_Type = nullptr;
207 const TypeFunc* OptoRuntime::_complete_monitor_enter_Type = nullptr;
208 const TypeFunc* OptoRuntime::_complete_monitor_exit_Type = nullptr;
209 const TypeFunc* OptoRuntime::_monitor_notify_Type = nullptr;
210 const TypeFunc* OptoRuntime::_uncommon_trap_Type = nullptr;
211 const TypeFunc* OptoRuntime::_athrow_Type = nullptr;
212 const TypeFunc* OptoRuntime::_rethrow_Type = nullptr;
213 const TypeFunc* OptoRuntime::_Math_D_D_Type = nullptr;
214 const TypeFunc* OptoRuntime::_Math_DD_D_Type = nullptr;
215 const TypeFunc* OptoRuntime::_modf_Type = nullptr;
216 const TypeFunc* OptoRuntime::_l2f_Type = nullptr;
217 const TypeFunc* OptoRuntime::_void_long_Type = nullptr;
218 const TypeFunc* OptoRuntime::_void_void_Type = nullptr;
219 const TypeFunc* OptoRuntime::_jfr_write_checkpoint_Type = nullptr;
220 const TypeFunc* OptoRuntime::_flush_windows_Type = nullptr;
221 const TypeFunc* OptoRuntime::_fast_arraycopy_Type = nullptr;
307 oopDesc* dest, jint dest_pos,
308 jint length, JavaThread* thread) {
309 SharedRuntime::slow_arraycopy_C(src, src_pos, dest, dest_pos, length, thread);
310 }
311
312 void OptoRuntime::complete_monitor_locking_C(oopDesc* obj, BasicLock* lock, JavaThread* current) {
313 SharedRuntime::complete_monitor_locking_C(obj, lock, current);
314 }
315
316
317 //=============================================================================
318 // Opto compiler runtime routines
319 //=============================================================================
320
321
322 //=============================allocation======================================
323 // We failed the fast-path allocation. Now we need to do a scavenge or GC
324 // and try allocation again.
325
326 // object allocation
327 JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(Klass* klass, bool is_larval, JavaThread* current))
328 JRT_BLOCK;
329 #ifndef PRODUCT
330 SharedRuntime::_new_instance_ctr++; // new instance requires GC
331 #endif
332 assert(check_compiled_frame(current), "incorrect caller");
333
334 // These checks are cheap to make and support reflective allocation.
335 int lh = klass->layout_helper();
336 if (Klass::layout_helper_needs_slow_path(lh) || !InstanceKlass::cast(klass)->is_initialized()) {
337 Handle holder(current, klass->klass_holder()); // keep the klass alive
338 klass->check_valid_for_instantiation(false, THREAD);
339 if (!HAS_PENDING_EXCEPTION) {
340 InstanceKlass::cast(klass)->initialize(THREAD);
341 }
342 }
343
344 if (!HAS_PENDING_EXCEPTION) {
345 // Scavenge and allocate an instance.
346 Handle holder(current, klass->klass_holder()); // keep the klass alive
347 instanceOop result = InstanceKlass::cast(klass)->allocate_instance(THREAD);
348 if (is_larval) {
349 // Check if this is a larval buffer allocation
350 result->set_mark(result->mark().enter_larval_state());
351 }
352 current->set_vm_result(result);
353
354 // Pass oops back through thread local storage. Our apparent type to Java
355 // is that we return an oop, but we can block on exit from this routine and
356 // a GC can trash the oop in C's return register. The generated stub will
357 // fetch the oop from TLS after any possible GC.
358 }
359
360 deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION);
361 JRT_BLOCK_END;
362
363 // inform GC that we won't do card marks for initializing writes.
364 SharedRuntime::on_slowpath_allocation_exit(current);
365 JRT_END
366
367
368 // array allocation
369 JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(Klass* array_type, int len, oopDesc* init_val, JavaThread* current))
370 JRT_BLOCK;
371 #ifndef PRODUCT
372 SharedRuntime::_new_array_ctr++; // new array requires GC
373 #endif
374 assert(check_compiled_frame(current), "incorrect caller");
375
376 // Scavenge and allocate an instance.
377 oop result;
378 Handle h_init_val(current, init_val); // keep the init_val object alive
379
380 if (array_type->is_flatArray_klass()) {
381 Handle holder(current, array_type->klass_holder()); // keep the array klass alive
382 FlatArrayKlass* fak = FlatArrayKlass::cast(array_type);
383 InlineKlass* vk = fak->element_klass();
384 result = oopFactory::new_flatArray(vk, len, fak->layout_kind(), THREAD);
385 if (array_type->is_null_free_array_klass() && !h_init_val.is_null()) {
386 // Null-free arrays need to be initialized
387 for (int i = 0; i < len; i++) {
388 vk->write_value_to_addr(h_init_val(), ((flatArrayOop)result)->value_at_addr(i, fak->layout_helper()), fak->layout_kind(), true, CHECK);
389 }
390 }
391 } else if (array_type->is_typeArray_klass()) {
392 // The oopFactory likes to work with the element type.
393 // (We could bypass the oopFactory, since it doesn't add much value.)
394 BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type();
395 result = oopFactory::new_typeArray(elem_type, len, THREAD);
396 } else {
397 Handle holder(current, array_type->klass_holder()); // keep the array klass alive
398 ObjArrayKlass* array_klass = ObjArrayKlass::cast(array_type);
399 result = array_klass->allocate(len, THREAD);
400 if (array_type->is_null_free_array_klass() && !h_init_val.is_null()) {
401 // Null-free arrays need to be initialized
402 for (int i = 0; i < len; i++) {
403 ((objArrayOop)result)->obj_at_put(i, h_init_val());
404 }
405 }
406 }
407
408 // Pass oops back through thread local storage. Our apparent type to Java
409 // is that we return an oop, but we can block on exit from this routine and
410 // a GC can trash the oop in C's return register. The generated stub will
411 // fetch the oop from TLS after any possible GC.
412 deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION);
413 current->set_vm_result(result);
414 JRT_BLOCK_END;
415
416 // inform GC that we won't do card marks for initializing writes.
417 SharedRuntime::on_slowpath_allocation_exit(current);
418 JRT_END
419
420 // array allocation without zeroing
421 JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_nozero_C(Klass* array_type, int len, JavaThread* current))
422 JRT_BLOCK;
423 #ifndef PRODUCT
424 SharedRuntime::_new_array_ctr++; // new array requires GC
425 #endif
582 JRT_BLOCK_ENTRY(void, OptoRuntime::monitor_notifyAll_C(oopDesc* obj, JavaThread* current))
583
584 if (!SafepointSynchronize::is_synchronizing() ) {
585 if (ObjectSynchronizer::quick_notify(obj, current, true)) {
586 return;
587 }
588 }
589
590 // This is the case the fast-path above isn't provisioned to handle.
591 // The fast-path is designed to handle frequently arising cases in an efficient manner.
592 // (The fast-path is just a degenerate variant of the slow-path).
593 // Perform the dreaded state transition and pass control into the slow-path.
594 JRT_BLOCK;
595 Handle h_obj(current, obj);
596 ObjectSynchronizer::notifyall(h_obj, CHECK);
597 JRT_BLOCK_END;
598 JRT_END
599
600 static const TypeFunc* make_new_instance_Type() {
601 // create input type (domain)
602 const Type **fields = TypeTuple::fields(2);
603 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Klass to be allocated
604 fields[TypeFunc::Parms+1] = TypeInt::BOOL; // is_larval
605 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields);
606
607 // create result type (range)
608 fields = TypeTuple::fields(1);
609 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop
610
611 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields);
612
613 return TypeFunc::make(domain, range);
614 }
615
616 #if INCLUDE_JVMTI
617 static const TypeFunc* make_notify_jvmti_vthread_Type() {
618 // create input type (domain)
619 const Type **fields = TypeTuple::fields(2);
620 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // VirtualThread oop
621 fields[TypeFunc::Parms+1] = TypeInt::BOOL; // jboolean
622 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields);
623
624 // no result type needed
625 fields = TypeTuple::fields(1);
628
629 return TypeFunc::make(domain,range);
630 }
631 #endif
632
633 static const TypeFunc* make_athrow_Type() {
634 // create input type (domain)
635 const Type **fields = TypeTuple::fields(1);
636 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Klass to be allocated
637 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields);
638
639 // create result type (range)
640 fields = TypeTuple::fields(0);
641
642 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
643
644 return TypeFunc::make(domain, range);
645 }
646
647 static const TypeFunc* make_new_array_Type() {
648 // create input type (domain)
649 const Type **fields = TypeTuple::fields(3);
650 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // element klass
651 fields[TypeFunc::Parms+1] = TypeInt::INT; // array size
652 fields[TypeFunc::Parms+2] = TypeInstPtr::NOTNULL; // init value
653 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+3, fields);
654
655 // create result type (range)
656 fields = TypeTuple::fields(1);
657 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop
658
659 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields);
660
661 return TypeFunc::make(domain, range);
662 }
663
664 static const TypeFunc* make_new_array_nozero_Type() {
665 // create input type (domain)
666 const Type **fields = TypeTuple::fields(2);
667 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // element klass
668 fields[TypeFunc::Parms+1] = TypeInt::INT; // array size
669 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields);
670
671 // create result type (range)
672 fields = TypeTuple::fields(1);
673 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop
674
675 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields);
676
677 return TypeFunc::make(domain, range);
678 }
679
680 const TypeFunc* OptoRuntime::multianewarray_Type(int ndim) {
681 // create input type (domain)
682 const int nargs = ndim + 1;
683 const Type **fields = TypeTuple::fields(nargs);
684 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // element klass
720 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
721
722 return TypeFunc::make(domain, range);
723 }
724
725 //-----------------------------------------------------------------------------
726 // Monitor Handling
727
728 static const TypeFunc* make_complete_monitor_enter_Type() {
729 // create input type (domain)
730 const Type **fields = TypeTuple::fields(2);
731 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Object to be Locked
732 fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // Address of stack location for lock
733 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields);
734
735 // create result type (range)
736 fields = TypeTuple::fields(0);
737
738 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields);
739
740 return TypeFunc::make(domain, range);
741 }
742
743 //-----------------------------------------------------------------------------
744
745 static const TypeFunc* make_complete_monitor_exit_Type() {
746 // create input type (domain)
747 const Type **fields = TypeTuple::fields(3);
748 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Object to be Locked
749 fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // Address of stack location for lock - BasicLock
750 fields[TypeFunc::Parms+2] = TypeRawPtr::BOTTOM; // Thread pointer (Self)
751 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+3, fields);
752
753 // create result type (range)
754 fields = TypeTuple::fields(0);
755
756 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
757
758 return TypeFunc::make(domain, range);
759 }
760
1958 RegisterMap::WalkContinuation::skip);
1959 frame stub_frame = thread->last_frame();
1960 assert(stub_frame.is_runtime_frame() || exception_blob()->contains(stub_frame.pc()), "sanity check");
1961 frame caller_frame = stub_frame.sender(®_map);
1962 return caller_frame.is_deoptimized_frame();
1963 }
1964
1965 static const TypeFunc* make_register_finalizer_Type() {
1966 // create input type (domain)
1967 const Type **fields = TypeTuple::fields(1);
1968 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // oop; Receiver
1969 // // The JavaThread* is passed to each routine as the last argument
1970 // fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL; // JavaThread *; Executing thread
1971 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1,fields);
1972
1973 // create result type (range)
1974 fields = TypeTuple::fields(0);
1975
1976 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields);
1977
1978 return TypeFunc::make(domain, range);
1979 }
1980
1981 #if INCLUDE_JFR
1982 static const TypeFunc* make_class_id_load_barrier_Type() {
1983 // create input type (domain)
1984 const Type **fields = TypeTuple::fields(1);
1985 fields[TypeFunc::Parms+0] = TypeInstPtr::KLASS;
1986 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms + 1, fields);
1987
1988 // create result type (range)
1989 fields = TypeTuple::fields(0);
1990
1991 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms + 0, fields);
1992
1993 return TypeFunc::make(domain,range);
1994 }
1995 #endif // INCLUDE_JFR
1996
1997 //-----------------------------------------------------------------------------
1998 static const TypeFunc* make_dtrace_method_entry_exit_Type() {
1999 // create input type (domain)
2000 const Type **fields = TypeTuple::fields(2);
2001 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // Thread-local storage
2002 fields[TypeFunc::Parms+1] = TypeMetadataPtr::BOTTOM; // Method*; Method we are entering
2003 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields);
2004
2005 // create result type (range)
2006 fields = TypeTuple::fields(0);
2007
2008 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields);
2009
2010 return TypeFunc::make(domain, range);
2011 }
2012
2013 static const TypeFunc* make_dtrace_object_alloc_Type() {
2014 // create input type (domain)
2015 const Type **fields = TypeTuple::fields(2);
2016 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // Thread-local storage
2017 fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // oop; newly allocated object
2018
2019 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields);
2020
2021 // create result type (range)
2022 fields = TypeTuple::fields(0);
2023
2024 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields);
2025
2026 return TypeFunc::make(domain, range);
2027 }
2028
2029 JRT_ENTRY_NO_ASYNC(void, OptoRuntime::register_finalizer_C(oopDesc* obj, JavaThread* current))
2030 assert(oopDesc::is_oop(obj), "must be a valid oop");
2031 assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
2032 InstanceKlass::register_finalizer(instanceOop(obj), CHECK);
2033 JRT_END
2034
2035 //-----------------------------------------------------------------------------
2036
2037 NamedCounter * volatile OptoRuntime::_named_counters = nullptr;
2038
2039 //
2040 // dump the collected NamedCounters.
2041 //
2042 void OptoRuntime::print_named_counters() {
2043 int total_lock_count = 0;
2044 int eliminated_lock_count = 0;
2045
2046 NamedCounter* c = _named_counters;
2097 }
2098 st.print("@%d", bci);
2099 // To print linenumbers instead of bci use: m->line_number_from_bci(bci)
2100 }
2101 NamedCounter* c = new NamedCounter(st.freeze(), tag);
2102
2103 // atomically add the new counter to the head of the list. We only
2104 // add counters so this is safe.
2105 NamedCounter* head;
2106 do {
2107 c->set_next(nullptr);
2108 head = _named_counters;
2109 c->set_next(head);
2110 } while (Atomic::cmpxchg(&_named_counters, head, c) != head);
2111 return c;
2112 }
2113
2114 void OptoRuntime::initialize_types() {
2115 _new_instance_Type = make_new_instance_Type();
2116 _new_array_Type = make_new_array_Type();
2117 _new_array_nozero_Type = make_new_array_nozero_Type();
2118 _multianewarray2_Type = multianewarray_Type(2);
2119 _multianewarray3_Type = multianewarray_Type(3);
2120 _multianewarray4_Type = multianewarray_Type(4);
2121 _multianewarray5_Type = multianewarray_Type(5);
2122 _multianewarrayN_Type = make_multianewarrayN_Type();
2123 _complete_monitor_enter_Type = make_complete_monitor_enter_Type();
2124 _complete_monitor_exit_Type = make_complete_monitor_exit_Type();
2125 _monitor_notify_Type = make_monitor_notify_Type();
2126 _uncommon_trap_Type = make_uncommon_trap_Type();
2127 _athrow_Type = make_athrow_Type();
2128 _rethrow_Type = make_rethrow_Type();
2129 _Math_D_D_Type = make_Math_D_D_Type();
2130 _Math_DD_D_Type = make_Math_DD_D_Type();
2131 _modf_Type = make_modf_Type();
2132 _l2f_Type = make_l2f_Type();
2133 _void_long_Type = make_void_long_Type();
2134 _void_void_Type = make_void_void_Type();
2135 _jfr_write_checkpoint_Type = make_jfr_write_checkpoint_Type();
2136 _flush_windows_Type = make_flush_windows_Type();
2137 _fast_arraycopy_Type = make_arraycopy_Type(ac_fast);
2193 static void trace_exception(outputStream* st, oop exception_oop, address exception_pc, const char* msg) {
2194 trace_exception_counter++;
2195 stringStream tempst;
2196
2197 tempst.print("%d [Exception (%s): ", trace_exception_counter, msg);
2198 exception_oop->print_value_on(&tempst);
2199 tempst.print(" in ");
2200 CodeBlob* blob = CodeCache::find_blob(exception_pc);
2201 if (blob->is_nmethod()) {
2202 blob->as_nmethod()->method()->print_value_on(&tempst);
2203 } else if (blob->is_runtime_stub()) {
2204 tempst.print("<runtime-stub>");
2205 } else {
2206 tempst.print("<unknown>");
2207 }
2208 tempst.print(" at " INTPTR_FORMAT, p2i(exception_pc));
2209 tempst.print("]");
2210
2211 st->print_raw_cr(tempst.freeze());
2212 }
2213
2214 const TypeFunc *OptoRuntime::store_inline_type_fields_Type() {
2215 // create input type (domain)
2216 uint total = SharedRuntime::java_return_convention_max_int + SharedRuntime::java_return_convention_max_float*2;
2217 const Type **fields = TypeTuple::fields(total);
2218 // We don't know the number of returned values and their
2219 // types. Assume all registers available to the return convention
2220 // are used.
2221 fields[TypeFunc::Parms] = TypePtr::BOTTOM;
2222 uint i = 1;
2223 for (; i < SharedRuntime::java_return_convention_max_int; i++) {
2224 fields[TypeFunc::Parms+i] = TypeInt::INT;
2225 }
2226 for (; i < total; i+=2) {
2227 fields[TypeFunc::Parms+i] = Type::DOUBLE;
2228 fields[TypeFunc::Parms+i+1] = Type::HALF;
2229 }
2230 const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + total, fields);
2231
2232 // create result type (range)
2233 fields = TypeTuple::fields(1);
2234 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL;
2235
2236 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1,fields);
2237
2238 return TypeFunc::make(domain, range);
2239 }
2240
2241 const TypeFunc *OptoRuntime::pack_inline_type_Type() {
2242 // create input type (domain)
2243 uint total = 1 + SharedRuntime::java_return_convention_max_int + SharedRuntime::java_return_convention_max_float*2;
2244 const Type **fields = TypeTuple::fields(total);
2245 // We don't know the number of returned values and their
2246 // types. Assume all registers available to the return convention
2247 // are used.
2248 fields[TypeFunc::Parms] = TypeRawPtr::BOTTOM;
2249 fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM;
2250 uint i = 2;
2251 for (; i < SharedRuntime::java_return_convention_max_int+1; i++) {
2252 fields[TypeFunc::Parms+i] = TypeInt::INT;
2253 }
2254 for (; i < total; i+=2) {
2255 fields[TypeFunc::Parms+i] = Type::DOUBLE;
2256 fields[TypeFunc::Parms+i+1] = Type::HALF;
2257 }
2258 const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + total, fields);
2259
2260 // create result type (range)
2261 fields = TypeTuple::fields(1);
2262 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL;
2263
2264 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1,fields);
2265
2266 return TypeFunc::make(domain, range);
2267 }
2268
2269 JRT_BLOCK_ENTRY(void, OptoRuntime::load_unknown_inline_C(flatArrayOopDesc* array, int index, JavaThread* current))
2270 JRT_BLOCK;
2271 oop buffer = array->read_value_from_flat_array(index, THREAD);
2272 deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION);
2273 current->set_vm_result(buffer);
2274 JRT_BLOCK_END;
2275 JRT_END
2276
2277 const TypeFunc* OptoRuntime::load_unknown_inline_Type() {
2278 // create input type (domain)
2279 const Type** fields = TypeTuple::fields(2);
2280 fields[TypeFunc::Parms] = TypeOopPtr::NOTNULL;
2281 fields[TypeFunc::Parms+1] = TypeInt::POS;
2282
2283 const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+2, fields);
2284
2285 // create result type (range)
2286 fields = TypeTuple::fields(1);
2287 fields[TypeFunc::Parms] = TypeInstPtr::BOTTOM;
2288
2289 const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+1, fields);
2290
2291 return TypeFunc::make(domain, range);
2292 }
2293
2294 JRT_BLOCK_ENTRY(void, OptoRuntime::store_unknown_inline_C(instanceOopDesc* buffer, flatArrayOopDesc* array, int index, JavaThread* current))
2295 JRT_BLOCK;
2296 array->write_value_to_flat_array(buffer, index, THREAD);
2297 if (HAS_PENDING_EXCEPTION) {
2298 fatal("This entry must be changed to be a non-leaf entry because writing to a flat array can now throw an exception");
2299 }
2300 JRT_BLOCK_END;
2301 JRT_END
2302
2303 const TypeFunc* OptoRuntime::store_unknown_inline_Type() {
2304 // create input type (domain)
2305 const Type** fields = TypeTuple::fields(3);
2306 fields[TypeFunc::Parms] = TypeInstPtr::NOTNULL;
2307 fields[TypeFunc::Parms+1] = TypeOopPtr::NOTNULL;
2308 fields[TypeFunc::Parms+2] = TypeInt::POS;
2309
2310 const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+3, fields);
2311
2312 // create result type (range)
2313 fields = TypeTuple::fields(0);
2314 const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields);
2315
2316 return TypeFunc::make(domain, range);
2317 }
|