/* Sun-$Revision: 23.11 $ */
/* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University.
See the LICENSE file for license information. */
# pragma interface
extern oop sneaky_method_argument_to_interpret;
extern "C" {
oop interpret( oop rcv,
oop sel,
oop del,
oop meth,
oop _mh,
oop* _args,
int32 _nargs );
oop interpret_from_compiled_sender();
}
enum ReturnPatchReason { not_patched, patched_for_profiling, patched };
class interpreter: public abstract_interpreter {
friend class interpreted_vframe; // needs mi.literals, etc
friend class InterpreterIterator;
public:
// WARNING all oops here must appear in ITERATOR below
oop receiver;
// next 2 are not redundant because of performs:
oop selector;
oop delegatee;
oop method_object;
protected:
oop _methodHolder;
public:
oop* args;
int32 length_args;
oop* locals;
int32 _length_locals;
int32 minOffset;
bool hasParentLocalSlot;
oop* cloned_blocks; // NULL or cloned block
oop* stack;
int32 sp;
oop self;
// put next two in here instead of locals so that
// they will get scavenged; they have to survive a send
// when a prim fails
oop rcvToSend;
oop selToSend; // could be anything if a perform
int32 arg_count; // for the send, not for me
// unlilke compiled frames, cannot patch the return address
// because that would lose the call used to verify that this is
// an interpreted frame. Instead, save the address that WOULD
// be installed here, and check it upon return.
ReturnPatchReason return_patch_reason;
bool restartSend;
interpreter* parentI; // interp of lexical parent or NULL
protected:
frame* _block_scope_or_NLR_target;
inline frame* block_scope_or_NLR_target();
public:
interpreter( oop rcv,
oop sel,
oop del,
oop meth,
oop _mh,
oop* _args,
int32 _nargs);
oop top() { return stack[sp-1]; }
inline int32 length_cloned_blocks();
inline void set_cloned_blocks(void* p);
inline int32 length_stack() { return mi.length_codes; }
inline void set_stack(void* p);
inline int32 length_locals() { return _length_locals; }
inline void set_locals(void* p);
PrimDesc* current_primDesc; // for stack walking
PrimDesc* getPrimDesc() { return current_primDesc; }
void set_restartSend(bool b) {restartSend = b;}
void interpret_method();
oop methodHolder() {
assert( ! _methodHolder->is_map(), "interp mh always object");
return _methodHolder;
}
void set_methodHolder(oop mh) { _methodHolder= mh; }
// frame oop iterators need this one (via INTERPRETER_ITERATOR below):
oop* methodHolder_addr() { return &_methodHolder; }
abstract_vframe* parentVF();
protected:
void do_SELF_CODE();
void do_POP_CODE();
void do_NONLOCAL_RETURN_CODE();
void do_literal_code(oop lit);
void do_read_write_local_code(bool isWrite);
void do_send_code(bool isSelfImplicit, stringOop selector);
void do_branch_code( int32 target_PC, oop target_oop = badOop );
void do_BRANCH_INDEXED_CODE();
public:
void send( LookupType, oop delegatee );
oop lookup_and_send( LookupType,
oop mh,
oop delegatee);
oop send_prim( );
public:
oop try_perform_prim( bool hasFailBlock,
bool& is_perform );
oop get_slot(slotDesc* sd);
void set_slot(slotDesc* sd, oop x);
protected:
fint return_pc() { return mi.length_codes - 1; }
fint restart_pc() { return mi.length_codes; }
void local_slot_desc(interpreter*& interp, abstract_vframe*& vf, slotDesc*& sd);
void block_scope_and_desc_of_home( frame*& block_scope_frame, int32& block_desc);
public:
bool is_return_patched() { return return_patch_reason != not_patched; }
void patch_return(ReturnPatchReason x) { return_patch_reason = x; }
ReturnPatchReason get_return_patch_reason() {
return return_patch_reason; }
void print();
public: // should be prot but friend doesn't work
void setup_for_method( );
void setup_for_block( );
protected:
void start_NLR(oop res);
void continue_NLR();
};
extern void InterpreterLookup_cont( simpleLookup *L, int32 arg_count);
// for scavenging, see frame.c
// Don't do:
// for (p = is->args; p < &is->args[is->length_args]; p++) { template; }
// because when args are passed from interpreter, they are iterated
// in its stack anyway. This means that non-interp calling interp
// must arrange to scavenge, etc the top-level args.
# define INTERPRETER_ITERATOR(interp, template, zap, reinit) \
{ \
ABSTRACT_INTERPRETER_ITERATOR(interp, template, zap, reinit) \
\
oop* p; \
\
p = &(interp)->receiver; template; \
p = (oop*)&(interp)->selector; template; \
p = (oop*)&(interp)->delegatee; template; \
p = (oop*)&(interp)->method_object; template; \
p = &(interp)->self; template; \
p = (interp)->methodHolder_addr(); template; \
\
for ( p = (interp)->locals; \
p < &(interp)->locals[(interp)->length_locals()]; \
++p) { \
template; \
} \
for ( p = (interp)->cloned_blocks; \
p < &(interp)->cloned_blocks[(interp)->mi.length_literals]; \
++p) { \
if (*p != NULL) { template; } \
} \
for (p = (interp)->stack; p < &(interp)->stack[(interp)->sp]; p++) { \
template; \
} \
if (zap) for ( ; p < &(interp)->stack[(interp)->length_stack()]; p++) { \
*p = badOop; \
} \
p = &(interp)->rcvToSend; template; \
p = (oop*)&(interp)->selToSend; template; \
}
// new style:
class InterpreterIterator: public StackObj {
private:
interpreter* interp;
OopClosure* oop_closure;
bool zap;
bool reinit;
public:
InterpreterIterator(interpreter* i, OopClosure* oc, bool z, bool r) {
interp = i; oop_closure = oc; zap = z; reinit = r;
do_all();
}
private:
void do_all() {
ABSTRACT_INTERPRETER_ITERATOR(interp, oop_closure->do_oop(p), zap, reinit)
oop* p;
p = &(interp)->receiver; oop_closure->do_oop(p);
p = (oop*)&(interp)->selector; oop_closure->do_oop(p);
p = (oop*)&(interp)->delegatee; oop_closure->do_oop(p);
p = (oop*)&(interp)->method_object; oop_closure->do_oop(p);
p = &(interp)->self; oop_closure->do_oop(p);
p = (interp)->methodHolder_addr(); oop_closure->do_oop(p);
for ( p = (interp)->locals;
p < &(interp)->locals[(interp)->length_locals()];
++p) {
oop_closure->do_oop(p);
}
for ( p = (interp)->cloned_blocks;
p < &(interp)->cloned_blocks[(interp)->mi.length_literals];
++p) {
if (*p != NULL) { oop_closure->do_oop(p); }
}
for (p = (interp)->stack; p < &(interp)->stack[(interp)->sp]; p++) {
oop_closure->do_oop(p);
}
if (zap) for ( ; p < &(interp)->stack[(interp)->length_stack()]; p++) {
*p = badOop;
}
p = &(interp)->rcvToSend; oop_closure->do_oop(p);
p = (oop*)&(interp)->selToSend; oop_closure->do_oop(p);
}
};