genjvm.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 1,594 行 · 第 1/4 页

SCALA
1,594
字号
              case StringTag  => jcode.emitPUSH(const.stringValue)              case NullTag    => jcode.emitACONST_NULL()              case ClassTag   =>                val kind = toTypeKind(const.typeValue);                if (kind.isValueType)                  jcode.emitPUSH(classLiteral(kind));                else                  jcode.emitPUSH(javaType(kind).asInstanceOf[JReferenceType]);              case EnumTag   =>                val sym = const.symbolValue                jcode.emitGETSTATIC(javaName(sym.owner),                                    javaName(sym),                                    javaType(const.tpe))              case _          => abort("Unknown constant value: " + const);            }          case LOAD_ARRAY_ITEM(kind) =>            jcode.emitALOAD(javaType(kind))          case LOAD_LOCAL(local) =>            jcode.emitLOAD(indexOf(local), javaType(local.kind))          case LOAD_FIELD(field, isStatic) =>            var owner = javaName(field.owner);//            if (field.owner.hasFlag(Flags.MODULE)) owner = owner + "$";            if (settings.debug.value)                          log("LOAD_FIELD with owner: " + owner +                  " flags: " + Flags.flagsToString(field.owner.flags))            if (isStatic)              jcode.emitGETSTATIC(owner,                                  javaName(field),                                  javaType(field))            else              jcode.emitGETFIELD(owner,                                  javaName(field),                                  javaType(field))                        case LOAD_MODULE(module) =>//            assert(module.isModule, "Expected module: " + module)            if (settings.debug.value)              log("genearting LOAD_MODULE for: " + module + " flags: " +                   Flags.flagsToString(module.flags));            if (clasz.symbol == module.moduleClass && jmethod.getName() != nme.readResolve.toString)              jcode.emitALOAD_0()            else              jcode.emitGETSTATIC(javaName(module) /* + "$" */ ,                                  nme.MODULE_INSTANCE_FIELD.toString,                                  javaType(module));          case STORE_ARRAY_ITEM(kind) =>            jcode.emitASTORE(javaType(kind))          case STORE_LOCAL(local) =>            jcode.emitSTORE(indexOf(local), javaType(local.kind))          case STORE_THIS(_) =>            // this only works for impl classes because the self parameter comes first            // in the method signature. If that changes, this code has to be revisited.            jcode.emitASTORE_0()          case STORE_FIELD(field, isStatic) =>            val owner = javaName(field.owner) // + (if (field.owner.hasFlag(Flags.MODULE)) "$" else "");            if (isStatic)              jcode.emitPUTSTATIC(owner,                                  javaName(field),                                  javaType(field))            else              jcode.emitPUTFIELD(owner,                                  javaName(field),                                  javaType(field))          case CALL_PRIMITIVE(primitive) =>            genPrimitive(primitive, instr.pos)          case call @ CALL_METHOD(method, style) =>            val owner: String = javaName(method.owner);            //reference the type of the receiver instead of the method owner (if not an interface!)            val dynamicOwner =              if (needsInterfaceCall(call.hostClass)) owner              else javaName(call.hostClass)            style match {              case Dynamic =>                if (needsInterfaceCall(method.owner))                  jcode.emitINVOKEINTERFACE(owner,                                            javaName(method),                                            javaType(method).asInstanceOf[JMethodType])                else                  jcode.emitINVOKEVIRTUAL(dynamicOwner,                                          javaName(method),                                          javaType(method).asInstanceOf[JMethodType]);              case Static(instance) =>                if (instance) {                  jcode.emitINVOKESPECIAL(owner,                                          javaName(method),                                          javaType(method).asInstanceOf[JMethodType]);                } else                  jcode.emitINVOKESTATIC(owner,                                          javaName(method),                                          javaType(method).asInstanceOf[JMethodType]);              case SuperCall(_) =>                  jcode.emitINVOKESPECIAL(owner,                                          javaName(method),                                          javaType(method).asInstanceOf[JMethodType]);                  // we initialize the MODULE$ field immediately after the super ctor                  if (isStaticModule(clasz.symbol) && !isModuleInitialized &&                      jmethod.getName() == JMethod.INSTANCE_CONSTRUCTOR_NAME &&                      javaName(method) == JMethod.INSTANCE_CONSTRUCTOR_NAME) {                        isModuleInitialized = true;                        jcode.emitALOAD_0();                        jcode.emitPUTSTATIC(jclass.getName(),                                            nme.MODULE_INSTANCE_FIELD.toString,                                            jclass.getType());                      }            }          case BOX(kind) =>            val boxedType = definitions.boxedClass(kind.toType.typeSymbol)            val mtype = new JMethodType(javaType(boxedType), Array(javaType(kind)))            jcode.emitINVOKESTATIC(BoxesRunTime, "boxTo" + boxedType.nameString, mtype)          case UNBOX(kind) =>            val mtype = new JMethodType(javaType(kind), Array(JObjectType.JAVA_LANG_OBJECT))            jcode.emitINVOKESTATIC(BoxesRunTime, "unboxTo" + kind.toType.typeSymbol.nameString, mtype)          case NEW(REFERENCE(cls)) =>            val className = javaName(cls)            jcode.emitNEW(className)          case CREATE_ARRAY(elem, 1) => elem match {            case REFERENCE(_) | ARRAY(_) =>              jcode.emitANEWARRAY(javaType(elem).asInstanceOf[JReferenceType])            case _ =>              jcode.emitNEWARRAY(javaType(elem))          }          case CREATE_ARRAY(elem, dims) =>             jcode.emitMULTIANEWARRAY(javaType(ArrayN(elem, dims)).asInstanceOf[JReferenceType], dims)          case IS_INSTANCE(tpe) =>            tpe match {              case REFERENCE(cls) => jcode.emitINSTANCEOF(new JObjectType(javaName(cls)))              case ARRAY(elem)    => jcode.emitINSTANCEOF(new JArrayType(javaType(elem)))              case _ => abort("Unknown reference type in IS_INSTANCE: " + tpe)            }          case CHECK_CAST(tpe) =>            tpe match {              case REFERENCE(cls) => jcode.emitCHECKCAST(new JObjectType(javaName(cls)))              case ARRAY(elem)    => jcode.emitCHECKCAST(new JArrayType(javaType(elem)))              case _ => abort("Unknown reference type in IS_INSTANCE: " + tpe)            }          case SWITCH(tags, branches) =>            val tagArray = new Array[Array[Int]](tags.length)            var caze = tags            var i = 0            while (i < tagArray.length) {              tagArray(i) = new Array[Int](caze.head.length)              caze.head.copyToArray(tagArray(i), 0)              i = i + 1              caze = caze.tail            }            val branchArray = new Array[JCode$Label](tagArray.length)            if (settings.debug.value)              log("Emitting SWITHCH:\ntags: " + tags + "\nbranches: " + branches);            jcode.emitSWITCH(tagArray,                              { (branches map labels dropRight 1).copyToArray(branchArray, 0);                               branchArray },                             labels(branches.last),                             MIN_SWITCH_DENSITY);          case JUMP(whereto) =>            if (nextBlock != whereto)              jcode.emitGOTO_maybe_W(labels(whereto), false); // default to short jumps          case CJUMP(success, failure, cond, kind) =>            kind match {              case BOOL | BYTE | CHAR | SHORT | INT =>                if (nextBlock == success) {                  jcode.emitIF_ICMP(conds(negate(cond)), labels(failure))                  // .. and fall through to success label                } else {                  jcode.emitIF_ICMP(conds(cond), labels(success))                  if (nextBlock != failure)                    jcode.emitGOTO_maybe_W(labels(failure), false);                }              case REFERENCE(_) | ARRAY(_) =>                if (nextBlock == success) {                  jcode.emitIF_ACMP(conds(negate(cond)), labels(failure))                  // .. and fall through to success label                } else {                  jcode.emitIF_ACMP(conds(cond), labels(success))                  if (nextBlock != failure)                    jcode.emitGOTO_maybe_W(labels(failure), false);                }              case _ =>                (kind: @unchecked) match {                  case LONG   => jcode.emitLCMP()                  case FLOAT  =>                     if (cond == LT || cond == LE) jcode.emitFCMPG()                    else jcode.emitFCMPL()                  case DOUBLE =>                     if (cond == LT || cond == LE) jcode.emitDCMPG()                    else jcode.emitDCMPL()                }                if (nextBlock == success) {                  jcode.emitIF(conds(negate(cond)), labels(failure));                  // .. and fall through to success label                } else {                  jcode.emitIF(conds(cond), labels(success));                  if (nextBlock != failure)                    jcode.emitGOTO_maybe_W(labels(failure), false);                }            }                      case CZJUMP(success, failure, cond, kind) =>            kind match {              case BOOL | BYTE | CHAR | SHORT | INT =>                if (nextBlock == success) {                  jcode.emitIF(conds(negate(cond)), labels(failure));                } else {                  jcode.emitIF(conds(cond), labels(success))                  if (nextBlock != failure)                    jcode.emitGOTO_maybe_W(labels(failure), false);                }              case REFERENCE(_) | ARRAY(_) =>                if (nextBlock == success) {                  jcode.emitIFNONNULL(labels(failure))                } else {                  jcode.emitIFNULL(labels(success));                  if (nextBlock != failure)                    jcode.emitGOTO_maybe_W(labels(failure), false);                }              case _ =>                (kind: @unchecked) match {                  case LONG   => jcode.emitLCONST_0(); jcode.emitLCMP()                  case FLOAT  =>                     jcode.emitFCONST_0();                     if (cond == LT || cond == LE) jcode.emitFCMPG()                    else jcode.emitFCMPL()                                      case DOUBLE =>                     jcode.emitDCONST_0();                     if (cond == LT || cond == LE) jcode.emitDCMPG()                    else jcode.emitDCMPL()                }                if (nextBlock == success) {                  jcode.emitIF(conds(negate(cond)), labels(failure))                } else {                  jcode.emitIF(conds(cond), labels(success))                  if (nextBlock != failure)                    jcode.emitGOTO_maybe_W(labels(failure), false);                }            }          case RETURN(kind) =>            jcode.emitRETURN(javaType(kind))          case THROW() =>            jcode.emitATHROW()          case DROP(kind) =>            kind match {              case LONG | DOUBLE => jcode.emitPOP2()              case _ => jcode.emitPOP()            }          case DUP(kind) =>            kind match {              case LONG | DOUBLE => jcode.emitDUP2()              case _ => jcode.emitDUP()            }          case MONITOR_ENTER() =>            jcode.emitMONITORENTER()          case MONITOR_EXIT() =>            jcode.emitMONITOREXIT()                      case SCOPE_ENTER(lv) =>             varsInBlock += lv            lv.start = jcode.getPC()                      case SCOPE_EXIT(lv) =>            if (varsInBlock contains lv) {              lv.ranges = (lv.start, jcode.getPC()) :: lv.ranges              varsInBlock -= lv            } else if (b.varsInScope contains lv) {              lv.ranges = (labels(b).getAnchor(), jcode.getPC()) :: lv.ranges              b.varsInScope -= lv            } else              assert(false, "Illegal local var nesting: " + method)          case LOAD_EXCEPTION() =>            ()        }        crtPC = jcode.getPC()        //        assert(instr.pos.source.isEmpty || instr.pos.source.get == (clasz.cunit.source), "sources don't match")//        val crtLine = instr.pos.line.get(lastLineNr);        val crtLine = try {          (instr.pos).line.get        } catch {          case _: NoSuchElementException =>            log("Warning: wrong position in: " + method)            lastLineNr        }                  if (b.lastInstruction == instr)          endPC(b) = jcode.getPC();        //System.err.println("CRTLINE: " + instr.pos + " " +         //           /* (if (instr.pos < clasz.cunit.source.content.length) clasz.cunit.source.content(instr.pos) else '*') + */ " " + crtLine);        if (crtPC > lastMappedPC) {          jcode.completeLineNumber(lastMappedPC, crtPC, crtLine)          lastMappedPC = crtPC          lastLineNr   = crtLine        }      }); // b.traverse             // local vars that survived this basic block       for (val lv <- varsInBlock) {        lv.ranges = (lv.start, jcode.getPC()) :: lv.ranges      }      for (val lv <- b.varsInScope) {        lv.ranges = (labels(b).getAnchor(), jcode.getPC()) :: lv.ranges      }    }    /**     *  @param primitive ...     *  @param pos       ...     */    def genPrimitive(primitive: Primitive, pos: Position) {      primitive match {        case Negation(kind) =>          kind match {            case BOOL | BYTE | CHAR | SHORT | INT =>               jcode.emitINEG()            case LONG   => jcode.emitLNEG()            case FLOAT  => jcode.emitFNEG()            case DOUBLE => jcode.emitDNEG()            case _ => abort("Impossible to negate a " + kind)          }        case Arithmetic(op, kind) =>          op match {            case ADD => jcode.emitADD(javaType(kind))            case SUB =>              (kind: @unchecked) match {                case BOOL | BYTE | CHAR | SHORT | INT =>                  jcode.emitISUB()                case LONG   => jcode.emitLSUB()                case FLOAT  => jcode.emitFSUB()                case DOUBLE => jcode.emitDSUB()              }            case MUL =>              (kind: @unchecked) match {                case BOOL | BYTE | CHAR | SHORT | INT =>                  jcode.emitIMUL()                case LONG   => jcode.emitLMUL()                case FLOAT  => jcode.emitFMUL()                case DOUBLE => jcode.emitDMUL()              }            case DIV =>              (kind: @unchecked) match {                case BOOL | BYTE | CHAR | SHORT | INT =>                  jcode.emitIDIV()                case LONG   => jcode.emitLDIV()                case FLOAT  => jcode.emitFDIV()                case DOUBLE => jcode.emitDDIV()              }            case REM =>              (kind: @unchecked) match {                case BOOL | BYTE | CHAR | SHORT | INT =>                  jcode.emitIREM()                case LONG   => jcode.emitLREM()                case FLOAT  => jcode.emitFREM()                case DOUBLE => jcode.emitDREM()              }            case NOT =>              kind match {                case BOOL | BYTE | CHAR | SHORT | INT =>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?