/* Sun-$Revision: 23.20 $ */ /* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University. See the LICENSE file for license information. */ # pragma interface class abstract_interpreter; typedef void (*aiCheckFn)(abstract_interpreter*, oop); // I am an abstract super class for interpreting bytecodes class abstract_interpreter_method_info: public PartObj { friend class frame; // for the ITERATORs (_map_oop) (ugh) friend class InterpreterIterator; // for the interators friend class FrameIterator; protected: mapOop _map_oop; // =badOop when checking codes and literals public: u_char* codes; fint length_codes; oop* literals; fint length_literals; // next two are for real interpreter scavenging & gc objVectorOop literals_object; byteVectorOop codes_object; abstract_interpreter_method_info(methodMap *mm); abstract_interpreter_method_info(byteVectorOop codes, objVectorOop literals); // hide whether oop or map is stored mapOop map_oop() { return as_mapOop(_map_oop); } methodMap* map() { return (methodMap*) _map_oop->addr(); } void print_short(); bool verify(); protected: void init(byteVectorOop codes, objVectorOop literals); }; # define ABSTRACT_INTERPRETER_METHOD_INFO_ITERATOR(mi, template, doReinit ) \ { \ oop* p; \ p = (oop*)&(mi)->_map_oop; template; \ p = (oop*)&(mi)->literals_object; template; \ p = (oop*)&(mi)->codes_object; template; \ \ if (doReinit) { \ assert_objVector((mi)->literals_object, \ "literals must be object vector"); \ (mi)->literals= (mi)->literals_object->objs(); \ assert_byteVector((mi)->codes_object, "codes must be byte vector"); \ (mi)->codes= (unsigned char*) (mi)->codes_object->bytes(); \ } \ } class abstract_interpreter_bytecode_info: public PartObj { public: fint code; // the whole bytecode fint op; // opcode field fint x; // index field inline void decode(fint c); void print_short(); }; class abstract_interpreter_interbytecode_state: public PartObj { public: fint lexical_level; // set by lexical level code, used by local accessors fint index; // set by index code for extended indices oop last_literal; // set by literal code, used for setting delegatee stringOop delegatee; // delegatee for next send, or NULL bool is_undirected_resend; inline abstract_interpreter_interbytecode_state(); void reset_index() { index= 0; } void reset_lexical_level() { lexical_level= 0; } void reset_send_modifiers() { delegatee= NULL; is_undirected_resend= false; } char* check_no_index() { return index == 0 ? NULL : "this code does not use or preserve index"; } char* check_no_lexical_level() { return lexical_level == 0 ? NULL : "this code does not use or preserve lexical_level"; } char* check_no_operand() { char* c= check_no_index(); return c ? c : check_no_lexical_level(); } char* check_no_send_modifiers() { return !is_undirected_resend && delegatee == NULL ? NULL : "send modifiers should be set right before the send" ; } char* check_no_two_send_modifiers() { return !is_undirected_resend || delegatee == NULL ? NULL : "send cannot be both undirected and directed" ; } void print_short(); }; # define ABSTRACT_INTERPRETER_INTERBYTECODE_STATE_ITERATOR(is, \ template, \ reinit ) \ { \ oop* p; \ p = &(is)->last_literal; template; \ p = (oop*)&(is)->delegatee; template; \ } // I factor out bytecode decoding for all the places in the VM // that do it. // I only know about "syntax". class abstract_interpreter: public AnywhereObj { friend class frame; // for the ITERATORs (ugh) friend class FrameIterator; // for the ITERATORs (ugh) friend class InterpreterIterator; friend Location location_of_interpreter(void*); // needs prot fns public: fint pc; protected: char* error_msg; class abstract_interpreter_method_info mi; class abstract_interpreter_bytecode_info bc; class abstract_interpreter_interbytecode_state is; public: inline abstract_interpreter(oop meth); inline abstract_interpreter(methodMap *m); inline abstract_interpreter(byteVectorOop codes, objVectorOop literals); protected: // Checkers friend void check_index_range( abstract_interpreter*, oop); friend void check_selector_string( abstract_interpreter*, oop); friend void check_branch_target( abstract_interpreter*, oop); friend void check_no_send_modifiers( abstract_interpreter*, oop); friend void check_no_lexical_level( abstract_interpreter*, oop); friend void check_no_two_send_modifiers( abstract_interpreter*, oop); friend void check_no_operand( abstract_interpreter*, oop); friend void check_delegatee( abstract_interpreter*, oop); friend void check_branch_vector( abstract_interpreter*, oop); friend void check_for_pop( abstract_interpreter*, oop); void set_error_msg(char* s) { if (!error_msg) error_msg= s; } // want first one public: char* get_error_msg() { return error_msg; } protected: // inflection points for bytecode checker virtual void check_branch_target(oop p) { if (!p->is_smi()) set_error_msg( "branch target must be smallInt"); else if ( // == length_codes means return 0 <= smiOop(p)->value() && smiOop(p)->value() <= mi.length_codes ) { } else set_error_msg( "bad branch target"); } virtual bool check(aiCheckFn fn, oop p = NULL) { assert( ( (*fn)(this, p), !error_msg), error_msg); UsedOnlyInAssert((void*)fn); UsedOnlyInAssert(p); return true; } virtual bool check_for_pop(oop) { SubclassResponsibility(); return false; } protected: oop get_literal() { return check(check_index_range) ? mi.literals[is.index] : NULL; } inline stringOop get_selector(); int32 get_branch_pc() { oop p = get_literal(); return check(::check_branch_target, p) ? smiOop(p)->value() : 0; } objVectorOop get_branch_vector() { oop p = get_literal(); return check(check_branch_vector, p) ? objVectorOop(p) : Memory->objVectorObj; } public: virtual void interpret_method(); virtual void interpret_bytecode() { fetch_and_decode_bytecode(); dispatch_bytecode(); } virtual void fetch_and_decode_bytecode(); void dispatch_bytecode(); protected: // NOTE: The pre_*_CODE, do_*_CODE, and post_*_CODE // routines are called via macro from dispatch_bytecode() // The following pre_ routines check "syntax" here, // i.e. checks that do not use method. void pre_INDEX_CODE() { } void pre_SEND_CODE() { check(check_no_send_modifiers); check(check_no_lexical_level); } void pre_IMPLICIT_SEND_CODE() { check(check_no_lexical_level); check(check_no_two_send_modifiers); } void pre_LEXICAL_LEVEL_CODE() { check(check_no_send_modifiers); } void pre_READ_LOCAL_CODE() { check(check_no_send_modifiers); } void pre_WRITE_LOCAL_CODE() { check(check_no_send_modifiers); } void pre_LITERAL_CODE() { check(check_no_send_modifiers); } void pre_DELEGATEE_CODE() { check(check_no_send_modifiers); check(check_delegatee); } void pre_SELF_CODE() { check(check_no_operand); check(check_no_send_modifiers); } void pre_POP_CODE() { check(check_no_operand); check(check_no_send_modifiers); } void pre_NONLOCAL_RETURN_CODE() { check(check_no_operand); check(check_no_send_modifiers); } void pre_UNDIRECTED_RESEND_CODE() { check(check_no_operand); check(check_no_send_modifiers); } void pre_DIRECTED_RESEND_CODE() { check(check_no_operand); check(check_no_send_modifiers); } void pre_branch_code() { check(check_no_send_modifiers); check(check_no_lexical_level); } void pre_BRANCH_CODE() { pre_branch_code(); } void pre_BRANCH_TRUE_CODE() { pre_branch_code(); } void pre_BRANCH_FALSE_CODE() { pre_branch_code(); } void pre_BRANCH_INDEXED_CODE() { pre_branch_code(); } void pre_illegal_no_operand_code() { } void pre_illegal_code() { } protected: // NOTE: these routines are called via macro from dispatch_bytecode() // see comment above the pre_'s // override the following virtuals to do something real virtual void do_SELF_CODE() { } virtual void do_POP_CODE() { } virtual void do_NONLOCAL_RETURN_CODE() { } virtual void do_INDEX_CODE() { } virtual void do_literal_code(oop lit) { Unused(lit); } virtual void do_LITERAL_CODE(); // override either first one or 2 and 3 virtual void do_read_write_local_code(bool isWrite) { Unused(isWrite); } virtual void do_READ_LOCAL_CODE() { do_read_write_local_code(false); } virtual void do_WRITE_LOCAL_CODE() { do_read_write_local_code(true); } // override either first one or 2 and 3 virtual void do_send_code(bool isSelfImplicit, stringOop selector) { Unused(isSelfImplicit); Unused(selector); } virtual void do_SEND_CODE() { do_send_code(false, get_selector()); } virtual void do_IMPLICIT_SEND_CODE() { do_send_code(true, get_selector()); } virtual void do_UNDIRECTED_RESEND_CODE() { } virtual void do_DELEGATEE_CODE() { } virtual void do_LEXICAL_LEVEL_CODE() { } virtual void do_branch_code( int32 target_PC, oop target_oop = badOop ) { Unused(target_PC); Unused(target_oop); } virtual void do_BRANCH_CODE() { do_branch_code( get_branch_pc() ); } virtual void do_BRANCH_TRUE_CODE() { do_branch_code( get_branch_pc(), (oop) Memory->trueObj ); } virtual void do_BRANCH_FALSE_CODE() { do_branch_code( get_branch_pc(), (oop) Memory->falseObj ); } virtual void do_BRANCH_INDEXED_CODE() { get_branch_vector(); } virtual void do_illegal_no_operand_code() { do_illegal_code(); } virtual void do_illegal_code() { fatal3("bad op code: %ld (opcode: $ld, index: %ld)", bc.code, bc.op, bc.x); } protected: // NOTE: these routines are called via macro from dispatch_bytecode() // see comment above the pre_'s // fixup after bytcode void post_SELF_CODE() { } void post_POP_CODE() { } void post_NONLOCAL_RETURN_CODE() { } void post_INDEX_CODE() { } void post_LITERAL_CODE() { is.reset_index(); } void post_READ_LOCAL_CODE() { is.reset_index(); is.reset_lexical_level(); } void post_WRITE_LOCAL_CODE() { is.reset_index(); is.reset_lexical_level(); } void post_SEND_CODE() { is.reset_index(); is.reset_send_modifiers(); } void post_IMPLICIT_SEND_CODE() { is.reset_index(); is.reset_send_modifiers(); } void post_UNDIRECTED_RESEND_CODE() { is.is_undirected_resend= true; } void post_DELEGATEE_CODE() { is.delegatee= stringOop(get_literal()); is.reset_index(); } void post_LEXICAL_LEVEL_CODE() { is.lexical_level= is.index; is.reset_index(); } void post_BRANCH_CODE() { is.reset_index(); } void post_BRANCH_TRUE_CODE() { is.reset_index(); } void post_BRANCH_FALSE_CODE() { is.reset_index(); } void post_BRANCH_INDEXED_CODE() { is.reset_index(); } void post_illegal_no_operand_code() { } void post_illegal_code() { } public: void print_short(); virtual bool verify(); }; // for scavenging, etc, see interpreter.h # define ABSTRACT_INTERPRETER_ITERATOR(intrp, template, zap, reinit) \ { \ ABSTRACT_INTERPRETER_METHOD_INFO_ITERATOR( &(intrp)->mi, template, reinit) \ ABSTRACT_INTERPRETER_INTERBYTECODE_STATE_ITERATOR(&(intrp)->is, template, reinit) \ }