001 /* 002 * Copyright 2010-2015 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.kotlin.codegen.optimization.common; 018 019 import org.jetbrains.annotations.NotNull; 020 import org.jetbrains.annotations.Nullable; 021 import org.jetbrains.org.objectweb.asm.Opcodes; 022 import org.jetbrains.org.objectweb.asm.Type; 023 import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; 024 import org.jetbrains.org.objectweb.asm.tree.LdcInsnNode; 025 import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException; 026 import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter; 027 import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue; 028 029 public class OptimizationBasicInterpreter extends BasicInterpreter { 030 private static final BasicValue BOOLEAN_VALUE = new BasicValue(Type.BOOLEAN_TYPE); 031 private static final BasicValue CHAR_VALUE = new BasicValue(Type.CHAR_TYPE); 032 private static final BasicValue BYTE_VALUE = new BasicValue(Type.BYTE_TYPE); 033 private static final BasicValue SHORT_VALUE = new BasicValue(Type.SHORT_TYPE); 034 035 @Override 036 @Nullable 037 public BasicValue newValue(@Nullable Type type) { 038 if (type == null) { 039 return super.newValue(null); 040 } 041 042 switch (type.getSort()) { 043 case Type.VOID: 044 return null; 045 case Type.BOOLEAN: 046 return BOOLEAN_VALUE; 047 case Type.CHAR: 048 return CHAR_VALUE; 049 case Type.BYTE: 050 return BYTE_VALUE; 051 case Type.SHORT: 052 return SHORT_VALUE; 053 case Type.OBJECT: 054 return new BasicValue(type); 055 default: 056 return super.newValue(type); 057 } 058 } 059 060 @Override 061 public BasicValue newOperation(@NotNull AbstractInsnNode insn) throws AnalyzerException { 062 if (insn.getOpcode() == Opcodes.LDC) { 063 Object cst = ((LdcInsnNode) insn).cst; 064 065 if (cst instanceof Long) { 066 return BasicValue.LONG_VALUE; 067 } 068 069 if (cst instanceof Boolean || 070 cst instanceof Integer || 071 cst instanceof Short || 072 cst instanceof Byte || 073 cst instanceof Character) { 074 return BasicValue.INT_VALUE; 075 } 076 077 if (cst instanceof Float) { 078 return BasicValue.FLOAT_VALUE; 079 } 080 081 if (cst instanceof Double) { 082 return BasicValue.DOUBLE_VALUE; 083 } 084 } 085 086 return super.newOperation(insn); 087 } 088 089 @NotNull 090 @Override 091 public BasicValue merge( 092 @NotNull BasicValue v, @NotNull BasicValue w 093 ) { 094 if (!v.equals(w)) { 095 if (v == BasicValue.UNINITIALIZED_VALUE || w == BasicValue.UNINITIALIZED_VALUE) { 096 return BasicValue.UNINITIALIZED_VALUE; 097 } 098 099 // if merge of two references then `lub` is java/lang/Object 100 // arrays also are BasicValues with reference type's 101 if (v.getType().getSort() == Type.OBJECT && w.getType().getSort() == Type.OBJECT) { 102 return BasicValue.REFERENCE_VALUE; 103 } 104 105 assert v.getType().getSort() != Type.ARRAY && w.getType().getSort() != Type.ARRAY : "There should not be arrays"; 106 107 // if merge of something can be stored in int var (int, char, boolean, byte, character) 108 if (v.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE && 109 w.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE) { 110 return BasicValue.INT_VALUE; 111 } 112 113 return BasicValue.UNINITIALIZED_VALUE; 114 } 115 return v; 116 } 117 }