mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 03:24:38 +02:00
Merge
This commit is contained in:
commit
a03d25366a
11 changed files with 53 additions and 16 deletions
|
@ -1997,7 +1997,13 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
|
|||
if (!UseInlineCaches && is_loaded && code == Bytecodes::_invokevirtual
|
||||
&& !target->can_be_statically_bound()) {
|
||||
// Find a vtable index if one is available
|
||||
vtable_index = target->resolve_vtable_index(calling_klass, callee_holder);
|
||||
// For arrays, callee_holder is Object. Resolving the call with
|
||||
// Object would allow an illegal call to finalize() on an
|
||||
// array. We use holder instead: illegal calls to finalize() won't
|
||||
// be compiled as vtable calls (IC call resolution will catch the
|
||||
// illegal call) and the few legal calls on array types won't be
|
||||
// either.
|
||||
vtable_index = target->resolve_vtable_index(calling_klass, holder);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "precompiled.hpp"
|
||||
#include "code/vtableStubs.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "compiler/disassembler.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
|
@ -62,6 +63,7 @@ void* VtableStub::operator new(size_t size, int code_size) throw() {
|
|||
// If changing the name, update the other file accordingly.
|
||||
BufferBlob* blob = BufferBlob::create("vtable chunks", bytes);
|
||||
if (blob == NULL) {
|
||||
CompileBroker::handle_full_code_cache();
|
||||
return NULL;
|
||||
}
|
||||
_chunk = blob->content_begin();
|
||||
|
|
|
@ -1093,6 +1093,7 @@ IRT_END
|
|||
address SignatureHandlerLibrary::set_handler_blob() {
|
||||
BufferBlob* handler_blob = BufferBlob::create("native signature handlers", blob_size);
|
||||
if (handler_blob == NULL) {
|
||||
CompileBroker::handle_full_code_cache();
|
||||
return NULL;
|
||||
}
|
||||
address handler = handler_blob->code_begin();
|
||||
|
|
|
@ -871,8 +871,11 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod*
|
|||
Node* receiver_node = kit.argument(0);
|
||||
const TypeOopPtr* receiver_type = gvn.type(receiver_node)->isa_oopptr();
|
||||
// call_does_dispatch and vtable_index are out-parameters. They might be changed.
|
||||
target = C->optimize_virtual_call(caller, jvms->bci(), klass, target, receiver_type,
|
||||
is_virtual,
|
||||
// optimize_virtual_call() takes 2 different holder
|
||||
// arguments for a corner case that doesn't apply here (see
|
||||
// Parse::do_call())
|
||||
target = C->optimize_virtual_call(caller, jvms->bci(), klass, klass,
|
||||
target, receiver_type, is_virtual,
|
||||
call_does_dispatch, vtable_index); // out-parameters
|
||||
// We lack profiling at this call but type speculation may
|
||||
// provide us with a type
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "classfile/systemDictionary.hpp"
|
||||
#include "code/exceptionHandlerTable.hpp"
|
||||
#include "code/nmethod.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "compiler/compileLog.hpp"
|
||||
#include "compiler/disassembler.hpp"
|
||||
#include "compiler/oopMap.hpp"
|
||||
|
@ -555,6 +556,7 @@ void Compile::init_scratch_buffer_blob(int const_size) {
|
|||
if (scratch_buffer_blob() == NULL) {
|
||||
// Let CompilerBroker disable further compilations.
|
||||
record_failure("Not enough space for scratch buffer in CodeCache");
|
||||
CompileBroker::handle_full_code_cache();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -852,8 +852,8 @@ class Compile : public Phase {
|
|||
|
||||
// Helper functions to identify inlining potential at call-site
|
||||
ciMethod* optimize_virtual_call(ciMethod* caller, int bci, ciInstanceKlass* klass,
|
||||
ciMethod* callee, const TypeOopPtr* receiver_type,
|
||||
bool is_virtual,
|
||||
ciKlass* holder, ciMethod* callee,
|
||||
const TypeOopPtr* receiver_type, bool is_virtual,
|
||||
bool &call_does_dispatch, int &vtable_index);
|
||||
ciMethod* optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass* klass,
|
||||
ciMethod* callee, const TypeOopPtr* receiver_type);
|
||||
|
|
|
@ -468,8 +468,14 @@ void Parse::do_call() {
|
|||
Node* receiver_node = stack(sp() - nargs);
|
||||
const TypeOopPtr* receiver_type = _gvn.type(receiver_node)->isa_oopptr();
|
||||
// call_does_dispatch and vtable_index are out-parameters. They might be changed.
|
||||
callee = C->optimize_virtual_call(method(), bci(), klass, orig_callee, receiver_type,
|
||||
is_virtual,
|
||||
// For arrays, klass below is Object. When vtable calls are used,
|
||||
// resolving the call with Object would allow an illegal call to
|
||||
// finalize() on an array. We use holder instead: illegal calls to
|
||||
// finalize() won't be compiled as vtable calls (IC call
|
||||
// resolution will catch the illegal call) and the few legal calls
|
||||
// on array types won't be either.
|
||||
callee = C->optimize_virtual_call(method(), bci(), klass, holder, orig_callee,
|
||||
receiver_type, is_virtual,
|
||||
call_does_dispatch, vtable_index); // out-parameters
|
||||
speculative_receiver_type = receiver_type != NULL ? receiver_type->speculative_type() : NULL;
|
||||
}
|
||||
|
@ -940,8 +946,8 @@ void Parse::count_compiled_calls(bool at_method_entry, bool is_inline) {
|
|||
|
||||
|
||||
ciMethod* Compile::optimize_virtual_call(ciMethod* caller, int bci, ciInstanceKlass* klass,
|
||||
ciMethod* callee, const TypeOopPtr* receiver_type,
|
||||
bool is_virtual,
|
||||
ciKlass* holder, ciMethod* callee,
|
||||
const TypeOopPtr* receiver_type, bool is_virtual,
|
||||
bool& call_does_dispatch, int& vtable_index) {
|
||||
// Set default values for out-parameters.
|
||||
call_does_dispatch = true;
|
||||
|
@ -956,7 +962,7 @@ ciMethod* Compile::optimize_virtual_call(ciMethod* caller, int bci, ciInstanceKl
|
|||
call_does_dispatch = false;
|
||||
} else if (!UseInlineCaches && is_virtual && callee->is_loaded()) {
|
||||
// We can make a vtable call at this site
|
||||
vtable_index = callee->resolve_vtable_index(caller->holder(), klass);
|
||||
vtable_index = callee->resolve_vtable_index(caller->holder(), holder);
|
||||
}
|
||||
return callee;
|
||||
}
|
||||
|
@ -979,8 +985,10 @@ ciMethod* Compile::optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass*
|
|||
ciInstanceKlass* actual_receiver = klass;
|
||||
if (receiver_type != NULL) {
|
||||
// Array methods are all inherited from Object, and are monomorphic.
|
||||
// finalize() call on array is not allowed.
|
||||
if (receiver_type->isa_aryptr() &&
|
||||
callee->holder() == env()->Object_klass()) {
|
||||
callee->holder() == env()->Object_klass() &&
|
||||
callee->name() != ciSymbol::finalize_method_name()) {
|
||||
return callee;
|
||||
}
|
||||
|
||||
|
|
|
@ -1163,6 +1163,7 @@ CodeBuffer* Compile::init_buffer(uint* blk_starts) {
|
|||
// Have we run out of code space?
|
||||
if ((cb->blob() == NULL) || (!CompileBroker::should_compile_new_jobs())) {
|
||||
C->record_failure("CodeCache is full");
|
||||
CompileBroker::handle_full_code_cache();
|
||||
return NULL;
|
||||
}
|
||||
// Configure the code buffer.
|
||||
|
@ -1487,6 +1488,7 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) {
|
|||
cb->insts()->maybe_expand_to_ensure_remaining(MAX_inst_size);
|
||||
if ((cb->blob() == NULL) || (!CompileBroker::should_compile_new_jobs())) {
|
||||
C->record_failure("CodeCache is full");
|
||||
CompileBroker::handle_full_code_cache();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1643,6 +1645,7 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) {
|
|||
// One last check for failed CodeBuffer::expand:
|
||||
if ((cb->blob() == NULL) || (!CompileBroker::should_compile_new_jobs())) {
|
||||
C->record_failure("CodeCache is full");
|
||||
CompileBroker::handle_full_code_cache();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -557,8 +557,9 @@ class Parse : public GraphKit {
|
|||
|
||||
float dynamic_branch_prediction(float &cnt);
|
||||
float branch_prediction(float &cnt, BoolTest::mask btest, int target_bci);
|
||||
bool seems_never_taken(float prob);
|
||||
bool seems_stable_comparison(BoolTest::mask btest, Node* c);
|
||||
bool seems_never_taken(float prob) const;
|
||||
bool path_is_suitable_for_uncommon_trap(float prob) const;
|
||||
bool seems_stable_comparison() const;
|
||||
|
||||
void do_ifnull(BoolTest::mask btest, Node* c);
|
||||
void do_if(BoolTest::mask btest, Node* c);
|
||||
|
|
|
@ -886,7 +886,7 @@ float Parse::branch_prediction(float& cnt,
|
|||
// some branches (e.g., _213_javac.Assembler.eliminate) validly produce
|
||||
// very small but nonzero probabilities, which if confused with zero
|
||||
// counts would keep the program recompiling indefinitely.
|
||||
bool Parse::seems_never_taken(float prob) {
|
||||
bool Parse::seems_never_taken(float prob) const {
|
||||
return prob < PROB_MIN;
|
||||
}
|
||||
|
||||
|
@ -898,7 +898,7 @@ bool Parse::seems_never_taken(float prob) {
|
|||
// already acting in a stable fashion. If the comparison
|
||||
// seems stable, we will put an expensive uncommon trap
|
||||
// on the untaken path.
|
||||
bool Parse::seems_stable_comparison(BoolTest::mask btest, Node* cmp) {
|
||||
bool Parse::seems_stable_comparison() const {
|
||||
if (C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1127,6 +1127,14 @@ void Parse::do_if(BoolTest::mask btest, Node* c) {
|
|||
}
|
||||
}
|
||||
|
||||
bool Parse::path_is_suitable_for_uncommon_trap(float prob) const {
|
||||
// Don't want to speculate on uncommon traps when running with -Xcomp
|
||||
if (!UseInterpreter) {
|
||||
return false;
|
||||
}
|
||||
return (seems_never_taken(prob) && seems_stable_comparison());
|
||||
}
|
||||
|
||||
//----------------------------adjust_map_after_if------------------------------
|
||||
// Adjust the JVM state to reflect the result of taking this path.
|
||||
// Basically, it means inspecting the CmpNode controlling this
|
||||
|
@ -1140,7 +1148,7 @@ void Parse::adjust_map_after_if(BoolTest::mask btest, Node* c, float prob,
|
|||
|
||||
bool is_fallthrough = (path == successor_for_bci(iter().next_bci()));
|
||||
|
||||
if (seems_never_taken(prob) && seems_stable_comparison(btest, c)) {
|
||||
if (path_is_suitable_for_uncommon_trap(prob)) {
|
||||
repush_if_args();
|
||||
uncommon_trap(Deoptimization::Reason_unstable_if,
|
||||
Deoptimization::Action_reinterpret,
|
||||
|
|
|
@ -34,6 +34,9 @@ void AbstractICache::initialize() {
|
|||
ResourceMark rm;
|
||||
|
||||
BufferBlob* b = BufferBlob::create("flush_icache_stub", ICache::stub_size);
|
||||
if (b == NULL) {
|
||||
vm_exit_out_of_memory(ICache::stub_size, OOM_MALLOC_ERROR, "CodeCache: no space for flush_icache_stub");
|
||||
}
|
||||
CodeBuffer c(b);
|
||||
|
||||
ICacheStubGenerator g(&c);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue