~ubuntu-branches/ubuntu/trusty/proguard/trusty

« back to all changes in this revision

Viewing changes to src/proguard/optimize/peephole/InstructionSequenceReplacer.java

  • Committer: Package Import Robot
  • Author(s): tony mancill
  • Date: 2013-06-06 21:43:59 UTC
  • mfrom: (7.1.1 quantal)
  • Revision ID: package-import@ubuntu.com-20130606214359-anr49am8ewoj0taa
Tags: 4.8-0.1
* Non-maintainer upload.
* New upstream release. (Closes: #678049, #643255)
* Sync changes from Ubuntu packaging.
  - Thank you to Sebastian Carneiro.
* Bump Standards-Version to 3.9.4.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3
3
 *             of Java bytecode.
4
4
 *
5
 
 * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
 
5
 * Copyright (c) 2002-2012 Eric Lafortune (eric@graphics.cornell.edu)
6
6
 *
7
7
 * This program is free software; you can redistribute it and/or modify it
8
8
 * under the terms of the GNU General Public License as published by the Free
22
22
 
23
23
import proguard.classfile.*;
24
24
import proguard.classfile.attribute.CodeAttribute;
25
 
import proguard.classfile.constant.Constant;
 
25
import proguard.classfile.constant.*;
26
26
import proguard.classfile.constant.visitor.ConstantVisitor;
27
 
import proguard.classfile.editor.CodeAttributeEditor;
 
27
import proguard.classfile.editor.*;
28
28
import proguard.classfile.instruction.*;
29
29
import proguard.classfile.instruction.visitor.InstructionVisitor;
30
30
import proguard.classfile.util.*;
42
42
implements   InstructionVisitor,
43
43
             ConstantVisitor
44
44
{
 
45
    /*
 
46
    public  static       boolean DEBUG = true;
 
47
    /*/
45
48
    private static final boolean DEBUG = false;
 
49
    //*/
 
50
 
 
51
    public static final int X = InstructionSequenceMatcher.X;
 
52
    public static final int Y = InstructionSequenceMatcher.Y;
 
53
    public static final int Z = InstructionSequenceMatcher.Z;
 
54
 
 
55
    public static final int A = InstructionSequenceMatcher.A;
 
56
    public static final int B = InstructionSequenceMatcher.B;
 
57
    public static final int C = InstructionSequenceMatcher.C;
 
58
    public static final int D = InstructionSequenceMatcher.D;
 
59
 
 
60
    private static final int BOOLEAN_STRING = 0x1;
 
61
    private static final int CHAR_STRING    = 0x2;
 
62
    private static final int INT_STRING     = 0x3;
 
63
    private static final int LONG_STRING    = 0x4;
 
64
    private static final int FLOAT_STRING   = 0x5;
 
65
    private static final int DOUBLE_STRING  = 0x6;
 
66
    private static final int STRING_STRING  = 0x7;
 
67
 
 
68
    public static final int STRING_A_LENGTH  = 0x20000000;
 
69
    public static final int BOOLEAN_A_STRING = 0x20000001;
 
70
    public static final int CHAR_A_STRING    = 0x20000002;
 
71
    public static final int INT_A_STRING     = 0x20000003;
 
72
    public static final int LONG_A_STRING    = 0x20000004;
 
73
    public static final int FLOAT_A_STRING   = 0x20000005;
 
74
    public static final int DOUBLE_A_STRING  = 0x20000006;
 
75
    public static final int STRING_A_STRING  = 0x20000007;
 
76
    public static final int BOOLEAN_B_STRING = 0x20000010;
 
77
    public static final int CHAR_B_STRING    = 0x20000020;
 
78
    public static final int INT_B_STRING     = 0x20000030;
 
79
    public static final int LONG_B_STRING    = 0x20000040;
 
80
    public static final int FLOAT_B_STRING   = 0x20000050;
 
81
    public static final int DOUBLE_B_STRING  = 0x20000060;
 
82
    public static final int STRING_B_STRING  = 0x20000070;
46
83
 
47
84
 
48
85
    private final InstructionSequenceMatcher instructionSequenceMatcher;
 
86
    private final Constant[]                 patternConstants;
49
87
    private final Instruction[]              replacementInstructions;
50
88
    private final BranchTargetFinder         branchTargetFinder;
51
89
    private final CodeAttributeEditor        codeAttributeEditor;
101
139
                                       InstructionVisitor  extraInstructionVisitor)
102
140
    {
103
141
        this.instructionSequenceMatcher = new InstructionSequenceMatcher(patternConstants, patternInstructions);
 
142
        this.patternConstants           = patternConstants;
104
143
        this.replacementInstructions    = replacementInstructions;
105
144
        this.branchTargetFinder         = branchTargetFinder;
106
145
        this.codeAttributeEditor        = codeAttributeEditor;
140
179
                for (int index = 0; index < replacementInstructions.length; index++)
141
180
                {
142
181
                    int matchedOffset = instructionSequenceMatcher.matchedInstructionOffset(index);
143
 
                    System.out.println("    "+replacementInstructionFactory.create(index).shrink().toString(matchedOffset));
 
182
                    System.out.println("    "+replacementInstructionFactory.create(clazz, index).shrink().toString(matchedOffset));
144
183
                }
145
184
            }
146
185
 
148
187
            for (int index = 0; index < replacementInstructions.length; index++)
149
188
            {
150
189
                codeAttributeEditor.replaceInstruction(instructionSequenceMatcher.matchedInstructionOffset(index),
151
 
                                                       replacementInstructionFactory.create(index).shrink());
 
190
                                                       replacementInstructionFactory.create(clazz, index).shrink());
152
191
            }
