Mercurial > hg > truffle
comparison src/share/vm/oops/method.cpp @ 10105:aeaca88565e6
8010862: The Method counter fields used for profiling can be allocated lazily.
Summary: Allocate the method's profiling related metadata until they are needed.
Reviewed-by: coleenp, roland
author | jiangli |
---|---|
date | Tue, 09 Apr 2013 17:17:41 -0400 |
parents | 0ca3dd0ffaba |
children | 0cfa93c2fcc4 |
comparison
equal
deleted
inserted
replaced
9055:dcdeb150988c | 10105:aeaca88565e6 |
---|---|
89 set_jfr_towrite(false); | 89 set_jfr_towrite(false); |
90 set_force_inline(false); | 90 set_force_inline(false); |
91 set_hidden(false); | 91 set_hidden(false); |
92 set_dont_inline(false); | 92 set_dont_inline(false); |
93 set_method_data(NULL); | 93 set_method_data(NULL); |
94 set_interpreter_throwout_count(0); | 94 set_method_counters(NULL); |
95 set_vtable_index(Method::garbage_vtable_index); | 95 set_vtable_index(Method::garbage_vtable_index); |
96 | 96 |
97 // Fix and bury in Method* | 97 // Fix and bury in Method* |
98 set_interpreter_entry(NULL); // sets i2i entry and from_int | 98 set_interpreter_entry(NULL); // sets i2i entry and from_int |
99 set_adapter_entry(NULL); | 99 set_adapter_entry(NULL); |
103 clear_native_function(); | 103 clear_native_function(); |
104 set_signature_handler(NULL); | 104 set_signature_handler(NULL); |
105 } | 105 } |
106 | 106 |
107 NOT_PRODUCT(set_compiled_invocation_count(0);) | 107 NOT_PRODUCT(set_compiled_invocation_count(0);) |
108 set_interpreter_invocation_count(0); | |
109 invocation_counter()->init(); | |
110 backedge_counter()->init(); | |
111 clear_number_of_breakpoints(); | |
112 | |
113 #ifdef TIERED | |
114 set_rate(0); | |
115 set_prev_event_count(0); | |
116 set_prev_time(0); | |
117 #endif | |
118 } | 108 } |
119 | 109 |
120 // Release Method*. The nmethod will be gone when we get here because | 110 // Release Method*. The nmethod will be gone when we get here because |
121 // we've walked the code cache. | 111 // we've walked the code cache. |
122 void Method::deallocate_contents(ClassLoaderData* loader_data) { | 112 void Method::deallocate_contents(ClassLoaderData* loader_data) { |
123 MetadataFactory::free_metadata(loader_data, constMethod()); | 113 MetadataFactory::free_metadata(loader_data, constMethod()); |
124 set_constMethod(NULL); | 114 set_constMethod(NULL); |
125 MetadataFactory::free_metadata(loader_data, method_data()); | 115 MetadataFactory::free_metadata(loader_data, method_data()); |
126 set_method_data(NULL); | 116 set_method_data(NULL); |
117 MetadataFactory::free_metadata(loader_data, method_counters()); | |
118 set_method_counters(NULL); | |
127 // The nmethod will be gone when we get here. | 119 // The nmethod will be gone when we get here. |
128 if (code() != NULL) _code = NULL; | 120 if (code() != NULL) _code = NULL; |
129 } | 121 } |
130 | 122 |
131 address Method::get_i2c_entry() { | 123 address Method::get_i2c_entry() { |
321 if (is_accessor() || is_empty_method() || (code() != NULL)) { | 313 if (is_accessor() || is_empty_method() || (code() != NULL)) { |
322 // interpreter doesn't bump invocation counter of trivial methods | 314 // interpreter doesn't bump invocation counter of trivial methods |
323 // compiler does not bump invocation counter of compiled methods | 315 // compiler does not bump invocation counter of compiled methods |
324 return true; | 316 return true; |
325 } | 317 } |
326 else if (_invocation_counter.carry() || (method_data() != NULL && method_data()->invocation_counter()->carry())) { | 318 else if ((method_counters() != NULL && |
319 method_counters()->invocation_counter()->carry()) || | |
320 (method_data() != NULL && | |
321 method_data()->invocation_counter()->carry())) { | |
327 // The carry bit is set when the counter overflows and causes | 322 // The carry bit is set when the counter overflows and causes |
328 // a compilation to occur. We don't know how many times | 323 // a compilation to occur. We don't know how many times |
329 // the counter has been reset, so we simply assume it has | 324 // the counter has been reset, so we simply assume it has |
330 // been executed more than n times. | 325 // been executed more than n times. |
331 return true; | 326 return true; |
383 method->print_name(tty); | 378 method->print_name(tty); |
384 tty->cr(); | 379 tty->cr(); |
385 // At the end of the run, the MDO, full of data, will be dumped. | 380 // At the end of the run, the MDO, full of data, will be dumped. |
386 } | 381 } |
387 } | 382 } |
383 } | |
384 | |
385 MethodCounters* Method::build_method_counters(Method* m, TRAPS) { | |
386 methodHandle mh(m); | |
387 ClassLoaderData* loader_data = mh->method_holder()->class_loader_data(); | |
388 MethodCounters* counters = MethodCounters::allocate(loader_data, CHECK_NULL); | |
389 if (mh->method_counters() == NULL) { | |
390 mh->set_method_counters(counters); | |
391 } else { | |
392 MetadataFactory::free_metadata(loader_data, counters); | |
393 } | |
394 return mh->method_counters(); | |
388 } | 395 } |
389 | 396 |
390 void Method::cleanup_inline_caches() { | 397 void Method::cleanup_inline_caches() { |
391 // The current system doesn't use inline caches in the interpreter | 398 // The current system doesn't use inline caches in the interpreter |
392 // => nothing to do (keep this method around for future use) | 399 // => nothing to do (keep this method around for future use) |
792 if (is_native()) { | 799 if (is_native()) { |
793 *native_function_addr() = NULL; | 800 *native_function_addr() = NULL; |
794 set_signature_handler(NULL); | 801 set_signature_handler(NULL); |
795 } | 802 } |
796 NOT_PRODUCT(set_compiled_invocation_count(0);) | 803 NOT_PRODUCT(set_compiled_invocation_count(0);) |
797 invocation_counter()->reset(); | |
798 backedge_counter()->reset(); | |
799 _adapter = NULL; | 804 _adapter = NULL; |
800 _from_compiled_entry = NULL; | 805 _from_compiled_entry = NULL; |
801 | 806 |
802 // In case of DumpSharedSpaces, _method_data should always be NULL. | 807 // In case of DumpSharedSpaces, _method_data should always be NULL. |
803 // | 808 // |
806 // have already been called (before an exception happened), so | 811 // have already been called (before an exception happened), so |
807 // this->_method_data may not be NULL. | 812 // this->_method_data may not be NULL. |
808 assert(!DumpSharedSpaces || _method_data == NULL, "unexpected method data?"); | 813 assert(!DumpSharedSpaces || _method_data == NULL, "unexpected method data?"); |
809 | 814 |
810 set_method_data(NULL); | 815 set_method_data(NULL); |
811 set_interpreter_throwout_count(0); | 816 set_method_counters(NULL); |
812 set_interpreter_invocation_count(0); | |
813 } | 817 } |
814 | 818 |
815 // Called when the method_holder is getting linked. Setup entrypoints so the method | 819 // Called when the method_holder is getting linked. Setup entrypoints so the method |
816 // is ready to be called from interpreter, compiler, and vtables. | 820 // is ready to be called from interpreter, compiler, and vtables. |
817 void Method::link_method(methodHandle h_method, TRAPS) { | 821 void Method::link_method(methodHandle h_method, TRAPS) { |
1543 clear_matches(this, -1); | 1547 clear_matches(this, -1); |
1544 } | 1548 } |
1545 | 1549 |
1546 | 1550 |
1547 int Method::invocation_count() { | 1551 int Method::invocation_count() { |
1552 MethodCounters *mcs = method_counters(); | |
1548 if (TieredCompilation) { | 1553 if (TieredCompilation) { |
1549 MethodData* const mdo = method_data(); | 1554 MethodData* const mdo = method_data(); |
1550 if (invocation_counter()->carry() || ((mdo != NULL) ? mdo->invocation_counter()->carry() : false)) { | 1555 if (((mcs != NULL) ? mcs->invocation_counter()->carry() : false) || |
1556 ((mdo != NULL) ? mdo->invocation_counter()->carry() : false)) { | |
1551 return InvocationCounter::count_limit; | 1557 return InvocationCounter::count_limit; |
1552 } else { | 1558 } else { |
1553 return invocation_counter()->count() + ((mdo != NULL) ? mdo->invocation_counter()->count() : 0); | 1559 return ((mcs != NULL) ? mcs->invocation_counter()->count() : 0) + |
1560 ((mdo != NULL) ? mdo->invocation_counter()->count() : 0); | |
1554 } | 1561 } |
1555 } else { | 1562 } else { |
1556 return invocation_counter()->count(); | 1563 return (mcs == NULL) ? 0 : mcs->invocation_counter()->count(); |
1557 } | 1564 } |
1558 } | 1565 } |
1559 | 1566 |
1560 int Method::backedge_count() { | 1567 int Method::backedge_count() { |
1568 MethodCounters *mcs = method_counters(); | |
1561 if (TieredCompilation) { | 1569 if (TieredCompilation) { |
1562 MethodData* const mdo = method_data(); | 1570 MethodData* const mdo = method_data(); |
1563 if (backedge_counter()->carry() || ((mdo != NULL) ? mdo->backedge_counter()->carry() : false)) { | 1571 if (((mcs != NULL) ? mcs->backedge_counter()->carry() : false) || |
1572 ((mdo != NULL) ? mdo->backedge_counter()->carry() : false)) { | |
1564 return InvocationCounter::count_limit; | 1573 return InvocationCounter::count_limit; |
1565 } else { | 1574 } else { |
1566 return backedge_counter()->count() + ((mdo != NULL) ? mdo->backedge_counter()->count() : 0); | 1575 return ((mcs != NULL) ? mcs->backedge_counter()->count() : 0) + |
1576 ((mdo != NULL) ? mdo->backedge_counter()->count() : 0); | |
1567 } | 1577 } |
1568 } else { | 1578 } else { |
1569 return backedge_counter()->count(); | 1579 return (mcs == NULL) ? 0 : mcs->backedge_counter()->count(); |
1570 } | 1580 } |
1571 } | 1581 } |
1572 | 1582 |
1573 int Method::highest_comp_level() const { | 1583 int Method::highest_comp_level() const { |
1574 MethodData* mdo = method_data(); | 1584 MethodData* mdo = method_data(); |
1619 if (code == Bytecodes::_breakpoint) | 1629 if (code == Bytecodes::_breakpoint) |
1620 code = method->orig_bytecode_at(_bci); | 1630 code = method->orig_bytecode_at(_bci); |
1621 assert(orig_bytecode() == code, "original bytecode must be the same"); | 1631 assert(orig_bytecode() == code, "original bytecode must be the same"); |
1622 } | 1632 } |
1623 #endif | 1633 #endif |
1634 Thread *thread = Thread::current(); | |
1624 *method->bcp_from(_bci) = Bytecodes::_breakpoint; | 1635 *method->bcp_from(_bci) = Bytecodes::_breakpoint; |
1625 method->incr_number_of_breakpoints(); | 1636 method->incr_number_of_breakpoints(thread); |
1626 SystemDictionary::notice_modification(); | 1637 SystemDictionary::notice_modification(); |
1627 { | 1638 { |
1628 // Deoptimize all dependents on this method | 1639 // Deoptimize all dependents on this method |
1629 Thread *thread = Thread::current(); | |
1630 HandleMark hm(thread); | 1640 HandleMark hm(thread); |
1631 methodHandle mh(thread, method); | 1641 methodHandle mh(thread, method); |
1632 Universe::flush_dependents_on_method(mh); | 1642 Universe::flush_dependents_on_method(mh); |
1633 } | 1643 } |
1634 } | 1644 } |
1635 | 1645 |
1636 void BreakpointInfo::clear(Method* method) { | 1646 void BreakpointInfo::clear(Method* method) { |
1637 *method->bcp_from(_bci) = orig_bytecode(); | 1647 *method->bcp_from(_bci) = orig_bytecode(); |
1638 assert(method->number_of_breakpoints() > 0, "must not go negative"); | 1648 assert(method->number_of_breakpoints() > 0, "must not go negative"); |
1639 method->decr_number_of_breakpoints(); | 1649 method->decr_number_of_breakpoints(Thread::current()); |
1640 } | 1650 } |
1641 | 1651 |
1642 // jmethodID handling | 1652 // jmethodID handling |
1643 | 1653 |
1644 // This is a block allocating object, sort of like JNIHandleBlock, only a | 1654 // This is a block allocating object, sort of like JNIHandleBlock, only a |