Mercurial > hg > graal-jvmci-8
comparison src/share/vm/graal/graalCodeInstaller.cpp @ 20044:c1f116cd4b67
Speed up debug info generation for virtual objects
author | Tom Rodriguez <tom.rodriguez@oracle.com> |
---|---|
date | Fri, 27 Mar 2015 00:41:11 -0700 |
parents | deab43a789ad |
children | 92fc95e8667d |
comparison
equal
deleted
inserted
replaced
20043:b9041d4e91c5 | 20044:c1f116cd4b67 |
---|---|
201 | 201 |
202 static void record_metadata_in_patch(Handle& constant, OopRecorder* oop_recorder) { | 202 static void record_metadata_in_patch(Handle& constant, OopRecorder* oop_recorder) { |
203 record_metadata_reference(HotSpotMetaspaceConstantImpl::metaspaceObject(constant), HotSpotMetaspaceConstantImpl::primitive(constant), HotSpotMetaspaceConstantImpl::compressed(constant), oop_recorder); | 203 record_metadata_reference(HotSpotMetaspaceConstantImpl::metaspaceObject(constant), HotSpotMetaspaceConstantImpl::primitive(constant), HotSpotMetaspaceConstantImpl::compressed(constant), oop_recorder); |
204 } | 204 } |
205 | 205 |
206 ScopeValue* CodeInstaller::get_scope_value(oop value, int total_frame_size, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, OopRecorder* oop_recorder) { | 206 ScopeValue* CodeInstaller::get_scope_value(oop value, GrowableArray<ScopeValue*>* objects, ScopeValue* &second) { |
207 second = NULL; | 207 second = NULL; |
208 if (value == AbstractValue::ILLEGAL()) { | 208 if (value == AbstractValue::ILLEGAL()) { |
209 return _illegal_value; | 209 return _illegal_value; |
210 } | 210 } |
211 | 211 |
280 if(offset >= 0) { | 280 if(offset >= 0) { |
281 offset += 128; | 281 offset += 128; |
282 } | 282 } |
283 #endif | 283 #endif |
284 if (StackSlot::addFrameSize(value)) { | 284 if (StackSlot::addFrameSize(value)) { |
285 offset += total_frame_size; | 285 offset += _total_frame_size; |
286 } | 286 } |
287 ScopeValue* value = new LocationValue(Location::new_stk_loc(locationType, offset)); | 287 ScopeValue* value = new LocationValue(Location::new_stk_loc(locationType, offset)); |
288 if (type == T_DOUBLE || (type == T_LONG && !reference)) { | 288 if (type == T_DOUBLE || (type == T_LONG && !reference)) { |
289 second = value; | 289 second = value; |
290 } | 290 } |
291 return value; | 291 return value; |
292 } else if (value->is_a(JavaConstant::klass())){ | 292 } else if (value->is_a(JavaConstant::klass())){ |
293 record_metadata_in_constant(value, oop_recorder); | 293 record_metadata_in_constant(value, _oop_recorder); |
294 if (value->is_a(PrimitiveConstant::klass())) { | 294 if (value->is_a(PrimitiveConstant::klass())) { |
295 assert(!reference, "unexpected primitive constant type"); | 295 assert(!reference, "unexpected primitive constant type"); |
296 if(value->is_a(RawConstant::klass())) { | 296 if(value->is_a(RawConstant::klass())) { |
297 jlong prim = PrimitiveConstant::primitive(value); | 297 jlong prim = PrimitiveConstant::primitive(value); |
298 return new ConstantLongValue(prim); | 298 return new ConstantLongValue(prim); |
321 assert(obj != NULL, "null value must be in NullConstant"); | 321 assert(obj != NULL, "null value must be in NullConstant"); |
322 return new ConstantOopWriteValue(JNIHandles::make_local(obj)); | 322 return new ConstantOopWriteValue(JNIHandles::make_local(obj)); |
323 } | 323 } |
324 } | 324 } |
325 } else if (value->is_a(VirtualObject::klass())) { | 325 } else if (value->is_a(VirtualObject::klass())) { |
326 oop type = VirtualObject::type(value); | |
327 int id = VirtualObject::id(value); | 326 int id = VirtualObject::id(value); |
328 oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type); | 327 ScopeValue* object = objects->at(id); |
329 Klass* klass = java_lang_Class::as_Klass(javaMirror); | 328 assert(object != NULL, "missing value"); |
330 bool isLongArray = klass == Universe::longArrayKlassObj(); | 329 return object; |
331 | |
332 for (jint i = 0; i < objects->length(); i++) { | |
333 ObjectValue* obj = (ObjectValue*) objects->at(i); | |
334 if (obj->id() == id) { | |
335 return obj; | |
336 } | |
337 } | |
338 | |
339 ObjectValue* sv = new ObjectValue(id, new ConstantOopWriteValue(JNIHandles::make_local(Thread::current(), javaMirror))); | |
340 objects->append(sv); | |
341 | |
342 objArrayOop values = VirtualObject::values(value); | |
343 for (jint i = 0; i < values->length(); i++) { | |
344 ScopeValue* cur_second = NULL; | |
345 oop object = values->obj_at(i); | |
346 ScopeValue* value = get_scope_value(object, total_frame_size, objects, cur_second, oop_recorder); | |
347 | |
348 if (isLongArray && cur_second == NULL) { | |
349 // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations. | |
350 // add an int 0 constant | |
351 cur_second = _int_0_scope_value; | |
352 } | |
353 | |
354 if (cur_second != NULL) { | |
355 sv->field_values()->append(cur_second); | |
356 } | |
357 sv->field_values()->append(value); | |
358 } | |
359 return sv; | |
360 } else { | 330 } else { |
361 value->klass()->print(); | 331 value->klass()->print(); |
362 value->print(); | 332 value->print(); |
363 } | 333 } |
364 ShouldNotReachHere(); | 334 ShouldNotReachHere(); |
365 return NULL; | 335 return NULL; |
366 } | 336 } |
367 | 337 |
368 MonitorValue* CodeInstaller::get_monitor_value(oop value, int total_frame_size, GrowableArray<ScopeValue*>* objects, OopRecorder* oop_recorder) { | 338 void CodeInstaller::record_object_value(ObjectValue* sv, oop value, GrowableArray<ScopeValue*>* objects) { |
339 oop type = VirtualObject::type(value); | |
340 int id = VirtualObject::id(value); | |
341 oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type); | |
342 Klass* klass = java_lang_Class::as_Klass(javaMirror); | |
343 bool isLongArray = klass == Universe::longArrayKlassObj(); | |
344 | |
345 objArrayOop values = VirtualObject::values(value); | |
346 for (jint i = 0; i < values->length(); i++) { | |
347 ScopeValue* cur_second = NULL; | |
348 oop object = values->obj_at(i); | |
349 ScopeValue* value = get_scope_value(object, objects, cur_second); | |
350 | |
351 if (isLongArray && cur_second == NULL) { | |
352 // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations. | |
353 // add an int 0 constant | |
354 cur_second = _int_0_scope_value; | |
355 } | |
356 | |
357 if (cur_second != NULL) { | |
358 sv->field_values()->append(cur_second); | |
359 } | |
360 assert(value != NULL, "missing value"); | |
361 sv->field_values()->append(value); | |
362 } | |
363 } | |
364 | |
365 MonitorValue* CodeInstaller::get_monitor_value(oop value, GrowableArray<ScopeValue*>* objects) { | |
369 guarantee(value->is_a(StackLockValue::klass()), "Monitors must be of type MonitorValue"); | 366 guarantee(value->is_a(StackLockValue::klass()), "Monitors must be of type MonitorValue"); |
370 | 367 |
371 ScopeValue* second = NULL; | 368 ScopeValue* second = NULL; |
372 ScopeValue* owner_value = get_scope_value(StackLockValue::owner(value), total_frame_size, objects, second, oop_recorder); | 369 ScopeValue* owner_value = get_scope_value(StackLockValue::owner(value), objects, second); |
373 assert(second == NULL, "monitor cannot occupy two stack slots"); | 370 assert(second == NULL, "monitor cannot occupy two stack slots"); |
374 | 371 |
375 ScopeValue* lock_data_value = get_scope_value(StackLockValue::slot(value), total_frame_size, objects, second, oop_recorder); | 372 ScopeValue* lock_data_value = get_scope_value(StackLockValue::slot(value), objects, second); |
376 assert(second == lock_data_value, "monitor is LONG value that occupies two stack slots"); | 373 assert(second == lock_data_value, "monitor is LONG value that occupies two stack slots"); |
377 assert(lock_data_value->is_location(), "invalid monitor location"); | 374 assert(lock_data_value->is_location(), "invalid monitor location"); |
378 Location lock_data_loc = ((LocationValue*)lock_data_value)->location(); | 375 Location lock_data_loc = ((LocationValue*)lock_data_value)->location(); |
379 | 376 |
380 bool eliminated = false; | 377 bool eliminated = false; |
725 return true; | 722 return true; |
726 } | 723 } |
727 return true; | 724 return true; |
728 } | 725 } |
729 | 726 |
727 GrowableArray<ScopeValue*>* CodeInstaller::record_virtual_objects(oop debug_info) { | |
728 objArrayOop virtualObjects = DebugInfo::virtualObjectMapping(debug_info); | |
729 if (virtualObjects == NULL) { | |
730 return NULL; | |
731 } | |
732 GrowableArray<ScopeValue*>* objects = new GrowableArray<ScopeValue*>(virtualObjects->length(), virtualObjects->length(), NULL); | |
733 // Create the unique ObjectValues | |
734 for (int i = 0; i < virtualObjects->length(); i++) { | |
735 oop value = virtualObjects->obj_at(i); | |
736 int id = VirtualObject::id(value); | |
737 oop type = VirtualObject::type(value); | |
738 oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type); | |
739 ObjectValue* sv = new ObjectValue(id, new ConstantOopWriteValue(JNIHandles::make_local(Thread::current(), javaMirror))); | |
740 assert(objects->at(id) == NULL, "once"); | |
741 objects->at_put(id, sv); | |
742 } | |
743 // All the values which could be referenced by the VirtualObjects | |
744 // exist, so now describe all the VirtualObjects themselves. | |
745 for (int i = 0; i < virtualObjects->length(); i++) { | |
746 oop value = virtualObjects->obj_at(i); | |
747 int id = VirtualObject::id(value); | |
748 record_object_value(objects->at(id)->as_ObjectValue(), value, objects); | |
749 } | |
750 _debug_recorder->dump_object_pool(objects); | |
751 return objects; | |
752 } | |
753 | |
754 void CodeInstaller::record_scope(jint pc_offset, oop debug_info) { | |
755 oop position = DebugInfo::bytecodePosition(debug_info); | |
756 if (position == NULL) { | |
757 // Stubs do not record scope info, just oop maps | |
758 return; | |
759 } | |
760 | |
761 GrowableArray<ScopeValue*>* objectMapping = record_virtual_objects(debug_info); | |
762 record_scope(pc_offset, position, objectMapping); | |
763 } | |
764 | |
730 void CodeInstaller::record_scope(jint pc_offset, oop position, GrowableArray<ScopeValue*>* objects) { | 765 void CodeInstaller::record_scope(jint pc_offset, oop position, GrowableArray<ScopeValue*>* objects) { |
731 oop frame = NULL; | 766 oop frame = NULL; |
732 if (position->is_a(BytecodeFrame::klass())) { | 767 if (position->is_a(BytecodeFrame::klass())) { |
733 frame = position; | 768 frame = position; |
734 } | 769 } |
783 tty->print_cr("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count); | 818 tty->print_cr("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count); |
784 } | 819 } |
785 | 820 |
786 for (jint i = 0; i < values->length(); i++) { | 821 for (jint i = 0; i < values->length(); i++) { |
787 ScopeValue* second = NULL; | 822 ScopeValue* second = NULL; |
788 oop value= values->obj_at(i); | 823 oop value = values->obj_at(i); |
789 if (i < local_count) { | 824 if (i < local_count) { |
790 ScopeValue* first = get_scope_value(value, _total_frame_size, objects, second, _oop_recorder); | 825 ScopeValue* first = get_scope_value(value, objects, second); |
791 if (second != NULL) { | 826 if (second != NULL) { |
792 locals->append(second); | 827 locals->append(second); |
793 } | 828 } |
794 locals->append(first); | 829 locals->append(first); |
795 } else if (i < local_count + expression_count) { | 830 } else if (i < local_count + expression_count) { |
796 ScopeValue* first = get_scope_value(value, _total_frame_size, objects, second, _oop_recorder); | 831 ScopeValue* first = get_scope_value(value, objects, second); |
797 if (second != NULL) { | 832 if (second != NULL) { |
798 expressions->append(second); | 833 expressions->append(second); |
799 } | 834 } |
800 expressions->append(first); | 835 expressions->append(first); |
801 } else { | 836 } else { |
802 monitors->append(get_monitor_value(value, _total_frame_size, objects, _oop_recorder)); | 837 monitors->append(get_monitor_value(value, objects)); |
803 } | 838 } |
804 if (second != NULL) { | 839 if (second != NULL) { |
805 i++; | 840 i++; |
806 assert(i < values->length(), "double-slot value not followed by Value.ILLEGAL"); | 841 assert(i < values->length(), "double-slot value not followed by Value.ILLEGAL"); |
807 assert(values->obj_at(i) == AbstractValue::ILLEGAL(), "double-slot value not followed by Value.ILLEGAL"); | 842 assert(values->obj_at(i) == AbstractValue::ILLEGAL(), "double-slot value not followed by Value.ILLEGAL"); |
808 } | 843 } |
809 } | 844 } |
810 | 845 |
811 _debug_recorder->dump_object_pool(objects); | |
812 | |
813 locals_token = _debug_recorder->create_scope_values(locals); | 846 locals_token = _debug_recorder->create_scope_values(locals); |
814 expressions_token = _debug_recorder->create_scope_values(expressions); | 847 expressions_token = _debug_recorder->create_scope_values(expressions); |
815 monitors_token = _debug_recorder->create_monitor_values(monitors); | 848 monitors_token = _debug_recorder->create_monitor_values(monitors); |
816 | 849 |
817 throw_exception = BytecodeFrame::rethrowException(frame) == JNI_TRUE; | 850 throw_exception = BytecodeFrame::rethrowException(frame) == JNI_TRUE; |
818 } | 851 } |
819 | 852 |
820 _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token); | 853 _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, |
854 locals_token, expressions_token, monitors_token); | |
821 } | 855 } |
822 | 856 |
823 void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) { | 857 void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) { |
824 oop debug_info = CompilationResult_Infopoint::debugInfo(site); | 858 oop debug_info = CompilationResult_Infopoint::debugInfo(site); |
825 assert(debug_info != NULL, "debug info expected"); | 859 assert(debug_info != NULL, "debug info expected"); |
826 | 860 |
827 // address instruction = _instructions->start() + pc_offset; | 861 // address instruction = _instructions->start() + pc_offset; |
828 // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start(); | 862 // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start(); |
829 _debug_recorder->add_safepoint(pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info)); | 863 _debug_recorder->add_safepoint(pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info)); |
830 | 864 record_scope(pc_offset, debug_info); |
831 oop frame = DebugInfo::bytecodePosition(debug_info); | |
832 if (frame != NULL) { | |
833 record_scope(pc_offset, frame, new GrowableArray<ScopeValue*>()); | |
834 } else { | |
835 // Stubs do not record scope info, just oop maps | |
836 } | |
837 | |
838 _debug_recorder->end_safepoint(pc_offset); | 865 _debug_recorder->end_safepoint(pc_offset); |
839 } | 866 } |
840 | 867 |
841 void CodeInstaller::site_Infopoint(CodeBuffer& buffer, jint pc_offset, oop site) { | 868 void CodeInstaller::site_Infopoint(CodeBuffer& buffer, jint pc_offset, oop site) { |
842 oop debug_info = CompilationResult_Infopoint::debugInfo(site); | 869 oop debug_info = CompilationResult_Infopoint::debugInfo(site); |
843 assert(debug_info != NULL, "debug info expected"); | 870 assert(debug_info != NULL, "debug info expected"); |
844 | 871 |
845 _debug_recorder->add_non_safepoint(pc_offset); | 872 _debug_recorder->add_non_safepoint(pc_offset); |
846 | 873 record_scope(pc_offset, debug_info); |
847 oop position = DebugInfo::bytecodePosition(debug_info); | |
848 if (position != NULL) { | |
849 record_scope(pc_offset, position, NULL); | |
850 } | |
851 | |
852 _debug_recorder->end_non_safepoint(pc_offset); | 874 _debug_recorder->end_non_safepoint(pc_offset); |
853 } | 875 } |
854 | 876 |
855 void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, oop site) { | 877 void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, oop site) { |
856 oop target = CompilationResult_Call::target(site); | 878 oop target = CompilationResult_Call::target(site); |
871 | 893 |
872 NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset); | 894 NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset); |
873 jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method); | 895 jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method); |
874 | 896 |
875 if (debug_info != NULL) { | 897 if (debug_info != NULL) { |
876 oop frame = DebugInfo::bytecodePosition(debug_info); | |
877 _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info)); | 898 _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info)); |
878 if (frame != NULL) { | 899 record_scope(next_pc_offset, debug_info); |
879 record_scope(next_pc_offset, frame, new GrowableArray<ScopeValue*>()); | |
880 } else { | |
881 // Stubs do not record scope info, just oop maps | |
882 } | |
883 } | 900 } |
884 | 901 |
885 if (foreign_call != NULL) { | 902 if (foreign_call != NULL) { |
886 jlong foreign_call_destination = HotSpotForeignCallLinkageImpl::address(foreign_call); | 903 jlong foreign_call_destination = HotSpotForeignCallLinkageImpl::address(foreign_call); |
887 CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination); | 904 CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination); |