1674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/* 2674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Copyright 2003,2004 The Apache Software Foundation 3674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 4674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Licensed under the Apache License, Version 2.0 (the "License"); 5674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * you may not use this file except in compliance with the License. 6674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * You may obtain a copy of the License at 7674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 8674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * http://www.apache.org/licenses/LICENSE-2.0 9674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 10674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Unless required by applicable law or agreed to in writing, software 11674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * distributed under the License is distributed on an "AS IS" BASIS, 12674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * See the License for the specific language governing permissions and 14674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * limitations under the License. 15674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 16674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpackage org.mockito.cglib.core; 17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.math.BigDecimal; 19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.math.BigInteger; 20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.util.*; 21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Label; 23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Type; 24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpublic class EmitUtils { 26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature CSTRUCT_NULL = 27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseConstructor(""); 28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature CSTRUCT_THROWABLE = 29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseConstructor("Throwable"); 30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature GET_NAME = 32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("String getName()"); 33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature HASH_CODE = 34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("int hashCode()"); 35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature EQUALS = 36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("boolean equals(Object)"); 37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature STRING_LENGTH = 38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("int length()"); 39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature STRING_CHAR_AT = 40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("char charAt(int)"); 41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature FOR_NAME = 42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("Class forName(String)"); 43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature DOUBLE_TO_LONG_BITS = 44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("long doubleToLongBits(double)"); 45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature FLOAT_TO_INT_BITS = 46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("int floatToIntBits(float)"); 47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature TO_STRING = 48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("String toString()"); 49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature APPEND_STRING = 50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("StringBuffer append(String)"); 51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature APPEND_INT = 52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("StringBuffer append(int)"); 53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature APPEND_DOUBLE = 54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("StringBuffer append(double)"); 55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature APPEND_FLOAT = 56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("StringBuffer append(float)"); 57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature APPEND_CHAR = 58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("StringBuffer append(char)"); 59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature APPEND_LONG = 60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("StringBuffer append(long)"); 61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature APPEND_BOOLEAN = 62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("StringBuffer append(boolean)"); 63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature LENGTH = 64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("int length()"); 65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature SET_LENGTH = 66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("void setLength(int)"); 67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static final Signature GET_DECLARED_METHOD = 68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen TypeUtils.parseSignature("java.lang.reflect.Method getDeclaredMethod(String, Class[])"); 69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static final ArrayDelimiters DEFAULT_DELIMITERS = new ArrayDelimiters("{", ", ", "}"); 73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private EmitUtils() { 75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void factory_method(ClassEmitter ce, Signature sig) { 78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, sig, null); 79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.new_instance_this(); 80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_args(); 82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_constructor_this(TypeUtils.parseConstructor(sig.getArgumentTypes())); 83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void null_constructor(ClassEmitter ce) { 88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, CSTRUCT_NULL, null); 89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.super_invoke_constructor(); 91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 96674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Process an array on the stack. Assumes the top item on the stack 97674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * is an array of the specified type. For each element in the array, 98674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * puts the element on the stack and triggers the callback. 99674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param type the type of the array (type.isArray() must be true) 100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param callback the callback triggered for each element 101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void process_array(CodeEmitter e, Type type, ProcessArrayCallback callback) { 103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type componentType = TypeUtils.getComponentType(type); 104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Local array = e.make_local(); 105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Local loopvar = e.make_local(Type.INT_TYPE); 106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label loopbody = e.make_label(); 107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label checkloop = e.make_label(); 108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.store_local(array); 109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(0); 110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.store_local(loopvar); 111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(checkloop); 112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(loopbody); 114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_local(array); 115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_local(loopvar); 116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.array_load(componentType); 117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen callback.processElement(componentType); 118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.iinc(loopvar, 1); 119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(checkloop); 121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_local(loopvar); 122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_local(array); 123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.arraylength(); 124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.if_icmp(e.LT, loopbody); 125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Process two arrays on the stack in parallel. Assumes the top two items on the stack 129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * are arrays of the specified class. The arrays must be the same length. For each pair 130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * of elements in the arrays, puts the pair on the stack and triggers the callback. 131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param type the type of the arrays (type.isArray() must be true) 132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param callback the callback triggered for each pair of elements 133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void process_arrays(CodeEmitter e, Type type, ProcessArrayCallback callback) { 135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type componentType = TypeUtils.getComponentType(type); 136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Local array1 = e.make_local(); 137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Local array2 = e.make_local(); 138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Local loopvar = e.make_local(Type.INT_TYPE); 139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label loopbody = e.make_label(); 140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label checkloop = e.make_label(); 141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.store_local(array1); 142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.store_local(array2); 143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(0); 144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.store_local(loopvar); 145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(checkloop); 146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(loopbody); 148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_local(array1); 149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_local(loopvar); 150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.array_load(componentType); 151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_local(array2); 152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_local(loopvar); 153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.array_load(componentType); 154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen callback.processElement(componentType); 155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.iinc(loopvar, 1); 156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(checkloop); 158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_local(loopvar); 159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_local(array1); 160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.arraylength(); 161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.if_icmp(e.LT, loopbody); 162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void string_switch(CodeEmitter e, String[] strings, int switchStyle, ObjectSwitchCallback callback) { 165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen try { 166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen switch (switchStyle) { 167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Constants.SWITCH_STYLE_TRIE: 168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen string_switch_trie(e, strings, callback); 169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Constants.SWITCH_STYLE_HASH: 171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen string_switch_hash(e, strings, callback, false); 172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Constants.SWITCH_STYLE_HASHONLY: 174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen string_switch_hash(e, strings, callback, true); 175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen default: 177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException("unknown switch style " + switchStyle); 178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (RuntimeException ex) { 180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw ex; 181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (Error ex) { 182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw ex; 183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (Exception ex) { 184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new CodeGenerationException(ex); 185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void string_switch_trie(final CodeEmitter e, 189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen String[] strings, 190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ObjectSwitchCallback callback) throws Exception { 191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label def = e.make_label(); 192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label end = e.make_label(); 193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Map buckets = CollectionUtils.bucket(Arrays.asList(strings), new Transformer() { 194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Object transform(Object value) { 195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return new Integer(((String)value).length()); 196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING, STRING_LENGTH); 200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.process_switch(getSwitchKeys(buckets), new ProcessSwitchCallback() { 201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processCase(int key, Label ignore_end) throws Exception { 202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List bucket = (List)buckets.get(new Integer(key)); 203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stringSwitchHelper(e, bucket, callback, def, end, 0); 204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processDefault() { 206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(def); 207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 208674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 209674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(def); 210674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); 211674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen callback.processDefault(); 212674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(end); 213674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 214674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 215674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void stringSwitchHelper(final CodeEmitter e, 216674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List strings, 217674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ObjectSwitchCallback callback, 218674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label def, 219674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label end, 220674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int index) throws Exception { 221674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int len = ((String)strings.get(0)).length(); 222674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Map buckets = CollectionUtils.bucket(strings, new Transformer() { 223674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Object transform(Object value) { 224674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return new Integer(((String)value).charAt(index)); 225674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 226674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 227674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 228674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(index); 229674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING, STRING_CHAR_AT); 230674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.process_switch(getSwitchKeys(buckets), new ProcessSwitchCallback() { 231674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processCase(int key, Label ignore_end) throws Exception { 232674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List bucket = (List)buckets.get(new Integer(key)); 233674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (index + 1 == len) { 234674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); 235674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen callback.processCase(bucket.get(0), end); 236674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 237674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen stringSwitchHelper(e, bucket, callback, def, end, index + 1); 238674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 239674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 240674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processDefault() { 241674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(def); 242674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 243674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 244674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 245674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 246674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen static int[] getSwitchKeys(Map buckets) { 247674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int[] keys = new int[buckets.size()]; 248674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int index = 0; 249674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (Iterator it = buckets.keySet().iterator(); it.hasNext();) { 250674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen keys[index++] = ((Integer)it.next()).intValue(); 251674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 252674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Arrays.sort(keys); 253674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return keys; 254674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 255674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 256674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void string_switch_hash(final CodeEmitter e, 257674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final String[] strings, 258674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ObjectSwitchCallback callback, 259674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final boolean skipEquals) throws Exception { 260674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Map buckets = CollectionUtils.bucket(Arrays.asList(strings), new Transformer() { 261674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Object transform(Object value) { 262674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return new Integer(value.hashCode()); 263674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 264674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 265674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label def = e.make_label(); 266674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label end = e.make_label(); 267674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 268674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_OBJECT, HASH_CODE); 269674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.process_switch(getSwitchKeys(buckets), new ProcessSwitchCallback() { 270674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processCase(int key, Label ignore_end) throws Exception { 271674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List bucket = (List)buckets.get(new Integer(key)); 272674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label next = null; 273674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (skipEquals && bucket.size() == 1) { 274674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (skipEquals) 275674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); 276674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen callback.processCase((String)bucket.get(0), end); 277674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 278674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (Iterator it = bucket.iterator(); it.hasNext();) { 279674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen String string = (String)it.next(); 280674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (next != null) { 281674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(next); 282674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 283674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (it.hasNext()) { 284674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 285674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 286674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(string); 287674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_OBJECT, EQUALS); 288674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (it.hasNext()) { 289674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.if_jump(e.EQ, next = e.make_label()); 290674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); 291674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 292674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.if_jump(e.EQ, def); 293674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 294674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen callback.processCase(string, end); 295674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 296674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 297674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 298674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processDefault() { 299674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); 300674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 301674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 302674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(def); 303674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen callback.processDefault(); 304674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(end); 305674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 306674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 307674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void load_class_this(CodeEmitter e) { 308674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen load_class_helper(e, e.getClassEmitter().getClassType()); 309674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 310674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 311674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void load_class(CodeEmitter e, Type type) { 312674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (TypeUtils.isPrimitive(type)) { 313674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (type == Type.VOID_TYPE) { 314674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException("cannot load void type"); 315674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 316674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.getstatic(TypeUtils.getBoxedType(type), "TYPE", Constants.TYPE_CLASS); 317674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 318674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen load_class_helper(e, type); 319674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 320674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 321674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 322674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void load_class_helper(CodeEmitter e, final Type type) { 323674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (e.isStaticHook()) { 324674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // have to fall back on non-optimized load 325674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(TypeUtils.emulateClassGetName(type)); 326674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_static(Constants.TYPE_CLASS, FOR_NAME); 327674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 328674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ClassEmitter ce = e.getClassEmitter(); 329674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen String typeName = TypeUtils.emulateClassGetName(type); 330674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 331674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // TODO: can end up with duplicated field names when using chained transformers; incorporate static hook # somehow 332674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen String fieldName = "CGLIB$load_class$" + TypeUtils.escapeType(typeName); 333674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!ce.isFieldDeclared(fieldName)) { 334674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ce.declare_field(Constants.PRIVATE_FINAL_STATIC, fieldName, Constants.TYPE_CLASS, null); 335674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter hook = ce.getStaticHook(); 336674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen hook.push(typeName); 337674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen hook.invoke_static(Constants.TYPE_CLASS, FOR_NAME); 338674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen hook.putstatic(ce.getClassType(), fieldName, Constants.TYPE_CLASS); 339674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 340674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.getfield(fieldName); 341674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 342674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 343674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 344674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void push_array(CodeEmitter e, Object[] array) { 345674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(array.length); 346674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.newarray(Type.getType(remapComponentType(array.getClass().getComponentType()))); 347674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < array.length; i++) { 348674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 349674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(i); 350674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen push_object(e, array[i]); 351674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.aastore(); 352674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 353674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 354674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 355674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static Class remapComponentType(Class componentType) { 356674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (componentType.equals(Type.class)) 357674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return Class.class; 358674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return componentType; 359674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 360674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 361674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void push_object(CodeEmitter e, Object obj) { 362674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (obj == null) { 363674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.aconst_null(); 364674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 365674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Class type = obj.getClass(); 366674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (type.isArray()) { 367674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen push_array(e, (Object[])obj); 368674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (obj instanceof String) { 369674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push((String)obj); 370674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (obj instanceof Type) { 371674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen load_class(e, (Type)obj); 372674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (obj instanceof Class) { 373674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen load_class(e, Type.getType((Class)obj)); 374674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (obj instanceof BigInteger) { 375674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.new_instance(Constants.TYPE_BIG_INTEGER); 376674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 377674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(obj.toString()); 378674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_constructor(Constants.TYPE_BIG_INTEGER); 379674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (obj instanceof BigDecimal) { 380674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.new_instance(Constants.TYPE_BIG_DECIMAL); 381674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 382674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(obj.toString()); 383674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_constructor(Constants.TYPE_BIG_DECIMAL); 384674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 385674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new IllegalArgumentException("unknown type: " + obj.getClass()); 386674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 387674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 388674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 389674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 390674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void hash_code(CodeEmitter e, Type type, int multiplier, Customizer customizer) { 391674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (TypeUtils.isArray(type)) { 392674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen hash_array(e, type, multiplier, customizer); 393674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 394674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.swap(Type.INT_TYPE, type); 395674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(multiplier); 396674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.math(e.MUL, Type.INT_TYPE); 397674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.swap(type, Type.INT_TYPE); 398674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (TypeUtils.isPrimitive(type)) { 399674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen hash_primitive(e, type); 400674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 401674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen hash_object(e, type, customizer); 402674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 403674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.math(e.ADD, Type.INT_TYPE); 404674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 405674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 406674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 407674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void hash_array(final CodeEmitter e, Type type, final int multiplier, final Customizer customizer) { 408674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label skip = e.make_label(); 409674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label end = e.make_label(); 410674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 411674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.ifnull(skip); 412674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen EmitUtils.process_array(e, type, new ProcessArrayCallback() { 413674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processElement(Type type) { 414674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen hash_code(e, type, multiplier, customizer); 415674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 416674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 417674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(end); 418674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(skip); 419674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); 420674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(end); 421674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 422674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 423674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void hash_object(CodeEmitter e, Type type, Customizer customizer) { 424674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // (f == null) ? 0 : f.hashCode(); 425674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label skip = e.make_label(); 426674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label end = e.make_label(); 427674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 428674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.ifnull(skip); 429674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (customizer != null) { 430674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen customizer.customize(e, type); 431674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 432674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_OBJECT, HASH_CODE); 433674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(end); 434674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(skip); 435674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); 436674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(0); 437674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(end); 438674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 439674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 440674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void hash_primitive(CodeEmitter e, Type type) { 441674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen switch (type.getSort()) { 442674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Type.BOOLEAN: 443674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // f ? 0 : 1 444674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(1); 445674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.math(e.XOR, Type.INT_TYPE); 446674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 447674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Type.FLOAT: 448674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Float.floatToIntBits(f) 449674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_static(Constants.TYPE_FLOAT, FLOAT_TO_INT_BITS); 450674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 451674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Type.DOUBLE: 452674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // Double.doubleToLongBits(f), hash_code(Long.TYPE) 453674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_static(Constants.TYPE_DOUBLE, DOUBLE_TO_LONG_BITS); 454674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // fall through 455674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Type.LONG: 456674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen hash_long(e); 457674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 458674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 459674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 460674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void hash_long(CodeEmitter e) { 461674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // (int)(f ^ (f >>> 32)) 462674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup2(); 463674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(32); 464674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.math(e.USHR, Type.LONG_TYPE); 465674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.math(e.XOR, Type.LONG_TYPE); 466674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.cast_numeric(Type.LONG_TYPE, Type.INT_TYPE); 467674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 468674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 469674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// public static void not_equals(CodeEmitter e, Type type, Label notEquals) { 470674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// not_equals(e, type, notEquals, null); 471674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen// } 472674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 473674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 474674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Branches to the specified label if the top two items on the stack 475674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * are not equal. The items must both be of the specified 476674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * class. Equality is determined by comparing primitive values 477674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * directly and by invoking the <code>equals</code> method for 478674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Objects. Arrays are recursively processed in the same manner. 479674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 480674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void not_equals(final CodeEmitter e, Type type, final Label notEquals, final Customizer customizer) { 481674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen (new ProcessArrayCallback() { 482674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processElement(Type type) { 483674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen not_equals_helper(e, type, notEquals, customizer, this); 484674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 485674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }).processElement(type); 486674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 487674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 488674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void not_equals_helper(CodeEmitter e, 489674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type type, 490674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label notEquals, 491674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Customizer customizer, 492674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ProcessArrayCallback callback) { 493674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (TypeUtils.isPrimitive(type)) { 494674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.if_cmp(type, e.NE, notEquals); 495674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 496674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label end = e.make_label(); 497674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen nullcmp(e, notEquals, end); 498674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (TypeUtils.isArray(type)) { 499674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label checkContents = e.make_label(); 500674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup2(); 501674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.arraylength(); 502674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.swap(); 503674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.arraylength(); 504674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.if_icmp(e.EQ, checkContents); 505674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop2(); 506674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(notEquals); 507674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(checkContents); 508674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen EmitUtils.process_arrays(e, type, callback); 509674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 510674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (customizer != null) { 511674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen customizer.customize(e, type); 512674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.swap(); 513674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen customizer.customize(e, type); 514674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 515674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_OBJECT, EQUALS); 516674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.if_jump(e.EQ, notEquals); 517674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 518674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(end); 519674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 520674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 521674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 522674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /** 523674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * If both objects on the top of the stack are non-null, does nothing. 524674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * If one is null, or both are null, both are popped off and execution 525674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * branches to the respective label. 526674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param oneNull label to branch to if only one of the objects is null 527674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @param bothNull label to branch to if both of the objects are null 528674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 529674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void nullcmp(CodeEmitter e, Label oneNull, Label bothNull) { 530674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup2(); 531674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label nonNull = e.make_label(); 532674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label oneNullHelper = e.make_label(); 533674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label end = e.make_label(); 534674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.ifnonnull(nonNull); 535674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.ifnonnull(oneNullHelper); 536674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop2(); 537674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(bothNull); 538674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 539674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(nonNull); 540674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.ifnull(oneNullHelper); 541674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(end); 542674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 543674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(oneNullHelper); 544674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop2(); 545674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(oneNull); 546674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 547674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(end); 548674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 549674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 550674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* 551674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void to_string(CodeEmitter e, 552674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type type, 553674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ArrayDelimiters delims, 554674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Customizer customizer) { 555674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.new_instance(Constants.TYPE_STRING_BUFFER); 556674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 557674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_constructor(Constants.TYPE_STRING_BUFFER); 558674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.swap(); 559674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen append_string(e, type, delims, customizer); 560674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, TO_STRING); 561674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 562674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 563674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 564674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void append_string(final CodeEmitter e, 565674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type type, 566674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ArrayDelimiters delims, 567674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Customizer customizer) { 568674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ArrayDelimiters d = (delims != null) ? delims : DEFAULT_DELIMITERS; 569674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ProcessArrayCallback callback = new ProcessArrayCallback() { 570674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processElement(Type type) { 571674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen append_string_helper(e, type, d, customizer, this); 572674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(d.inside); 573674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING); 574674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 575674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }; 576674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen append_string_helper(e, type, d, customizer, callback); 577674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 578674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 579674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void append_string_helper(CodeEmitter e, 580674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type type, 581674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ArrayDelimiters delims, 582674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Customizer customizer, 583674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ProcessArrayCallback callback) { 584674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label skip = e.make_label(); 585674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Label end = e.make_label(); 586674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (TypeUtils.isPrimitive(type)) { 587674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen switch (type.getSort()) { 588674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Type.INT: 589674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Type.SHORT: 590674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Type.BYTE: 591674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_INT); 592674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 593674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Type.DOUBLE: 594674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_DOUBLE); 595674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 596674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Type.FLOAT: 597674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_FLOAT); 598674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 599674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Type.LONG: 600674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_LONG); 601674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 602674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Type.BOOLEAN: 603674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_BOOLEAN); 604674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 605674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen case Type.CHAR: 606674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_CHAR); 607674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen break; 608674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 609674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else if (TypeUtils.isArray(type)) { 610674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 611674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.ifnull(skip); 612674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.swap(); 613674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (delims != null && delims.before != null && !"".equals(delims.before)) { 614674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(delims.before); 615674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING); 616674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.swap(); 617674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 618674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen EmitUtils.process_array(e, type, callback); 619674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen shrinkStringBuffer(e, 2); 620674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (delims != null && delims.after != null && !"".equals(delims.after)) { 621674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(delims.after); 622674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING); 623674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 624674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 625674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 626674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.ifnull(skip); 627674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (customizer != null) { 628674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen customizer.customize(e, type); 629674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 630674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING); 631674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING); 632674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 633674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(end); 634674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(skip); 635674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); 636674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push("null"); 637674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING); 638674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(end); 639674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 640674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 641674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void shrinkStringBuffer(CodeEmitter e, int amt) { 642674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 643674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 644674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, LENGTH); 645674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(amt); 646674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.math(e.SUB, Type.INT_TYPE); 647674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_STRING_BUFFER, SET_LENGTH); 648674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 649674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 650674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static class ArrayDelimiters { 651674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private String before; 652674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private String inside; 653674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private String after; 654674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 655674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public ArrayDelimiters(String before, String inside, String after) { 656674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.before = before; 657674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.inside = inside; 658674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen this.after = after; 659674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 660674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 661674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 662674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void load_method(CodeEmitter e, MethodInfo method) { 663674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen load_class(e, method.getClassInfo().getType()); 664674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(method.getSignature().getName()); 665674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen push_object(e, method.getSignature().getArgumentTypes()); 666674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_CLASS, GET_DECLARED_METHOD); 667674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 668674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 669674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private interface ParameterTyper { 670674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type[] getParameterTypes(MethodInfo member); 671674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 672674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 673674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void method_switch(CodeEmitter e, 674674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List methods, 675674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ObjectSwitchCallback callback) { 676674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen member_switch_helper(e, methods, callback, true); 677674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 678674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 679674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void constructor_switch(CodeEmitter e, 680674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List constructors, 681674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ObjectSwitchCallback callback) { 682674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen member_switch_helper(e, constructors, callback, false); 683674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 684674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 685674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void member_switch_helper(final CodeEmitter e, 686674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List members, 687674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ObjectSwitchCallback callback, 688674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean useName) { 689674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen try { 690674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Map cache = new HashMap(); 691674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ParameterTyper cached = new ParameterTyper() { 692674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Type[] getParameterTypes(MethodInfo member) { 693674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type[] types = (Type[])cache.get(member); 694674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (types == null) { 695674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen cache.put(member, types = member.getSignature().getArgumentTypes()); 696674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 697674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return types; 698674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 699674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }; 700674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label def = e.make_label(); 701674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label end = e.make_label(); 702674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (useName) { 703674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.swap(); 704674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Map buckets = CollectionUtils.bucket(members, new Transformer() { 705674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Object transform(Object value) { 706674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return ((MethodInfo)value).getSignature().getName(); 707674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 708674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 709674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen String[] names = (String[])buckets.keySet().toArray(new String[buckets.size()]); 710674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { 711674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processCase(Object key, Label dontUseEnd) throws Exception { 712674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen member_helper_size(e, (List)buckets.get(key), callback, cached, def, end); 713674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 714674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processDefault() throws Exception { 715674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(def); 716674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 717674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 718674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 719674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen member_helper_size(e, members, callback, cached, def, end); 720674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 721674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(def); 722674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); 723674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen callback.processDefault(); 724674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.mark(end); 725674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (RuntimeException ex) { 726674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw ex; 727674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (Error ex) { 728674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw ex; 729674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (Exception ex) { 730674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new CodeGenerationException(ex); 731674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 732674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 733674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 734674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void member_helper_size(final CodeEmitter e, 735674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List members, 736674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ObjectSwitchCallback callback, 737674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ParameterTyper typer, 738674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label def, 739674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label end) throws Exception { 740674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Map buckets = CollectionUtils.bucket(members, new Transformer() { 741674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Object transform(Object value) { 742674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return new Integer(typer.getParameterTypes((MethodInfo)value).length); 743674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 744674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 745674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 746674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.arraylength(); 747674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.process_switch(EmitUtils.getSwitchKeys(buckets), new ProcessSwitchCallback() { 748674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processCase(int key, Label dontUseEnd) throws Exception { 749674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List bucket = (List)buckets.get(new Integer(key)); 750674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen member_helper_type(e, bucket, callback, typer, def, end, new BitSet()); 751674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 752674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processDefault() throws Exception { 753674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(def); 754674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 755674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 756674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 757674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 758674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen private static void member_helper_type(final CodeEmitter e, 759674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen List members, 760674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ObjectSwitchCallback callback, 761674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final ParameterTyper typer, 762674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label def, 763674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Label end, 764674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final BitSet checked) throws Exception { 765674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (members.size() == 1) { 766674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen MethodInfo member = (MethodInfo)members.get(0); 767674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type[] types = typer.getParameterTypes(member); 768674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // need to check classes that have not already been checked via switches 769674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < types.length; i++) { 770674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (checked == null || !checked.get(i)) { 771674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 772674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.aaload(i); 773674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_CLASS, GET_NAME); 774674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.push(TypeUtils.emulateClassGetName(types[i])); 775674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_OBJECT, EQUALS); 776674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.if_jump(e.EQ, def); 777674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 778674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 779674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.pop(); 780674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen callback.processCase(member, end); 781674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 782674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // choose the index that has the best chance of uniquely identifying member 783674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type[] example = typer.getParameterTypes((MethodInfo)members.get(0)); 784674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Map buckets = null; 785674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen int index = -1; 786674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < example.length; i++) { 787674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final int j = i; 788674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Map test = CollectionUtils.bucket(members, new Transformer() { 789674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public Object transform(Object value) { 790674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return TypeUtils.emulateClassGetName(typer.getParameterTypes((MethodInfo)value)[j]); 791674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 792674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 793674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (buckets == null || test.size() > buckets.size()) { 794674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen buckets = test; 795674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen index = i; 796674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 797674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 798674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (buckets == null || buckets.size() == 1) { 799674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // TODO: switch by returnType 800674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // must have two methods with same name, types, and different return types 801674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(def); 802674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } else { 803674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen checked.set(index); 804674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 805674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup(); 806674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.aaload(index); 807674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_virtual(Constants.TYPE_CLASS, GET_NAME); 808674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 809674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen final Map fbuckets = buckets; 810674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen String[] names = (String[])buckets.keySet().toArray(new String[buckets.size()]); 811674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { 812674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processCase(Object key, Label dontUseEnd) throws Exception { 813674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen member_helper_type(e, (List)fbuckets.get(key), callback, typer, def, end, checked); 814674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 815674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public void processDefault() throws Exception { 816674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.goTo(def); 817674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 818674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen }); 819674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 820674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 821674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 822674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 823674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void wrap_throwable(Block block, Type wrapper) { 824674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e = block.getCodeEmitter(); 825674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.catch_exception(block, Constants.TYPE_THROWABLE); 826674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.new_instance(wrapper); 827674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup_x1(); 828674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.swap(); 829674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_constructor(wrapper, CSTRUCT_THROWABLE); 830674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.athrow(); 831674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 832674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 833674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void add_properties(ClassEmitter ce, String[] names, Type[] types) { 834674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < names.length; i++) { 835674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen String fieldName = "$cglib_prop_" + names[i]; 836674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen ce.declare_field(Constants.ACC_PRIVATE, fieldName, types[i], null); 837674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen EmitUtils.add_property(ce, names[i], types[i], fieldName); 838674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 839674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 840674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 841674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void add_property(ClassEmitter ce, String name, Type type, String fieldName) { 842674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen String property = TypeUtils.upperFirst(name); 843674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen CodeEmitter e; 844674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e = ce.begin_method(Constants.ACC_PUBLIC, 845674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen new Signature("get" + property, 846674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen type, 847674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Constants.TYPES_EMPTY), 848674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen null); 849674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 850674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.getfield(fieldName); 851674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 852674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 853674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 854674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e = ce.begin_method(Constants.ACC_PUBLIC, 855674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen new Signature("set" + property, 856674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Type.VOID_TYPE, 857674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen new Type[]{ type }), 858674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen null); 859674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_this(); 860674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.load_arg(0); 861674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.putfield(fieldName); 862674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.return_value(); 863674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.end_method(); 864674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 865674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 866674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen /* generates: 867674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (RuntimeException e) { 868674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw e; 869674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (Error e) { 870674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw e; 871674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (<DeclaredException> e) { 872674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw e; 873674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } catch (Throwable e) { 874674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen throw new <Wrapper>(e); 875674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 876674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */ 877674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static void wrap_undeclared_throwable(CodeEmitter e, Block handler, Type[] exceptions, Type wrapper) { 878674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen Set set = (exceptions == null) ? Collections.EMPTY_SET : new HashSet(Arrays.asList(exceptions)); 879674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 880674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (set.contains(Constants.TYPE_THROWABLE)) 881674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return; 882674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 883674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen boolean needThrow = exceptions != null; 884674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!set.contains(Constants.TYPE_RUNTIME_EXCEPTION)) { 885674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.catch_exception(handler, Constants.TYPE_RUNTIME_EXCEPTION); 886674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen needThrow = true; 887674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 888674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (!set.contains(Constants.TYPE_ERROR)) { 889674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.catch_exception(handler, Constants.TYPE_ERROR); 890674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen needThrow = true; 891674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 892674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (exceptions != null) { 893674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen for (int i = 0; i < exceptions.length; i++) { 894674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.catch_exception(handler, exceptions[i]); 895674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 896674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 897674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen if (needThrow) { 898674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.athrow(); 899674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 900674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen // e -> eo -> oeo -> ooe -> o 901674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.catch_exception(handler, Constants.TYPE_THROWABLE); 902674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.new_instance(wrapper); 903674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.dup_x1(); 904674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.swap(); 905674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.invoke_constructor(wrapper, CSTRUCT_THROWABLE); 906674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen e.athrow(); 907674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 908674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 909674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static CodeEmitter begin_method(ClassEmitter e, MethodInfo method) { 910674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return begin_method(e, method, method.getModifiers()); 911674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 912674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen 913674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen public static CodeEmitter begin_method(ClassEmitter e, MethodInfo method, int access) { 914674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen return e.begin_method(access, 915674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen method.getSignature(), 916674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen method.getExceptionTypes()); 917674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen } 918674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen} 919