Source Code Cross Referenced for CompactArrayInitializer.java in  » Database-DBMS » db4o-6.4 » EDU » purdue » cs » bloat » trans » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » db4o 6.4 » EDU.purdue.cs.bloat.trans 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* Copyright (C) 2004 - 2007  db4objects Inc.  http://www.db4o.com
002:
003:        This file is part of the db4o open source object database.
004:
005:        db4o is free software; you can redistribute it and/or modify it under
006:        the terms of version 2 of the GNU General Public License as published
007:        by the Free Software Foundation and as clarified by db4objects' GPL 
008:        interpretation policy, available at
009:        http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010:        Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011:        Suite 350, San Mateo, CA 94403, USA.
012:
013:        db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014:        WARRANTY; without even the implied warranty of MERCHANTABILITY or
015:        FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
016:        for more details.
017:
018:        You should have received a copy of the GNU General Public License along
019:        with this program; if not, write to the Free Software Foundation, Inc.,
020:        59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */
021:        package EDU.purdue.cs.bloat.trans;
022:
023:        import java.util.*;
024:
025:        import EDU.purdue.cs.bloat.editor.*;
026:
027:        /**
028:         * <tt>CompactArrayInitializer</tt> optimizes the initialization of arrays by
029:         * transforming the initialization code into a loop that loads the array
030:         * elements from a string in the class's constant pool.
031:         */
032:        public class CompactArrayInitializer implements  Opcode {
033:            public static boolean DEBUG = false;
034:
035:            private static final MemberRef GET_CHARS;
036:
037:            // Various states that the analyzer can be in. The state indicates
038:            // what kind of instruction the analyzer expects to see next.
039:            private static final int EXPECT_SIZE = 0;
040:
041:            private static final int EXPECT_NEW = 1;
042:
043:            private static final int EXPECT_DUP = 2;
044:
045:            private static final int EXPECT_INDEX_OR_SIZE = 3;
046:
047:            private static final int EXPECT_VALUE_OR_SIZE_OR_NEW = 4;
048:
049:            private static final int EXPECT_STORE_OR_NEW = 5;
050:
051:            private static final int EXPECT_PUT_OR_DUP = 6;
052:
053:            private static final int THRESHOLD = 16;
054:
055:            private static final String[] STATES = { "EXPECT_SIZE",
056:                    "EXPECT_NEW", "EXPECT_DUP", "EXPECT_INDEX_OR_SIZE",
057:                    "EXPECT_VALUE_OR_SIZE_OR_NEW", "EXPECT_STORE_OR_NEW",
058:                    "EXPECT_PUT_OR_DUP" };
059:
060:            static {
061:
062:                // void String.getChars(int srcBegin, int scrEnd, char dst[],
063:                // int dstBegin);
064:                // Copies characters from a String object into a char array.
065:
066:                GET_CHARS = new MemberRef(Type.STRING, new NameAndType(
067:                        "getChars", Type.getType("(II[CI)V")));
068:            }
069:
070:            /**
071:             * Some Java compilers initialize arrays using straight-line code. For
072:             * classes that have large, initialized arrays this results in unnecessarily
073:             * large classfiles. <tt>CompactArrayInitializer</tt> examines a method
074:             * (via its <tt>MethodEditor</tt>) creates a string in the method's
075:             * class's constant pool that contains all of the elements of the
076:             * initialized array. After the old initialization code is removed from the
077:             * method, new code is inserted that essentially is a loop that loads each
078:             * element from the string into the array. Note that only arrays of
079:             * <tt>int</tt>, <tt>short</tt>, <tt>char</tt>, <tt>byte</tt>,
080:             * and <tt>boolean</tt> are compacted.
081:             * 
082:             * @param method
083:             *            The method whose array initializations are to be compacted.
084:             */
085:
086:            public static boolean transform(final MethodEditor method) {
087:                if (CompactArrayInitializer.DEBUG) {
088:                    System.out.println("Compacting array initializer in "
089:                            + method);
090:                }
091:
092:                boolean filled = false; // Was the constant string generated and
093:                // entered?
094:
095:                int state = CompactArrayInitializer.EXPECT_SIZE; // The state that we
096:                // are currently in
097:
098:                int size = 0; // Size of the array
099:                int value = 0; // A value in the array
100:                int index = 0; // Current index into the array
101:                int[] data = null; // Contents of the array whose initialization is
102:                // being optimized.
103:                Type elementType = null; // Of what Type is the array?
104:
105:                // Keep track of all the Instructions and Labels that deal with array
106:                // initialization.
107:                final ArrayList2 buf = new ArrayList2(method.code().size());
108:
109:                // Get the code (Labels and Instructions) for the method we're editing
110:                final Iterator iter = method.code().iterator();
111:
112:                while (iter.hasNext()) {
113:                    final Object ce = iter.next();
114:
115:                    if (CompactArrayInitializer.DEBUG) {
116:                        System.out.println("Examining " + ce);
117:                        // if (false) {
118:                        System.out.println("state = "
119:                                + CompactArrayInitializer.STATES[state]);
120:                        // }
121:                    }
122:
123:                    if (ce instanceof  Instruction) {
124:                        final Instruction inst = (Instruction) ce;
125:
126:                        switch (state) {
127:                        case EXPECT_SIZE:
128:                            switch (inst.opcodeClass()) {
129:                            case opcx_ldc:
130:                                if ((inst.operand() instanceof  Byte)
131:                                        || (inst.operand() instanceof  Short)
132:                                        || (inst.operand() instanceof  Integer)) {
133:                                    size = ((Number) inst.operand()).intValue();
134:                                    state = CompactArrayInitializer.EXPECT_NEW;
135:                                }
136:                                break;
137:                            default:
138:                                state = CompactArrayInitializer.EXPECT_SIZE;
139:                                break;
140:                            }
141:                            break;
142:                        case EXPECT_NEW:
143:                            switch (inst.opcodeClass()) {
144:                            case opcx_newarray:
145:                                elementType = (Type) inst.operand();
146:
147:                                if (elementType.isIntegral()) {
148:                                    data = new int[size];
149:                                    state = CompactArrayInitializer.EXPECT_DUP;
150:                                } else {
151:                                    state = CompactArrayInitializer.EXPECT_SIZE;
152:                                }
153:                                break;
154:                            case opcx_ldc:
155:                                if ((inst.operand() instanceof  Byte)
156:                                        || (inst.operand() instanceof  Short)
157:                                        || (inst.operand() instanceof  Integer)) {
158:                                    size = ((Number) inst.operand()).intValue();
159:                                    state = CompactArrayInitializer.EXPECT_NEW;
160:                                } else {
161:                                    state = CompactArrayInitializer.EXPECT_SIZE;
162:                                }
163:                                break;
164:                            default:
165:                                state = CompactArrayInitializer.EXPECT_SIZE;
166:                                break;
167:                            }
168:                            break;
169:                        case EXPECT_DUP:
170:                            switch (inst.opcodeClass()) {
171:                            case opcx_dup:
172:                                state = CompactArrayInitializer.EXPECT_INDEX_OR_SIZE;
173:                                break;
174:                            case opcx_ldc:
175:                                if ((inst.operand() instanceof  Byte)
176:                                        || (inst.operand() instanceof  Short)
177:                                        || (inst.operand() instanceof  Integer)) {
178:                                    size = ((Number) inst.operand()).intValue();
179:                                    state = CompactArrayInitializer.EXPECT_NEW;
180:                                } else {
181:                                    state = CompactArrayInitializer.EXPECT_SIZE;
182:                                }
183:                                break;
184:                            default:
185:                                state = CompactArrayInitializer.EXPECT_SIZE;
186:                                break;
187:                            }
188:                            break;
189:                        case EXPECT_INDEX_OR_SIZE:
190:                            switch (inst.opcodeClass()) {
191:                            case opcx_ldc:
192:                                if ((inst.operand() instanceof  Byte)
193:                                        || (inst.operand() instanceof  Short)
194:                                        || (inst.operand() instanceof  Integer)) {
195:
196:                                    index = ((Number) inst.operand())
197:                                            .intValue();
198:
199:                                    if (index < data.length) {
200:                                        state = CompactArrayInitializer.EXPECT_VALUE_OR_SIZE_OR_NEW;
201:                                    } else {
202:                                        // Out of range. Can't be an index,
203:                                        // so assume it's a size.
204:                                        size = index;
205:                                        state = CompactArrayInitializer.EXPECT_NEW;
206:                                    }
207:                                } else {
208:                                    state = CompactArrayInitializer.EXPECT_SIZE;
209:                                }
210:                                break;
211:                            default:
212:                                state = CompactArrayInitializer.EXPECT_SIZE;
213:                                break;
214:                            }
215:                            break;
216:                        case EXPECT_VALUE_OR_SIZE_OR_NEW:
217:                            switch (inst.opcodeClass()) {
218:                            case opcx_ldc:
219:                                if ((inst.operand() instanceof  Byte)
220:                                        || (inst.operand() instanceof  Short)
221:                                        || (inst.operand() instanceof  Integer)) {
222:
223:                                    value = ((Number) inst.operand())
224:                                            .intValue();
225:                                    state = CompactArrayInitializer.EXPECT_STORE_OR_NEW;
226:                                } else if (inst.operand() instanceof  Character) {
227:                                    final Character ch = (Character) inst
228:                                            .operand();
229:                                    value = ch.charValue();
230:                                    state = CompactArrayInitializer.EXPECT_STORE_OR_NEW;
231:                                } else {
232:                                    state = CompactArrayInitializer.EXPECT_SIZE;
233:                                }
234:                                break;
235:                            case opcx_newarray:
236:                                size = index;
237:                                elementType = (Type) inst.operand();
238:
239:                                if (elementType.isIntegral()) {
240:                                    data = new int[size];
241:                                    state = CompactArrayInitializer.EXPECT_DUP;
242:                                } else {
243:                                    state = CompactArrayInitializer.EXPECT_SIZE;
244:                                }
245:                                break;
246:                            default:
247:                                state = CompactArrayInitializer.EXPECT_SIZE;
248:                                break;
249:                            }
250:                            break;
251:                        case EXPECT_STORE_OR_NEW:
252:                            switch (inst.opcodeClass()) {
253:                            case opcx_bastore:
254:                                if (elementType.equals(Type.BYTE)
255:                                        || elementType.equals(Type.BOOLEAN)) {
256:                                    data[index] = value;
257:                                    state = CompactArrayInitializer.EXPECT_PUT_OR_DUP;
258:                                }
259:                                break;
260:                            case opcx_castore:
261:                                if (elementType.equals(Type.CHARACTER)) {
262:                                    data[index] = value;
263:                                    state = CompactArrayInitializer.EXPECT_PUT_OR_DUP;
264:                                }
265:                                break;
266:                            case opcx_sastore:
267:                                if (elementType.equals(Type.SHORT)) {
268:                                    data[index] = value;
269:                                    state = CompactArrayInitializer.EXPECT_PUT_OR_DUP;
270:                                }
271:                                break;
272:                            case opcx_iastore:
273:                                if (elementType.equals(Type.INTEGER)) {
274:                                    data[index] = value;
275:                                    state = CompactArrayInitializer.EXPECT_PUT_OR_DUP;
276:                                }
277:                                break;
278:                            case opcx_ldc:
279:                                if ((inst.operand() instanceof  Byte)
280:                                        || (inst.operand() instanceof  Short)
281:                                        || (inst.operand() instanceof  Integer)) {
282:
283:                                    size = ((Number) inst.operand()).intValue();
284:                                    state = CompactArrayInitializer.EXPECT_NEW;
285:                                } else {
286:                                    state = CompactArrayInitializer.EXPECT_SIZE;
287:                                }
288:                                break;
289:                            case opcx_newarray:
290:                                size = value;
291:                                elementType = (Type) inst.operand();
292:
293:                                if (elementType.isIntegral()) {
294:                                    data = new int[size];
295:                                    state = CompactArrayInitializer.EXPECT_DUP;
296:                                } else {
297:                                    state = CompactArrayInitializer.EXPECT_SIZE;
298:                                }
299:                                break;
300:                            default:
301:                                state = CompactArrayInitializer.EXPECT_SIZE;
302:                                break;
303:                            }
304:                            break;
305:                        case EXPECT_PUT_OR_DUP:
306:                            switch (inst.opcodeClass()) {
307:                            case opcx_dup:
308:                                state = CompactArrayInitializer.EXPECT_INDEX_OR_SIZE;
309:                                break;
310:                            case opcx_ldc:
311:                                if ((inst.operand() instanceof  Byte)
312:                                        || (inst.operand() instanceof  Short)
313:                                        || (inst.operand() instanceof  Integer)) {
314:                                    size = ((Number) inst.operand()).intValue();
315:                                    state = CompactArrayInitializer.EXPECT_NEW;
316:                                } else {
317:                                    state = CompactArrayInitializer.EXPECT_SIZE;
318:                                }
319:                                break;
320:                            case opcx_astore:
321:                            case opcx_aastore:
322:                            case opcx_putstatic:
323:                            case opcx_putstatic_nowb:
324:                            case opcx_putfield:
325:                            case opcx_putfield_nowb:
326:                                if (data.length >= CompactArrayInitializer.THRESHOLD) {
327:                                    CompactArrayInitializer.fillArray(method,
328:                                            buf, elementType, data);
329:                                    filled = true;
330:                                }
331:                                state = CompactArrayInitializer.EXPECT_SIZE;
332:                                break;
333:                            default:
334:                                state = CompactArrayInitializer.EXPECT_SIZE;
335:                                break;
336:                            }
337:                            break;
338:                        }
339:                    } else {
340:                        final Label label = (Label) ce;
341:
342:                        if (label.startsBlock()) {
343:                            state = CompactArrayInitializer.EXPECT_SIZE;
344:                        }
345:                    }
346:
347:                    if (CompactArrayInitializer.DEBUG /* && false */) {
348:                        System.out.println("     -> "
349:                                + CompactArrayInitializer.STATES[state]);
350:                    }
351:
352:                    buf.add(ce);
353:                }
354:
355:                if (filled) {
356:                    method.code().clear();
357:                    method.code().addAll(buf);
358:
359:                    if (CompactArrayInitializer.DEBUG) {
360:                        for (int i = 0; i < method.code().size(); i++) {
361:                            System.out.println("code[" + i + "] "
362:                                    + method.code().get(i));
363:                        }
364:                    }
365:                }
366:
367:                return filled;
368:            }
369:
370:            /**
371:             * Construct a UTF8 string that stores the contents of an integral (int,
372:             * char, or byte/boolean) array. Each element of the UTF8 string is 16 bits
373:             * wide meaning that an int is stored into two elements, a char is store in
374:             * one element, and two bytes/booleans are stored in one element.
375:             * Essentially each integer in the <tt>data</tt> parmeter is converted
376:             * into a character and placed in an array.
377:             * <p>
378:             * A UTF8 string cannot be larger than 64K. To be on the safe side, we do
379:             * not generate UTF8 strings that are larger than 32K.
380:             * <p>
381:             * We then remove all of the old initialization code, so that the previous
382:             * instruction is a <tt>newarray</tt> opcode (meaning that the array
383:             * object will be on top of the stack).
384:             * <p>
385:             * Then new code is generated for loading data from the UTF8 string. Loading
386:             * character data is relatively straightforward. The <tt>getChars</tt>
387:             * method is invoked on the UTF8 string (an instance of <tt>String</tt>)
388:             * to copy characters from the string into a character array.
389:             * <p>
390:             * A little more work has to be done for non-character data types. First,
391:             * the UTF8 string is read into a (local) character array. Then, the data is
392:             * extracted from the character array and placed in the new array. For some
393:             * data types, labels are added to the program.
394:             * 
395:             * @param m
396:             *            The method that contains the array
397:             * @param buf
398:             *            Instructions from the method that are used in array
399:             *            initialization
400:             * @param elementType
401:             *            The Type of the array
402:             * @param data
403:             *            The contents of the array
404:             * 
405:             */
406:            private static void fillArray(final MethodEditor m,
407:                    final ArrayList2 buf, final Type elementType,
408:                    final int[] data) {
409:                // Max UTF8 constant size is 65535 bytes. We divide this in 2 to
410:                // prevent DataOutputStream from crashing. Since our arrays can be
411:                // longer than 32767, we break the image into segments.
412:
413:                char[] c; // string that will be entered into the constant pool
414:
415:                if (elementType.equals(Type.CHARACTER)) {
416:                    // Fill the string with char data (16-bits). Each char in string
417:                    // holds a single char.
418:                    c = new char[data.length];
419:
420:                    for (int i = 0; i < data.length; i++) {
421:                        c[i] = (char) data[i];
422:                    }
423:                } else if (elementType.equals(Type.BYTE)
424:                        || elementType.equals(Type.BOOLEAN)) {
425:                    // Fill the string with 8-bit data. Each char in string holds
426:                    // two 8-bit data.
427:                    c = new char[(data.length + 1) / 2];
428:
429:                    int j = 0;
430:
431:                    for (int i = 0; i + 1 < data.length; i += 2) {
432:                        c[j++] = (char) ((data[i] << 8) | (data[i + 1] & 0xff));
433:                    }
434:
435:                    if (j != c.length) {
436:                        c[j++] = (char) (data[data.length - 1] << 8);
437:                    }
438:                } else if (elementType.equals(Type.SHORT)) {
439:                    // Fill the string with short (16-bit) data. I don't know why we
440:                    // add 0x8000 to it, but we subtract 32768 (0x8000) in the
441:                    // generated byetcode. Mysteries of BLOAT...
442:
443:                    c = new char[data.length];
444:
445:                    for (int i = 0; i < data.length; i++) {
446:                        c[i] = (char) (data[i] + 0x8000);
447:                    }
448:                } else if (elementType.equals(Type.INTEGER)) {
449:                    // Fill the string with int (32-bit) data. ints are stored as
450:                    // chars in big-endian format
451:                    c = new char[data.length * 2];
452:
453:                    int j = 0;
454:
455:                    for (int i = 0; i < data.length; i++) {
456:                        final int n = data[i];
457:                        c[j++] = (char) ((n >>> 16) & 0xffff);
458:                        c[j++] = (char) ((n >>> 0) & 0xffff);
459:                    }
460:                } else {
461:                    return;
462:                }
463:
464:                // The Strings of data divided into 32K chunks. Each chunk is an
465:                // element in the ArrayList
466:                final ArrayList image = new ArrayList();
467:
468:                // The start index in the array for each segment of the image.
469:                final ArrayList startIndex = new ArrayList();
470:
471:                // The end index+1 in the array for each segment of the image.
472:                final ArrayList endIndex = new ArrayList();
473:
474:                StringBuffer sb = new StringBuffer();
475:                int utfLength = 0;
476:                startIndex.add(new Integer(0));
477:
478:                // Iterate over every character in the array buffer. Use a
479:                // StringBuffer to create String of length less than 32K.
480:                for (int i = 0; i < c.length; i++) {
481:                    final char n = c[i];
482:                    int len = 0;
483:
484:                    if (n == '\u0000') {
485:                        len = 2;
486:                    } else if (n < '\u0800') {
487:                        len = 1;
488:                    } else if (n < '\u8000') {
489:                        len = 2;
490:                    } else {
491:                        len = 3;
492:                    }
493:
494:                    if (utfLength + len > 32767) {
495:                        // We've reached the limit on the size of the constant pool
496:                        // string.
497:                        // Add the current string buffer, and make a new one.
498:                        image.add(sb.toString());
499:                        endIndex.add(new Integer(i));
500:
501:                        sb = new StringBuffer();
502:                        utfLength = 0;
503:                        startIndex.add(new Integer(i));
504:                    }
505:
506:                    sb.append(n);
507:                    utfLength += len;
508:                }
509:
510:                if (sb.length() > 0) {
511:                    // If we've got leftovers, add it to the end of the current image
512:                    // entry.
513:                    image.add(sb.toString());
514:                    endIndex.add(new Integer(data.length));
515:                } else {
516:                    startIndex.remove(startIndex.size() - 1);
517:                }
518:
519:                int bufStart = -1;
520:
521:                // Remove the old code, leaving just the creation of the array!!!!!
522:
523:                for (int i = buf.size() - 1; i >= 0; i--) {
524:                    final Instruction inst = (Instruction) buf.get(i);
525:                    if (inst.opcodeClass() == Opcode.opcx_newarray) {
526:                        // ..., ldc, new, dup ldc ldc store, dup ldc ldc store, ...
527:                        buf.removeRange(i + 1, buf.size());
528:                        bufStart = i;
529:                        break;
530:                    }
531:                }
532:
533:                if (bufStart == -1) {
534:                    // There was no code to remove? Something went wrong. Run away!
535:                    return;
536:                }
537:
538:                // Insert the new:
539:                if (elementType.equals(Type.CHARACTER)) {
540:                    // We envoke the method String.getChars() to copy characters from
541:                    // a String object (the UTF8 constant in the constant pool) to
542:                    // a character array. Remember that the destination array is on
543:                    // the top of the stack.
544:
545:                    final LocalVariable array = m.newLocal(Type.OBJECT); // character
546:                    // array
547:
548:                    buf.add(new Instruction(Opcode.opcx_dup, array));
549:                    buf.add(new Instruction(Opcode.opcx_astore, array));
550:
551:                    // Call getChars() for every image
552:
553:                    for (int i = 0; i < image.size(); i++) {
554:                        final String im = (String) image.get(i);
555:                        final Integer start = (Integer) startIndex.get(i);
556:
557:                        // void getChars(int srcBegin, int srcEnd, char dst[],
558:                        // int dstBegin)
559:
560:                        buf.add(new Instruction(Opcode.opcx_ldc, im)); // String
561:                        buf
562:                                .add(new Instruction(Opcode.opcx_ldc,
563:                                        new Integer(0)));
564:                        buf.add(new Instruction(Opcode.opcx_ldc, new Integer(im
565:                                .length())));
566:                        buf.add(new Instruction(Opcode.opcx_aload, array));
567:                        buf.add(new Instruction(Opcode.opcx_ldc, start)); // dstBegin
568:                        buf.add(new Instruction(Opcode.opcx_invokevirtual,
569:                                CompactArrayInitializer.GET_CHARS));
570:                    }
571:
572:                } else {
573:
574:                    // Loading and storing non-character data is a little more
575:                    // tricky. First we must read the UTF8 string into a character
576:                    // array. The we must go through the array and pick out the
577:                    // elements of the int, short, byte/boolean array.
578:
579:                    // array is a character array used to hold the UTF8 string
580:                    // index1 is an index into the destination (int, boolean, etc.)
581:                    // array and index2 is an index into the char array from the
582:                    // constant pool. tmp is a temporary char local variable that
583:                    // is used because booleans and bytes need to be left shifted.
584:
585:                    final LocalVariable array = m.newLocal(Type.OBJECT); // char
586:                    // array
587:                    final LocalVariable index1 = m.newLocal(Type.INTEGER);
588:                    final LocalVariable index2 = m.newLocal(Type.INTEGER);
589:                    LocalVariable tmp = null;
590:
591:                    if (elementType.equals(Type.BYTE)
592:                            || elementType.equals(Type.BOOLEAN)) {
593:                        tmp = m.newLocal(Type.CHARACTER);
594:                    }
595:
596:                    // Call getChars() to read the UTF8 string from the constant
597:                    // pool into an array of characters, array.
598:
599:                    for (int i = 0; i < image.size(); i++) {
600:                        final Label top = m.newLabel();
601:                        top.setStartsBlock(true);
602:
603:                        final Label bottom = m.newLabel();
604:                        bottom.setStartsBlock(true);
605:
606:                        final String im = (String) image.get(i);
607:                        final Integer start = (Integer) startIndex.get(i);
608:                        final Integer end = (Integer) endIndex.get(i);
609:
610:                        if (CompactArrayInitializer.DEBUG) {
611:                            System.out.println("image " + im);
612:                            System.out.println("start " + start);
613:                            System.out.println("end   " + end);
614:                        }
615:
616:                        buf.add(new Instruction(Opcode.opcx_ldc, start));
617:                        buf.add(new Instruction(Opcode.opcx_istore, index1));
618:
619:                        buf
620:                                .add(new Instruction(Opcode.opcx_ldc,
621:                                        new Integer(0)));
622:                        buf.add(new Instruction(Opcode.opcx_istore, index2));
623:
624:                        // Create a new array of characters and copy the UTF8 string
625:                        // into it.
626:                        buf.add(new Instruction(Opcode.opcx_ldc, new Integer(im
627:                                .length())));
628:                        buf.add(new Instruction(Opcode.opcx_newarray,
629:                                Type.CHARACTER));
630:                        buf.add(new Instruction(Opcode.opcx_astore, array));
631:                        buf.add(new Instruction(Opcode.opcx_ldc, im));
632:                        buf
633:                                .add(new Instruction(Opcode.opcx_ldc,
634:                                        new Integer(0)));
635:                        buf.add(new Instruction(Opcode.opcx_ldc, new Integer(im
636:                                .length())));
637:                        buf.add(new Instruction(Opcode.opcx_aload, array));
638:                        buf
639:                                .add(new Instruction(Opcode.opcx_ldc,
640:                                        new Integer(0)));
641:                        buf.add(new Instruction(Opcode.opcx_invokevirtual,
642:                                CompactArrayInitializer.GET_CHARS));
643:
644:                        // Start the fill loop for [start[i], end[i]).
645:                        buf.add(top);
646:
647:                        // Store the image data into the data array
648:                        // (at the top of the stack).
649:                        if (elementType.equals(Type.SHORT)) {
650:                            // Load an integer from the character array and then
651:                            // subtract
652:                            // 32768 (0x8000) from it. Convert the integer to a short
653:                            // and store it in the destination array (which happens to
654:                            // be
655:                            // on the top of the stack).
656:
657:                            buf.add(new Instruction(Opcode.opcx_dup));
658:                            buf.add(new Instruction(Opcode.opcx_iload, index1));
659:                            buf.add(new Instruction(Opcode.opcx_iinc,
660:                                    new IncOperand(index1, 1)));
661:                            buf.add(new Instruction(Opcode.opcx_aload, array));
662:                            buf.add(new Instruction(Opcode.opcx_iload, index2));
663:                            buf.add(new Instruction(Opcode.opcx_iinc,
664:                                    new IncOperand(index2, 1)));
665:                            buf.add(new Instruction(Opcode.opcx_caload));
666:                            buf.add(new Instruction(Opcode.opcx_ldc,
667:                                    new Integer(32768)));
668:                            buf.add(new Instruction(Opcode.opcx_isub));
669:                            buf.add(new Instruction(Opcode.opcx_i2s));
670:                            buf.add(new Instruction(Opcode.opcx_sastore));
671:
672:                        } else if (elementType.equals(Type.BYTE)
673:                                || elementType.equals(Type.BOOLEAN)) {
674:                            // For byte (and boolean) arrays we need to use a temporary
675:                            // variable to hold the character because it needs to be
676:                            // shifted. Recall that two bytes were glued together into
677:                            // one character.
678:
679:                            // Incremenet index2 and load the character from the
680:                            // character array and store it in tmp.
681:                            // t = c[j++]
682:                            buf.add(new Instruction(Opcode.opcx_aload, array));
683:                            buf.add(new Instruction(Opcode.opcx_iload, index2));
684:                            buf.add(new Instruction(Opcode.opcx_iinc,
685:                                    new IncOperand(index2, 1)));
686:                            buf.add(new Instruction(Opcode.opcx_caload));
687:                            buf.add(new Instruction(Opcode.opcx_istore, tmp));
688:
689:                            // Store the higher 8 bits of tmp into the byte array
690:                            // b[i++] = (byte) (t >>> 8)
691:                            buf.add(new Instruction(Opcode.opcx_dup));
692:                            buf.add(new Instruction(Opcode.opcx_iload, index1));
693:                            buf.add(new Instruction(Opcode.opcx_iinc,
694:                                    new IncOperand(index1, 1)));
695:                            buf.add(new Instruction(Opcode.opcx_iload, tmp));
696:                            buf.add(new Instruction(Opcode.opcx_ldc,
697:                                    new Integer(8)));
698:                            buf.add(new Instruction(Opcode.opcx_iushr));
699:                            buf.add(new Instruction(Opcode.opcx_i2b));
700:                            buf.add(new Instruction(Opcode.opcx_bastore));
701:
702:                            // If we've read the last byte, go home
703:                            // if (i >= end) break
704:                            buf.add(new Instruction(Opcode.opcx_iload, index1));
705:                            buf.add(new Instruction(Opcode.opcx_ldc, end));
706:                            buf.add(new Instruction(Opcode.opcx_if_icmpge,
707:                                    bottom));
708:
709:                            // Add a new label because we're starting a new basic
710:                            // block(?)
711:                            final Label nobreak = m.newLabel();
712:                            nobreak.setStartsBlock(true);
713:                            buf.add(nobreak);
714:
715:                            // Store the lower order 8 bits of tmp into the byte array
716:                            // b[i++] = (byte) (t & 0xff)
717:                            buf.add(new Instruction(Opcode.opcx_dup));
718:                            buf.add(new Instruction(Opcode.opcx_iload, index1));
719:                            buf.add(new Instruction(Opcode.opcx_iinc,
720:                                    new IncOperand(index1, 1)));
721:                            buf.add(new Instruction(Opcode.opcx_iload, tmp));
722:                            buf.add(new Instruction(Opcode.opcx_ldc,
723:                                    new Integer(0xff)));
724:                            buf.add(new Instruction(Opcode.opcx_iand));
725:                            buf.add(new Instruction(Opcode.opcx_i2b));
726:                            buf.add(new Instruction(Opcode.opcx_bastore));
727:
728:                        } else if (elementType.equals(Type.INTEGER)) {
729:                            // Recall that an integer is 32 bits and is therefore
730:                            // contained in two characters. So, read the first, then
731:                            // read the second.
732:
733:                            // Increment index1 and index2 and load the character from
734:                            // the character array.
735:                            buf.add(new Instruction(Opcode.opcx_dup));
736:                            buf.add(new Instruction(Opcode.opcx_iload, index1));
737:                            buf.add(new Instruction(Opcode.opcx_iinc,
738:                                    new IncOperand(index1, 1)));
739:
740:                            buf.add(new Instruction(Opcode.opcx_aload, array));
741:                            buf.add(new Instruction(Opcode.opcx_iload, index2));
742:                            buf.add(new Instruction(Opcode.opcx_iinc,
743:                                    new IncOperand(index2, 1)));
744:                            buf.add(new Instruction(Opcode.opcx_caload));
745:
746:                            // Isolate the high-order 16 bits by shifting left
747:                            buf.add(new Instruction(Opcode.opcx_ldc,
748:                                    new Integer(16)));
749:                            buf.add(new Instruction(Opcode.opcx_ishl));
750:
751:                            // Increment index2 and obtain the character containing the
752:                            // low-order 16 bits of the integer
753:                            buf.add(new Instruction(Opcode.opcx_aload, array));
754:                            buf.add(new Instruction(Opcode.opcx_iload, index2));
755:                            buf.add(new Instruction(Opcode.opcx_iinc,
756:                                    new IncOperand(index2, 1)));
757:                            buf.add(new Instruction(Opcode.opcx_caload));
758:
759:                            // Or the higher-order bits and the lower-order bits
760:                            // together
761:                            // and store the result in the integer array.
762:                            buf.add(new Instruction(Opcode.opcx_ior));
763:                            buf.add(new Instruction(Opcode.opcx_iastore));
764:                        }
765:
766:                        // Branch back if we're not out of the loop.
767:                        // while (i < end)
768:                        buf.add(new Instruction(Opcode.opcx_iload, index1));
769:                        buf.add(new Instruction(Opcode.opcx_ldc, end));
770:                        buf.add(new Instruction(Opcode.opcx_if_icmplt, top));
771:
772:                        buf.add(bottom);
773:                    }
774:                }
775:
776:                if (CompactArrayInitializer.DEBUG) {
777:                    for (int i = bufStart; i < buf.size(); i++) {
778:                        System.out.println("fill[" + i + "] " + buf.get(i));
779:                    }
780:                }
781:            }
782:        }
783:
784:        /**
785:         * Recall that Nate used beta versions of the JDK1.2 util classes to build
786:         * BLOAT. While most of the conversion to the final util API was simple, there
787:         * were a couple of changes made that force us to make some changes.
788:         * 
789:         * The final version of the API makes the ArrayList.removeRange() method
790:         * protected. So, we have to make this silly wrapper class in order to access
791:         * it. Silly.
792:         */
793:        class ArrayList2 extends ArrayList {
794:            public ArrayList2(final int initialCapacity) {
795:                super (initialCapacity);
796:            }
797:
798:            public void removeRange(final int fromIndex, final int toIndex) {
799:                super.removeRange(fromIndex, toIndex);
800:            }
801:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.