23 */
24
25 #include "precompiled.hpp"
26 #include "classfile/moduleEntry.hpp"
27 #include "code/codeCache.hpp"
28 #include "code/scopeDesc.hpp"
29 #include "code/vmreg.inline.hpp"
30 #include "compiler/abstractCompiler.hpp"
31 #include "compiler/disassembler.hpp"
32 #include "compiler/oopMap.hpp"
33 #include "gc/shared/collectedHeap.inline.hpp"
34 #include "interpreter/interpreter.hpp"
35 #include "interpreter/oopMapCache.hpp"
36 #include "logging/log.hpp"
37 #include "memory/resourceArea.hpp"
38 #include "memory/universe.hpp"
39 #include "oops/markWord.hpp"
40 #include "oops/method.inline.hpp"
41 #include "oops/methodData.hpp"
42 #include "oops/oop.inline.hpp"
43 #include "oops/stackChunkOop.inline.hpp"
44 #include "oops/verifyOopClosure.hpp"
45 #include "prims/methodHandles.hpp"
46 #include "runtime/continuation.hpp"
47 #include "runtime/continuationEntry.inline.hpp"
48 #include "runtime/frame.inline.hpp"
49 #include "runtime/handles.inline.hpp"
50 #include "runtime/javaCalls.hpp"
51 #include "runtime/javaThread.hpp"
52 #include "runtime/monitorChunk.hpp"
53 #include "runtime/os.hpp"
54 #include "runtime/sharedRuntime.hpp"
55 #include "runtime/safefetch.hpp"
56 #include "runtime/signature.hpp"
57 #include "runtime/stackValue.hpp"
58 #include "runtime/stubCodeGenerator.hpp"
59 #include "runtime/stubRoutines.hpp"
60 #include "utilities/debug.hpp"
61 #include "utilities/decoder.hpp"
62 #include "utilities/formatBuffer.hpp"
63
64 RegisterMap::RegisterMap(JavaThread *thread, UpdateMap update_map, ProcessFrames process_frames, WalkContinuation walk_cont) {
65 _thread = thread;
66 _update_map = update_map == UpdateMap::include;
67 _process_frames = process_frames == ProcessFrames::include;
68 _walk_cont = walk_cont == WalkContinuation::include;
69 clear();
70 DEBUG_ONLY (_update_for_id = nullptr;)
71 NOT_PRODUCT(_skip_missing = false;)
72 NOT_PRODUCT(_async = false;)
73
74 if (walk_cont == WalkContinuation::include && thread != nullptr && thread->last_continuation() != nullptr) {
75 _chunk = stackChunkHandle(Thread::current()->handle_area()->allocate_null_handle(), true /* dummy */);
76 }
77 _chunk_index = -1;
78
79 #ifndef PRODUCT
80 for (int i = 0; i < reg_count ; i++ ) _location[i] = nullptr;
81 #endif /* PRODUCT */
82 }
342 return !nm->is_at_poll_return(pc());
343 }
344
345 void frame::deoptimize(JavaThread* thread) {
346 assert(thread == nullptr
347 || (thread->frame_anchor()->has_last_Java_frame() &&
348 thread->frame_anchor()->walkable()), "must be");
349 // Schedule deoptimization of an nmethod activation with this frame.
350 assert(_cb != nullptr && _cb->is_nmethod(), "must be");
351
352 // If the call site is a MethodHandle call site use the MH deopt handler.
353 nmethod* nm = _cb->as_nmethod();
354 address deopt = nm->is_method_handle_return(pc()) ?
355 nm->deopt_mh_handler_begin() :
356 nm->deopt_handler_begin();
357
358 NativePostCallNop* inst = nativePostCallNop_at(pc());
359
360 // Save the original pc before we patch in the new one
361 nm->set_original_pc(this, pc());
362 patch_pc(thread, deopt);
363 assert(is_deoptimized_frame(), "must be");
364
365 #ifdef ASSERT
366 if (thread != nullptr) {
367 frame check = thread->last_frame();
368 if (is_older(check.id())) {
369 RegisterMap map(thread,
370 RegisterMap::UpdateMap::skip,
371 RegisterMap::ProcessFrames::include,
372 RegisterMap::WalkContinuation::skip);
373 while (id() != check.id()) {
374 check = check.sender(&map);
375 }
376 assert(check.is_deoptimized_frame(), "missed deopt");
377 }
378 }
379 #endif // ASSERT
380 }
381
730 }
731
732
733 /*
734 The interpreter_frame_expression_stack_at method in the case of SPARC needs the
735 max_stack value of the method in order to compute the expression stack address.
736 It uses the Method* in order to get the max_stack value but during GC this
737 Method* value saved on the frame is changed by reverse_and_push and hence cannot
738 be used. So we save the max_stack value in the FrameClosure object and pass it
739 down to the interpreter_frame_expression_stack_at method
740 */
741 class InterpreterFrameClosure : public OffsetClosure {
742 private:
743 const frame* _fr;
744 OopClosure* _f;
745 int _max_locals;
746 int _max_stack;
747
748 public:
749 InterpreterFrameClosure(const frame* fr, int max_locals, int max_stack,
750 OopClosure* f) {
751 _fr = fr;
752 _max_locals = max_locals;
753 _max_stack = max_stack;
754 _f = f;
755 }
756
757 void offset_do(int offset) {
758 oop* addr;
759 if (offset < _max_locals) {
760 addr = (oop*) _fr->interpreter_frame_local_at(offset);
761 assert((intptr_t*)addr >= _fr->sp(), "must be inside the frame");
762 _f->do_oop(addr);
763 } else {
764 addr = (oop*) _fr->interpreter_frame_expression_stack_at((offset - _max_locals));
765 // In case of exceptions, the expression stack is invalid and the esp will be reset to express
766 // this condition. Therefore, we call f only if addr is 'inside' the stack (i.e., addr >= esp for Intel).
767 bool in_stack;
768 if (frame::interpreter_frame_expression_stack_direction() > 0) {
769 in_stack = (intptr_t*)addr <= _fr->interpreter_frame_tos_address();
770 } else {
771 in_stack = (intptr_t*)addr >= _fr->interpreter_frame_tos_address();
772 }
773 if (in_stack) {
774 _f->do_oop(addr);
775 }
776 }
777 }
778 };
779
780
781 class InterpretedArgumentOopFinder: public SignatureIterator {
782 private:
783 OopClosure* _f; // Closure to invoke
784 int _offset; // TOS-relative offset, decremented with each argument
785 bool _has_receiver; // true if the callee has a receiver
786 const frame* _fr;
787
788 friend class SignatureIterator; // so do_parameters_on can call do_type
789 void do_type(BasicType type) {
790 _offset -= parameter_type_word_count(type);
791 if (is_reference_type(type)) oop_offset_do();
792 }
793
794 void oop_offset_do() {
929 signature = call.signature();
930 has_receiver = call.has_receiver();
931 if (map->include_argument_oops() &&
932 interpreter_frame_expression_stack_size() > 0) {
933 ResourceMark rm(thread); // is this right ???
934 // we are at a call site & the expression stack is not empty
935 // => process callee's arguments
936 //
937 // Note: The expression stack can be empty if an exception
938 // occurred during method resolution/execution. In all
939 // cases we empty the expression stack completely be-
940 // fore handling the exception (the exception handling
941 // code in the interpreter calls a blocking runtime
942 // routine which can cause this code to be executed).
943 // (was bug gri 7/27/98)
944 oops_interpreted_arguments_do(signature, has_receiver, f);
945 }
946 }
947 }
948
949 InterpreterFrameClosure blk(this, max_locals, m->max_stack(), f);
950
951 // process locals & expression stack
952 InterpreterOopMap mask;
953 if (query_oop_map_cache) {
954 m->mask_for(m, bci, &mask);
955 } else {
956 OopMapCache::compute_one_oop_map(m, bci, &mask);
957 }
958 mask.iterate_oop(&blk);
959 }
960
961
962 void frame::oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f) const {
963 InterpretedArgumentOopFinder finder(signature, has_receiver, this, f);
964 finder.oops_do();
965 }
966
967 void frame::oops_nmethod_do(OopClosure* f, NMethodClosure* cf, DerivedOopClosure* df, DerivedPointerIterationMode derived_mode, const RegisterMap* reg_map) const {
968 assert(_cb != nullptr, "sanity check");
969 assert((oop_map() == nullptr) == (_cb->oop_maps() == nullptr), "frame and _cb must agree that oopmap is set or not");
970 if (oop_map() != nullptr) {
971 if (df != nullptr) {
972 _oop_map->oops_do(this, reg_map, f, df);
973 } else {
974 _oop_map->oops_do(this, reg_map, f, derived_mode);
975 }
976
977 // Preserve potential arguments for a callee. We handle this by dispatching
978 // on the codeblob. For c2i, we do
979 if (reg_map->include_argument_oops() && _cb->is_nmethod()) {
980 // Only nmethod preserves outgoing arguments at call.
993 class CompiledArgumentOopFinder: public SignatureIterator {
994 protected:
995 OopClosure* _f;
996 int _offset; // the current offset, incremented with each argument
997 bool _has_receiver; // true if the callee has a receiver
998 bool _has_appendix; // true if the call has an appendix
999 frame _fr;
1000 RegisterMap* _reg_map;
1001 int _arg_size;
1002 VMRegPair* _regs; // VMReg list of arguments
1003
1004 friend class SignatureIterator; // so do_parameters_on can call do_type
1005 void do_type(BasicType type) {
1006 if (is_reference_type(type)) handle_oop_offset();
1007 _offset += parameter_type_word_count(type);
1008 }
1009
1010 virtual void handle_oop_offset() {
1011 // Extract low order register number from register array.
1012 // In LP64-land, the high-order bits are valid but unhelpful.
1013 VMReg reg = _regs[_offset].first();
1014 oop *loc = _fr.oopmapreg_to_oop_location(reg, _reg_map);
1015 #ifdef ASSERT
1016 if (loc == nullptr) {
1017 if (_reg_map->should_skip_missing()) {
1018 return;
1019 }
1020 tty->print_cr("Error walking frame oops:");
1021 _fr.print_on(tty);
1022 assert(loc != nullptr, "missing register map entry reg: %d %s loc: " INTPTR_FORMAT, reg->value(), reg->name(), p2i(loc));
1023 }
1024 #endif
1025 _f->do_oop(loc);
1026 }
1027
1028 public:
1029 CompiledArgumentOopFinder(Symbol* signature, bool has_receiver, bool has_appendix, OopClosure* f, frame fr, const RegisterMap* reg_map)
1030 : SignatureIterator(signature) {
1031
1032 // initialize CompiledArgumentOopFinder
1033 _f = f;
1034 _offset = 0;
1035 _has_receiver = has_receiver;
1036 _has_appendix = has_appendix;
1037 _fr = fr;
1038 _reg_map = (RegisterMap*)reg_map;
1039 _arg_size = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0) + (has_appendix ? 1 : 0);
1040
1041 int arg_size;
1042 _regs = SharedRuntime::find_callee_arguments(signature, has_receiver, has_appendix, &arg_size);
1043 assert(arg_size == _arg_size, "wrong arg size");
1044 }
1045
1046 void oops_do() {
1047 if (_has_receiver) {
1048 handle_oop_offset();
1049 _offset++;
1050 }
1051 do_parameters_on(this);
1052 if (_has_appendix) {
1053 handle_oop_offset();
1054 _offset++;
1055 }
1056 }
1057 };
1058
1059 void frame::oops_compiled_arguments_do(Symbol* signature, bool has_receiver, bool has_appendix,
1060 const RegisterMap* reg_map, OopClosure* f) const {
1061 // ResourceMark rm;
1062 CompiledArgumentOopFinder finder(signature, has_receiver, has_appendix, f, *this, reg_map);
1063 finder.oops_do();
|
23 */
24
25 #include "precompiled.hpp"
26 #include "classfile/moduleEntry.hpp"
27 #include "code/codeCache.hpp"
28 #include "code/scopeDesc.hpp"
29 #include "code/vmreg.inline.hpp"
30 #include "compiler/abstractCompiler.hpp"
31 #include "compiler/disassembler.hpp"
32 #include "compiler/oopMap.hpp"
33 #include "gc/shared/collectedHeap.inline.hpp"
34 #include "interpreter/interpreter.hpp"
35 #include "interpreter/oopMapCache.hpp"
36 #include "logging/log.hpp"
37 #include "memory/resourceArea.hpp"
38 #include "memory/universe.hpp"
39 #include "oops/markWord.hpp"
40 #include "oops/method.inline.hpp"
41 #include "oops/methodData.hpp"
42 #include "oops/oop.inline.hpp"
43 #include "oops/inlineKlass.hpp"
44 #include "oops/stackChunkOop.inline.hpp"
45 #include "oops/verifyOopClosure.hpp"
46 #include "prims/methodHandles.hpp"
47 #include "runtime/continuation.hpp"
48 #include "runtime/continuationEntry.inline.hpp"
49 #include "runtime/frame.inline.hpp"
50 #include "runtime/handles.inline.hpp"
51 #include "runtime/javaCalls.hpp"
52 #include "runtime/javaThread.hpp"
53 #include "runtime/monitorChunk.hpp"
54 #include "runtime/os.hpp"
55 #include "runtime/sharedRuntime.hpp"
56 #include "runtime/safefetch.hpp"
57 #include "runtime/signature.hpp"
58 #include "runtime/stackValue.hpp"
59 #include "runtime/stubCodeGenerator.hpp"
60 #include "runtime/stubRoutines.hpp"
61 #include "utilities/debug.hpp"
62 #include "utilities/decoder.hpp"
63 #include "utilities/formatBuffer.hpp"
64 #ifdef COMPILER1
65 #include "c1/c1_Runtime1.hpp"
66 #endif
67
68 RegisterMap::RegisterMap(JavaThread *thread, UpdateMap update_map, ProcessFrames process_frames, WalkContinuation walk_cont) {
69 _thread = thread;
70 _update_map = update_map == UpdateMap::include;
71 _process_frames = process_frames == ProcessFrames::include;
72 _walk_cont = walk_cont == WalkContinuation::include;
73 clear();
74 DEBUG_ONLY (_update_for_id = nullptr;)
75 NOT_PRODUCT(_skip_missing = false;)
76 NOT_PRODUCT(_async = false;)
77
78 if (walk_cont == WalkContinuation::include && thread != nullptr && thread->last_continuation() != nullptr) {
79 _chunk = stackChunkHandle(Thread::current()->handle_area()->allocate_null_handle(), true /* dummy */);
80 }
81 _chunk_index = -1;
82
83 #ifndef PRODUCT
84 for (int i = 0; i < reg_count ; i++ ) _location[i] = nullptr;
85 #endif /* PRODUCT */
86 }
346 return !nm->is_at_poll_return(pc());
347 }
348
349 void frame::deoptimize(JavaThread* thread) {
350 assert(thread == nullptr
351 || (thread->frame_anchor()->has_last_Java_frame() &&
352 thread->frame_anchor()->walkable()), "must be");
353 // Schedule deoptimization of an nmethod activation with this frame.
354 assert(_cb != nullptr && _cb->is_nmethod(), "must be");
355
356 // If the call site is a MethodHandle call site use the MH deopt handler.
357 nmethod* nm = _cb->as_nmethod();
358 address deopt = nm->is_method_handle_return(pc()) ?
359 nm->deopt_mh_handler_begin() :
360 nm->deopt_handler_begin();
361
362 NativePostCallNop* inst = nativePostCallNop_at(pc());
363
364 // Save the original pc before we patch in the new one
365 nm->set_original_pc(this, pc());
366
367 #ifdef COMPILER1
368 if (nm->is_compiled_by_c1() && nm->method()->has_scalarized_args() &&
369 pc() < nm->verified_inline_entry_point()) {
370 // The VEP and VIEP(RO) of C1-compiled methods call into the runtime to buffer scalarized value
371 // type args. We can't deoptimize at that point because the buffers have not yet been initialized.
372 // Also, if the method is synchronized, we first need to acquire the lock.
373 // Don't patch the return pc to delay deoptimization until we enter the method body (the check
374 // added in LIRGenerator::do_Base will detect the pending deoptimization by checking the original_pc).
375 #if defined ASSERT && !defined AARCH64 // Stub call site does not look like NativeCall on AArch64
376 NativeCall* call = nativeCall_before(this->pc());
377 address dest = call->destination();
378 assert(dest == Runtime1::entry_for(C1StubId::buffer_inline_args_no_receiver_id) ||
379 dest == Runtime1::entry_for(C1StubId::buffer_inline_args_id), "unexpected safepoint in entry point");
380 #endif
381 return;
382 }
383 #endif
384
385 patch_pc(thread, deopt);
386 assert(is_deoptimized_frame(), "must be");
387
388 #ifdef ASSERT
389 if (thread != nullptr) {
390 frame check = thread->last_frame();
391 if (is_older(check.id())) {
392 RegisterMap map(thread,
393 RegisterMap::UpdateMap::skip,
394 RegisterMap::ProcessFrames::include,
395 RegisterMap::WalkContinuation::skip);
396 while (id() != check.id()) {
397 check = check.sender(&map);
398 }
399 assert(check.is_deoptimized_frame(), "missed deopt");
400 }
401 }
402 #endif // ASSERT
403 }
404
753 }
754
755
756 /*
757 The interpreter_frame_expression_stack_at method in the case of SPARC needs the
758 max_stack value of the method in order to compute the expression stack address.
759 It uses the Method* in order to get the max_stack value but during GC this
760 Method* value saved on the frame is changed by reverse_and_push and hence cannot
761 be used. So we save the max_stack value in the FrameClosure object and pass it
762 down to the interpreter_frame_expression_stack_at method
763 */
764 class InterpreterFrameClosure : public OffsetClosure {
765 private:
766 const frame* _fr;
767 OopClosure* _f;
768 int _max_locals;
769 int _max_stack;
770
771 public:
772 InterpreterFrameClosure(const frame* fr, int max_locals, int max_stack,
773 OopClosure* f, BufferedValueClosure* bvt_f) {
774 _fr = fr;
775 _max_locals = max_locals;
776 _max_stack = max_stack;
777 _f = f;
778 }
779
780 void offset_do(int offset) {
781 oop* addr;
782 if (offset < _max_locals) {
783 addr = (oop*) _fr->interpreter_frame_local_at(offset);
784 assert((intptr_t*)addr >= _fr->sp(), "must be inside the frame");
785 if (_f != nullptr) {
786 _f->do_oop(addr);
787 }
788 } else {
789 addr = (oop*) _fr->interpreter_frame_expression_stack_at((offset - _max_locals));
790 // In case of exceptions, the expression stack is invalid and the esp will be reset to express
791 // this condition. Therefore, we call f only if addr is 'inside' the stack (i.e., addr >= esp for Intel).
792 bool in_stack;
793 if (frame::interpreter_frame_expression_stack_direction() > 0) {
794 in_stack = (intptr_t*)addr <= _fr->interpreter_frame_tos_address();
795 } else {
796 in_stack = (intptr_t*)addr >= _fr->interpreter_frame_tos_address();
797 }
798 if (in_stack) {
799 if (_f != nullptr) {
800 _f->do_oop(addr);
801 }
802 }
803 }
804 }
805 };
806
807
808 class InterpretedArgumentOopFinder: public SignatureIterator {
809 private:
810 OopClosure* _f; // Closure to invoke
811 int _offset; // TOS-relative offset, decremented with each argument
812 bool _has_receiver; // true if the callee has a receiver
813 const frame* _fr;
814
815 friend class SignatureIterator; // so do_parameters_on can call do_type
816 void do_type(BasicType type) {
817 _offset -= parameter_type_word_count(type);
818 if (is_reference_type(type)) oop_offset_do();
819 }
820
821 void oop_offset_do() {
956 signature = call.signature();
957 has_receiver = call.has_receiver();
958 if (map->include_argument_oops() &&
959 interpreter_frame_expression_stack_size() > 0) {
960 ResourceMark rm(thread); // is this right ???
961 // we are at a call site & the expression stack is not empty
962 // => process callee's arguments
963 //
964 // Note: The expression stack can be empty if an exception
965 // occurred during method resolution/execution. In all
966 // cases we empty the expression stack completely be-
967 // fore handling the exception (the exception handling
968 // code in the interpreter calls a blocking runtime
969 // routine which can cause this code to be executed).
970 // (was bug gri 7/27/98)
971 oops_interpreted_arguments_do(signature, has_receiver, f);
972 }
973 }
974 }
975
976 InterpreterFrameClosure blk(this, max_locals, m->max_stack(), f, nullptr);
977
978 // process locals & expression stack
979 InterpreterOopMap mask;
980 if (query_oop_map_cache) {
981 m->mask_for(m, bci, &mask);
982 } else {
983 OopMapCache::compute_one_oop_map(m, bci, &mask);
984 }
985 mask.iterate_oop(&blk);
986 }
987
988 void frame::buffered_values_interpreted_do(BufferedValueClosure* f) {
989 assert(is_interpreted_frame(), "Not an interpreted frame");
990 Thread *thread = Thread::current();
991 methodHandle m (thread, interpreter_frame_method());
992 jint bci = interpreter_frame_bci();
993
994 assert(m->is_method(), "checking frame value");
995 assert(!m->is_native() && bci >= 0 && bci < m->code_size(),
996 "invalid bci value");
997
998 InterpreterFrameClosure blk(this, m->max_locals(), m->max_stack(), nullptr, f);
999
1000 // process locals & expression stack
1001 InterpreterOopMap mask;
1002 m->mask_for(bci, &mask);
1003 mask.iterate_oop(&blk);
1004 }
1005
1006 void frame::oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f) const {
1007 InterpretedArgumentOopFinder finder(signature, has_receiver, this, f);
1008 finder.oops_do();
1009 }
1010
1011 void frame::oops_nmethod_do(OopClosure* f, NMethodClosure* cf, DerivedOopClosure* df, DerivedPointerIterationMode derived_mode, const RegisterMap* reg_map) const {
1012 assert(_cb != nullptr, "sanity check");
1013 assert((oop_map() == nullptr) == (_cb->oop_maps() == nullptr), "frame and _cb must agree that oopmap is set or not");
1014 if (oop_map() != nullptr) {
1015 if (df != nullptr) {
1016 _oop_map->oops_do(this, reg_map, f, df);
1017 } else {
1018 _oop_map->oops_do(this, reg_map, f, derived_mode);
1019 }
1020
1021 // Preserve potential arguments for a callee. We handle this by dispatching
1022 // on the codeblob. For c2i, we do
1023 if (reg_map->include_argument_oops() && _cb->is_nmethod()) {
1024 // Only nmethod preserves outgoing arguments at call.
1037 class CompiledArgumentOopFinder: public SignatureIterator {
1038 protected:
1039 OopClosure* _f;
1040 int _offset; // the current offset, incremented with each argument
1041 bool _has_receiver; // true if the callee has a receiver
1042 bool _has_appendix; // true if the call has an appendix
1043 frame _fr;
1044 RegisterMap* _reg_map;
1045 int _arg_size;
1046 VMRegPair* _regs; // VMReg list of arguments
1047
1048 friend class SignatureIterator; // so do_parameters_on can call do_type
1049 void do_type(BasicType type) {
1050 if (is_reference_type(type)) handle_oop_offset();
1051 _offset += parameter_type_word_count(type);
1052 }
1053
1054 virtual void handle_oop_offset() {
1055 // Extract low order register number from register array.
1056 // In LP64-land, the high-order bits are valid but unhelpful.
1057 assert(_offset < _arg_size, "out of bounds");
1058 VMReg reg = _regs[_offset].first();
1059 oop *loc = _fr.oopmapreg_to_oop_location(reg, _reg_map);
1060 #ifdef ASSERT
1061 if (loc == nullptr) {
1062 if (_reg_map->should_skip_missing()) {
1063 return;
1064 }
1065 tty->print_cr("Error walking frame oops:");
1066 _fr.print_on(tty);
1067 assert(loc != nullptr, "missing register map entry reg: %d %s loc: " INTPTR_FORMAT, reg->value(), reg->name(), p2i(loc));
1068 }
1069 #endif
1070 _f->do_oop(loc);
1071 }
1072
1073 public:
1074 CompiledArgumentOopFinder(Symbol* signature, bool has_receiver, bool has_appendix, OopClosure* f, frame fr, const RegisterMap* reg_map)
1075 : SignatureIterator(signature) {
1076
1077 // initialize CompiledArgumentOopFinder
1078 _f = f;
1079 _offset = 0;
1080 _has_receiver = has_receiver;
1081 _has_appendix = has_appendix;
1082 _fr = fr;
1083 _reg_map = (RegisterMap*)reg_map;
1084 _regs = SharedRuntime::find_callee_arguments(signature, has_receiver, has_appendix, &_arg_size);
1085 }
1086
1087 void oops_do() {
1088 if (_has_receiver) {
1089 handle_oop_offset();
1090 _offset++;
1091 }
1092 do_parameters_on(this);
1093 if (_has_appendix) {
1094 handle_oop_offset();
1095 _offset++;
1096 }
1097 }
1098 };
1099
1100 void frame::oops_compiled_arguments_do(Symbol* signature, bool has_receiver, bool has_appendix,
1101 const RegisterMap* reg_map, OopClosure* f) const {
1102 // ResourceMark rm;
1103 CompiledArgumentOopFinder finder(signature, has_receiver, has_appendix, f, *this, reg_map);
1104 finder.oops_do();
|