/* Sun-$Revision: 23.6 $ */ /* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University. See the LICENSE file for license information. */ # pragma interface # define OPWIDTH 4 # define INDEXWIDTH (8 - OPWIDTH) # define MAXOP nthMask(OPWIDTH) # define MAXINDEX nthMask(INDEXWIDTH) enum ByteCodeKind { INDEX_CODE, // shift index left, OR in my index field LITERAL_CODE, // push lits[index] SEND_CODE, // send w/ receiver on stack, // selector in literals[indx] IMPLICIT_SEND_CODE, // send w/ implicit receiver, // selector in literals[indx] NO_OPERAND_CODE, // no operand, opcode in index bits, see NoOparandKind READ_LOCAL_CODE, // read local; lexical lvl in lex reg, see below WRITE_LOCAL_CODE, // write local; lexical lvl in lex reg, see below LEXICAL_LEVEL_CODE, // lexical level of next RW_LOCAL op BRANCH_CODE, // uncond branch via lit BRANCH_TRUE_CODE, // branch on true via literal BRANCH_FALSE_CODE, // branch on false via literal BRANCH_INDEXED_CODE, // branch via literal vector, index on stack DELEGATEE_CODE // delegate next send to lits[index] }; enum NoOperandKind { SELF_CODE, // push self onto stack POP_CODE, // pop value from stack NONLOCAL_RETURN_CODE, // non-local-return from block UNDIRECTED_RESEND_CODE // next send is an undirected resend }; inline ByteCodeKind getOp(u_char c) { return ByteCodeKind(c >> INDEXWIDTH); } inline fint getIndex(fint c) { return c & MAXINDEX; } inline NoOperandKind getNoOpOp(u_char c) {return NoOperandKind(getIndex(c));} inline bool isSendOp(ByteCodeKind op) { return op == SEND_CODE || op == IMPLICIT_SEND_CODE; } inline fint BuildCode(fint op, fint x) { assert(x <= MAXINDEX, "bad index"); return (op << INDEXWIDTH) | x; } // the position table is generated by a parallel process, so // have one abstract superclass: class AbstractByteCode: public preservedVmObj { public: objVectorOop literals; fint literalIndex; fint maxLiteralIndex; int32 stack_depth; // for branch checking LabelSet* labelSet; BranchSet* branchSet; char* errorMessage; public: AbstractByteCode( objVectorOop lits = NULL) { if ( lits == NULL ) { literals= Memory->literalsObj->cloneSize(50); literalIndex= 0; } else { literals = lits; literalIndex= lits->length(); } maxLiteralIndex= literals->length(); stack_depth= 0; labelSet= new LabelSet; branchSet= new BranchSet; errorMessage = ""; } // generation routines void GenLiteralByteCode( fint offset, fint length, oop literal); void GenDelegateeByteCode( fint offset, fint length, stringOop delegatee); void GenSendByteCode( fint offset, fint length, stringOop selector, bool isSelfImplicit, bool isUndirectedResend, stringOop resendTarget); void GenSelfByteCode(fint offset, fint length); void GenPopByteCode( fint offset, fint length); void GenUndirectedResendByteCode( fint offset, fint length); void GenNonLocalReturnByteCode(fint offset, fint length); void GenRWLocalByteCode( fint offset, fint length, bool isRead, int32 lexicalLevel, int32 index); bool GenBranchByteCode( fint offset, fint length, oop label); bool GenBranchTrueByteCode( fint offset, fint length, oop label); bool GenBranchFalseByteCode( fint offset, fint length, oop label); bool GenBranchIndexedByteCode( fint offset, fint length, objVectorOop labels); bool GenLabelDefinition( oop label); bool ResolveBranches(); // preserve operation void oops_do(oopsDoFn f) { (*f)((oop*)&literals); branchSet->oops_do(f); labelSet->oops_do(f); } // helpers virtual bool isPositionTable() = 0; virtual void GenCode(fint offset, fint length, fint c) = 0; virtual fint bci() = 0; bool GenSimpleBranchByteCode( fint offset, fint length, oop label, ByteCodeKind op ); fint GenLiteral(oop p); // must make a new object so literal slot won't get reused fint GenLabelLiteral() { return GenLiteral( Memory->nilObj->clone()); } fint GenIndex(fint offset, fint length, fint x); fint GenExtendedIndex(fint offset, fint length, fint x); int32 getLabelIndex( oop label); }; class ByteCode: public AbstractByteCode { public: // instance variables byteVectorOop codes; // the finished vector is a canonical string fint codeIndex; fint maxCodeIndex; stringOop file; smiOop line; stringOop source; smiOop sourceOffset; smiOop sourceLen; // constructors ByteCode() : AbstractByteCode() { maxCodeIndex = 100; codeIndex = 0; codes= Memory->byteVectorObj->cloneSize(maxCodeIndex); file = NULL; source = NULL; // must initialize for GC sourceOffset= smiOop_zero; sourceLen= smiOop_zero; } ByteCode(byteVectorOop c, objVectorOop l, stringOop f, smiOop ln, stringOop s) : AbstractByteCode( l ) { codes = c; codeIndex = maxCodeIndex = c->length(); file = f; line = ln; source = s; sourceOffset= smiOop_zero; sourceLen= smiOop_zero; } bool Finish(); bool Finish(char* fname, fint sourceLine, char* srcStart, fint srcLen); bool Finish(char* fname, char* src); bool Finish(char* fname, fint sourceLine, fint srcOffset, fint srcLen); // preserve operation void oops_do(oopsDoFn f) { AbstractByteCode::oops_do(f); (*f)((oop*)&codes); (*f)((oop*)&file); (*f)((oop*)&source); } // helpers bool isPositionTable() { return false; } void GenCode(fint offset, fint length, fint c); fint bci() { return codeIndex; } // programming friend oop create_outer_method_prim( oop ignore, byteVectorOop bv, objVectorOop lits, stringOop file, smiOop line, stringOop source); friend oop create_block_method_prim( oop ignore, byteVectorOop bv, objVectorOop lits, stringOop file, smiOop line, stringOop source); };