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