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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user