153
192
 
154
193
            // Delete any remaining instructions in the from sequence.
204
243
         * Creates the replacement instruction for the given index in the
205
244
         * instruction sequence.
206
245
         */
207
 
        public Instruction create(int index)
 
246
        public Instruction create(Clazz clazz, int index)
208
247
        {
209
248
            // Create the instruction.
210
 
            replacementInstructions[index].accept(null,
 
249
            replacementInstructions[index].accept(clazz,
211
250
                                                  null,
212
251
                                                  null,
213
252
                                                  instructionSequenceMatcher.matchedInstructionOffset(index),
224
263
        {
225
264
            replacementInstruction =
226
265
                new SimpleInstruction(simpleInstruction.opcode,
227
 
                                      instructionSequenceMatcher.matchedArgument(simpleInstruction.constant));
 
266
                                      matchedArgument(clazz, simpleInstruction.constant));
228
267
        }
229
268
 
230
269
 
241
280
        {
242
281
            replacementInstruction =
243
282
                new ConstantInstruction(constantInstruction.opcode,
244
 
                                        instructionSequenceMatcher.matchedConstantIndex(constantInstruction.constantIndex),
 
283
                                        matchedConstantIndex((ProgramClass)clazz,
 
284
                                                             constantInstruction.constantIndex),
245
285
                                        instructionSequenceMatcher.matchedArgument(constantInstruction.constant));
246
286
        }
247
287
 
250
290
        {
251
291
            replacementInstruction =
252
292
                new BranchInstruction(branchInstruction.opcode,
253
 
                                      instructionSequenceMatcher.matchedBranchOffset(offset, branchInstruction.branchOffset));
 
293
                                      instructionSequenceMatcher.matchedBranchOffset(offset,
 
294
                                                                                     branchInstruction.branchOffset));
254
295
        }
255
296
 
256
297
 
261
302
                                           instructionSequenceMatcher.matchedBranchOffset(offset, tableSwitchInstruction.defaultOffset),
262
303
                                           instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.lowCase),
263
304
                                           instructionSequenceMatcher.matchedArgument(tableSwitchInstruction.highCase),
264
 
                                           instructionSequenceMatcher.matchedJumpOffsets(offset, tableSwitchInstruction.jumpOffsets));
 
305
                                           instructionSequenceMatcher.matchedJumpOffsets(offset,
 
306
                                                                                         tableSwitchInstruction.jumpOffsets));
265
307
 
266
308
        }
267
309
 
274
316
                                            instructionSequenceMatcher.matchedArguments(lookUpSwitchInstruction.cases),
275
317
                                            instructionSequenceMatcher.matchedJumpOffsets(offset, lookUpSwitchInstruction.jumpOffsets));
276
318
        }
 
319
 
 
320
 
 
321
        /**
 
322
         * Returns the matched argument for the given pattern argument.
 
323
         */
 
324
        private int matchedArgument(Clazz clazz, int argument)
 
