massive refactoring of CodegenUtil

- generation method names standartized on genXXX
- many methods moved to newly created AsmUtil
- some methods moved to CodegenContext
- got rid of almost trivial StubCodegen
This commit is contained in:
Alex Tkachman
2012-09-20 20:19:01 +03:00
parent c355e182e8
commit bc1a4a1fe9
31 changed files with 663 additions and 635 deletions
@@ -0,0 +1,420 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed 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 org.jetbrains.jet.codegen;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Label;
import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.CodegenUtil.isInterface;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
/**
* @author alex.tkachman
*/
public class AsmUtil {
private static final Set<ClassDescriptor> PRIMITIVE_NUMBER_CLASSES = Sets.newHashSet(
JetStandardLibrary.getInstance().getByte(),
JetStandardLibrary.getInstance().getShort(),
JetStandardLibrary.getInstance().getInt(),
JetStandardLibrary.getInstance().getLong(),
JetStandardLibrary.getInstance().getFloat(),
JetStandardLibrary.getInstance().getDouble(),
JetStandardLibrary.getInstance().getChar()
);
private static final int NO_FLAG_LOCAL = 0;
private static final int NO_FLAG_PACKAGE_PRIVATE = 0;
@NotNull
private static final Map<Visibility, Integer> visibilityToAccessFlag = ImmutableMap.<Visibility, Integer>builder()
.put(Visibilities.PRIVATE, ACC_PRIVATE)
.put(Visibilities.PROTECTED, ACC_PROTECTED)
.put(Visibilities.PUBLIC, ACC_PUBLIC)
.put(Visibilities.INTERNAL, ACC_PUBLIC)
.put(Visibilities.LOCAL, NO_FLAG_LOCAL)
.put(JavaDescriptorResolver.PACKAGE_VISIBILITY, NO_FLAG_PACKAGE_PRIVATE)
.build();
public static final String RECEIVER$0 = "receiver$0";
public static final String THIS$0 = "this$0";
private static final String STUB_EXCEPTION = "java/lang/RuntimeException";
private static final String STUB_EXCEPTION_MESSAGE = "Stubs are for compiler only, do not add them to runtime classpath";
private AsmUtil() {
}
public static Type boxType(Type asmType) {
JvmPrimitiveType jvmPrimitiveType = JvmPrimitiveType.getByAsmType(asmType);
if (jvmPrimitiveType != null) {
return jvmPrimitiveType.getWrapper().getAsmType();
}
else {
return asmType;
}
}
public static boolean isIntPrimitive(Type type) {
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE;
}
public static boolean isNumberPrimitive(Type type) {
return isIntPrimitive(type) || type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE || type == Type.LONG_TYPE;
}
public static boolean isPrimitive(Type type) {
return type.getSort() != Type.OBJECT && type.getSort() != Type.ARRAY;
}
public static boolean isPrimitiveNumberClassDescriptor(DeclarationDescriptor descriptor) {
if (!(descriptor instanceof ClassDescriptor)) {
return false;
}
return PRIMITIVE_NUMBER_CLASSES.contains(descriptor);
}
public static Type correctElementType(Type type) {
String internalName = type.getInternalName();
assert internalName.charAt(0) == '[';
return Type.getType(internalName.substring(1));
}
public static Type unboxType(final Type type) {
JvmPrimitiveType jvmPrimitiveType = JvmPrimitiveType.getByWrapperAsmType(type);
if (jvmPrimitiveType != null) {
return jvmPrimitiveType.getAsmType();
}
else {
throw new UnsupportedOperationException("Unboxing: " + type);
}
}
//TODO: move mapping logic to front-end java
public static int getVisibilityAccessFlag(@NotNull MemberDescriptor descriptor) {
Integer specialCase = specialCaseVisibility(descriptor);
if (specialCase != null) {
return specialCase;
}
Integer defaultMapping = visibilityToAccessFlag.get(descriptor.getVisibility());
if (defaultMapping == null) {
throw new IllegalStateException(descriptor.getVisibility() + " is not a valid visibility in backend.");
}
return defaultMapping;
}
@Nullable
private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) {
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
if (isInterface(containingDeclaration)) {
return ACC_PUBLIC;
}
Visibility memberVisibility = memberDescriptor.getVisibility();
if (memberVisibility != Visibilities.PRIVATE) {
return null;
}
if (isClassObject(containingDeclaration)) {
return NO_FLAG_PACKAGE_PRIVATE;
}
if (memberDescriptor instanceof ConstructorDescriptor) {
ClassKind kind = ((ClassDescriptor) containingDeclaration).getKind();
if (kind == ClassKind.OBJECT) {
//TODO: should be NO_FLAG_PACKAGE_PRIVATE
// see http://youtrack.jetbrains.com/issue/KT-2700
return ACC_PUBLIC;
}
else if (kind == ClassKind.ENUM_ENTRY) {
return NO_FLAG_PACKAGE_PRIVATE;
}
else if (kind == ClassKind.ENUM_CLASS) {
//TODO: should be ACC_PRIVATE
// see http://youtrack.jetbrains.com/issue/KT-2680
return ACC_PROTECTED;
}
}
if (containingDeclaration instanceof NamespaceDescriptor) {
return ACC_PUBLIC;
}
return null;
}
private static Type stringValueOfOrStringBuilderAppendType(Type type) {
final int sort = type.getSort();
return sort == Type.OBJECT || sort == Type.ARRAY
? AsmTypeConstants.OBJECT_TYPE
: sort == Type.BYTE || sort == Type.SHORT ? Type.INT_TYPE : type;
}
public static void genThrow(MethodVisitor mv, String exception, String message) {
InstructionAdapter iv = new InstructionAdapter(mv);
iv.anew(Type.getObjectType(exception));
iv.dup();
iv.aconst(message);
iv.invokespecial(exception, "<init>", "(Ljava/lang/String;)V");
iv.athrow();
}
public static void genMethodThrow(MethodVisitor mv, String exception, String message) {
mv.visitCode();
genThrow(mv, exception, message);
mv.visitMaxs(-1, -1);
mv.visitEnd();
}
public static void genClosureFields(CalculatedClosure closure, ClassBuilder v, JetTypeMapper typeMapper) {
final ClassifierDescriptor captureThis = closure.getCaptureThis();
final int access = ACC_PUBLIC | ACC_SYNTHETIC | ACC_FINAL;
if (captureThis != null) {
v.newField(null, access, THIS$0, typeMapper.mapType(captureThis).getDescriptor(), null,
null);
}
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
if (captureReceiver != null) {
v.newField(null, access, RECEIVER$0, typeMapper.mapType(captureReceiver).getDescriptor(),
null, null);
}
final List<Pair<String, Type>> fields = closure.getRecordedFields();
for (Pair<String, Type> field : fields) {
v.newField(null, access, field.first, field.second.getDescriptor(), null, null);
}
}
public static void genInitSingletonField(Type classAsmType, InstructionAdapter iv) {
iv.anew(classAsmType);
iv.dup();
iv.invokespecial(classAsmType.getInternalName(), "<init>", "()V");
iv.putstatic(classAsmType.getInternalName(), JvmAbi.INSTANCE_FIELD, classAsmType.getDescriptor());
}
public static void genStringBuilderConstructor(InstructionAdapter v) {
v.visitTypeInsn(NEW, "java/lang/StringBuilder");
v.dup();
v.invokespecial("java/lang/StringBuilder", "<init>", "()V");
}
public static void genInvokeAppendMethod(InstructionAdapter v, Type type) {
type = stringValueOfOrStringBuilderAppendType(type);
v.invokevirtual("java/lang/StringBuilder", "append", "(" + type.getDescriptor() + ")Ljava/lang/StringBuilder;");
}
public static StackValue genToString(InstructionAdapter v, StackValue receiver) {
final Type type = stringValueOfOrStringBuilderAppendType(receiver.type);
receiver.put(type, v);
v.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;");
return StackValue.onStack(JAVA_STRING_TYPE);
}
static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type) {
if (type.getSort() == Type.ARRAY) {
final Type elementType = correctElementType(type);
if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
iv.invokestatic("java/util/Arrays", "hashCode", "([Ljava/lang/Object;)I");
}
else {
iv.invokestatic("java/util/Arrays", "hashCode", "(" + type.getDescriptor() + ")I");
}
}
else if (type.getSort() == Type.OBJECT) {
iv.invokevirtual("java/lang/Object", "hashCode", "()I");
}
else if (type.getSort() == Type.LONG) {
genLongHashCode(mv, iv);
}
else if (type.getSort() == Type.DOUBLE) {
iv.invokestatic("java/lang/Double", "doubleToLongBits", "(D)J");
genLongHashCode(mv, iv);
}
else if (type.getSort() == Type.FLOAT) {
iv.invokestatic("java/lang/Float", "floatToIntBits", "(F)I");
}
else if (type.getSort() == Type.BOOLEAN) {
Label end = new Label();
iv.dup();
iv.ifeq(end);
iv.pop();
iv.iconst(1);
iv.mark(end);
}
else { // byte short char int
// do nothing
}
}
private static void genLongHashCode(MethodVisitor mv, InstructionAdapter iv) {
iv.dup2();
iv.iconst(32);
iv.ushr(Type.LONG_TYPE);
iv.xor(Type.LONG_TYPE);
mv.visitInsn(L2I);
}
static StackValue compareExpressionsOnStack(InstructionAdapter v, IElementType opToken, Type operandType) {
if (operandType.getSort() == Type.OBJECT) {
v.invokeinterface("java/lang/Comparable", "compareTo", "(Ljava/lang/Object;)I");
v.iconst(0);
operandType = Type.INT_TYPE;
}
return StackValue.cmp(opToken, operandType);
}
static StackValue genNullSafeEquals(
InstructionAdapter v,
IElementType opToken,
boolean leftNullable,
boolean rightNullable
) {
if (!leftNullable) {
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
if (opToken == JetTokens.EXCLEQ) {
genInvertBoolean(v);
}
}
else {
if (rightNullable) {
v.dup2(); // left right left right
Label rightNull = new Label();
v.ifnull(rightNull);
Label leftNull = new Label();
v.ifnull(leftNull);
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
genInvertBoolean(v);
}
Label end = new Label();
v.goTo(end);
v.mark(rightNull);
// left right left
Label bothNull = new Label();
v.ifnull(bothNull);
v.mark(leftNull);
v.pop2();
v.iconst(opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ ? 1 : 0);
v.goTo(end);
v.mark(bothNull);
v.pop2();
v.iconst(opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ ? 0 : 1);
v.mark(end);
}
else {
v.dup2(); // left right left right
v.pop();
Label leftNull = new Label();
v.ifnull(leftNull);
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
genInvertBoolean(v);
}
Label end = new Label();
v.goTo(end);
// left right
v.mark(leftNull);
v.pop2();
v.iconst(opToken == JetTokens.EXCLEQ ? 1 : 0);
v.mark(end);
}
}
return StackValue.onStack(Type.BOOLEAN_TYPE);
}
static void genInvertBoolean(InstructionAdapter v) {
v.iconst(1);
v.xor(Type.INT_TYPE);
}
public static StackValue genEqualsForExpressionsOnStack(
InstructionAdapter v,
IElementType opToken,
Type leftType,
Type rightType,
boolean leftNullable,
boolean rightNullable
) {
if ((isNumberPrimitive(leftType) || leftType.getSort() == Type.BOOLEAN) && leftType == rightType) {
return compareExpressionsOnStack(v, opToken, leftType);
}
else {
if (opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) {
return StackValue.cmp(opToken, leftType);
}
else {
return genNullSafeEquals(v, opToken, leftNullable, rightNullable);
}
}
}
public static Type genIncrement(Type expectedType, int myDelta, InstructionAdapter v) {
if (expectedType == Type.LONG_TYPE) {
//noinspection UnnecessaryBoxing
v.lconst(myDelta);
}
else if (expectedType == Type.FLOAT_TYPE) {
//noinspection UnnecessaryBoxing
v.fconst(myDelta);
}
else if (expectedType == Type.DOUBLE_TYPE) {
//noinspection UnnecessaryBoxing
v.dconst(myDelta);
}
else {
v.iconst(myDelta);
expectedType = Type.INT_TYPE;
}
v.add(expectedType);
return expectedType;
}
public static Type genNegate(Type expectedType, InstructionAdapter v) {
if (expectedType == Type.BYTE_TYPE || expectedType == Type.SHORT_TYPE || expectedType == Type.CHAR_TYPE) {
expectedType = Type.INT_TYPE;
}
v.neg(expectedType);
return expectedType;
}
public static void genStubThrow(MethodVisitor mv) {
genThrow(mv, STUB_EXCEPTION, STUB_EXCEPTION_MESSAGE);
}
public static void genStubCode(MethodVisitor mv) {
genMethodThrow(mv, STUB_EXCEPTION, STUB_EXCEPTION_MESSAGE);
}
}
@@ -34,8 +34,8 @@ import java.util.Collections;
import java.util.List;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.CodegenUtil.generateMethodThrow;
import static org.jetbrains.jet.codegen.CodegenUtil.getVisibilityAccessFlag;
import static org.jetbrains.jet.codegen.AsmUtil.genMethodThrow;
import static org.jetbrains.jet.codegen.AsmUtil.getVisibilityAccessFlag;
/**
* @author max
@@ -89,7 +89,7 @@ public abstract class ClassBodyCodegen extends GenerationStateAware {
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
CodegenUtil.generateFunctionOrProperty(state, (JetTypeParameterListOwner) declaration, context, v);
context.genFunctionOrProperty(state, (JetTypeParameterListOwner) declaration, v);
}
}
@@ -146,7 +146,7 @@ public abstract class ClassBodyCodegen extends GenerationStateAware {
// generates stub 'remove' function for subclasses of Iterator to be compatible with java.util.Iterator
if (DescriptorUtils.isIteratorWithoutRemoveImpl(descriptor)) {
final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "remove", "()V", null, null);
generateMethodThrow(mv, "java/lang/UnsupportedOperationException", "Mutating method called on a Kotlin Iterator");
genMethodThrow(mv, "java/lang/UnsupportedOperationException", "Mutating method called on a Kotlin Iterator");
}
}
}
@@ -28,6 +28,8 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import javax.inject.Inject;
import java.util.*;
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive;
/**
* @author max
* @author alex.tkachman
@@ -114,7 +116,7 @@ public final class ClassFileFactory extends GenerationStateAware {
public ClassBuilder forClassImplementation(ClassDescriptor aClass) {
Type type = state.getTypeMapper().mapType(aClass.getDefaultType(), JetTypeMapperMode.IMPL);
if (CodegenUtil.isPrimitive(type)) {
if (isPrimitive(type)) {
throw new IllegalStateException("Codegen for primitive type is not possible: " + aClass);
}
return newVisitor(type.getInternalName() + ".class");
@@ -49,6 +49,7 @@ import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.classNameForAnonymousClass;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun;
@@ -108,7 +109,7 @@ public class ClosureCodegen extends GenerationStateAware {
generateConstInstance(fun, cv);
}
generateClosureFields(closure, cv, state.getTypeMapper());
genClosureFields(closure, cv, state.getTypeMapper());
cv.done();
@@ -122,11 +123,11 @@ public class ClosureCodegen extends GenerationStateAware {
cv.newField(fun, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, JvmAbi.INSTANCE_FIELD, name.getDescriptor(), null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
initSingletonField(name.getAsmType(), iv);
genInitSingletonField(name.getAsmType(), iv);
mv.visitInsn(RETURN);
FunctionCodegen.endVisit(mv, "<clinit>", fun);
}
@@ -164,7 +165,7 @@ public class ClosureCodegen extends GenerationStateAware {
cv.newMethod(fun, ACC_PUBLIC | ACC_BRIDGE | ACC_VOLATILE, "invoke", bridge.getAsmMethod().getDescriptor(), null,
new String[0]);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -212,7 +213,7 @@ public class ClosureCodegen extends GenerationStateAware {
final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -16,44 +16,29 @@
package org.jetbrains.jet.codegen;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Label;
import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.psi.JetClassObject;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.*;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
/**
@@ -61,31 +46,6 @@ import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
* @author alex.tkachman
*/
public class CodegenUtil {
public static final String RECEIVER$0 = "receiver$0";
public static final String THIS$0 = "this$0";
private static final int NO_FLAG_LOCAL = 0;
private static final int NO_FLAG_PACKAGE_PRIVATE = 0;
@NotNull
private static final Map<Visibility, Integer> visibilityToAccessFlag = ImmutableMap.<Visibility, Integer>builder()
.put(Visibilities.PRIVATE, ACC_PRIVATE)
.put(Visibilities.PROTECTED, ACC_PROTECTED)
.put(Visibilities.PUBLIC, ACC_PUBLIC)
.put(Visibilities.INTERNAL, ACC_PUBLIC)
.put(Visibilities.LOCAL, NO_FLAG_LOCAL)
.put(JavaDescriptorResolver.PACKAGE_VISIBILITY, NO_FLAG_PACKAGE_PRIVATE)
.build();
private static final Set<ClassDescriptor> PRIMITIVE_NUMBER_CLASSES = Sets.newHashSet(
JetStandardLibrary.getInstance().getByte(),
JetStandardLibrary.getInstance().getShort(),
JetStandardLibrary.getInstance().getInt(),
JetStandardLibrary.getInstance().getLong(),
JetStandardLibrary.getInstance().getFloat(),
JetStandardLibrary.getInstance().getDouble(),
JetStandardLibrary.getInstance().getChar()
);
private CodegenUtil() {
}
@@ -130,7 +90,7 @@ public class CodegenUtil {
}
public static String generateTmpVariableName(Collection<String> existingNames) {
public static String createTmpVariableName(Collection<String> existingNames) {
String prefix = "tmp";
int i = RANDOM.nextInt(Integer.MAX_VALUE);
String name = prefix + i;
@@ -142,9 +102,8 @@ public class CodegenUtil {
}
public static
@NotNull
BitSet getFlagsForVisibility(@NotNull Visibility visibility) {
public static BitSet getFlagsForVisibility(@NotNull Visibility visibility) {
BitSet flags = new BitSet();
if (visibility == Visibilities.INTERNAL) {
flags.set(JvmStdlibNames.FLAG_INTERNAL_BIT);
@@ -155,22 +114,6 @@ public class CodegenUtil {
return flags;
}
public static void generateThrow(MethodVisitor mv, String exception, String message) {
InstructionAdapter iv = new InstructionAdapter(mv);
iv.anew(Type.getObjectType(exception));
iv.dup();
iv.aconst(message);
iv.invokespecial(exception, "<init>", "(Ljava/lang/String;)V");
iv.athrow();
}
public static void generateMethodThrow(MethodVisitor mv, String exception, String message) {
mv.visitCode();
generateThrow(mv, exception, message);
mv.visitMaxs(-1, -1);
mv.visitEnd();
}
@NotNull
public static JvmClassName getInternalClassName(FunctionDescriptor descriptor) {
final int paramCount = descriptor.getValueParameters().size();
@@ -216,123 +159,10 @@ public class CodegenUtil {
return closure.getCaptureThis() == null && closure.getCaptureReceiver() == null && closure.getCaptureVariables().isEmpty();
}
public static void generateClosureFields(CalculatedClosure closure, ClassBuilder v, JetTypeMapper typeMapper) {
final ClassifierDescriptor captureThis = closure.getCaptureThis();
final int access = ACC_PUBLIC | ACC_SYNTHETIC | ACC_FINAL;
if (captureThis != null) {
v.newField(null, access, THIS$0, typeMapper.mapType(captureThis).getDescriptor(), null,
null);
}
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
if (captureReceiver != null) {
v.newField(null, access, RECEIVER$0, typeMapper.mapType(captureReceiver).getDescriptor(),
null, null);
}
final List<Pair<String, Type>> fields = closure.getRecordedFields();
for (Pair<String, Type> field : fields) {
v.newField(null, access, field.first, field.second.getDescriptor(), null, null);
}
}
public static <T> T peekFromStack(Stack<T> stack) {
return stack.empty() ? null : stack.peek();
}
//TODO: move mapping logic to front-end java
public static int getVisibilityAccessFlag(@NotNull MemberDescriptor descriptor) {
Integer specialCase = specialCaseVisibility(descriptor);
if (specialCase != null) {
return specialCase;
}
Integer defaultMapping = visibilityToAccessFlag.get(descriptor.getVisibility());
if (defaultMapping == null) {
throw new IllegalStateException(descriptor.getVisibility() + " is not a valid visibility in backend.");
}
return defaultMapping;
}
@Nullable
private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) {
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
if (isInterface(containingDeclaration)) {
return ACC_PUBLIC;
}
Visibility memberVisibility = memberDescriptor.getVisibility();
if (memberVisibility != Visibilities.PRIVATE) {
return null;
}
if (isClassObject(containingDeclaration)) {
return NO_FLAG_PACKAGE_PRIVATE;
}
if (memberDescriptor instanceof ConstructorDescriptor) {
ClassKind kind = ((ClassDescriptor) containingDeclaration).getKind();
if (kind == ClassKind.OBJECT) {
//TODO: should be NO_FLAG_PACKAGE_PRIVATE
// see http://youtrack.jetbrains.com/issue/KT-2700
return ACC_PUBLIC;
}
else if (kind == ClassKind.ENUM_ENTRY) {
return NO_FLAG_PACKAGE_PRIVATE;
}
else if (kind == ClassKind.ENUM_CLASS) {
//TODO: should be ACC_PRIVATE
// see http://youtrack.jetbrains.com/issue/KT-2680
return ACC_PROTECTED;
}
}
if (containingDeclaration instanceof NamespaceDescriptor) {
return ACC_PUBLIC;
}
return null;
}
public static Type unboxType(final Type type) {
JvmPrimitiveType jvmPrimitiveType = JvmPrimitiveType.getByWrapperAsmType(type);
if (jvmPrimitiveType != null) {
return jvmPrimitiveType.getAsmType();
}
else {
throw new UnsupportedOperationException("Unboxing: " + type);
}
}
public static Type boxType(Type asmType) {
JvmPrimitiveType jvmPrimitiveType = JvmPrimitiveType.getByAsmType(asmType);
if (jvmPrimitiveType != null) {
return jvmPrimitiveType.getWrapper().getAsmType();
}
else {
return asmType;
}
}
public static boolean isIntPrimitive(Type type) {
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE;
}
public static boolean isNumberPrimitive(Type type) {
return isIntPrimitive(type) || type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE || type == Type.LONG_TYPE;
}
public static boolean isPrimitive(Type type) {
return type.getSort() != Type.OBJECT && type.getSort() != Type.ARRAY;
}
public static boolean isPrimitiveNumberClassDescriptor(DeclarationDescriptor descriptor) {
if (!(descriptor instanceof ClassDescriptor)) {
return false;
}
return PRIMITIVE_NUMBER_CLASSES.contains(descriptor);
}
public static Type correctElementType(Type type) {
String internalName = type.getInternalName();
assert internalName.charAt(0) == '[';
return Type.getType(internalName.substring(1));
}
@Nullable
public static String getLocalNameForObject(JetObjectDeclaration object) {
PsiElement parent = object.getParent();
@@ -369,309 +199,4 @@ public class CodegenUtil {
throw new IllegalStateException("code generation for synthesized members should be handled separately");
}
}
public static void initSingletonField(Type classAsmType, InstructionAdapter iv) {
iv.anew(classAsmType);
iv.dup();
iv.invokespecial(classAsmType.getInternalName(), "<init>", "()V");
iv.putstatic(classAsmType.getInternalName(), JvmAbi.INSTANCE_FIELD, classAsmType.getDescriptor());
}
public static void generateStringBuilderConstructor(InstructionAdapter v) {
v.visitTypeInsn(NEW, "java/lang/StringBuilder");
v.dup();
v.invokespecial("java/lang/StringBuilder", "<init>", "()V");
}
public static void invokeAppendMethod(InstructionAdapter v, Type type) {
type = getStringValueOfOrStringBuilderAppendType(type);
v.invokevirtual("java/lang/StringBuilder", "append", "(" + type.getDescriptor() + ")Ljava/lang/StringBuilder;");
}
public static StackValue genToString(InstructionAdapter v, StackValue receiver) {
final Type type = getStringValueOfOrStringBuilderAppendType(receiver.type);
receiver.put(type, v);
v.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;");
return StackValue.onStack(JAVA_STRING_TYPE);
}
private static Type getStringValueOfOrStringBuilderAppendType(Type type) {
final int sort = type.getSort();
return sort == Type.OBJECT || sort == Type.ARRAY
? AsmTypeConstants.OBJECT_TYPE
: sort == Type.BYTE || sort == Type.SHORT ? Type.INT_TYPE : type;
}
static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type) {
if (type.getSort() == Type.ARRAY) {
final Type elementType = correctElementType(type);
if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
iv.invokestatic("java/util/Arrays", "hashCode", "([Ljava/lang/Object;)I");
}
else {
iv.invokestatic("java/util/Arrays", "hashCode", "(" + type.getDescriptor() + ")I");
}
}
else if (type.getSort() == Type.OBJECT) {
iv.invokevirtual("java/lang/Object", "hashCode", "()I");
}
else if (type.getSort() == Type.LONG) {
genLongHashCode(mv, iv);
}
else if (type.getSort() == Type.DOUBLE) {
iv.invokestatic("java/lang/Double", "doubleToLongBits", "(D)J");
genLongHashCode(mv, iv);
}
else if (type.getSort() == Type.FLOAT) {
iv.invokestatic("java/lang/Float", "floatToIntBits", "(F)I");
}
else if (type.getSort() == Type.BOOLEAN) {
Label end = new Label();
iv.dup();
iv.ifeq(end);
iv.pop();
iv.iconst(1);
iv.mark(end);
}
else { // byte short char int
// do nothing
}
}
private static void genLongHashCode(MethodVisitor mv, InstructionAdapter iv) {
iv.dup2();
iv.iconst(32);
iv.ushr(Type.LONG_TYPE);
iv.xor(Type.LONG_TYPE);
mv.visitInsn(L2I);
}
static StackValue compareExpressionsOnStack(InstructionAdapter v, IElementType opToken, Type operandType) {
if (operandType.getSort() == Type.OBJECT) {
v.invokeinterface("java/lang/Comparable", "compareTo", "(Ljava/lang/Object;)I");
v.iconst(0);
operandType = Type.INT_TYPE;
}
return StackValue.cmp(opToken, operandType);
}
static StackValue generateNullSafeEquals(
InstructionAdapter v,
IElementType opToken,
boolean leftNullable,
boolean rightNullable
) {
if (!leftNullable) {
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
if (opToken == JetTokens.EXCLEQ) {
invertBoolean(v);
}
}
else {
if (rightNullable) {
v.dup2(); // left right left right
Label rightNull = new Label();
v.ifnull(rightNull);
Label leftNull = new Label();
v.ifnull(leftNull);
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
invertBoolean(v);
}
Label end = new Label();
v.goTo(end);
v.mark(rightNull);
// left right left
Label bothNull = new Label();
v.ifnull(bothNull);
v.mark(leftNull);
v.pop2();
v.iconst(opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ ? 1 : 0);
v.goTo(end);
v.mark(bothNull);
v.pop2();
v.iconst(opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ ? 0 : 1);
v.mark(end);
}
else {
v.dup2(); // left right left right
v.pop();
Label leftNull = new Label();
v.ifnull(leftNull);
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
invertBoolean(v);
}
Label end = new Label();
v.goTo(end);
// left right
v.mark(leftNull);
v.pop2();
v.iconst(opToken == JetTokens.EXCLEQ ? 1 : 0);
v.mark(end);
}
}
return StackValue.onStack(Type.BOOLEAN_TYPE);
}
static void invertBoolean(InstructionAdapter v) {
v.iconst(1);
v.xor(Type.INT_TYPE);
}
public static StackValue generateEqualsForExpressionsOnStack(
InstructionAdapter v,
IElementType opToken,
Type leftType,
Type rightType,
boolean leftNullable,
boolean rightNullable
) {
if ((isNumberPrimitive(leftType) || leftType.getSort() == Type.BOOLEAN) && leftType == rightType) {
return compareExpressionsOnStack(v, opToken, leftType);
}
else {
if (opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) {
return StackValue.cmp(opToken, leftType);
}
else {
return generateNullSafeEquals(v, opToken, leftNullable, rightNullable);
}
}
}
public static Type genIncrement(Type expectedType, int myDelta, InstructionAdapter v) {
if (expectedType == Type.LONG_TYPE) {
//noinspection UnnecessaryBoxing
v.lconst(myDelta);
}
else if (expectedType == Type.FLOAT_TYPE) {
//noinspection UnnecessaryBoxing
v.fconst(myDelta);
}
else if (expectedType == Type.DOUBLE_TYPE) {
//noinspection UnnecessaryBoxing
v.dconst(myDelta);
}
else {
v.iconst(myDelta);
expectedType = Type.INT_TYPE;
}
v.add(expectedType);
return expectedType;
}
public static Type genNegate(Type expectedType, InstructionAdapter v) {
if (expectedType == Type.BYTE_TYPE || expectedType == Type.SHORT_TYPE || expectedType == Type.CHAR_TYPE) {
expectedType = Type.INT_TYPE;
}
v.neg(expectedType);
return expectedType;
}
public static void generate(GenerationState state, CodegenContext context, JetClassOrObject aClass) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
if (descriptor == null || ErrorUtils.isError(descriptor) || descriptor.getName().equals(JetPsiUtil.NO_NAME_PROVIDED)) {
if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
throw new IllegalStateException(
"Generating bad descriptor in ClassBuilderMode = " + state.getClassBuilderMode() + ": " + descriptor);
}
return;
}
ClassBuilder classBuilder = state.getFactory().forClassImplementation(descriptor);
final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) {
// Outer class implementation must happen prior inner classes so we get proper scoping tree in JetLightClass's delegate
// The same code is present below for the case when we generate real bytecode. This is because the order should be
// different for the case when we compute closures
generateImplementation(state, context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder);
}
genInners(state, aClass, contextForInners);
if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
generateImplementation(state, context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder);
}
classBuilder.done();
}
public static void genInners(GenerationState state, JetClassOrObject aClass, CodegenContext contextForInners) {
for (JetDeclaration declaration : aClass.getDeclarations()) {
if (declaration instanceof JetClass) {
if (declaration instanceof JetEnumEntry && !enumEntryNeedSubclass(
state.getBindingContext(), (JetEnumEntry) declaration)) {
continue;
}
generate(state, contextForInners, (JetClass) declaration);
}
else if (declaration instanceof JetClassObject) {
generate(state, contextForInners, ((JetClassObject) declaration).getObjectDeclaration());
}
else if (declaration instanceof JetObjectDeclaration) {
generate(state, contextForInners, (JetObjectDeclaration) declaration);
}
}
}
private static void generateImplementation(
GenerationState state,
CodegenContext context,
JetClassOrObject aClass,
OwnerKind kind,
Map<DeclarationDescriptor, DeclarationDescriptor> accessors,
ClassBuilder classBuilder
) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
CodegenContext classContext = context.intoClass(descriptor, kind, state);
classContext.copyAccessors(accessors);
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate();
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
ClassBuilder traitBuilder = state.getFactory().forTraitImplementation(descriptor, state);
new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state), traitBuilder, state)
.generate();
traitBuilder.done();
}
}
public static void generateFunctionOrProperty(
GenerationState state,
@NotNull JetTypeParameterListOwner functionOrProperty,
@NotNull CodegenContext context, @NotNull ClassBuilder classBuilder
) {
FunctionCodegen functionCodegen = new FunctionCodegen(context, classBuilder, state);
if (functionOrProperty instanceof JetNamedFunction) {
try {
functionCodegen.gen((JetNamedFunction) functionOrProperty);
}
catch (CompilationException e) {
throw e;
}
catch (Exception e) {
throw new CompilationException("Failed to generate function " + functionOrProperty.getName(), e, functionOrProperty);
}
}
else if (functionOrProperty instanceof JetProperty) {
try {
new PropertyCodegen(context, classBuilder, functionCodegen).gen((JetProperty) functionOrProperty);
}
catch (CompilationException e) {
throw e;
}
catch (Exception e) {
throw new CompilationException("Failed to generate property " + functionOrProperty.getName(), e, functionOrProperty);
}
}
else {
throw new IllegalArgumentException("Unknown parameter: " + functionOrProperty);
}
}
}
@@ -30,7 +30,7 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
public class CompilationException extends RuntimeException {
private final PsiElement element;
CompilationException(@NotNull String message, @Nullable Throwable cause, @NotNull PsiElement element) {
public CompilationException(@NotNull String message, @Nullable Throwable cause, @NotNull PsiElement element) {
super(message, cause);
this.element = element;
}
@@ -61,6 +61,7 @@ import org.jetbrains.jet.lexer.JetTokens;
import java.util.*;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
@@ -117,7 +118,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
final CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor);
final CodegenContext contextForInners = context.intoClass(classDescriptor, OwnerKind.IMPLEMENTATION, state);
genInners(state, objectDeclaration, contextForInners);
contextForInners.genInners(state, objectDeclaration);
final CodegenContext objectContext = context.intoAnonymousClass(classDescriptor, this);
objectContext.copyAccessors(contextForInners.getAccessors());
@@ -994,7 +995,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return StackValue.constant(constantValue.toString(), type);
}
else {
generateStringBuilderConstructor(v);
genStringBuilderConstructor(v);
for (JetStringTemplateEntry entry : entries) {
if (entry instanceof JetStringTemplateEntryWithExpression) {
invokeAppend(entry.getExpression());
@@ -1004,7 +1005,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
? ((JetEscapeStringTemplateEntry) entry).getUnescapedValue()
: entry.getText();
v.aconst(text);
invokeAppendMethod(v, JAVA_STRING_TYPE);
genInvokeAppendMethod(v, JAVA_STRING_TYPE);
}
}
v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
@@ -1665,9 +1666,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
final int flag = CodegenUtil.getVisibilityAccessFlag(propertyDescriptor) |
(getter == null ? 0 : CodegenUtil.getVisibilityAccessFlag(getter)) |
(setter == null ? 0 : CodegenUtil.getVisibilityAccessFlag(setter));
final int flag = getVisibilityAccessFlag(propertyDescriptor) |
(getter == null ? 0 : getVisibilityAccessFlag(getter)) |
(setter == null ? 0 : getVisibilityAccessFlag(setter));
if ((flag & ACC_PRIVATE) == 0) {
return propertyDescriptor;
@@ -1677,7 +1678,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
private FunctionDescriptor accessableFunctionDescriptor(FunctionDescriptor fd) {
final int flag = CodegenUtil.getVisibilityAccessFlag(fd);
final int flag = getVisibilityAccessFlag(fd);
if ((flag & ACC_PRIVATE) == 0) {
return fd;
}
@@ -2261,7 +2262,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
else {
invokeFunctionByReference(expression.getOperationReference());
if (inverted) {
invertBoolean(v);
genInvertBoolean(v);
}
}
return StackValue.onStack(Type.BOOLEAN_TYPE);
@@ -2302,7 +2303,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
v.and(Type.INT_TYPE);
if (inverted) {
invertBoolean(v);
genInvertBoolean(v);
}
}
@@ -2362,10 +2363,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (isPrimitive(leftType)) // both are primitive
{
return generateEqualsForExpressionsOnStack(v, opToken, leftType, rightType, false, false);
return genEqualsForExpressionsOnStack(v, opToken, leftType, rightType, false, false);
}
return generateEqualsForExpressionsOnStack(v, opToken, leftType, rightType, leftJetType.isNullable(), rightJetType.isNullable());
return
genEqualsForExpressionsOnStack(v, opToken, leftType, rightType, leftJetType.isNullable(), rightJetType.isNullable());
}
private StackValue genCmpWithNull(JetExpression exp, Type expType, IElementType opToken) {
@@ -2514,7 +2516,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
Type exprType = expressionType(expr);
gen(expr, exprType);
invokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType);
genInvokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType);
}
@Nullable
@@ -3187,10 +3189,10 @@ The "returned" value of try expression with no finally is either the last expres
boolean patternIsNullable = false;
JetType condJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, patternExpression);
Type condType;
if (CodegenUtil.isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) {
if (isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) {
assert condJetType != null;
condType = asmType(condJetType);
if (!(CodegenUtil.isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) {
if (!(isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) {
subjectType = boxType(subjectType);
expressionToMatch.coerceTo(subjectType, v);
}
@@ -3200,8 +3202,8 @@ The "returned" value of try expression with no finally is either the last expres
patternIsNullable = condJetType != null && condJetType.isNullable();
}
gen(patternExpression, condType);
return generateEqualsForExpressionsOnStack(v, JetTokens.EQEQ, subjectType, condType, expressionToMatchIsNullable,
patternIsNullable);
return genEqualsForExpressionsOnStack(v, JetTokens.EQEQ, subjectType, condType, expressionToMatchIsNullable,
patternIsNullable);
}
else {
return gen(patternExpression);
@@ -3326,7 +3328,7 @@ The "returned" value of try expression with no finally is either the last expres
//invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v);
invokeFunctionByReference(operationReference);
if (inverted) {
invertBoolean(v);
genInvertBoolean(v);
}
}
return StackValue.onStack(Type.BOOLEAN_TYPE);
@@ -48,6 +48,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import java.util.*;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalFun;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
@@ -130,7 +131,7 @@ public class FunctionCodegen extends GenerationStateAware {
}
if (!isAbstract && state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
@@ -258,7 +259,7 @@ public class FunctionCodegen extends GenerationStateAware {
Type sharedVarType = state.getTypeMapper().getSharedVarType(parameter);
mv.visitLocalVariable(parameterName, type.getDescriptor(), null, methodBegin, divideLabel, k);
String nameForSharedVar = generateTmpVariableName(localVariableNames);
String nameForSharedVar = createTmpVariableName(localVariableNames);
localVariableNames.add(nameForSharedVar);
mv.visitLocalVariable(nameForSharedVar, sharedVarType.getDescriptor(), null, divideLabel, methodEnd, k);
@@ -516,7 +517,7 @@ public class FunctionCodegen extends GenerationStateAware {
descriptor, null, null);
InstructionAdapter iv = new InstructionAdapter(mv);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
generateDefaultImpl(owner, state, jvmSignature, functionDescriptor, kind, receiverParameter, hasReceiver, isStatic,
@@ -684,7 +685,7 @@ public class FunctionCodegen extends GenerationStateAware {
final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overridden.getDescriptor(), null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -738,7 +739,7 @@ public class FunctionCodegen extends GenerationStateAware {
final MethodVisitor mv = v.newMethod(null, flags, method.getName(), method.getDescriptor(), null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -19,8 +19,6 @@ package org.jetbrains.jet.codegen;
import com.google.common.collect.Lists;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.AnnotationVisitor;
@@ -43,7 +41,6 @@ import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.OverridingUtil;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
@@ -61,6 +58,7 @@ import org.jetbrains.jet.utils.BitSetUtils;
import java.util.*;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
@@ -394,7 +392,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateFunctionsForDataClasses();
generateClosureFields(context.closure, v, state.getTypeMapper());
genClosureFields(context.closure, v, state.getTypeMapper());
}
private List<PropertyDescriptor> getDataProperties() {
@@ -451,7 +449,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
genPropertyOnStack(iv, propertyDescriptor, 2);
if (asmType.getSort() == Type.ARRAY) {
final Type elementType = CodegenUtil.correctElementType(asmType);
final Type elementType = correctElementType(asmType);
if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
iv.invokestatic("java/util/Arrays", "equals", "([Ljava/lang/Object;[Ljava/lang/Object;)Z");
}
@@ -461,7 +459,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
else {
final StackValue value =
generateEqualsForExpressionsOnStack(iv, JetTokens.EQEQ, asmType, asmType, type.isNullable(), type.isNullable());
genEqualsForExpressionsOnStack(iv, JetTokens.EQEQ, asmType, asmType, type.isNullable(), type.isNullable());
value.put(Type.BOOLEAN_TYPE, iv);
}
@@ -530,7 +528,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final InstructionAdapter iv = new InstructionAdapter(mv);
mv.visitCode();
generateStringBuilderConstructor(iv);
genStringBuilderConstructor(iv);
boolean first = true;
for (PropertyDescriptor propertyDescriptor : properties) {
@@ -541,7 +539,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
else {
iv.aconst(", " + propertyDescriptor.getName().getName()+"=");
}
invokeAppendMethod(iv, JAVA_STRING_TYPE);
genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
Type type = genPropertyOnStack(iv, propertyDescriptor, 0);
@@ -558,11 +556,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
}
invokeAppendMethod(iv, type);
genInvokeAppendMethod(iv, type);
}
iv.aconst(")");
invokeAppendMethod(iv, JAVA_STRING_TYPE);
genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
iv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
iv.areturn(JAVA_STRING_TYPE);
@@ -673,7 +671,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
MethodVisitor mv = v.newMethod(null, ACC_BRIDGE | ACC_SYNTHETIC | ACC_STATIC, bridge.getName().getName(),
method.getDescriptor(), null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -718,7 +716,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
original,
getter.getVisibility());
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -753,7 +751,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
original,
setter.getVisibility());
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -795,7 +793,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
staticInitializerChunks.add(new CodeChunk() {
@Override
public void generate(InstructionAdapter iv) {
initSingletonField(classAsmType, iv);
genInitSingletonField(classAsmType, iv);
}
});
}
@@ -841,7 +839,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
writeParameterAnnotations(constructorDescriptor, constructorMethod, hasThis0, mv);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
return;
}
@@ -1238,7 +1236,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
aw.visitEnd();
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -128,19 +128,17 @@ public class NamespaceCodegen extends GenerationStateAware {
for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetProperty) {
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
CodegenUtil.generateFunctionOrProperty(
state, (JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
context.genFunctionOrProperty(state, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
}
else if (declaration instanceof JetNamedFunction) {
if (!multiFile) {
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
CodegenUtil.generateFunctionOrProperty(
state, (JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
context.genFunctionOrProperty(state, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
}
}
else if (declaration instanceof JetClassOrObject) {
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
CodegenUtil.generate(state, context, (JetClassOrObject) declaration);
context.genClassOrObject(state, (JetClassOrObject) declaration);
}
else if (declaration instanceof JetScript) {
state.getScriptCodegen().generate((JetScript) declaration);
@@ -176,16 +174,12 @@ public class NamespaceCodegen extends GenerationStateAware {
{
final CodegenContext context =
CodegenContext.STATIC.intoNamespace(descriptor);
CodegenUtil
.generateFunctionOrProperty(state, (JetTypeParameterListOwner) declaration,
context, builder);
context.genFunctionOrProperty(state, (JetTypeParameterListOwner) declaration, builder);
}
{
final CodegenContext context =
CodegenContext.STATIC.intoNamespacePart(className, descriptor);
CodegenUtil
.generateFunctionOrProperty(state, (JetTypeParameterListOwner) declaration,
context, v.getClassBuilder());
context.genFunctionOrProperty(state, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
}
}
}
@@ -42,6 +42,8 @@ import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import java.util.BitSet;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.genStubThrow;
import static org.jetbrains.jet.codegen.AsmUtil.getVisibilityAccessFlag;
import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
@@ -214,7 +216,7 @@ public class PropertyCodegen extends GenerationStateAware {
if (propertyDescriptor.getModality() != Modality.ABSTRACT) {
mv.visitCode();
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubThrow(mv);
genStubThrow(mv);
}
else {
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -316,7 +318,7 @@ public class PropertyCodegen extends GenerationStateAware {
if (propertyDescriptor.getModality() != Modality.ABSTRACT) {
mv.visitCode();
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubThrow(mv);
genStubThrow(mv);
}
else {
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -27,6 +27,8 @@ import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitiveNumberClassDescriptor;
/**
* @author abreslav
*/
@@ -91,7 +93,7 @@ public class RangeCodegenUtil {
public static boolean isOptimizableRangeTo(CallableDescriptor rangeTo) {
if ("rangeTo".equals(rangeTo.getName().getName())) {
if (CodegenUtil.isPrimitiveNumberClassDescriptor(rangeTo.getContainingDeclaration())) {
if (isPrimitiveNumberClassDescriptor(rangeTo.getContainingDeclaration())) {
return true;
}
}
@@ -202,7 +202,7 @@ public class ScriptCodegen extends GenerationStateAware {
private void genMembers(@NotNull JetScript scriptDeclaration, @NotNull CodegenContext context, @NotNull ClassBuilder classBuilder) {
for (JetDeclaration decl : scriptDeclaration.getDeclarations()) {
CodegenUtil.generateFunctionOrProperty(state, (JetTypeParameterListOwner) decl, context, classBuilder);
context.genFunctionOrProperty(state, (JetTypeParameterListOwner) decl, classBuilder);
}
}
@@ -39,6 +39,8 @@ import org.jetbrains.jet.lexer.JetTokens;
import java.util.List;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
import static org.jetbrains.jet.codegen.AsmUtil.isIntPrimitive;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
/**
@@ -61,7 +63,7 @@ public abstract class StackValue {
instructionAdapter.aconst(null);
}
else {
Type boxed = CodegenUtil.boxType(type);
Type boxed = boxType(type);
instructionAdapter.invokestatic(boxed.getInternalName(), "valueOf", "(" + type.getDescriptor() + ")" + boxed.getDescriptor());
}
}
@@ -76,7 +78,7 @@ public abstract class StackValue {
* JVM stack after this value was generated.
*
* @param type the type as which the value should be put
* @param v the visitor used to generate the instructions
* @param v the visitor used to genClassOrObject the instructions
* @param depth the number of new values put onto the stack
*/
protected void moveToTopOfStack(Type type, InstructionAdapter v, int depth) {
@@ -171,7 +173,7 @@ public abstract class StackValue {
private static void box(final Type type, final Type toType, InstructionAdapter v) {
// TODO handle toType correctly
if (type == Type.INT_TYPE || (CodegenUtil.isIntPrimitive(type) && toType.getInternalName().equals("java/lang/Integer"))) {
if (type == Type.INT_TYPE || (isIntPrimitive(type) && toType.getInternalName().equals("java/lang/Integer"))) {
v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
}
else if (type == Type.BOOLEAN_TYPE) {
@@ -614,7 +616,7 @@ public abstract class StackValue {
public ArrayElement(Type type, boolean unbox) {
super(type);
this.boxed = unbox ? CodegenUtil.boxType(type) : type;
this.boxed = unbox ? boxType(type) : type;
}
@Override
@@ -1,41 +0,0 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed 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 org.jetbrains.jet.codegen;
import org.jetbrains.asm4.MethodVisitor;
import static org.jetbrains.jet.codegen.CodegenUtil.generateMethodThrow;
import static org.jetbrains.jet.codegen.CodegenUtil.generateThrow;
/**
* @author Stepan Koltsov
*/
public class StubCodegen {
private static final String STUB_EXCEPTION = "java/lang/RuntimeException";
private static final String STUB_EXCEPTION_MESSAGE = "Stubs are for compiler only, do not add them to runtime classpath";
private StubCodegen() {
}
public static void generateStubThrow(MethodVisitor mv) {
generateThrow(mv, STUB_EXCEPTION, STUB_EXCEPTION_MESSAGE);
}
public static void generateStubCode(MethodVisitor mv) {
generateMethodThrow(mv, STUB_EXCEPTION, STUB_EXCEPTION_MESSAGE);
}
}
@@ -19,7 +19,6 @@ package org.jetbrains.jet.codegen.binding;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*;
@@ -39,6 +38,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import static org.jetbrains.jet.codegen.CodegenUtil.isInterface;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
@@ -365,7 +365,7 @@ public class CodegenBinding {
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
assert superClassDescriptor != null;
if (!CodegenUtil.isInterface(superClassDescriptor)) {
if (!isInterface(superClassDescriptor)) {
return (JetDelegatorToSuperCall) specifier;
}
}
@@ -26,13 +26,16 @@ import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.ErrorUtils;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.CLASS_FOR_FUNCTION;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.FQN;
import static org.jetbrains.jet.codegen.AsmUtil.THIS$0;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
/*
@@ -261,7 +264,7 @@ public abstract class CodegenContext {
final ClassDescriptor enclosingClass = getEnclosingClass();
outerExpression = enclosingClass != null
? StackValue
.field(typeMapper.mapType(enclosingClass), CodegenBinding.getJvmInternalName(typeMapper.getBindingTrace(), classDescriptor), CodegenUtil.THIS$0,
.field(typeMapper.mapType(enclosingClass), CodegenBinding.getJvmInternalName(typeMapper.getBindingTrace(), classDescriptor), THIS$0,
false)
: null;
}
@@ -298,4 +301,108 @@ public abstract class CodegenContext {
public Map<DeclarationDescriptor, DeclarationDescriptor> getAccessors() {
return accessors == null ? Collections.<DeclarationDescriptor, DeclarationDescriptor>emptyMap() : accessors;
}
public void genFunctionOrProperty(
GenerationState state,
@NotNull JetTypeParameterListOwner functionOrProperty,
@NotNull ClassBuilder classBuilder
) {
FunctionCodegen functionCodegen = new FunctionCodegen(this, classBuilder, state);
if (functionOrProperty instanceof JetNamedFunction) {
try {
functionCodegen.gen((JetNamedFunction) functionOrProperty);
}
catch (CompilationException e) {
throw e;
}
catch (Exception e) {
throw new CompilationException("Failed to generate function " + functionOrProperty.getName(), e, functionOrProperty);
}
}
else if (functionOrProperty instanceof JetProperty) {
try {
new PropertyCodegen(this, classBuilder, functionCodegen).gen((JetProperty) functionOrProperty);
}
catch (CompilationException e) {
throw e;
}
catch (Exception e) {
throw new CompilationException("Failed to generate property " + functionOrProperty.getName(), e, functionOrProperty);
}
}
else {
throw new IllegalArgumentException("Unknown parameter: " + functionOrProperty);
}
}
public void genImplementation(
GenerationState state,
JetClassOrObject aClass,
OwnerKind kind,
Map<DeclarationDescriptor, DeclarationDescriptor> accessors,
ClassBuilder classBuilder
) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
CodegenContext classContext = intoClass(descriptor, kind, state);
classContext.copyAccessors(accessors);
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate();
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
ClassBuilder traitBuilder = state.getFactory().forTraitImplementation(descriptor, state);
new TraitImplBodyCodegen(aClass, intoClass(descriptor, OwnerKind.TRAIT_IMPL, state), traitBuilder, state)
.generate();
traitBuilder.done();
}
}
public void genInners(GenerationState state, JetClassOrObject aClass) {
for (JetDeclaration declaration : aClass.getDeclarations()) {
if (declaration instanceof JetClass) {
if (declaration instanceof JetEnumEntry && !enumEntryNeedSubclass(
state.getBindingContext(), (JetEnumEntry) declaration)) {
continue;
}
genClassOrObject(state, (JetClass) declaration);
}
else if (declaration instanceof JetClassObject) {
genClassOrObject(state, ((JetClassObject) declaration).getObjectDeclaration());
}
else if (declaration instanceof JetObjectDeclaration) {
genClassOrObject(state, (JetObjectDeclaration) declaration);
}
}
}
public void genClassOrObject(GenerationState state, JetClassOrObject aClass) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
if (descriptor == null || ErrorUtils.isError(descriptor) || descriptor.getName().equals(JetPsiUtil.NO_NAME_PROVIDED)) {
if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
throw new IllegalStateException(
"Generating bad descriptor in ClassBuilderMode = " + state.getClassBuilderMode() + ": " + descriptor);
}
return;
}
ClassBuilder classBuilder = state.getFactory().forClassImplementation(descriptor);
final CodegenContext contextForInners = intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) {
// Outer class implementation must happen prior inner classes so we get proper scoping tree in JetLightClass's delegate
// The same code is present below for the case when we genClassOrObject real bytecode. This is because the order should be
// different for the case when we compute closures
genImplementation(state, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder);
}
contextForInners.genInners(state, aClass);
if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
genImplementation(state, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder);
}
classBuilder.done();
}
}
@@ -17,7 +17,6 @@
package org.jetbrains.jet.codegen.context;
import org.jetbrains.asm4.Type;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.binding.MutableClosure;
@@ -27,6 +26,7 @@ import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.types.JetType;
import static org.jetbrains.jet.codegen.AsmUtil.RECEIVER$0;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.classNameForAnonymousClass;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
@@ -122,7 +122,7 @@ public interface LocalLookup {
final JetType receiverType = ((CallableDescriptor) d).getReceiverParameter().getType();
Type type = state.getTypeMapper().mapType(receiverType);
StackValue innerValue = StackValue.field(type, className, CodegenUtil.RECEIVER$0, false);
StackValue innerValue = StackValue.field(type, className, RECEIVER$0, false);
closure.setCaptureReceiver();
return innerValue;
@@ -20,15 +20,16 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.correctElementType;
/**
* @author alex.tkachman
*/
@@ -44,7 +45,7 @@ public class ArrayGet implements IntrinsicMethod {
@NotNull GenerationState state
) {
receiver.put(AsmTypeConstants.OBJECT_TYPE, v);
Type type = CodegenUtil.correctElementType(receiver.type);
Type type = correctElementType(receiver.type);
codegen.gen(arguments.get(0), Type.INT_TYPE);
@@ -20,15 +20,16 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.correctElementType;
/**
* @author alex.tkachman
*/
@@ -44,7 +45,7 @@ public class ArraySet implements IntrinsicMethod {
@NotNull GenerationState state
) {
receiver.put(AsmTypeConstants.OBJECT_TYPE, v);
Type type = CodegenUtil.correctElementType(receiver.type);
Type type = correctElementType(receiver.type);
codegen.gen(arguments.get(0), Type.INT_TYPE);
codegen.gen(arguments.get(1), type);
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -29,6 +28,8 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
/**
* @author yole
@@ -52,7 +53,7 @@ public class BinaryOp implements IntrinsicMethod {
) {
boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType);
expectedType = unboxType(expectedType);
}
if (arguments.size() == 1) {
// Intrinsic is called as an ordinary function
@@ -68,7 +69,7 @@ public class BinaryOp implements IntrinsicMethod {
v.visitInsn(expectedType.getOpcode(opcode));
if (nullable) {
StackValue.onStack(expectedType).put(expectedType = CodegenUtil.boxType(expectedType), v);
StackValue.onStack(expectedType).put(expectedType = boxType(expectedType), v);
}
return StackValue.onStack(expectedType);
}
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -29,6 +28,9 @@ import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.genInvokeAppendMethod;
import static org.jetbrains.jet.codegen.AsmUtil.genStringBuilderConstructor;
/**
* @author yole
*/
@@ -44,15 +46,15 @@ public class Concat implements IntrinsicMethod {
@NotNull GenerationState state
) {
if (receiver == null || receiver == StackValue.none()) { // LHS + RHS
CodegenUtil.generateStringBuilderConstructor(v);
genStringBuilderConstructor(v);
codegen.invokeAppend(arguments.get(0)); // StringBuilder(LHS)
codegen.invokeAppend(arguments.get(1));
}
else { // LHS.plus(RHS)
receiver.put(AsmTypeConstants.OBJECT_TYPE, v);
CodegenUtil.generateStringBuilderConstructor(v);
genStringBuilderConstructor(v);
v.swap(); // StringBuilder LHS
CodegenUtil.invokeAppendMethod(v, expectedType); // StringBuilder(LHS)
genInvokeAppendMethod(v, expectedType); // StringBuilder(LHS)
codegen.invokeAppend(arguments.get(0));
}
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -33,6 +32,8 @@ import org.jetbrains.jet.lexer.JetTokens;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.genEqualsForExpressionsOnStack;
/**
* @author alex.tkachman
*/
@@ -75,9 +76,8 @@ public class Equals implements IntrinsicMethod {
codegen.gen(rightExpr).put(AsmTypeConstants.OBJECT_TYPE, v);
assert rightType != null;
return CodegenUtil
.generateEqualsForExpressionsOnStack(v, JetTokens.EQEQ, AsmTypeConstants.OBJECT_TYPE, AsmTypeConstants.OBJECT_TYPE,
leftNullable,
rightType.isNullable());
return genEqualsForExpressionsOnStack(v, JetTokens.EQEQ, AsmTypeConstants.OBJECT_TYPE, AsmTypeConstants.OBJECT_TYPE,
leftNullable,
rightType.isNullable());
}
}
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -30,6 +29,8 @@ import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.*;
/**
* @author yole
*/
@@ -52,7 +53,7 @@ public class Increment implements IntrinsicMethod {
) {
boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType);
expectedType = unboxType(expectedType);
}
if (arguments.size() > 0) {
JetExpression operand = arguments.get(0);
@@ -61,7 +62,7 @@ public class Increment implements IntrinsicMethod {
}
if (operand instanceof JetReferenceExpression) {
final int index = codegen.indexOfLocal((JetReferenceExpression) operand);
if (index >= 0 && CodegenUtil.isIntPrimitive(expectedType)) {
if (index >= 0 && isIntPrimitive(expectedType)) {
return StackValue.preIncrement(index, myDelta);
}
}
@@ -70,12 +71,12 @@ public class Increment implements IntrinsicMethod {
value.dupReceiver(v);
value.put(expectedType, v);
value.store(CodegenUtil.genIncrement(expectedType, myDelta, v), v);
value.store(genIncrement(expectedType, myDelta, v), v);
value.put(expectedType, v);
}
else {
receiver.put(expectedType, v);
StackValue.coerce(CodegenUtil.genIncrement(expectedType, myDelta, v), expectedType, v);
StackValue.coerce(genIncrement(expectedType, myDelta, v), expectedType, v);
}
return StackValue.onStack(expectedType);
}
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -28,6 +27,8 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
/**
* @author yole
* @author alex.tkachman
@@ -45,7 +46,7 @@ public class Inv implements IntrinsicMethod {
) {
boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType);
expectedType = unboxType(expectedType);
}
receiver.put(expectedType, v);
if (expectedType == Type.LONG_TYPE) {
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -28,6 +27,8 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.genToString;
/**
* @author alex.tkachman
*/
@@ -42,6 +43,6 @@ public class ToString implements IntrinsicMethod {
StackValue receiver,
@NotNull GenerationState state
) {
return CodegenUtil.genToString(v, receiver);
return genToString(v, receiver);
}
}
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -28,6 +27,9 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.genNegate;
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
/**
* @author yole
*/
@@ -44,7 +46,7 @@ public class UnaryMinus implements IntrinsicMethod {
) {
boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType);
expectedType = unboxType(expectedType);
}
if (arguments.size() == 1) {
codegen.gen(arguments.get(0), expectedType);
@@ -52,7 +54,7 @@ public class UnaryMinus implements IntrinsicMethod {
else {
receiver.put(expectedType, v);
}
StackValue.coerce(CodegenUtil.genNegate(expectedType, v), expectedType, v);
StackValue.coerce(genNegate(expectedType, v), expectedType, v);
return StackValue.onStack(expectedType);
}
}
@@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -29,6 +28,8 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
/**
* @author alex.tkachman
*/
@@ -45,7 +46,7 @@ public class UnaryPlus implements IntrinsicMethod {
) {
boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType);
expectedType = unboxType(expectedType);
}
if (receiver != null && receiver != StackValue.none()) {
receiver.put(expectedType, v);
@@ -46,6 +46,7 @@ import java.util.List;
import java.util.Map;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
@@ -658,7 +659,7 @@ public class JetTypeMapper extends BindingTraceAware {
((ClassDescriptor) parentDescriptor).getKind() == ClassKind.ANNOTATION_CLASS;
String name = isAnnotation ? descriptor.getName().getName() : PropertyCodegen.getterName(descriptor.getName());
// TODO: do not generate generics if not needed
// TODO: do not genClassOrObject generics if not needed
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
writeFormalTypeParameters(descriptor.getTypeParameters(), signatureWriter);
@@ -29,7 +29,6 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.NamespaceCodegen;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.java.JavaPsiFacadeKotlinHacks;
@@ -41,6 +40,8 @@ import org.jetbrains.jet.util.QualifiedNamesUtil;
import java.util.*;
import static org.jetbrains.jet.codegen.CodegenUtil.getLocalNameForObject;
public class JavaElementFinder extends PsiElementFinder implements JavaPsiFacadeKotlinHacks.KotlinFinderMarker {
private final Project project;
private final PsiManager psiManager;
@@ -166,7 +167,7 @@ public class JavaElementFinder extends PsiElementFinder implements JavaPsiFacade
if (given != null) return given;
if (declaration instanceof JetObjectDeclaration) {
return CodegenUtil.getLocalNameForObject((JetObjectDeclaration) declaration);
return getLocalNameForObject((JetObjectDeclaration) declaration);
}
return null;
@@ -266,7 +266,7 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa
public static PsiMethod wrapMethod(@NotNull JetNamedFunction function) {
//noinspection unchecked
if (PsiTreeUtil.getParentOfType(function, JetFunction.class, JetProperty.class) != null) {
// Don't generate method wrappers for internal declarations. Their classes are not generated during calcStub
// Don't genClassOrObject method wrappers for internal declarations. Their classes are not generated during calcStub
// with ClassBuilderMode.SIGNATURES mode, and this produces "Class not found exception" in getDelegate()
return null;
}