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 @NotNull 061 @Override 062 public BasicValue merge( 063 @NotNull BasicValue v, @NotNull BasicValue w 064 ) { 065 if (v == BasicValue.UNINITIALIZED_VALUE || w == BasicValue.UNINITIALIZED_VALUE) { 066 return BasicValue.UNINITIALIZED_VALUE; 067 } 068 // Objects must be equal, others can just have the same sort 069 if (v.getType().getSort() == w.getType().getSort() && (v.getType().getSort() != Type.OBJECT || v.equals(w))) { 070 return v; 071 } 072 073 // if merge of two references then `lub` is java/lang/Object 074 // arrays also are BasicValues with reference type's 075 if (v.getType().getSort() == Type.OBJECT && w.getType().getSort() == Type.OBJECT) { 076 return BasicValue.REFERENCE_VALUE; 077 } 078 079 assert v.getType().getSort() != Type.ARRAY && w.getType().getSort() != Type.ARRAY : "There should not be arrays"; 080 081 // if merge of something can be stored in int var (int, char, boolean, byte, character) 082 if (v.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE && 083 w.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE) { 084 return BasicValue.INT_VALUE; 085 } 086 087 return BasicValue.UNINITIALIZED_VALUE; 088 } 089 }