325
        {
 
326
            // Special case: do we have to compute the string length?
 
327
            if (argument == STRING_A_LENGTH)
 
328
            {
 
329
                // Return the string length.
 
330
                return clazz.getStringString(instructionSequenceMatcher.matchedArgument(A)).length();
 
331
            }
 
332
 
 
333
            // Otherwise, just return the matched argument.
 
334
            return instructionSequenceMatcher.matchedArgument(argument);
 
335
        }
 
336
 
 
337
 
 
338
        /**
 
339
         * Returns the matched or newly created constant index for the given
 
340
         * pattern constant index.
 
341
         */
 
342
        private int matchedConstantIndex(ProgramClass programClass, int constantIndex)
 
343
        {
 
344
            // Special case: do we have to create a concatenated string?
 
345
            if (constantIndex >= BOOLEAN_A_STRING &&
 
346
                constantIndex <= (STRING_A_STRING  | STRING_B_STRING))
 
347
            {
 
348
                // Create a new string constant and return its index.
 
349
                return new ConstantPoolEditor(programClass).addStringConstant(
 
350
                    argumentAsString(programClass,  constantIndex        & 0xf, A) +
 
351
                    argumentAsString(programClass, (constantIndex >>> 4) & 0xf, B),
 
352
                    null,
 
353
                    null);
 
354
            }
 
355
 
 
356
            int matchedConstantIndex =
 
357
                instructionSequenceMatcher.matchedConstantIndex(constantIndex);
 
358
 
 
359
            // Do we have a matched constant index?
 
360
            if (matchedConstantIndex > 0)
 
361
            {
 
362
                // Return its index.
 
363
                return matchedConstantIndex;
 
364
            }
 
365
 
 
366
            // Otherwise, we still have to create a new constant.
 
367
            // This currently only works for constants without any wildcards.
 
368
            ProgramClass dummyClass = new ProgramClass();
 
369
            dummyClass.constantPool = patternConstants;
 
370
 
 
371
            return new ConstantAdder(programClass).addConstant(dummyClass, constantIndex);
 
372
        }
 
373
 
 
374
 
 
375
        private String argumentAsString(ProgramClass programClass,
 
376
                                        int          valueType,
 
377
                                        int          argument)
 
378
        {
 
379
            switch (valueType)
 
380
            {
 
381
                case BOOLEAN_STRING:
 
382
                    return Boolean.toString((instructionSequenceMatcher.wasConstant(argument) ?
 
383
                        ((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
 
384
                        instructionSequenceMatcher.matchedArgument(argument)) != 0);
 
385
 
 
386
                case CHAR_STRING:
 
387
                    return Character.toString((char)(instructionSequenceMatcher.wasConstant(argument) ?
 
388
                        ((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
 
389
                        instructionSequenceMatcher.matchedArgument(argument)));
 
390
 
 
391
                case INT_STRING:
 
392
                    return Integer.toString(instructionSequenceMatcher.wasConstant(argument) ?
 
393
                        ((IntegerConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
 
394
                        instructionSequenceMatcher.matchedArgument(argument));
 
395
 
 
396
                case LONG_STRING:
 
397
                    return Long.toString(instructionSequenceMatcher.wasConstant(argument) ?
 
398
                        ((LongConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
 
399
                        instructionSequenceMatcher.matchedArgument(argument));
 
400
 
 
401
                case FLOAT_STRING:
 
402
                    return Float.toString(instructionSequenceMatcher.wasConstant(argument) ?
 
403
                        ((FloatConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
 
404
                        instructionSequenceMatcher.matchedArgument(argument));
 
405
 
 
406
                case DOUBLE_STRING:
 
407
                    return Double.toString(instructionSequenceMatcher.wasConstant(argument) ?
 
408
                        ((DoubleConstant)(programClass.getConstant(instructionSequenceMatcher.matchedConstantIndex(argument)))).getValue() :
 
409
                        instructionSequenceMatcher.matchedArgument(argument));
 
410
 
 
411
                case STRING_STRING:
 
412
                    return
 
413
                        programClass.getStringString(instructionSequenceMatcher.matchedConstantIndex(argument));
 
414
 
 
415
                default:
 
416
                    return "";
 
417
            }
 
418
        }
277
419
    }
278
420
}