// must call add_safepoint before: it sets PcDesc and this routine uses // the last PcDesc set void DebugInformationRecorder::describe_scope(int pc_offset, ciMethod* method, int bci, bool reexecute, bool is_method_handle_invoke, bool return_oop, DebugToken* locals, DebugToken* expressions, DebugToken* monitors) { assert(_recording_state != rs_null, "nesting of recording calls"); PcDesc* last_pd = last_pc(); assert(last_pd->pc_offset() == pc_offset, "must be last pc"); int sender_stream_offset = last_pd->scope_decode_offset(); // update the stream offset of current pc desc int stream_offset = stream()->position(); last_pd->set_scope_decode_offset(stream_offset); // Record flags into pcDesc. last_pd->set_should_reexecute(reexecute); last_pd->set_is_method_handle_invoke(is_method_handle_invoke); last_pd->set_return_oop(return_oop); // serialize sender stream offest stream()->write_int(sender_stream_offset); // serialize scope Metadata* method_enc = (method == NULL)? NULL: method->constant_encoding(); stream()->write_int(oop_recorder()->find_index(method_enc)); stream()->write_bci(bci); assert(method == NULL || (method->is_native() && bci == 0) || (!method->is_native() && 0 <= bci && bci < method->code_size()) || (method->is_compiled_lambda_form() && bci == -99) || // this might happen in C1 bci == -1, "illegal bci"); // serialize the locals/expressions/monitors stream()->write_int((intptr_t) locals); stream()->write_int((intptr_t) expressions); stream()->write_int((intptr_t) monitors); // Here's a tricky bit. We just wrote some bytes. // Wouldn't it be nice to find that we had already // written those same bytes somewhere else? // If we get lucky this way, reset the stream // and reuse the old bytes. By the way, this // trick not only shares parent scopes, but also // compresses equivalent non-safepoint PcDescs. int shared_stream_offset = find_sharable_decode_offset(stream_offset); if (shared_stream_offset != serialized_null) { stream()->set_position(stream_offset); last_pd->set_scope_decode_offset(shared_stream_offset); } }
int oop_size() { return oop_recorder()->oop_size(); }
void CodeBuffer::finalize_oop_references(methodHandle mh) { No_Safepoint_Verifier nsv; GrowableArray<oop> oops; // Make sure that immediate metadata records something in the OopRecorder for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) { // pull code out of each section CodeSection* cs = code_section(n); if (cs->is_empty()) continue; // skip trivial section RelocIterator iter(cs); while (iter.next()) { if (iter.type() == relocInfo::metadata_type) { metadata_Relocation* md = iter.metadata_reloc(); if (md->metadata_is_immediate()) { Metadata* m = md->metadata_value(); if (oop_recorder()->is_real(m)) { if (m->is_methodData()) { m = ((MethodData*)m)->method(); } if (m->is_method()) { m = ((Method*)m)->method_holder(); } if (m->is_klass()) { append_oop_references(&oops, (Klass*)m); } else { // XXX This will currently occur for MDO which don't // have a backpointer. This has to be fixed later. m->print(); ShouldNotReachHere(); } } } } } } if (!oop_recorder()->is_unused()) { for (int i = 0; i < oop_recorder()->metadata_count(); i++) { Metadata* m = oop_recorder()->metadata_at(i); if (oop_recorder()->is_real(m)) { if (m->is_methodData()) { m = ((MethodData*)m)->method(); } if (m->is_method()) { m = ((Method*)m)->method_holder(); } if (m->is_klass()) { append_oop_references(&oops, (Klass*)m); } else { m->print(); ShouldNotReachHere(); } } } } // Add the class loader of Method* for the nmethod itself append_oop_references(&oops, mh->method_holder()); // Add any oops that we've found Thread* thread = Thread::current(); for (int i = 0; i < oops.length(); i++) { oop_recorder()->find_index((jobject)thread->handle_area()->allocate_handle(oops.at(i))); } }