< prev index next > src/hotspot/share/opto/output.cpp
Print this page
_code_offsets(),
_node_bundling_limit(0),
_node_bundling_base(NULL),
_orig_pc_slot(0),
_orig_pc_slot_offset_in_bytes(0),
+ _sp_inc_slot(0),
+ _sp_inc_slot_offset_in_bytes(0),
_buf_sizes(),
_block(NULL),
_index(0) {
C->set_output(this);
if (C->stub_name() == NULL) {
- _orig_pc_slot = C->fixed_slots() - (sizeof(address) / VMRegImpl::stack_slot_size);
+ int fixed_slots = C->fixed_slots();
+ if (C->needs_stack_repair()) {
+ fixed_slots -= 2;
+ _sp_inc_slot = fixed_slots;
+ }
+ _orig_pc_slot = fixed_slots - (sizeof(address) / VMRegImpl::stack_slot_size);
}
}
PhaseOutput::~PhaseOutput() {
C->set_output(NULL);
Block *broot = C->cfg()->get_root_block();
const StartNode *start = entry->head()->as_Start();
// Replace StartNode with prolog
- MachPrologNode *prolog = new MachPrologNode();
+ Label verified_entry;
+ MachPrologNode* prolog = new MachPrologNode(&verified_entry);
entry->map_node(prolog, 0);
C->cfg()->map_node_to_block(prolog, entry);
C->cfg()->unmap_node_from_block(start); // start is no longer in any block
// Virtual methods need an unverified entry point
-
- if( C->is_osr_compilation() ) {
- if( PoisonOSREntry ) {
+ if (C->is_osr_compilation()) {
+ if (PoisonOSREntry) {
// TODO: Should use a ShouldNotReachHereNode...
C->cfg()->insert( broot, 0, new MachBreakpointNode() );
}
} else {
- if( C->method() && !C->method()->flags().is_static() ) {
- // Insert unvalidated entry point
- C->cfg()->insert( broot, 0, new MachUEPNode() );
+ if (C->method()) {
+ if (C->method()->has_scalarized_args()) {
+ // Add entry point to unpack all inline type arguments
+ C->cfg()->insert(broot, 0, new MachVEPNode(&verified_entry, /* verified */ true, /* receiver_only */ false));
+ if (!C->method()->is_static()) {
+ // Add verified/unverified entry points to only unpack inline type receiver at interface calls
+ C->cfg()->insert(broot, 0, new MachVEPNode(&verified_entry, /* verified */ false, /* receiver_only */ false));
+ C->cfg()->insert(broot, 0, new MachVEPNode(&verified_entry, /* verified */ true, /* receiver_only */ true));
+ C->cfg()->insert(broot, 0, new MachVEPNode(&verified_entry, /* verified */ false, /* receiver_only */ true));
+ }
+ } else if (!C->method()->is_static()) {
+ // Insert unvalidated entry point
+ C->cfg()->insert(broot, 0, new MachUEPNode());
+ }
}
-
}
// Break before main entry point
if ((C->method() && C->directive()->BreakAtExecuteOption) ||
(OptoBreakpoint && C->is_method_compilation()) ||
// Must be done before ScheduleAndBundle due to SPARC delay slots
uint* blk_starts = NEW_RESOURCE_ARRAY(uint, C->cfg()->number_of_blocks() + 1);
blk_starts[0] = 0;
shorten_branches(blk_starts);
+ if (!C->is_osr_compilation() && C->has_scalarized_args()) {
+ // Compute the offsets of the entry points required by the inline type calling convention
+ if (!C->method()->is_static()) {
+ // We have entries at the beginning of the method, implemented by the first 4 nodes.
+ // Entry (unverified) @ offset 0
+ // Verified_Inline_Entry_RO
+ // Inline_Entry (unverified)
+ // Verified_Inline_Entry
+ uint offset = 0;
+ _code_offsets.set_value(CodeOffsets::Entry, offset);
+
+ offset += ((MachVEPNode*)broot->get_node(0))->size(C->regalloc());
+ _code_offsets.set_value(CodeOffsets::Verified_Inline_Entry_RO, offset);
+
+ offset += ((MachVEPNode*)broot->get_node(1))->size(C->regalloc());
+ _code_offsets.set_value(CodeOffsets::Inline_Entry, offset);
+
+ offset += ((MachVEPNode*)broot->get_node(2))->size(C->regalloc());
+ _code_offsets.set_value(CodeOffsets::Verified_Inline_Entry, offset);
+ } else {
+ _code_offsets.set_value(CodeOffsets::Entry, -1); // will be patched later
+ _code_offsets.set_value(CodeOffsets::Verified_Inline_Entry, 0);
+ }
+ }
+
ScheduleAndBundle();
if (C->failing()) {
return;
}
reloc_size += CallStubImpl::reloc_call_trampoline();
MachCallNode *mcall = mach->as_MachCall();
// This destination address is NOT PC-relative
- mcall->method_set((intptr_t)mcall->entry_point());
+ if (mcall->entry_point() != NULL) {
+ mcall->method_set((intptr_t)mcall->entry_point());
+ }
if (mcall->is_MachCallJava() && mcall->as_MachCallJava()->_method) {
stub_size += CompiledStaticCall::to_interp_stub_size();
reloc_size += CompiledStaticCall::reloc_to_interp_stub();
#if INCLUDE_AOT
MachCallNode *mcall;
int safepoint_pc_offset = current_offset;
bool is_method_handle_invoke = false;
bool return_oop = false;
+ bool return_vt = false;
// Add the safepoint in the DebugInfoRecorder
if( !mach->is_MachCall() ) {
mcall = NULL;
C->debug_info()->add_safepoint(safepoint_pc_offset, sfn->_oop_map);
is_method_handle_invoke = true;
}
}
// Check if a call returns an object.
- if (mcall->returns_pointer()) {
+ if (mcall->returns_pointer() || mcall->returns_vt()) {
return_oop = true;
}
+ if (mcall->returns_vt()) {
+ return_vt = true;
+ }
safepoint_pc_offset += mcall->ret_addr_offset();
C->debug_info()->add_safepoint(safepoint_pc_offset, mcall->_oop_map);
}
// Loop over the JVMState list to add scope information
assert(jvms->bci() >= InvocationEntryBci && jvms->bci() <= 0x10000, "must be a valid or entry BCI");
assert(!jvms->should_reexecute() || depth == max_depth, "reexecute allowed only for the youngest");
// Now we can describe the scope.
methodHandle null_mh;
bool rethrow_exception = false;
- C->debug_info()->describe_scope(safepoint_pc_offset, null_mh, scope_method, jvms->bci(), jvms->should_reexecute(), rethrow_exception, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
+ C->debug_info()->describe_scope(safepoint_pc_offset, null_mh, scope_method, jvms->bci(), jvms->should_reexecute(), rethrow_exception, is_method_handle_invoke, return_oop, return_vt, locvals, expvals, monvals);
} // End jvms loop
// Mark the end of the scope set.
C->debug_info()->end_safepoint(safepoint_pc_offset);
}
// Compute the byte offset where we can store the deopt pc.
if (C->fixed_slots() != 0) {
_orig_pc_slot_offset_in_bytes = C->regalloc()->reg2offset(OptoReg::stack2reg(_orig_pc_slot));
}
+ if (C->needs_stack_repair()) {
+ // Compute the byte offset of the stack increment value
+ _sp_inc_slot_offset_in_bytes = C->regalloc()->reg2offset(OptoReg::stack2reg(_sp_inc_slot));
+ }
// Compute prolog code size
_method_size = 0;
_frame_slots = OptoReg::reg2stack(C->matcher()->_old_SP) + C->regalloc()->_framesize;
#if defined(IA64) && !defined(AIX)
// Remember the start of the last call in a basic block
if (is_mcall) {
MachCallNode *mcall = mach->as_MachCall();
- // This destination address is NOT PC-relative
- mcall->method_set((intptr_t)mcall->entry_point());
+ if (mcall->entry_point() != NULL) {
+ // This destination address is NOT PC-relative
+ mcall->method_set((intptr_t)mcall->entry_point());
+ }
// Save the return address
call_returns[block->_pre_order] = current_offset + mcall->ret_addr_offset();
if (mcall->is_MachCallLeaf()) {
}
ResourceMark rm;
_scratch_const_size = const_size;
int size = C2Compiler::initial_code_buffer_size(const_size);
+ #ifdef ASSERT
+ if (C->has_scalarized_args()) {
+ // Oop verification for loading object fields from scalarized inline types in the new entry point requires lots of space
+ size += 5120;
+ }
+ #endif
blob = BufferBlob::create("Compile::scratch_buffer", size);
// Record the buffer blob for next time.
set_scratch_buffer_blob(blob);
// Have we run out of code space?
if (scratch_buffer_blob() == NULL) {
if (is_branch) {
MacroAssembler masm(&buf);
masm.bind(fakeL);
n->as_MachBranch()->save_label(&saveL, &save_bnum);
n->as_MachBranch()->label_set(&fakeL, 0);
+ } else if (n->is_MachProlog()) {
+ saveL = ((MachPrologNode*)n)->_verified_entry;
+ ((MachPrologNode*)n)->_verified_entry = &fakeL;
+ } else if (n->is_MachVEP()) {
+ saveL = ((MachVEPNode*)n)->_verified_entry;
+ ((MachVEPNode*)n)->_verified_entry = &fakeL;
}
n->emit(buf, C->regalloc());
// Emitting into the scratch buffer should not fail
assert (!C->failing(), "Must not have pending failure. Reason is: %s", C->failure_reason());
- if (is_branch) // Restore label.
+ // Restore label.
+ if (is_branch) {
n->as_MachBranch()->label_set(saveL, save_bnum);
+ } else if (n->is_MachProlog()) {
+ ((MachPrologNode*)n)->_verified_entry = saveL;
+ } else if (n->is_MachVEP()) {
+ ((MachVEPNode*)n)->_verified_entry = saveL;
+ }
// End scratch_emit_size section.
set_in_scratch_emit_size(false);
return buf.insts_size();
if (C->is_osr_compilation()) {
_code_offsets.set_value(CodeOffsets::Verified_Entry, 0);
_code_offsets.set_value(CodeOffsets::OSR_Entry, _first_block_size);
} else {
_code_offsets.set_value(CodeOffsets::Verified_Entry, _first_block_size);
+ if (_code_offsets.value(CodeOffsets::Verified_Inline_Entry) == -1) {
+ _code_offsets.set_value(CodeOffsets::Verified_Inline_Entry, _first_block_size);
+ }
+ if (_code_offsets.value(CodeOffsets::Verified_Inline_Entry_RO) == -1) {
+ _code_offsets.set_value(CodeOffsets::Verified_Inline_Entry_RO, _first_block_size);
+ }
+ if (_code_offsets.value(CodeOffsets::Entry) == -1) {
+ _code_offsets.set_value(CodeOffsets::Entry, _first_block_size);
+ }
_code_offsets.set_value(CodeOffsets::OSR_Entry, 0);
}
C->env()->register_method(target,
- entry_bci,
- &_code_offsets,
- _orig_pc_slot_offset_in_bytes,
- code_buffer(),
- frame_size_in_words(),
- oop_map_set(),
- &_handler_table,
- inc_table(),
- compiler,
- has_unsafe_access,
- SharedRuntime::is_wide_vector(C->max_vector_size()),
- C->rtm_state());
+ entry_bci,
+ &_code_offsets,
+ _orig_pc_slot_offset_in_bytes,
+ code_buffer(),
+ frame_size_in_words(),
+ _oop_map_set,
+ &_handler_table,
+ &_inc_table,
+ compiler,
+ has_unsafe_access,
+ SharedRuntime::is_wide_vector(C->max_vector_size()),
+ C->rtm_state());
if (C->log() != NULL) { // Print code cache state into compiler log
C->log()->code_cache_state();
}
}
< prev index next >