ParallelSorterEmitter.java revision 674060f01e9090cd21b3c5656cc3204912ad17a6
1/*
2 * Copyright 2003 The Apache Software Foundation
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.mockito.cglib.util;
17
18import java.lang.reflect.Method;
19import java.lang.reflect.Modifier;
20
21import org.mockito.asm.ClassVisitor;
22import org.mockito.asm.Type;
23import org.mockito.cglib.core.*;
24
25class ParallelSorterEmitter extends ClassEmitter {
26    private static final Type PARALLEL_SORTER =
27      TypeUtils.parseType("org.mockito.cglib.util.ParallelSorter");
28    private static final Signature CSTRUCT_OBJECT_ARRAY =
29      TypeUtils.parseConstructor("Object[]");
30    private static final Signature NEW_INSTANCE =
31      new Signature("newInstance", PARALLEL_SORTER, new Type[]{ Constants.TYPE_OBJECT_ARRAY });
32    private static final Signature SWAP =
33      TypeUtils.parseSignature("void swap(int, int)");
34
35    public ParallelSorterEmitter(ClassVisitor v, String className, Object[] arrays) {
36        super(v);
37        begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, PARALLEL_SORTER, null, Constants.SOURCE_FILE);
38        EmitUtils.null_constructor(this);
39        EmitUtils.factory_method(this, NEW_INSTANCE);
40        generateConstructor(arrays);
41        generateSwap(arrays);
42        end_class();
43    }
44
45    private String getFieldName(int index) {
46        return "FIELD_" + index;
47    }
48
49    private void generateConstructor(Object[] arrays) {
50        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT_ARRAY, null);
51        e.load_this();
52        e.super_invoke_constructor();
53        e.load_this();
54        e.load_arg(0);
55        e.super_putfield("a", Constants.TYPE_OBJECT_ARRAY);
56        for (int i = 0; i < arrays.length; i++) {
57            Type type = Type.getType(arrays[i].getClass());
58            declare_field(Constants.ACC_PRIVATE, getFieldName(i), type, null);
59            e.load_this();
60            e.load_arg(0);
61            e.push(i);
62            e.aaload();
63            e.checkcast(type);
64            e.putfield(getFieldName(i));
65        }
66        e.return_value();
67        e.end_method();
68    }
69
70    private void generateSwap(final Object[] arrays) {
71        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SWAP, null);
72        for (int i = 0; i < arrays.length; i++) {
73            Type type = Type.getType(arrays[i].getClass());
74            Type component = TypeUtils.getComponentType(type);
75            Local T = e.make_local(type);
76
77            e.load_this();
78            e.getfield(getFieldName(i));
79            e.store_local(T);
80
81            e.load_local(T);
82            e.load_arg(0);
83
84            e.load_local(T);
85            e.load_arg(1);
86            e.array_load(component);
87
88            e.load_local(T);
89            e.load_arg(1);
90
91            e.load_local(T);
92            e.load_arg(0);
93            e.array_load(component);
94
95            e.array_store(component);
96            e.array_store(component);
97        }
98        e.return_value();
99        e.end_method();
100    }
101}
102