| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package macromedia.abc; |
| |
| import static macromedia.asc.embedding.avmplus.ActionBlockConstants.*; |
| import macromedia.asc.util.IntegerPool; |
| import macromedia.asc.util.IntList; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.util.*; |
| |
| /** |
| * abc encoder. If the encoder is provided with multiple constant pools, it will use do merging. |
| * |
| * @author Clement Wong |
| */ |
| public class Encoder implements Visitor |
| { |
| public Encoder(int majorVersion, int minorVersion) |
| { |
| this.majorVersion = majorVersion; |
| this.minorVersion = minorVersion; |
| |
| poolIndex = 0; |
| peepHole = false; |
| disableDebugging = false; |
| removeMetadata = false; |
| |
| } |
| |
| private ConstantPool pool; |
| private int majorVersion, minorVersion; |
| private int poolIndex, opcodePass, exPass; |
| private boolean disableDebugging, removeMetadata, peepHole; |
| |
| private HashSet<String> keep_metadata = new HashSet<String>(); |
| |
| private BytecodeBuffer2 methodInfo; |
| private ByteArrayPool2 metadataInfo; |
| private BytecodeBuffer2 classInfo; |
| private BytecodeBuffer2 scriptInfo; |
| private BytecodeBuffer2 methodBodies; |
| private BytecodeBuffer3 opcodes; |
| private BytecodeBuffer exceptions; |
| |
| private BytecodeBuffer currentBuffer; |
| |
| private ConstantPool[] pools; |
| |
| public void enablePeepHole() |
| { |
| peepHole = true; |
| } |
| |
| public void disableDebugging() |
| { |
| disableDebugging = true; |
| pool.history.disableDebugging(); |
| } |
| |
| public void removeMetadata() |
| { |
| removeMetadata = true; |
| } |
| |
| public void addMetadataToKeep(String meta_name) |
| { |
| keep_metadata.add(meta_name); |
| } |
| |
| public void addConstantPools(ConstantPool[] pools) |
| { |
| this.pools = pools; |
| pool = ConstantPool.merge(pools); |
| if( disableDebugging ) |
| pool.history.disableDebugging(); |
| } |
| |
| public void test() |
| { |
| // C: testing only... |
| for (int i = 0, size = pools.length; i < size; i++) |
| { |
| /* |
| for (int j = 1, count = pools[i].intpositions.length; j < count; j++) |
| { |
| int original = pools[i].getInt(j); |
| int real = pool.getInt(pool.history.getIndex(i, 0, j)); |
| |
| if (original != real) |
| { |
| throw new DecoderException("Error (int) in constant pooling merging..."); |
| } |
| } |
| |
| for (int j = 1, count = pools[i].uintpositions.length; j < count; j++) |
| { |
| long original = pools[i].getLong(j); |
| long real = pool.getLong(pool.history.getIndex(i, 1, j)); |
| |
| if (original != real) |
| { |
| throw new DecoderException("Error (uint) in constant pooling merging..."); |
| } |
| } |
| |
| for (int j = 1, count = pools[i].doublepositions.length; j < count; j++) |
| { |
| double original = pools[i].getDouble(j); |
| double real = pool.getDouble(pool.history.getIndex(i, 2, j)); |
| |
| if (original != real) |
| { |
| throw new DecoderException("Error (double) in constant pooling merging..."); |
| } |
| } |
| |
| for (int j = 1, count = pools[i].strpositions.length; j < count; j++) |
| { |
| String original = pools[i].getString(j); |
| System.out.println("(" + i + "," + j + ")-->(0," + pool.history.getIndex(i, 3, j) + "): " + original); |
| } |
| |
| for (int j = 1, count = pools[i].nspositions.length; j < count; j++) |
| { |
| String original = pools[i].getNamespaceName(j); |
| String real = pool.getNamespaceName(pool.history.getIndex(i, 4, j)); |
| |
| if (!original.equals(real)) |
| { |
| throw new DecoderException("Error (namespace) in constant pooling merging..."); |
| } |
| } |
| |
| for (int j = 1, count = pools[i].nsspositions.length; j < count; j++) |
| { |
| String[] original = pools[i].getNamespaceSet(j); |
| String[] real = pool.getNamespaceSet(pool.history.getIndex(i, 5, j)); |
| |
| if (original.length != real.length) |
| { |
| throw new DecoderException("Error (namespace set) in constant pooling merging..."); |
| } |
| else |
| { |
| for (int k = 0, len = original.length; k < len; k++) |
| { |
| if (!original[k].equals(real[k])) |
| { |
| throw new DecoderException("Error (namespace set) in constant pooling merging..."); |
| } |
| } |
| } |
| } |
| |
| for (int j = 1, count = pools[i].mnpositions.length; j < count; j++) |
| { |
| Object original = pools[i].getGeneralMultiname(j); |
| Object real = pool.getGeneralMultiname(pool.history.getIndex(i, 6, j)); |
| |
| if (original.getClass() != real.getClass()) |
| { |
| throw new DecoderException("Error (multiname) in constant pooling merging..."); |
| } |
| |
| if (original instanceof QName && !((QName) original).equals(real)) |
| { |
| throw new DecoderException("Error (multiname) in constant pooling merging..."); |
| } |
| |
| if (original instanceof MultiName && !((MultiName) original).equals(real)) |
| { |
| throw new DecoderException("Error (multiname) in constant pooling merging..."); |
| } |
| } |
| */ |
| } |
| } |
| |
| public void configure(Decoder[] decoders) |
| { |
| int estimatedSize = 0, total = 0; |
| int[] sizes = new int[decoders.length]; |
| for (int i = 0, size = sizes.length; i < size; i++) |
| { |
| estimatedSize += decoders[i].methodInfo.estimatedSize; |
| sizes[i] = decoders[i].methodInfo.size(); |
| total += sizes[i]; |
| } |
| methodInfo = new BytecodeBuffer2(estimatedSize, sizes); |
| methodInfo.writeU32(total); |
| |
| |
| estimatedSize = 0; total = 0; |
| sizes = new int[decoders.length]; |
| for (int i = 0, size = sizes.length; i < size; i++) |
| { |
| estimatedSize += decoders[i].metadataInfo.estimatedSize; |
| sizes[i] = decoders[i].metadataInfo.size(); |
| total += sizes[i]; |
| } |
| metadataInfo = new ByteArrayPool2(sizes); |
| |
| |
| estimatedSize = 0; total = 0; |
| sizes = new int[decoders.length]; |
| for (int i = 0, size = sizes.length; i < size; i++) |
| { |
| estimatedSize += decoders[i].classInfo.estimatedSize; |
| sizes[i] = decoders[i].classInfo.size(); |
| total += sizes[i]; |
| } |
| classInfo = new BytecodeBuffer2(estimatedSize, sizes); |
| classInfo.writeU32(total); |
| |
| |
| estimatedSize = 0; total = 0; |
| sizes = new int[decoders.length]; |
| for (int i = 0, size = sizes.length; i < size; i++) |
| { |
| estimatedSize += decoders[i].scriptInfo.estimatedSize; |
| sizes[i] = decoders[i].scriptInfo.size(); |
| total += sizes[i]; |
| } |
| scriptInfo = new BytecodeBuffer2(estimatedSize, sizes); |
| scriptInfo.writeU32(total); |
| |
| |
| estimatedSize = 0; total = 0; |
| sizes = new int[decoders.length]; |
| for (int i = 0, size = sizes.length; i < size; i++) |
| { |
| estimatedSize += decoders[i].methodBodies.estimatedSize; |
| sizes[i] = decoders[i].methodBodies.size(); |
| total += sizes[i]; |
| } |
| methodBodies = new BytecodeBuffer2(estimatedSize, sizes); |
| methodBodies.writeU32(total); |
| |
| opcodes = new BytecodeBuffer3(decoders, 4096); |
| exceptions = new BytecodeBuffer(4096); |
| } |
| |
| public void useConstantPool(int index) |
| { |
| poolIndex = index; |
| } |
| |
| public byte[] toABC() |
| { |
| /* |
| System.out.println(); |
| System.out.println("--Constant Pool--"); |
| System.out.println("total: " + pool.history.total + " duplicate: " + pool.history.duplicate); |
| System.out.println("totalBytes: " + pool.history.totalBytes + " duplicateBytes: " + pool.history.duplicateBytes); |
| System.out.println("--Method Info--"); |
| System.out.println("before: " + methodInfo.estimatedSize + " after: " + methodInfo.size()); |
| System.out.println("--Metadata Info--"); |
| System.out.println("before: " + metadataInfo.estimatedSize + " after: " + metadataInfo.size()); |
| System.out.println("--Class Info--"); |
| System.out.println("before: " + classInfo.estimatedSize + " after: " + classInfo.size()); |
| System.out.println("--Script Info--"); |
| System.out.println("before: " + scriptInfo.estimatedSize + " after: " + scriptInfo.size()); |
| System.out.println("--Method Bodies--"); |
| System.out.println("before: " + methodBodies.estimatedSize + " after: " + methodBodies.size()); |
| System.out.println(); |
| */ |
| |
| int size = pool.in.size() + methodInfo.size() + metadataInfo.size() + classInfo.size() + scriptInfo.size() + methodBodies.size(); |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(size); |
| |
| try |
| { |
| baos.write((byte) minorVersion); |
| baos.write((byte) (minorVersion >> 8)); |
| baos.write((byte) majorVersion); |
| baos.write((byte) (majorVersion >> 8)); |
| |
| pool.writeTo(baos); |
| methodInfo.writeTo(baos); |
| metadataInfo.writeTo(baos); |
| classInfo.writeTo(baos); |
| scriptInfo.writeTo(baos); |
| methodBodies.writeTo(baos); |
| } |
| catch (IOException ex) |
| { |
| return null; |
| } |
| |
| return baos.toByteArray(); |
| } |
| |
| public void methodInfo(int returnType, int[] paramTypes, int nativeName, int flags, int[] values, int[] value_kinds, int[] param_names) |
| { |
| if (paramTypes == null) |
| { |
| methodInfo.writeU32(0); |
| } |
| else |
| { |
| methodInfo.writeU32(paramTypes.length); |
| } |
| |
| methodInfo.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, returnType)); |
| |
| for (int i = 0, paramCount = (paramTypes == null) ? 0 : paramTypes.length; i < paramCount; i++) |
| { |
| methodInfo.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, paramTypes[i])); |
| } |
| |
| methodInfo.writeU32((disableDebugging) ? 0 : pool.history.getIndex(poolIndex, IndexHistory.cp_string, nativeName)); |
| |
| if( disableDebugging ) |
| { |
| // Nuke the param names if we're getting rid of debugging info, don't want them showing |
| // up in release code |
| flags &= ~METHOD_HasParamNames; |
| } |
| |
| methodInfo.writeU8(flags); |
| |
| if ((flags & METHOD_HasOptional) != 0) |
| { |
| if (values == null) |
| { |
| methodInfo.writeU32(0); |
| } |
| else |
| { |
| methodInfo.writeU32(values.length); |
| } |
| } |
| |
| for (int i = 0, optionalCount = (values == null) ? 0 : values.length; i < optionalCount; i++) |
| { |
| int kind = -1; |
| |
| switch (value_kinds[i]) |
| { |
| case CONSTANT_Utf8: |
| kind = IndexHistory.cp_string; |
| break; |
| case CONSTANT_Integer: |
| kind = IndexHistory.cp_int; |
| break; |
| case CONSTANT_UInteger: |
| kind = IndexHistory.cp_uint; |
| break; |
| case CONSTANT_Double: |
| kind = IndexHistory.cp_double; |
| break; |
| case CONSTANT_Decimal: |
| kind = IndexHistory.cp_decimal; |
| break; |
| case CONSTANT_Namespace: |
| case CONSTANT_PrivateNamespace: |
| case CONSTANT_PackageNamespace: |
| case CONSTANT_PackageInternalNs: |
| case CONSTANT_ProtectedNamespace: |
| case CONSTANT_ExplicitNamespace: |
| case CONSTANT_StaticProtectedNs: |
| kind = IndexHistory.cp_ns; |
| break; |
| case CONSTANT_Qname: |
| case CONSTANT_QnameA: |
| case CONSTANT_Multiname: |
| case CONSTANT_MultinameA: |
| case CONSTANT_TypeName: |
| kind = IndexHistory.cp_mn; |
| break; |
| case CONSTANT_Namespace_Set: |
| kind = IndexHistory.cp_nsset; |
| break; |
| } |
| |
| int newIndex = 0; |
| |
| switch(value_kinds[i]) |
| { |
| case 0: |
| case CONSTANT_False: |
| case CONSTANT_True: |
| case CONSTANT_Null: |
| // The index doesn't matter, as long as its non 0 |
| // there are no boolean values in any cpool, instead the value will be determined by the kind byte |
| newIndex = values[i]; |
| break; |
| default: |
| { |
| if (kind == -1) |
| { |
| System.out.println("writing MethodInfo: don't know what constant type it is... " + value_kinds[i] + "," + values[i]); |
| } |
| newIndex = pool.history.getIndex(poolIndex, kind, values[i]); |
| } |
| } |
| |
| methodInfo.writeU32(newIndex); |
| methodInfo.writeU8(value_kinds[i]); |
| } |
| // Nuke the param names if we're not keeping debugging around |
| if( (flags & METHOD_HasParamNames) != 0 && param_names != null) |
| { |
| for( int i = 0 ; i < param_names.length; ++i ) |
| { |
| methodInfo.writeU32( pool.history.getIndex(poolIndex, IndexHistory.cp_string, returnType) ); |
| } |
| } |
| } |
| |
| public void metadataInfo(int index, int name, int[] keys, int[] values) |
| { |
| |
| |
| try |
| { |
| String s = pools[poolIndex].getString(name); |
| if (removeMetadata && !keep_metadata.contains(s) ) |
| return; |
| |
| BytecodeBuffer b = new BytecodeBuffer(6); |
| b.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, name)); |
| if (keys == null) |
| { |
| b.writeU32(0); |
| } |
| else |
| { |
| b.writeU32(keys.length); |
| } |
| |
| for (int i = 0, keyCount = (keys == null) ? 0 : keys.length; i < keyCount; i++) |
| { |
| b.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, keys[i])); |
| } |
| |
| for (int i = 0, valueCount = (values == null) ? 0 : values.length; i < valueCount; i++) |
| { |
| b.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, values[i])); |
| } |
| |
| metadataInfo.addByteArray(poolIndex, index, b); |
| } |
| catch( DecoderException ex) |
| { |
| // this should never happen |
| // ex.printStackTrace(); |
| } |
| } |
| |
| public void startInstance(int name, int superName, boolean isDynamic, boolean isFinal, boolean isInterface, int[] interfaces, int iinit, int protectedNamespace) |
| { |
| classInfo.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, name)); |
| classInfo.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, superName)); |
| |
| int flags = 0; |
| flags = (isFinal) ? (flags | CLASS_FLAG_final) : flags; |
| flags = (!isDynamic) ? (flags | CLASS_FLAG_sealed) : flags; |
| flags = (isInterface) ? (flags | CLASS_FLAG_interface) : flags; |
| flags = (protectedNamespace != 0) ? (flags | CLASS_FLAG_protected) : flags; |
| classInfo.writeU8(flags); |
| |
| if (protectedNamespace != 0) |
| { |
| classInfo.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_ns, protectedNamespace)); |
| } |
| |
| if (interfaces == null) |
| { |
| classInfo.writeU32(0); |
| } |
| else |
| { |
| classInfo.writeU32(interfaces.length); |
| } |
| |
| for (int i = 0, interfaceCount = interfaces == null ? 0 : interfaces.length; i < interfaceCount; i++) |
| { |
| classInfo.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, interfaces[i])); |
| } |
| |
| classInfo.writeU32(methodInfo.getIndex(poolIndex, iinit)); |
| |
| currentBuffer = classInfo; |
| } |
| |
| public void endInstance() |
| { |
| currentBuffer = null; |
| } |
| |
| public void startClass(int name, int cinit) |
| { |
| classInfo.writeU32(methodInfo.getIndex(poolIndex, cinit)); |
| |
| currentBuffer = classInfo; |
| } |
| |
| public void endClass() |
| { |
| currentBuffer = null; |
| } |
| |
| public void startScript(int initID) |
| { |
| scriptInfo.writeU32(methodInfo.getIndex(poolIndex, initID)); |
| |
| currentBuffer = scriptInfo; |
| } |
| |
| public void endScript() |
| { |
| currentBuffer = null; |
| } |
| |
| public void startMethodBody(int methodInfo, int maxStack, int maxRegs, int scopeDepth, int maxScope, int codeStart, long codeLength) |
| { |
| methodBodies.writeU32(this.methodInfo.getIndex(poolIndex, methodInfo)); |
| methodBodies.writeU32(maxStack); |
| methodBodies.writeU32(maxRegs); |
| methodBodies.writeU32(scopeDepth); |
| methodBodies.writeU32(maxScope); |
| |
| currentBuffer = methodBodies; |
| opcodePass = 1; |
| exPass = 1; |
| } |
| |
| public void endMethodBody() |
| { |
| currentBuffer = null; |
| opcodes.clear(); |
| exceptions.clear(); |
| } |
| |
| public void startOpcodes(int methodInfo) |
| { |
| } |
| |
| public void endOpcodes() |
| { |
| if (opcodePass == 1) |
| { |
| opcodePass = 2; |
| } |
| else if (opcodePass == 2) |
| { |
| methodBodies.writeU32(opcodes.size()); |
| methodBodies.writeBytes(opcodes, 0, opcodes.size()); |
| } |
| } |
| |
| public void exception(long start, long end, long target, int type, int name) |
| { |
| if (exPass == 2) |
| { |
| exceptions.writeU32(opcodes.getOffset(start)); |
| exceptions.writeU32(opcodes.getOffset(end)); |
| exceptions.writeU32(opcodes.getOffset(target)); |
| exceptions.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, type)); |
| if (minorVersion != 15) |
| { |
| exceptions.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, name)); |
| } |
| } |
| } |
| |
| public void startExceptions(int exceptionCount) |
| { |
| if (exPass == 2) |
| { |
| exceptions.writeU32(exceptionCount); |
| } |
| } |
| |
| public void endExceptions() |
| { |
| if (exPass == 1) |
| { |
| exPass++; |
| } |
| else if (exPass == 2) |
| { |
| methodBodies.writeBytes(exceptions, 0, exceptions.size()); |
| } |
| } |
| |
| public void traitCount(int traitCount) |
| { |
| currentBuffer.writeU32(traitCount); |
| } |
| |
| // private void encodeMetaData(int kind, int[] metadata) |
| // { |
| // if (((kind >> 4) & TRAIT_FLAG_metadata) != 0) |
| // { |
| // if (metadata == null) |
| // { |
| // currentBuffer.writeU32(0); |
| // } |
| // else |
| // { |
| // currentBuffer.writeU32(metadata.length); |
| // } |
| // |
| // for (int i = 0, length = metadata == null ? 0 : metadata.length; i < length; i++) |
| // { |
| // currentBuffer.writeU32(metadataInfo.getIndex(poolIndex, metadata[i])); |
| // } |
| // } |
| // } |
| |
| private void encodeMetaData(int kind, IntList metadata) |
| { |
| if (((kind >> 4) & TRAIT_FLAG_metadata) != 0) |
| { |
| if (metadata == null) |
| { |
| currentBuffer.writeU32(0); |
| } |
| else |
| { |
| currentBuffer.writeU32(metadata.size()); |
| } |
| |
| for (int i = 0, length = metadata == null ? 0 : metadata.size(); i < length; i++) |
| { |
| currentBuffer.writeU32(metadata.get(i)); |
| } |
| } |
| } |
| |
| private IntList trimMetadata(int[] metadata) |
| { |
| IntList newMetadata = new IntList(); |
| int length = metadata != null ? metadata.length : 0; |
| for( int i = 0; i < length; ++i) |
| { |
| int new_index = metadataInfo.getIndex(poolIndex, metadata[i]) ; |
| if( new_index != -1 ) |
| { |
| newMetadata.add(new_index); |
| } |
| } |
| return newMetadata; |
| } |
| |
| public void slotTrait(int trait_kind, int name, int slotId, int type, int value, int value_kind, int[] metadata) |
| { |
| currentBuffer.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, name)); |
| IntList new_metadata = trimMetadata(metadata); |
| if ( ((trait_kind >> 4) & TRAIT_FLAG_metadata) != 0 && new_metadata.size()==0 ) |
| { |
| trait_kind = trait_kind & ~(TRAIT_FLAG_metadata << 4); |
| } |
| currentBuffer.writeU8(trait_kind); |
| |
| currentBuffer.writeU32(slotId); |
| currentBuffer.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, type)); |
| |
| int kind = -1; |
| |
| switch(value_kind) |
| { |
| case CONSTANT_Utf8: |
| kind = IndexHistory.cp_string; |
| break; |
| case CONSTANT_Integer: |
| kind = IndexHistory.cp_int; |
| break; |
| case CONSTANT_UInteger: |
| kind = IndexHistory.cp_uint; |
| break; |
| case CONSTANT_Double: |
| kind = IndexHistory.cp_double; |
| break; |
| case CONSTANT_Decimal: |
| kind = IndexHistory.cp_decimal; |
| break; |
| case CONSTANT_Namespace: |
| case CONSTANT_PrivateNamespace: |
| case CONSTANT_PackageNamespace: |
| case CONSTANT_PackageInternalNs: |
| case CONSTANT_ProtectedNamespace: |
| case CONSTANT_ExplicitNamespace: |
| case CONSTANT_StaticProtectedNs: |
| kind = IndexHistory.cp_ns; |
| break; |
| case CONSTANT_Qname: |
| case CONSTANT_QnameA: |
| case CONSTANT_Multiname: |
| case CONSTANT_MultinameA: |
| case CONSTANT_TypeName: |
| kind = IndexHistory.cp_mn; |
| break; |
| case CONSTANT_Namespace_Set: |
| kind = IndexHistory.cp_nsset; |
| break; |
| } |
| |
| int newIndex = 0; |
| switch(value_kind) |
| { |
| case 0: |
| case CONSTANT_False: |
| case CONSTANT_True: |
| case CONSTANT_Null: |
| newIndex = value; |
| break; |
| default: |
| { |
| if (kind == -1) |
| { |
| System.out.println("writing slotTrait: don't know what constant type it is... " + value_kind + "," + value); |
| } |
| newIndex = pool.history.getIndex(poolIndex, kind, value); |
| } |
| } |
| |
| currentBuffer.writeU32(newIndex); |
| if (value != 0) |
| { |
| currentBuffer.writeU8(value_kind); |
| } |
| |
| encodeMetaData(trait_kind, new_metadata); |
| } |
| |
| public void methodTrait(int trait_kind, int name, int dispId, int methodInfo, int[] metadata) |
| { |
| currentBuffer.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, name)); |
| IntList new_metadata = trimMetadata(metadata); |
| if ( ((trait_kind >> 4) & TRAIT_FLAG_metadata) != 0 && new_metadata.size()==0 ) |
| { |
| trait_kind = trait_kind & ~(TRAIT_FLAG_metadata << 4); |
| } |
| currentBuffer.writeU8(trait_kind); |
| |
| //currentBuffer.writeU32(0); |
| currentBuffer.writeU32(dispId); |
| currentBuffer.writeU32(this.methodInfo.getIndex(poolIndex, methodInfo)); |
| |
| encodeMetaData(trait_kind, new_metadata); |
| } |
| |
| public void classTrait(int kind, int name, int slotId, int classIndex, int[] metadata) |
| { |
| currentBuffer.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, name)); |
| IntList new_metadata = trimMetadata(metadata); |
| if ( ((kind >> 4) & TRAIT_FLAG_metadata) != 0 && new_metadata.size()==0 ) |
| { |
| kind = kind & ~(TRAIT_FLAG_metadata << 4); |
| } |
| currentBuffer.writeU8(kind); |
| |
| currentBuffer.writeU32(slotId); |
| currentBuffer.writeU32(classInfo.getIndex(poolIndex, classIndex)); |
| |
| encodeMetaData(kind, new_metadata); |
| } |
| |
| public void functionTrait(int kind, int name, int slotId, int methodInfo, int[] metadata) |
| { |
| currentBuffer.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, name)); |
| IntList new_metadata = trimMetadata(metadata); |
| if ( ((kind >> 4) & TRAIT_FLAG_metadata) != 0 && new_metadata.size()==0 ) |
| { |
| kind = kind & ~(TRAIT_FLAG_metadata << 4); |
| } |
| currentBuffer.writeU8(kind); |
| |
| currentBuffer.writeU32(slotId); |
| currentBuffer.writeU32(this.methodInfo.getIndex(poolIndex, methodInfo)); |
| |
| encodeMetaData(kind, new_metadata); |
| } |
| |
| static final int W = 8; |
| int[] window = new int[W]; |
| int window_size = 0; |
| int head = 0; |
| boolean reachable = true; |
| |
| void clearWindow() |
| { |
| for (int i=0; i < W; i++) |
| window[i] = 0; |
| window_size = 0; |
| } |
| |
| void beginop(int opcode) |
| { |
| window[head] = opcodes.size(); |
| head = (head+1) & (W-1); |
| if( window_size < 8 ) |
| ++window_size; |
| opcodes.writeU8(opcode); |
| } |
| |
| int opat(int i) |
| { |
| if (peepHole) |
| { |
| if( i <= window_size ) |
| { |
| int ip = window[(head-i) & (W-1)]; |
| if (ip < opcodes.size()) |
| return opcodes.readU8(ip); |
| } |
| } |
| return 0; |
| } |
| |
| void setOpcodeAt(int i, int opcode) |
| { |
| assert peepHole; |
| |
| if( i <= window_size ) |
| { |
| int ip = window[(head-i) & (W-1)]; |
| if (ip < opcodes.size()) |
| opcodes.writeU8(ip, opcode); |
| } |
| } |
| |
| int readByteAt(int i) |
| { |
| if( i <= window_size ) |
| { |
| int ip = 1+window[(head-i) & (W-1)]; |
| return (byte) opcodes.readU8(ip); |
| } |
| return 0; |
| } |
| |
| int readIntAt(int i) |
| { |
| if( i <= window_size ) |
| { |
| int ip = 1+window[(head-i) & (W-1)]; |
| return (int) opcodes.readU32(ip); |
| } |
| return 0; |
| } |
| |
| void rewind(int i) |
| { |
| int to = (head-i) & (W-1); |
| int ip = window[to]; |
| int end = opcodes.size(); |
| opcodes.delete(end-ip); |
| head = to; |
| window_size -= i; |
| } |
| |
| public void target(int oldPos) |
| { |
| if (opcodePass == 1) |
| { |
| opcodes.mapOffsets(oldPos); |
| clearWindow(); |
| } |
| } |
| |
| public void OP_returnvoid() |
| { |
| if (opcodePass == 1) |
| { |
| /* |
| if (opat(2) == OP_getlocal0 && opat(1) == OP_pushscope) |
| rewind(2); |
| |
| if (opat(1) == OP_returnvalue) |
| return; |
| */ |
| beginop(OP_returnvoid); |
| } |
| } |
| |
| public void OP_returnvalue() |
| { |
| if (opcodePass == 1) |
| { |
| |
| if (opat(1) == OP_coerce_a) |
| { |
| rewind(1); |
| } |
| |
| if (opat(1) == OP_pushundefined) |
| { |
| rewind(1); |
| OP_returnvoid(); |
| return; |
| } |
| |
| // eliminate dead code... maybe do this higher up? |
| /* |
| for (int i=1; i < W; i++) |
| { |
| if (opat(i) == OP_returnvalue) |
| { |
| rewind(i); |
| break; |
| } |
| } |
| |
| if ( opat(4) == OP_pushundefined && |
| opat(3) == OP_coerce_a && |
| opat(2) == OP_setlocal1 && |
| opat(1) == OP_getlocal1) |
| { |
| rewind(4); |
| OP_returnvoid(); |
| return; |
| } |
| */ |
| |
| beginop(OP_returnvalue); |
| } |
| } |
| |
| public void OP_nop() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_nop); |
| } |
| } |
| |
| public void OP_bkpt() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_bkpt); |
| } |
| } |
| |
| public void OP_timestamp() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_timestamp); |
| } |
| } |
| |
| public void OP_debugline(int linenum) |
| { |
| if (opcodePass == 1) |
| { |
| if (!disableDebugging) |
| { |
| beginop(OP_debugline); |
| opcodes.writeU32(linenum); |
| } |
| } |
| } |
| |
| public void OP_bkptline() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_bkptline); |
| } |
| } |
| |
| public void OP_debug(int di_local, int index, int slot, int linenum) |
| { |
| if (opcodePass == 1) |
| { |
| if (!disableDebugging) |
| { |
| beginop(OP_debug); |
| opcodes.writeU8(di_local); |
| // FIX: is this a constant pool index? if so, we need to know the constant type... |
| // opcodes.writeU32(index); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, index)); |
| opcodes.writeU8(slot); |
| opcodes.writeU32(linenum); |
| } |
| } |
| } |
| |
| public void OP_debugfile(int index) |
| { |
| if (opcodePass == 1) |
| { |
| if (!disableDebugging) |
| { |
| beginop(OP_debugfile); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, index)); |
| } |
| } |
| } |
| |
| public void OP_jump(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| /* |
| if (opat(1) == OP_jump) |
| { |
| // unreachable |
| return; |
| } |
| */ |
| |
| beginop(OP_jump); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_pushnull() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushnull); |
| } |
| } |
| |
| public void OP_pushundefined() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushundefined); |
| } |
| } |
| |
| public void OP_pushstring(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushstring); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, index)); |
| } |
| } |
| |
| public void OP_pushnamespace(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushnamespace); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_ns, index)); |
| } |
| } |
| |
| public void OP_pushint(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushint); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_int, index)); |
| } |
| } |
| |
| public void OP_pushuint(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushuint); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_uint, index)); |
| } |
| } |
| |
| public void OP_pushdouble(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushdouble); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_double, index)); |
| } |
| } |
| |
| public void OP_pushdecimal(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushdecimal); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_decimal, index)); |
| } |
| } |
| |
| public void OP_getlocal(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_getlocal); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_pushtrue() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushtrue); |
| } |
| } |
| |
| public void OP_pushfalse() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushfalse); |
| } |
| } |
| |
| public void OP_pushnan() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushnan); |
| } |
| } |
| |
| public void OP_pushdnan() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushdnan); |
| } |
| } |
| |
| public void OP_pop() |
| { |
| if (opcodePass == 1) |
| { |
| switch (opat(1)) |
| { |
| case OP_callproperty: |
| setOpcodeAt(1, OP_callpropvoid); |
| return; |
| case OP_callsuper: |
| setOpcodeAt(1, OP_callsupervoid); |
| return; |
| } |
| |
| beginop(OP_pop); |
| } |
| } |
| |
| public void OP_dup() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_dup); |
| } |
| } |
| |
| public void OP_swap() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_swap); |
| } |
| } |
| |
| public void OP_convert_s() |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_coerce_a) |
| rewind(1); |
| |
| switch (opat(1)) |
| { |
| case OP_coerce_s: |
| case OP_convert_s: |
| case OP_pushstring: |
| case OP_typeof: |
| // result is already string |
| return; |
| } |
| |
| if (opat(2) == OP_pushstring && opat(1) == OP_add) |
| { |
| // result must be string, so dont coerce after |
| return; |
| } |
| |
| beginop(OP_convert_s); |
| } |
| } |
| |
| public void OP_esc_xelem() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_esc_xelem); |
| } |
| } |
| |
| public void OP_esc_xattr() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_esc_xattr); |
| } |
| } |
| |
| public void OP_checkfilter() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_checkfilter); |
| } |
| } |
| |
| public void OP_convert_d() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_convert_d); |
| } |
| } |
| |
| public void OP_convert_m() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_convert_m); |
| } |
| } |
| |
| public void OP_convert_m_p(int param) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_convert_m); |
| opcodes.writeU32(param); |
| } |
| } |
| |
| |
| public void OP_convert_b() |
| { |
| if (opcodePass == 1) |
| { |
| switch(opat(1)) |
| { |
| case OP_equals: |
| case OP_strictequals: |
| case OP_not: |
| case OP_greaterthan: |
| case OP_lessthan: |
| case OP_greaterequals: |
| case OP_lessequals: |
| case OP_istype: |
| case OP_istypelate: |
| case OP_instanceof: |
| case OP_deleteproperty: |
| case OP_in: |
| case OP_convert_b: |
| case OP_pushtrue: |
| case OP_pushfalse: |
| // dont need convert |
| return; |
| } |
| |
| beginop(OP_convert_b); |
| } |
| } |
| |
| public void OP_convert_o() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_convert_o); |
| } |
| } |
| |
| public void OP_negate() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_negate); |
| } |
| } |
| |
| public void OP_negate_p(int param) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_negate_p); |
| opcodes.writeU32(param); |
| } |
| } |
| |
| public void OP_negate_i() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_negate_i); |
| } |
| } |
| |
| public void OP_increment() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_increment); |
| } |
| } |
| |
| public void OP_increment_p(int param) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_increment_p); |
| opcodes.writeU32(param); |
| } |
| } |
| |
| public void OP_increment_i() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_increment_i); |
| } |
| } |
| |
| public void OP_inclocal(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_inclocal); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_inclocal_p(int param, int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_inclocal_p); |
| opcodes.writeU32(param); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_kill(int index) |
| { |
| if (opcodePass == 1) |
| { |
| switch(opat(1)) |
| { |
| case OP_returnvalue: |
| case OP_returnvoid: |
| // unreachable |
| return; |
| } |
| |
| beginop(OP_kill); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_inclocal_i(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_inclocal_i); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_decrement() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_decrement); |
| } |
| } |
| |
| public void OP_decrement_p(int param) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_decrement_p); |
| opcodes.writeU32(param); |
| } |
| } |
| |
| public void OP_decrement_i() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_decrement_i); |
| } |
| } |
| |
| public void OP_declocal(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_declocal); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_declocal_p(int param, int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_declocal_p); |
| opcodes.writeU32(param); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_declocal_i(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_declocal_i); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_typeof() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_typeof); |
| } |
| } |
| |
| public void OP_not() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_not); |
| } |
| } |
| |
| public void OP_bitnot() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_bitnot); |
| } |
| } |
| |
| public void OP_setlocal(int index) |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(2) == OP_getlocal && readIntAt(2) == index && |
| opat(1) == OP_increment_i) |
| { |
| rewind(2); |
| OP_inclocal_i(index); |
| return; |
| } |
| |
| if (opat(2) == OP_getlocal && readIntAt(2) == index && |
| opat(1) == OP_increment) |
| { |
| rewind(2); |
| OP_inclocal(index); |
| return; |
| } |
| |
| beginop(OP_setlocal); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_add() |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_coerce_a) |
| rewind(1); |
| beginop(OP_add); |
| } |
| } |
| |
| public void OP_add_p(int param) |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_coerce_a) |
| rewind(1); |
| beginop(OP_add_p); |
| opcodes.writeU32(param); |
| } |
| } |
| |
| public void OP_add_i() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_add_i); |
| } |
| } |
| |
| public void OP_subtract() |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_pushbyte && readByteAt(1) == 1) |
| { |
| rewind(1); |
| OP_decrement(); |
| return; |
| } |
| beginop(OP_subtract); |
| } |
| } |
| |
| public void OP_subtract_p(int param) |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_pushbyte && readByteAt(1) == 1) |
| { |
| rewind(1); |
| OP_decrement_p(param); |
| return; |
| } |
| beginop(OP_subtract_p); |
| opcodes.writeU32(param); |
| } |
| } |
| |
| public void OP_subtract_i() |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_pushbyte && readIntAt(1) == 1) |
| { |
| rewind(1); |
| OP_decrement_i(); |
| return; |
| } |
| beginop(OP_subtract_i); |
| } |
| } |
| |
| public void OP_multiply() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_multiply); |
| } |
| } |
| |
| public void OP_multiply_p(int param) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_multiply_p); |
| opcodes.writeU32(param); |
| } |
| } |
| |
| public void OP_multiply_i() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_multiply_i); |
| } |
| } |
| |
| public void OP_divide() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_divide); |
| } |
| } |
| |
| public void OP_divide_p(int param) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_divide_p); |
| opcodes.writeU32(param); |
| } |
| } |
| |
| public void OP_modulo() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_modulo); |
| } |
| } |
| |
| public void OP_modulo_p(int param) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_modulo_p); |
| opcodes.writeU32(param); |
| } |
| } |
| |
| public void OP_lshift() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_lshift); |
| } |
| } |
| |
| public void OP_rshift() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_rshift); |
| } |
| } |
| |
| public void OP_urshift() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_urshift); |
| } |
| } |
| |
| public void OP_bitand() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_bitand); |
| } |
| } |
| |
| public void OP_bitor() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_bitor); |
| } |
| } |
| |
| public void OP_bitxor() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_bitxor); |
| } |
| } |
| |
| public void OP_equals() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_equals); |
| } |
| } |
| |
| public void OP_strictequals() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_strictequals); |
| } |
| } |
| |
| public void OP_lookupswitch(int defaultPos, int[] casePos, int oldPos, int oldTablePos) |
| { |
| if (opcodePass == 1) |
| { |
| opcodes.mapOffsets(oldPos); |
| beginop(OP_lookupswitch); |
| opcodes.mapOffsets(oldPos+1); |
| opcodes.writeS24(defaultPos); |
| opcodes.writeU32((casePos == null || casePos.length == 0) ? 0 : casePos.length - 1); |
| for (int i = 0, size = casePos.length; i < size; i++) |
| { |
| opcodes.mapOffsets(oldTablePos+3*i); |
| opcodes.writeS24(casePos[i]); |
| } |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(oldPos + 1, oldPos, oldPos + defaultPos); |
| for (int i = 0, size = casePos.length; i < size; i++) |
| { |
| opcodes.updateOffset(oldTablePos + (3 * i), oldPos, oldPos + casePos[i]); |
| } |
| } |
| } |
| |
| public void OP_iftrue(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_convert_b) |
| rewind(1); |
| |
| if (opat(1) == OP_pushtrue) |
| { |
| rewind(1); |
| OP_jump(offset,pos); |
| return; |
| } |
| |
| beginop(OP_iftrue); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_iffalse(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_convert_b) |
| { |
| rewind(1); |
| } |
| |
| if (opat(2) == OP_strictequals && opat(1) == OP_not) |
| { |
| rewind(2); |
| OP_ifstricteq(offset, pos); |
| return; |
| } |
| |
| if (opat(2) == OP_equals && opat(1) == OP_not) |
| { |
| rewind(2); |
| OP_ifeq(offset, pos); |
| return; |
| } |
| |
| if (opat(1) == OP_not) |
| { |
| rewind(1); |
| OP_iftrue(offset, pos); |
| return; |
| } |
| |
| if (opat(1) == OP_pushfalse) |
| { |
| rewind(1); |
| OP_jump(offset, pos); |
| return; |
| } |
| |
| beginop(OP_iffalse); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_ifeq(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_ifeq); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_ifne(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_ifne); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_ifstricteq(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_ifstricteq); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_ifstrictne(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_ifstrictne); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_iflt(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_iflt); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_ifle(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_ifle); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_ifgt(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_ifgt); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_ifge(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_ifge); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_lessthan() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_lessthan); |
| } |
| } |
| |
| public void OP_lessequals() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_lessequals); |
| } |
| } |
| |
| public void OP_greaterthan() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_greaterthan); |
| } |
| } |
| |
| public void OP_greaterequals() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_greaterequals); |
| } |
| } |
| |
| public void OP_newobject(int size) |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_coerce_a && size >= 1) |
| rewind(1); |
| |
| beginop(OP_newobject); |
| opcodes.writeU32(size); |
| } |
| } |
| |
| public void OP_newarray(int size) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_newarray); |
| opcodes.writeU32(size); |
| } |
| } |
| |
| public void OP_getproperty(int index) |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_findpropstrict && readIntAt(1) == pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)) |
| { |
| rewind(1); |
| OP_getlex(index); |
| return; |
| } |
| |
| beginop(OP_getproperty); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_setproperty(int index) |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_coerce_a) |
| rewind(1); |
| |
| beginop(OP_setproperty); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_initproperty(int index) |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_coerce_a) |
| rewind(1); |
| |
| beginop(OP_initproperty); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_getdescendants(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_getdescendants); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_findpropstrict(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_findpropstrict); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_findproperty(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_findproperty); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_finddef(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_finddef); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_getlex(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_getlex); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_nextname() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_nextname); |
| } |
| } |
| |
| public void OP_nextvalue() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_nextvalue); |
| } |
| } |
| |
| public void OP_hasnext() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_hasnext); |
| } |
| } |
| |
| public void OP_hasnext2(int objectRegister, int indexRegister) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_hasnext2); |
| opcodes.writeU32(objectRegister); |
| opcodes.writeU32(indexRegister); |
| } |
| } |
| |
| public void OP_deleteproperty(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_deleteproperty); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_setslot(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_setslot); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_getslot(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_getslot); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_setglobalslot(int index) |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_coerce_a) |
| rewind(1); |
| |
| beginop(OP_setglobalslot); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_getglobalslot(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_getglobalslot); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_call(int size) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_call); |
| opcodes.writeU32(size); |
| } |
| } |
| |
| public void OP_construct(int size) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_construct); |
| opcodes.writeU32(size); |
| } |
| } |
| |
| public void OP_applytype(int size) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_applytype); |
| opcodes.writeU32(size); |
| } |
| } |
| |
| public void OP_newfunction(int id) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_newfunction); |
| opcodes.writeU32(methodInfo.getIndex(poolIndex, id)); |
| } |
| } |
| |
| public void OP_newclass(int id) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_newclass); |
| opcodes.writeU32(classInfo.getIndex(poolIndex, id)); |
| } |
| } |
| |
| public void OP_callstatic(int id, int argc) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_callstatic); |
| opcodes.writeU32(methodInfo.getIndex(poolIndex, id)); |
| opcodes.writeU32(argc); |
| } |
| } |
| |
| public void OP_callmethod(int id, int argc) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_callmethod); |
| opcodes.writeU32(methodInfo.getIndex(poolIndex, id)); |
| opcodes.writeU32(argc); |
| } |
| } |
| |
| public void OP_callproperty(int index, int argc) |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_coerce_a) |
| rewind(1); |
| |
| beginop(OP_callproperty); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| opcodes.writeU32(argc); |
| } |
| } |
| |
| public void OP_callproplex(int index, int argc) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_callproplex); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| opcodes.writeU32(argc); |
| } |
| } |
| |
| public void OP_constructprop(int index, int argc) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_constructprop); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| opcodes.writeU32(argc); |
| } |
| } |
| |
| public void OP_callsuper(int index, int argc) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_callsuper); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| opcodes.writeU32(argc); |
| } |
| } |
| |
| public void OP_getsuper(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_getsuper); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_setsuper(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_setsuper); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_constructsuper(int argc) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_constructsuper); |
| opcodes.writeU32(argc); |
| } |
| } |
| |
| public void OP_pushshort(int n) |
| { |
| if (opcodePass == 1) |
| { |
| if (peepHole && n >= -128 && n <= 127) |
| { |
| OP_pushbyte(n); |
| return; |
| } |
| beginop(OP_pushshort); |
| opcodes.writeU32(n); |
| } |
| } |
| |
| public void OP_astype(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_astype); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_astypelate() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_astypelate); |
| } |
| } |
| |
| public void OP_coerce(int index) |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_coerce && readIntAt(1) == pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)) |
| { |
| // second coerce to same type is redundant |
| return; |
| } |
| |
| beginop(OP_coerce); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_coerce_b() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_coerce_b); |
| } |
| } |
| |
| public void OP_coerce_o() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_coerce_o); |
| } |
| } |
| |
| public void OP_coerce_a() |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_coerce_a) |
| return; |
| beginop(OP_coerce_a); |
| } |
| } |
| |
| public void OP_coerce_i() |
| { |
| if (opcodePass == 1) |
| { |
| switch (opat(1)) |
| { |
| case OP_coerce_i : |
| case OP_convert_i : |
| case OP_increment_i : |
| case OP_decrement_i : |
| case OP_pushbyte : |
| case OP_pushshort : |
| case OP_pushint : |
| case OP_bitand: |
| case OP_bitor: |
| case OP_bitxor: |
| case OP_lshift: |
| case OP_rshift: |
| case OP_add_i: |
| case OP_subtract_i: |
| case OP_multiply_i: |
| case OP_bitnot: |
| // coerce is redundant |
| return; |
| } |
| beginop(OP_coerce_i); |
| } |
| } |
| |
| public void OP_coerce_u() |
| { |
| if (opcodePass == 1) |
| { |
| switch (opat(1)) |
| { |
| case OP_coerce_u: |
| case OP_convert_u: |
| case OP_urshift: |
| // redundant coerce |
| return; |
| } |
| beginop(OP_coerce_u); |
| } |
| } |
| |
| public void OP_coerce_d() |
| { |
| if (opcodePass == 1) |
| { |
| switch (opat(1)) |
| { |
| case OP_subtract : |
| case OP_multiply : |
| case OP_divide : |
| case OP_modulo : |
| case OP_increment : |
| case OP_decrement : |
| case OP_inclocal : |
| case OP_declocal : |
| case OP_coerce_d : |
| case OP_convert_d : |
| // coerce is redundant |
| return; |
| } |
| beginop(OP_coerce_d); |
| } |
| } |
| |
| public void OP_coerce_s() |
| { |
| if (opcodePass == 1) |
| { |
| switch (opat(1)) |
| { |
| case OP_coerce_s: |
| case OP_convert_s: |
| case OP_pushstring: |
| case OP_typeof: |
| // result is already string |
| return; |
| } |
| |
| if (opat(2) == OP_pushstring && opat(1) == OP_add) |
| { |
| // result must be string, so dont coerce after |
| return; |
| } |
| |
| beginop(OP_coerce_s); |
| } |
| } |
| |
| public void OP_istype(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_istype); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| } |
| } |
| |
| public void OP_istypelate() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_istypelate); |
| } |
| } |
| |
| public void OP_pushbyte(int n) |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(1) == OP_pushbyte && readByteAt(1) == n || |
| opat(1) == OP_dup && opat(2) == OP_pushbyte && readByteAt(2) == n ) |
| { |
| OP_dup(); |
| return; |
| } |
| beginop(OP_pushbyte); |
| opcodes.writeU8(n); |
| } |
| } |
| |
| public void OP_getscopeobject(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_getscopeobject); |
| opcodes.writeU8(index); |
| } |
| } |
| |
| public void OP_pushscope() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushscope); |
| } |
| } |
| |
| public void OP_popscope() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_popscope); |
| } |
| } |
| |
| public void OP_convert_i() |
| { |
| if (opcodePass == 1) |
| { |
| switch (opat(1)) |
| { |
| case OP_convert_i: |
| case OP_coerce_i: |
| case OP_bitand: |
| case OP_bitor: |
| case OP_bitxor: |
| case OP_lshift: |
| case OP_rshift: |
| case OP_add_i: |
| case OP_subtract_i: |
| case OP_increment_i: |
| case OP_decrement_i: |
| case OP_multiply_i: |
| case OP_pushbyte: |
| case OP_pushshort: |
| case OP_pushint: |
| return; |
| } |
| |
| beginop(OP_convert_i); |
| } |
| } |
| |
| public void OP_convert_u() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_convert_u); |
| } |
| } |
| |
| public void OP_throw() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_throw); |
| } |
| } |
| |
| public void OP_instanceof() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_instanceof); |
| } |
| } |
| |
| public void OP_in() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_in); |
| } |
| } |
| |
| public void OP_dxns(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_dxns); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_string, index)); |
| } |
| } |
| |
| public void OP_dxnslate() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_dxnslate); |
| } |
| } |
| |
| public void OP_ifnlt(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_ifnlt); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_ifnle(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_ifnle); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_ifngt(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_ifngt); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_ifnge(int offset, int pos) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_ifnge); |
| opcodes.writeS24(offset); |
| opcodes.mapOffsets(pos); |
| } |
| else if (opcodePass == 2) |
| { |
| opcodes.updateOffset(pos + offset); |
| } |
| } |
| |
| public void OP_pushwith() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushwith); |
| } |
| } |
| |
| public void OP_newactivation() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_newactivation); |
| } |
| } |
| |
| public void OP_newcatch(int index) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_newcatch); |
| opcodes.writeU32(index); |
| } |
| } |
| |
| public void OP_deldescendants() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_deldescendants); |
| } |
| } |
| |
| public void OP_getglobalscope() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_getglobalscope); |
| } |
| } |
| |
| public void OP_getlocal0() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_getlocal0); |
| } |
| } |
| |
| public void OP_getlocal1() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_getlocal1); |
| } |
| } |
| |
| public void OP_getlocal2() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_getlocal2); |
| } |
| } |
| |
| public void OP_getlocal3() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_getlocal3); |
| } |
| } |
| |
| public void OP_setlocal0() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_setlocal0); |
| } |
| } |
| |
| public void OP_setlocal1() |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(2) == OP_getlocal1 && opat(1) == OP_increment_i) |
| { |
| rewind(2); |
| OP_inclocal_i(1); |
| return; |
| } |
| if (opat(2) == OP_getlocal1 && opat(1) == OP_increment) |
| { |
| rewind(2); |
| OP_inclocal(1); |
| return; |
| } |
| beginop(OP_setlocal1); |
| } |
| } |
| |
| public void OP_setlocal2() |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(2) == OP_getlocal2 && opat(1) == OP_increment_i) |
| { |
| rewind(2); |
| OP_inclocal_i(2); |
| return; |
| } |
| if (opat(2) == OP_getlocal2 && opat(1) == OP_increment) |
| { |
| rewind(2); |
| OP_inclocal(2); |
| return; |
| } |
| beginop(OP_setlocal2); |
| } |
| } |
| |
| public void OP_setlocal3() |
| { |
| if (opcodePass == 1) |
| { |
| if (opat(2) == OP_getlocal3 && opat(1) == OP_increment_i) |
| { |
| rewind(2); |
| OP_inclocal_i(3); |
| return; |
| } |
| if (opat(2) == OP_getlocal3 && opat(1) == OP_increment) |
| { |
| rewind(2); |
| OP_inclocal(3); |
| return; |
| } |
| beginop(OP_setlocal3); |
| } |
| } |
| |
| public void OP_label() |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_label); |
| } |
| } |
| |
| public void OP_pushconstant(int id) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_pushuninitialized); |
| opcodes.writeU32(id); |
| } |
| } |
| |
| public void OP_callsupervoid(int index, int argc) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_callsupervoid); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| opcodes.writeU32(argc); |
| } |
| } |
| |
| public void OP_callpropvoid(int index, int argc) |
| { |
| if (opcodePass == 1) |
| { |
| beginop(OP_callpropvoid); |
| opcodes.writeU32(pool.history.getIndex(poolIndex, IndexHistory.cp_mn, index)); |
| opcodes.writeU32(argc); |
| } |
| } |
| |
| public void OP_li8() |
| { |
| if( opcodePass == 1 ) |
| { |
| beginop(OP_li8); |
| } |
| } |
| |
| public void OP_li16() |
| { |
| if( opcodePass == 1 ) |
| { |
| beginop(OP_li16); |
| } |
| } |
| |
| public void OP_li32() |
| { |
| if( opcodePass == 1 ) |
| { |
| beginop(OP_li32); |
| } |
| } |
| |
| public void OP_lf32() |
| { |
| if( opcodePass == 1 ) |
| { |
| beginop(OP_lf32); |
| } |
| } |
| |
| public void OP_lf64() |
| { |
| if( opcodePass == 1 ) |
| { |
| beginop(OP_lf64); |
| } |
| } |
| |
| public void OP_si8() |
| { |
| if( opcodePass == 1 ) |
| { |
| beginop(OP_si8); |
| } |
| } |
| |
| public void OP_si16() |
| { |
| if( opcodePass == 1 ) |
| { |
| beginop(OP_si16); |
| } |
| } |
| |
| public void OP_si32() |
| { |
| if( opcodePass == 1 ) |
| { |
| beginop(OP_si32); |
| } |
| } |
| |
| public void OP_sf32() |
| { |
| if( opcodePass == 1 ) |
| { |
| beginop(OP_sf32); |
| } |
| } |
| |
| public void OP_sf64() |
| { |
| if( opcodePass == 1 ) |
| { |
| beginop(OP_sf64); |
| } |
| } |
| |
| public void OP_sxi1() |
| { |
| if( opcodePass == 1 ) |
| { |
| beginop(OP_sxi1); |
| } |
| } |
| |
| public void OP_sxi8() |
| { |
| if( opcodePass == 1 ) |
| { |
| beginop(OP_sxi8); |
| } |
| } |
| |
| public void OP_sxi16() |
| { |
| if( opcodePass == 1 ) |
| { |
| beginop(OP_sxi16); |
| } |
| } |
| |
| class ByteArrayPool2 extends ByteArrayPool |
| { |
| ByteArrayPool2(int[] sizes) |
| { |
| this.sizes = sizes; |
| indexes = new HashMap<Integer, Integer>(); |
| } |
| |
| int size = 0; |
| |
| private int[] sizes; |
| |
| private Map<Integer, Integer> indexes; |
| |
| int addByteArray(int poolIndex, int oldIndex, BytecodeBuffer ba) |
| { |
| int index = this.contains(ba, 0, ba.size()); |
| if( index == -1 ) |
| { |
| index = this.store(ba, 0, ba.size()); |
| size += ba.size(); |
| } |
| // ByteArrayPool is 1 based, we want zero based for metadataInfos |
| indexes.put(IntegerPool.getNumber(calcIndex(poolIndex, oldIndex)), IntegerPool.getNumber(index-1)); |
| return index; |
| } |
| |
| private int calcIndex(int poolIndex, int oldIndex) |
| { |
| int newIndex = 0; |
| for (int i = 0; i < poolIndex; i++) |
| { |
| newIndex += sizes[i]; |
| } |
| newIndex += oldIndex; |
| |
| return newIndex; |
| } |
| |
| int getIndex(int poolIndex, int oldIndex) |
| { |
| int newIndex = calcIndex(poolIndex, oldIndex); |
| Integer i = indexes.get(IntegerPool.getNumber(newIndex)); |
| return i != null ? i.intValue() : -1; |
| } |
| |
| int size() |
| { |
| return size; |
| } |
| |
| void writeTo(BytecodeBuffer b) |
| { |
| Map sortedMap = new TreeMap(); |
| |
| for (Iterator i = map.keySet().iterator(); i.hasNext();) |
| { |
| Object key = i.next(); // ByteArray |
| Object value = map.get(key); // Integer |
| sortedMap.put(value, key); |
| } |
| |
| b.writeU32((sortedMap.size() == 0) ? 0 : sortedMap.size() ); |
| |
| for (Iterator i = sortedMap.keySet().iterator(); i.hasNext();) |
| { |
| Integer index = (Integer) i.next(); |
| ByteArray a = (ByteArray) sortedMap.get(index); |
| b.writeBytes(a.b, a.start, a.end); |
| } |
| } |
| |
| void writeTo(OutputStream os) throws java.io.IOException |
| { |
| BytecodeBuffer b = new BytecodeBuffer(size()); |
| writeTo(b); |
| b.writeTo(os); |
| } |
| } |
| |
| class BytecodeBuffer2 extends BytecodeBuffer |
| { |
| BytecodeBuffer2(int estimatedSize, int[] sizes) |
| { |
| super(estimatedSize); |
| this.sizes = sizes; |
| this.estimatedSize = estimatedSize; |
| } |
| |
| private int[] sizes; |
| int estimatedSize; |
| |
| int getIndex(int poolIndex, int oldIndex) |
| { |
| int newIndex = 0; |
| for (int i = 0; i < poolIndex; i++) |
| { |
| newIndex += sizes[i]; |
| } |
| newIndex += oldIndex; |
| |
| return newIndex; |
| } |
| } |
| |
| class BytecodeBuffer3 extends BytecodeBuffer |
| { |
| BytecodeBuffer3(Decoder[] decoders, int estimatedSize) |
| { |
| super(estimatedSize); |
| offsets = new HashMap<Integer, Integer>(); |
| this.decoders = decoders; |
| } |
| |
| Map<Integer, Integer> offsets; |
| Decoder[] decoders; |
| |
| void mapOffsets(long offset) |
| { |
| Integer oldPos = IntegerPool.getNumber((int) offset); |
| Integer newPos = IntegerPool.getNumber(size()); |
| |
| offsets.put(IntegerPool.getNumber(oldPos), IntegerPool.getNumber(newPos)); |
| } |
| |
| long getOffset(long offset) |
| { |
| Integer i = offsets.get(IntegerPool.getNumber((int) offset)); |
| if (i != null) |
| { |
| return i.intValue(); |
| } |
| else |
| { |
| System.out.println("getOffset: can't match " + offset + " with a new offset "); |
| System.out.println(offsets); |
| return 0; |
| } |
| } |
| |
| void updateOffset(long offset) |
| { |
| Integer i = offsets.get(IntegerPool.getNumber((int) offset)); |
| Integer p = offsets.get(IntegerPool.getNumber(decoders[poolIndex].pos())); |
| |
| if (i != null && p != null) |
| { |
| writeS24(p-3, i-p); |
| } |
| else |
| { |
| /* cn: temporarily disable this warning. The warnings that are being generated are |
| * for jumps which are part of unreachable code, but I haven't found where those |
| * unecessary jumps are being genreated within codeGenerator yet. Disabling to redeuce |
| * annoyance in the short term, |
| * bug #149141 remains open until the root cause is found and removed |
| if (i == null) |
| System.out.println("updateOffset1: can't match i " + offset + " with a new offset"); |
| if (p == null) |
| System.out.println("updateOffset1: can't match p " + decoders[poolIndex].pos() + " with a new offset"); |
| System.out.println(offsets); |
| */ |
| } |
| } |
| |
| void updateOffset(long oldOffsetPos, long oldPos, long oldTarget) |
| { |
| Integer i = offsets.get(IntegerPool.getNumber((int) oldTarget)); |
| Integer p = offsets.get(IntegerPool.getNumber((int) oldPos)); |
| Integer s = offsets.get(IntegerPool.getNumber((int) oldOffsetPos)); |
| |
| if (i != null && p != null && s != null) |
| { |
| writeS24(s, i-p); |
| } |
| else |
| { |
| if (i == null) |
| System.out.println("updateOffset2: can't match i " + oldTarget + " with a new offset"); |
| if (p == null) |
| System.out.println("updateOffset2: can't match p " + oldPos + " with a new offset"); |
| if (s == null) |
| System.out.println("updateOffset2: can't match s " + oldOffsetPos + " with a new offset"); |
| System.out.println(offsets); |
| } |
| } |
| |
| public void clear() |
| { |
| super.clear(); |
| offsets.clear(); |
| } |
| } |
| } |
| |