/* Sun-$Revision: 23.12 $ */
/* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University.
See the LICENSE file for license information. */
# pragma interface
/* Portability strategy:
Each platform needs its own frame class.
Yet each one shares much in common.
Our solution is to #include the machine-dependent part into the
class definition, and have a platform.frame.c for the machine-dependent
routines.
*/
// in addition to fwded routines
// a new platform must typedef frame
typedef void (*returnTrapHandlerFn)(...);
class Conversion; // for friend declaration below
class frame {
// here are platform-dependent routines that must be supplied for
// each platform
// I think the "inner" refers to inner in the Beta sense; these are override
public: frame* sender();
protected: char** real_return_addr_addr();
public: void** location_addr(Location r, RegisterLocator* rl = NULL);
protected: void copy_to(char* sp, char* caller, char* pc, bool adjust);
protected: frame* copy(fint nsenders = 0, bool adjustBlocks = false);
protected: void adjust_blocks(frame* oldScope, frame* newScope, RegisterLocator* rl);
public: void fix_frame(char* pc, char* sp);
public: frame* home_frame_of_block_scope(frame* hint = NULL);
public: frame* block_scope_of_home_frame();
public: frame* home_frame_of_vfo_locals(frame* hint = NULL);
public: frame* vfo_locals_of_home_frame();
protected: int32 frame_size_of_uncopied_frame();
public: char* c_entry_point();
public: char* c_return_pc();
public: frame* make_full_frame(char* pc); // return this on 68k
public: frame* make_full_frame_after_trap(char* pc); // return this on 68k
public: frame* make_full_frame_on_user_stack(); // return this on 68k
public: sendDesc* send_desc();
public: void scavenge_contents(RegisterLocator*);
public: void gc_mark_contents(RegisterLocator*);
public: void gc_unmark_contents(RegisterLocator*);
public: void verify_oops(RegisterLocator*);
public: void switch_pointers(oop from, oop to, RegisterLocator*);
public: void oops_do(oopsDoFn f, RegisterLocator*);
public: void stack_locations_do(oopsDoFn f, RegisterLocator*); // iterates through marked locs
public: void zap(RegisterString mask, RegisterLocator*); // zap all locations unmarked in mask
protected: RegisterString mask_if_present(); // helper for above fns
// used for scavenging, must return allocated location
// for every interpreter state struct that may exist
// return IllegalLocation for non-interp frame
// (the 2nd fn does the same for block scope (one up in sparc))
protected: static Location location_of_interpreter_of_block_scope(void* entry_point);
protected: void print_compiled();
protected: oop get_lookup_arg(fint index);
// now the platform-independent ones:
public: frame* sendee(frame* hint = NULL);
public: void verify(int n, RegisterLocator* rl);
// nmethod_frame_chain methods
protected: frame** nmethod_frame_chain_addr();
public:
frame* nmethod_frame_chain();
void set_nmethod_frame_chain(frame* f);
// currentPC methods: Sometimes, we need to regain control before
// a given frame is returned INTO. So we patch the return address
// that would return into this frame to go somewhere else, and
// store what was there in the frame's currentPC.
protected:
public:
char** currentPC_addr();
char* currentPC();
void set_currentPC(char* p);
// real return address, where the pc for returning TO ME is
protected:
public:
char* real_return_addr();
void set_real_return_addr(char* x);
// return address routines (deal with patching)
// NB: this is the address where I will resume in my method,
// upon return to me, not the address I will return TO. -- dmu
public:
char* return_addr();
void set_return_addr(char* addr);
void adjust_return_addr(int32 delta);
void fix_current_return_address(char* addr);
public: void patch(frame* prev, bool forceSelfFrame = false);
public: void patch_profiler_trap();
protected: void patch_interpreted_self_frame(bool forProfiling);
protected: void patch_compiled_self_frame(returnTrapHandlerFn new_fn);
protected: returnTrapHandlerFn
return_addr_for_patching(bool forceSelfFrame, frame* sendee);
protected: void trace_patch(returnTrapHandlerFn new_fn);
public:
bool is_patched();
void remove_patch();
void remove_patches_up_to_C();
frame* get_patched_self_frame(char* sp_of_patched_frame);
// registers
// conversion & recompilation routines
public:
frame* selfSender();
frame* immediateSelfSender(); // same, but don't skip C frames
Stack* my_stack();
public:
int32 frame_size(); // in oops
// testers
public:
bool is_compiled_self_frame();
bool is_interpreted_self_frame();
interpreter* get_interpreter();
interpreter* get_interpreter_of_block_scope();
bool is_self_frame();
bool is_first_self_frame();
fint vdepth(bool includePrologueVframe = false);
bool is_in_prologue();
// operations
public:
nmethod* code();
void nmethod_moved_by(int32 delta);
// tracing operations
public:
void trace(oop receiver, nmethod* c);
void traceAssignment(oop receiver, nmethod* c);
void traceLookup(oop receiver, nmethod* c);
void print_trace_indent();
void print();
void printVerbose();
private:
void printVerbose_on_this_platform();
void printRegs();
// helpers for copy:
protected:
frame* find_last_frame_to_copy(fint nsenders);
frame* copy_frames_through(frame* last_frame_to_copy);
int32 copy_through_oop_count(frame* last_frame_to_copy);
void adjust_blocks_of_copied_frames(fint, frame*);
void adjust_frame_links_of_copied_frames( frame*, frame*);
protected:
friend struct Profiler;
friend struct Recompilation;
friend class ::Conversion; // currently platform-dependent
# include "_frame_pd.h.incl"
};
inline bool isPatchedReturnAddress(char* r) {
return r == first_inst_addr(ReturnTrap)
|| r == first_inst_addr(PrimCallReturnTrap)
|| r == first_inst_addr(ProfilerTrap);
}
// called from assembly glue
extern "C" {
void HandleReturnTrap(oop result, char* sp,
bool nlr, frame* home, int32 homeID);
# if defined(FAST_COMPILER) || defined(SIC_COMPILER)
char *HandleProfilerTrap(char* return_address);
# endif
}
# define SavedFrameChain ((frame*)1)
# define NoFrameChain NULL