001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm; 014 015 import org.jikesrvm.classloader.Atom; 016 import org.jikesrvm.classloader.RVMClass; 017 import org.jikesrvm.classloader.RVMMember; 018 019 /** 020 * This interface is implemented by org.jikesrvm.PrintContainer. The 021 * interfaces is used by our java.lang.Throwable to print stack traces. 022 */ 023 @SuppressWarnings("unused") 024 // Suppress the unused import warning as per comment above 025 public abstract class PrintLN { 026 // PrintLN(PrintWriter out); 027 // PrintLN(PrintStream out); 028 public boolean isSysWrite() { return false; } 029 030 public boolean isSystemErr() { return false; } 031 032 public abstract void flush(); 033 034 public abstract void println(); 035 036 public void println(String s) { 037 print(s); 038 println(); 039 } 040 041 public abstract void print(String s); 042 043 /* Here, we are writing code to make sure that we do not rely upon any 044 * external memory accesses. */ 045 // largest power of 10 representable as a Java integer. 046 // (max int is 2147483647) 047 static final int max_int_pow10 = 1000000000; 048 049 public void print(int n) { 050 boolean suppress_leading_zero = true; 051 if (n == 0x80000000) { 052 print("-2147483648"); 053 return; 054 } else if (n == 0) { 055 print('0'); 056 return; 057 } else if (n < 0) { 058 print('-'); 059 n = -n; 060 } 061 /* We now have a positive # of the proper range. Will need to exit from 062 the bottom of the loop. */ 063 for (int p = max_int_pow10; p >= 1; p /= 10) { 064 int digit = n / p; 065 n -= digit * p; 066 if (digit == 0 && suppress_leading_zero) { 067 continue; 068 } 069 suppress_leading_zero = false; 070 char c = (char) ('0' + digit); 071 print(c); 072 } 073 } 074 075 public void printHex(int n) { 076 print("0x"); 077 // print exactly 8 hexadec. digits. 078 for (int i = 32 - 4; i >= 0; i -= 4) { 079 int digit = (n >>> i) & 0x0000000F; // fill with 0 bits. 080 char c; 081 082 if (digit <= 9) { 083 c = (char) ('0' + digit); 084 } else { 085 c = (char) ('A' + (digit - 10)); 086 } 087 print(c); 088 } 089 } 090 091 public abstract void print(char c); 092 093 // /** Print the name of the class to which the argument belongs. 094 // * 095 // * @param o Print the name of the class to which o belongs. */ 096 // public void printClassName(Object o) { 097 098 // } 099 100 /** Print the name of the class represented by the class descriptor. 101 * 102 * @param descriptor The class descriptor whose name we'll print. */ 103 public void printClassName(Atom descriptor) { 104 // toByteArray does not allocate; just returns an existing descriptor. 105 byte[] val = descriptor.toByteArray(); 106 107 if (VM.VerifyAssertions) { 108 VM._assert(val[0] == 'L' && val[val.length - 1] == ';'); 109 } 110 for (int i = 1; i < val.length - 1; ++i) { 111 char c = (char) val[i]; 112 if (c == '/') { 113 print('.'); 114 } else { 115 print(c); 116 } 117 } 118 // We could do this in an emergency. But we don't need to. 119 // print(descriptor); 120 } 121 122 /* Code related to Atom.classNameFromDescriptor() */ 123 public void print(RVMClass class_) { 124 // getDescriptor() does no allocation. 125 Atom descriptor = class_.getDescriptor(); 126 printClassName(descriptor); 127 } 128 129 // A kludgy alternative: 130 // public void print(RVMClass c) { 131 // Atom descriptor = c.getDescriptor(); 132 // try { 133 // print(descriptor.classNameFromDescriptor()); 134 // } catch(OutOfMemoryError e) { 135 // print(descriptor); 136 // } 137 // } 138 139 // No such method: 140 //public void print(RVMClass c) { 141 // VM.sysWrite(c); 142 // } 143 144 /* Here we need to imitate the work that would normally be done by 145 * RVMMember.toString() (which RVMMethod.toString() inherits) */ 146 147 public void print(RVMMember m) { 148 print(m.getDeclaringClass()); // RVMClass 149 print('.'); 150 print(m.getName()); 151 print(' '); 152 print(m.getDescriptor()); 153 } 154 155 public void print(Atom a) { 156 byte[] val; 157 if (a != null) { 158 val = a.toByteArray(); 159 for (byte aVal : val) { 160 print((char) aVal); 161 } 162 } else { 163 print("(null)"); 164 } 165 } 166 } 167