Store refactoring
#KT-1213 Fixed
This commit is contained in:
@@ -20,6 +20,8 @@ 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 kotlin.Function1;
|
||||
import kotlin.Unit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
||||
@@ -431,11 +433,16 @@ public class AsmUtil {
|
||||
v.invokevirtual("java/lang/StringBuilder", "append", "(" + type.getDescriptor() + ")Ljava/lang/StringBuilder;", false);
|
||||
}
|
||||
|
||||
public static StackValue genToString(InstructionAdapter v, StackValue receiver, Type receiverType) {
|
||||
Type type = stringValueOfType(receiverType);
|
||||
receiver.put(type, v);
|
||||
v.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;", false);
|
||||
return StackValue.onStack(JAVA_STRING_TYPE);
|
||||
public static StackValue genToString(final InstructionAdapter v, final StackValue receiver, final Type receiverType) {
|
||||
return StackValue.operation(JAVA_STRING_TYPE, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter adapter) {
|
||||
Type type = stringValueOfType(receiverType);
|
||||
receiver.put(type, v);
|
||||
v.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;", false);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type) {
|
||||
@@ -489,26 +496,33 @@ public class AsmUtil {
|
||||
|
||||
@NotNull
|
||||
public static StackValue genEqualsForExpressionsOnStack(
|
||||
@NotNull InstructionAdapter v,
|
||||
@NotNull IElementType opToken,
|
||||
@NotNull Type leftType,
|
||||
@NotNull Type rightType
|
||||
final @NotNull IElementType opToken,
|
||||
final @NotNull StackValue left,
|
||||
final @NotNull StackValue right
|
||||
) {
|
||||
final Type leftType = left.type;
|
||||
final Type rightType = right.type;
|
||||
if (isPrimitive(leftType) && leftType == rightType) {
|
||||
return StackValue.cmp(opToken, leftType);
|
||||
return StackValue.cmp(opToken, leftType, left, right);
|
||||
}
|
||||
|
||||
if (opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
||||
return StackValue.cmp(opToken, leftType);
|
||||
return StackValue.cmp(opToken, leftType, left, right);
|
||||
}
|
||||
|
||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "areEqual", "(Ljava/lang/Object;Ljava/lang/Object;)Z", false);
|
||||
return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter v) {
|
||||
left.put(leftType, v);
|
||||
right.put(rightType, v);
|
||||
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "areEqual", "(Ljava/lang/Object;Ljava/lang/Object;)Z", false);
|
||||
|
||||
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
||||
genInvertBoolean(v);
|
||||
}
|
||||
|
||||
return StackValue.onStack(Type.BOOLEAN_TYPE);
|
||||
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
||||
genInvertBoolean(v);
|
||||
}
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void genIncrement(Type expectedType, int myDelta, InstructionAdapter v) {
|
||||
@@ -639,7 +653,7 @@ public class AsmUtil {
|
||||
if (!state.isCallAssertionsEnabled()) return stackValue;
|
||||
if (approximationInfo == null || !TypesPackage.assertNotNull(approximationInfo)) return stackValue;
|
||||
|
||||
return new StackValue(stackValue.type) {
|
||||
return new StackValue.StackValueWithoutReceiver(stackValue.type) {
|
||||
|
||||
@Override
|
||||
public void put(Type type, InstructionAdapter v) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterKind;
|
||||
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterSignature;
|
||||
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
@@ -170,4 +171,8 @@ public class CallableMethod implements Callable {
|
||||
public String toString() {
|
||||
return Printer.OPCODES[invokeOpcode] + " " + owner.getInternalName() + "." + signature;
|
||||
}
|
||||
|
||||
public boolean isStaticCall() {
|
||||
return getInvokeOpcode() == Opcodes.INVOKESTATIC;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ package org.jetbrains.jet.codegen;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import kotlin.Function1;
|
||||
import kotlin.Unit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
||||
@@ -202,18 +204,23 @@ public class ClosureCodegen extends ParentCodegenAware {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue putInstanceOnStack(@NotNull InstructionAdapter v, @NotNull ExpressionCodegen codegen) {
|
||||
if (isConst(closure)) {
|
||||
v.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor());
|
||||
}
|
||||
else {
|
||||
v.anew(asmType);
|
||||
v.dup();
|
||||
public StackValue putInstanceOnStack(@NotNull InstructionAdapter v, @NotNull final ExpressionCodegen codegen) {
|
||||
return StackValue.operation(asmType, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter v) {
|
||||
if (isConst(closure)) {
|
||||
v.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor());
|
||||
}
|
||||
else {
|
||||
v.anew(asmType);
|
||||
v.dup();
|
||||
|
||||
codegen.pushClosureOnStack(classDescriptor, true, codegen.defaultCallGenerator);
|
||||
v.invokespecial(asmType.getInternalName(), "<init>", constructor.getDescriptor(), false);
|
||||
}
|
||||
return StackValue.onStack(asmType);
|
||||
codegen.pushClosureOnStack(classDescriptor, true, codegen.defaultCallGenerator);
|
||||
v.invokespecial(asmType.getInternalName(), "<init>", constructor.getDescriptor(), false);
|
||||
}
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -579,7 +579,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.ifne(ne);
|
||||
}
|
||||
else {
|
||||
StackValue value = genEqualsForExpressionsOnStack(iv, JetTokens.EQEQ, asmType, asmType);
|
||||
StackValue value = genEqualsForExpressionsOnStack(JetTokens.EQEQ, StackValue.onStack(asmType), StackValue.onStack(asmType));
|
||||
value.put(Type.BOOLEAN_TYPE, iv);
|
||||
iv.ifeq(ne);
|
||||
}
|
||||
@@ -802,7 +802,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
assert property != null : "Copy function doesn't correspond to any property: " + function;
|
||||
codegen.v.load(0, thisDescriptorType);
|
||||
Type propertyType = typeMapper.mapType(property);
|
||||
codegen.intermediateValueForProperty(property, false, null).put(propertyType, codegen.v);
|
||||
codegen.intermediateValueForProperty(property, false, null, StackValue.none())
|
||||
.putNoReceiver(propertyType, codegen.v);
|
||||
}
|
||||
},
|
||||
null
|
||||
@@ -898,7 +899,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) &&
|
||||
!isClassObject(bridge.getContainingDeclaration());
|
||||
StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR);
|
||||
StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR, StackValue.none());
|
||||
|
||||
InstructionAdapter iv = codegen.v;
|
||||
|
||||
@@ -1055,18 +1056,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
if (classObjectIndex == -1) {
|
||||
classObjectIndex = frameMap.enter(classObjectDescriptor, OBJECT_TYPE);
|
||||
StackValue classObject = StackValue.singleton(classObjectDescriptor, typeMapper);
|
||||
classObject.put(classObject.type, codegen.v);
|
||||
StackValue.local(classObjectIndex, classObject.type).store(classObject.type, codegen.v);
|
||||
StackValue.local(classObjectIndex, classObject.type).store(classObject, codegen.v);
|
||||
}
|
||||
return classObjectIndex;
|
||||
}
|
||||
|
||||
private void copyFieldFromClassObject(PropertyDescriptor propertyDescriptor) {
|
||||
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||
StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, false, null);
|
||||
property.put(property.type, codegen.v);
|
||||
StackValue.Field field = StackValue.field(property.type, classAsmType, propertyDescriptor.getName().asString(), true);
|
||||
field.store(field.type, codegen.v);
|
||||
StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, false, null, StackValue.none());
|
||||
StackValue.Field field = StackValue.field(property.type, classAsmType, propertyDescriptor.getName().asString(), true, StackValue.none());
|
||||
field.store(property, codegen.v);
|
||||
}
|
||||
|
||||
private void generateClassObjectInitializer(@NotNull ClassDescriptor classObject) {
|
||||
@@ -1136,8 +1135,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
if (isObject(descriptor)) {
|
||||
iv.load(0, classAsmType);
|
||||
StackValue.singleton(descriptor, typeMapper).store(classAsmType, iv);
|
||||
StackValue.singleton(descriptor, typeMapper).store(StackValue.local(0, classAsmType), iv);
|
||||
}
|
||||
|
||||
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
||||
@@ -1210,7 +1208,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
@NotNull
|
||||
public StackValue getStackValue() {
|
||||
return StackValue.field(type, classAsmType, name, false);
|
||||
return StackValue.field(type, classAsmType, name, false, StackValue.none());
|
||||
}
|
||||
}
|
||||
private final Map<JetDelegatorByExpressionSpecifier, Field> fields = new HashMap<JetDelegatorByExpressionSpecifier, Field>();
|
||||
@@ -1271,9 +1269,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
DelegationFieldsInfo.Field fieldInfo = fieldsInfo.getInfo(specifier);
|
||||
if (fieldInfo.generateField) {
|
||||
iv.load(0, classAsmType);
|
||||
codegen.genToJVMStack(expression);
|
||||
|
||||
fieldInfo.getStackValue().store(fieldInfo.type, iv);
|
||||
StackValue rightSide = codegen.genLazy(expression, codegen.expressionType(expression));
|
||||
fieldInfo.getStackValue().store(rightSide, iv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1304,7 +1301,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
else return;
|
||||
|
||||
constructorContext.lookupInContext(toLookup, null, state, true);
|
||||
constructorContext.lookupInContext(toLookup, StackValue.local(0, OBJECT_TYPE), state, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -238,18 +238,14 @@ public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclaratio
|
||||
|
||||
JetType jetType = getPropertyOrDelegateType(property, propertyDescriptor);
|
||||
|
||||
StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null, MethodKind.INITIALIZER);
|
||||
|
||||
if (!propValue.isStatic) {
|
||||
codegen.v.load(0, OBJECT_TYPE);
|
||||
}
|
||||
StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null, MethodKind.INITIALIZER, StackValue.local(0, OBJECT_TYPE));
|
||||
|
||||
Type type = codegen.expressionType(initializer);
|
||||
if (jetType.isNullable()) {
|
||||
type = boxType(type);
|
||||
}
|
||||
codegen.gen(initializer, type);
|
||||
propValue.store(type, codegen.v);
|
||||
|
||||
propValue.store(codegen.genLazy(initializer, type), codegen.v);
|
||||
|
||||
ResolvedCall<FunctionDescriptor> pdResolvedCall =
|
||||
bindingContext.get(BindingContext.DELEGATED_PROPERTY_PD_RESOLVED_CALL, propertyDescriptor);
|
||||
|
||||
@@ -380,14 +380,7 @@ public class PropertyCodegen {
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
InstructionAdapter v = codegen.v;
|
||||
PropertyDescriptor propertyDescriptor = callableDescriptor.getCorrespondingProperty();
|
||||
|
||||
int paramCode = 0;
|
||||
if (codegen.getContext().getContextKind() != OwnerKind.PACKAGE) {
|
||||
v.load(0, OBJECT_TYPE);
|
||||
paramCode = 1;
|
||||
}
|
||||
|
||||
StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, true, null);
|
||||
StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.local(0, OBJECT_TYPE));
|
||||
|
||||
if (callableDescriptor instanceof PropertyGetterDescriptor) {
|
||||
Type type = signature.getReturnType();
|
||||
@@ -396,12 +389,13 @@ public class PropertyCodegen {
|
||||
}
|
||||
else if (callableDescriptor instanceof PropertySetterDescriptor) {
|
||||
ReceiverParameterDescriptor receiverParameter = propertyDescriptor.getExtensionReceiverParameter();
|
||||
int paramCode = codegen.getContext().getContextKind() != OwnerKind.PACKAGE ? 1 : 0;
|
||||
if (receiverParameter != null) {
|
||||
paramCode += codegen.typeMapper.mapType(receiverParameter.getType()).getSize();
|
||||
}
|
||||
Type type = codegen.typeMapper.mapType(propertyDescriptor);
|
||||
v.load(paramCode, type);
|
||||
property.store(type, v);
|
||||
StackValue.Local value = StackValue.local(paramCode, type);
|
||||
property.store(value, codegen.v);
|
||||
v.visitInsn(RETURN);
|
||||
} else {
|
||||
throw new IllegalStateException("Unknown property accessor: " + callableDescriptor);
|
||||
@@ -417,10 +411,6 @@ public class PropertyCodegen {
|
||||
final int indexInPropertyMetadataArray,
|
||||
int propertyMetadataArgumentIndex
|
||||
) {
|
||||
if (codegen.getContext().getContextKind() != OwnerKind.PACKAGE) {
|
||||
codegen.v.load(0, OBJECT_TYPE);
|
||||
}
|
||||
|
||||
CodegenContext<? extends ClassOrPackageFragmentDescriptor> ownerContext = codegen.getContext().getClassOrPackageParentContext();
|
||||
final Type owner;
|
||||
if (ownerContext instanceof ClassContext) {
|
||||
@@ -435,17 +425,18 @@ public class PropertyCodegen {
|
||||
|
||||
codegen.tempVariables.put(
|
||||
resolvedCall.getCall().getValueArguments().get(propertyMetadataArgumentIndex).asElement(),
|
||||
new StackValue(PROPERTY_METADATA_TYPE) {
|
||||
new StackValue.StackValueWithoutReceiver(PROPERTY_METADATA_TYPE) {
|
||||
@Override
|
||||
public void put(Type type, InstructionAdapter v) {
|
||||
v.getstatic(owner.getInternalName(), JvmAbi.PROPERTY_METADATA_ARRAY_NAME, "[" + PROPERTY_METADATA_TYPE);
|
||||
v.iconst(indexInPropertyMetadataArray);
|
||||
StackValue.arrayElement(PROPERTY_METADATA_TYPE).put(type, v);
|
||||
public void put(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||
Field array = StackValue
|
||||
.field(Type.getType("[" + PROPERTY_METADATA_TYPE), owner, JvmAbi.PROPERTY_METADATA_ARRAY_NAME, true,
|
||||
StackValue.none());
|
||||
StackValue.arrayElement(PROPERTY_METADATA_TYPE, array, StackValue.constant(indexInPropertyMetadataArray, Type.INT_TYPE)).put(type, v);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
StackValue delegatedProperty = codegen.intermediateValueForProperty(propertyDescriptor, true, null);
|
||||
StackValue delegatedProperty = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.local(0, OBJECT_TYPE));
|
||||
return codegen.invokeFunction(resolvedCall, delegatedProperty);
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ public class SamWrapperCodegen {
|
||||
|
||||
FunctionDescriptor invokeFunction = functionJetType.getMemberScope()
|
||||
.getFunctions(Name.identifier("invoke")).iterator().next().getOriginal();
|
||||
StackValue functionField = StackValue.field(functionType, ownerType, FUNCTION_FIELD_NAME, false);
|
||||
StackValue functionField = StackValue.field(functionType, ownerType, FUNCTION_FIELD_NAME, false, StackValue.none());
|
||||
codegen.genDelegate(erasedInterfaceFunction, invokeFunction, functionField);
|
||||
|
||||
// generate sam bridges
|
||||
|
||||
@@ -194,8 +194,11 @@ public class ScriptCodegen extends MemberCodegen<JetScript> {
|
||||
StackValue stackValue =
|
||||
new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, methodContext, state, this).gen(scriptDeclaration.getBlockExpression());
|
||||
if (stackValue.type != Type.VOID_TYPE) {
|
||||
StackValue.Field resultValue = StackValue
|
||||
.field(blockType, classType, ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME, false, StackValue.local(0, classType));
|
||||
resultValue.store(stackValue, iv);
|
||||
} else {
|
||||
stackValue.put(blockType, iv);
|
||||
iv.putfield(classType.getInternalName(), ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME, blockType.getDescriptor());
|
||||
}
|
||||
|
||||
iv.areturn(Type.VOID_TYPE);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.jet.codegen.StackValue.StackValueWithReceiver
|
||||
import org.jetbrains.jet.codegen.StackValue.StackValueWithoutReceiver
|
||||
import org.jetbrains.jet.codegen.StackValue.StackValueWithSimpleReceiver
|
||||
|
||||
public fun castValue(value: StackValue, castType: Type): StackValue {
|
||||
return if (value is StackValueWithReceiver) CastValueWithReceiver(value, castType) else CastValue(value, castType)
|
||||
}
|
||||
|
||||
class CastValueWithReceiver(val value: StackValueWithReceiver, val castType: Type) : StackValueWithSimpleReceiver(castType, !value.hasReceiver(true), !value.hasReceiver(false), value.receiver), StackValueI by value {
|
||||
|
||||
override fun putReceiver(v: InstructionAdapter, isRead: Boolean) {
|
||||
value.putReceiver(v, isRead )
|
||||
}
|
||||
|
||||
override fun putNoReceiver(type: Type, v: InstructionAdapter) {
|
||||
value.putNoReceiver(type, v)
|
||||
}
|
||||
|
||||
override fun hasReceiver(isRead: Boolean): Boolean {
|
||||
return value.hasReceiver(isRead)
|
||||
}
|
||||
}
|
||||
|
||||
class CastValue(val value: StackValue, val castType: Type) : StackValueWithoutReceiver(castType), StackValueI by value {
|
||||
|
||||
}
|
||||
|
||||
class FunctionCallStackValue(val resultType: Type, val lambda: (v: InstructionAdapter)-> Unit) : StackValueWithoutReceiver(resultType) {
|
||||
|
||||
override fun put(type: Type, v: InstructionAdapter) {
|
||||
lambda(v)
|
||||
coerceTo(type, v)
|
||||
}
|
||||
|
||||
override fun store(topOfStackType: Type, v: InstructionAdapter) {
|
||||
throw UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public class StackValueWithLeaveTask(val stackValue: StackValue, val leaveTasks: StackValueWithLeaveTask.()-> Unit) : StackValueWithReceiver(stackValue.type, if (stackValue is StackValueWithReceiver) stackValue.receiver else StackValue.none()), StackValueI by stackValue {
|
||||
|
||||
override fun put(type: Type, v: InstructionAdapter) {
|
||||
stackValue.put(type, v)
|
||||
leaveTasks()
|
||||
}
|
||||
|
||||
override fun condJump(label: Label, jumpIfFalse: Boolean, v: InstructionAdapter ) {
|
||||
stackValue.condJump(label, jumpIfFalse, v)
|
||||
leaveTasks()
|
||||
}
|
||||
|
||||
override fun putReceiver(v: InstructionAdapter, isRead: Boolean) {
|
||||
if (stackValue is StackValueWithReceiver) {
|
||||
stackValue.putReceiver(v, isRead)
|
||||
}
|
||||
}
|
||||
|
||||
override fun putNoReceiver(type: Type, v: InstructionAdapter) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun hasReceiver(isRead: Boolean): Boolean {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun store(topOfStackType: Type, v: InstructionAdapter) {
|
||||
throw UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
class OperationStackValue(val resultType: Type, val lambda: (v: InstructionAdapter)-> Unit) : StackValueWithoutReceiver(resultType) {
|
||||
|
||||
override fun put(type: Type, v: InstructionAdapter) {
|
||||
lambda(v)
|
||||
coerceTo(type, v)
|
||||
}
|
||||
|
||||
override fun store(topOfStackType: Type, v: InstructionAdapter) {
|
||||
throw UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.annotations.NotNull;
|
||||
import org.jetbrains.org.objectweb.asm.Label;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
public interface StackValueI {
|
||||
|
||||
void moveToTopOfStack(@NotNull Type type, @NotNull InstructionAdapter v, int depth);
|
||||
|
||||
void put(@NotNull Type type, @NotNull InstructionAdapter v);
|
||||
|
||||
void store(@NotNull Type topOfStackType, @NotNull InstructionAdapter v);
|
||||
|
||||
void store(@NotNull StackValue value, @NotNull InstructionAdapter v);
|
||||
|
||||
void store(@NotNull StackValue value, @NotNull InstructionAdapter v, boolean skipReceiver);
|
||||
|
||||
void condJump(@NotNull Label label, boolean jumpIfFalse, @NotNull InstructionAdapter v);
|
||||
|
||||
void coerceTo(@NotNull Type toType, @NotNull InstructionAdapter v);
|
||||
|
||||
void coerceFrom(@NotNull Type topOfStackType, @NotNull InstructionAdapter v);
|
||||
|
||||
void putAsBoolean(InstructionAdapter v);
|
||||
|
||||
void dup(@NotNull InstructionAdapter v, boolean withReceiver);
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.storage.LockBasedStorageManager;
|
||||
import org.jetbrains.jet.storage.NullableLazyValue;
|
||||
@@ -52,7 +53,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
|
||||
private Map<DeclarationDescriptor, DeclarationDescriptor> accessors;
|
||||
private Map<DeclarationDescriptor, CodegenContext> childContexts;
|
||||
private NullableLazyValue<StackValue> lazyOuterExpression;
|
||||
private NullableLazyValue<StackValue.Field> lazyOuterExpression;
|
||||
|
||||
public CodegenContext(
|
||||
@NotNull T contextDescriptor,
|
||||
@@ -128,7 +129,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
closure.setCaptureThis();
|
||||
}
|
||||
return prefix != null ? StackValue.composed(prefix, lazyOuterExpression.invoke()) : lazyOuterExpression.invoke();
|
||||
return StackValue.changeReceiverForFieldAndSharedVar(lazyOuterExpression.invoke(), prefix);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -260,15 +261,15 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
public abstract boolean isStatic();
|
||||
|
||||
protected void initOuterExpression(@NotNull final JetTypeMapper typeMapper, @NotNull final ClassDescriptor classDescriptor) {
|
||||
lazyOuterExpression = LockBasedStorageManager.NO_LOCKS.createNullableLazyValue(new Function0<StackValue>() {
|
||||
lazyOuterExpression = LockBasedStorageManager.NO_LOCKS.createNullableLazyValue(new Function0<StackValue.Field>() {
|
||||
@Override
|
||||
public StackValue invoke() {
|
||||
public StackValue.Field invoke() {
|
||||
ClassDescriptor enclosingClass = getEnclosingClass();
|
||||
if (enclosingClass == null) return null;
|
||||
|
||||
return canHaveOuter(typeMapper.getBindingContext(), classDescriptor)
|
||||
? StackValue.field(typeMapper.mapType(enclosingClass), typeMapper.mapType(classDescriptor),
|
||||
CAPTURED_THIS_FIELD, false)
|
||||
CAPTURED_THIS_FIELD, false, StackValue.local(0, AsmTypeConstants.OBJECT_TYPE))
|
||||
: null;
|
||||
}
|
||||
});
|
||||
@@ -279,25 +280,25 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
if (closure != null) {
|
||||
EnclosedValueDescriptor answer = closure.getCaptureVariables().get(d);
|
||||
if (answer != null) {
|
||||
StackValue innerValue = answer.getInnerValue();
|
||||
return result == null ? innerValue : StackValue.composed(result, innerValue);
|
||||
return StackValue.changeReceiverForFieldAndSharedVar(answer.getInnerValue(), result);
|
||||
}
|
||||
|
||||
for (LocalLookup.LocalLookupCase aCase : LocalLookup.LocalLookupCase.values()) {
|
||||
if (aCase.isCase(d)) {
|
||||
Type classType = state.getTypeMapper().mapType(getThisDescriptor());
|
||||
StackValue innerValue = aCase.innerValue(d, enclosingLocalLookup, state, closure, classType);
|
||||
StackValue.StackValueWithSimpleReceiver innerValue = aCase.innerValue(d, enclosingLocalLookup, state, closure, classType);
|
||||
if (innerValue == null) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
return result == null ? innerValue : composedOrStatic(result, innerValue);
|
||||
//return result == null ? innerValue : composedOrStatic(result, innerValue);
|
||||
return StackValue.changeReceiverForFieldAndSharedVar(innerValue, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myOuter = getOuterExpression(null, ignoreNoOuter, false);
|
||||
result = result == null || myOuter == null ? myOuter : StackValue.composed(result, myOuter);
|
||||
myOuter = getOuterExpression(result, ignoreNoOuter, false);
|
||||
result = myOuter;
|
||||
}
|
||||
|
||||
StackValue resultValue;
|
||||
@@ -441,15 +442,15 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
return childContexts == null ? null : childContexts.get(child);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static StackValue composedOrStatic(@NotNull StackValue prefix, @NotNull StackValue suffix) {
|
||||
if (isStaticField(suffix)) {
|
||||
return suffix;
|
||||
}
|
||||
return StackValue.composed(prefix, suffix);
|
||||
}
|
||||
//@NotNull
|
||||
//private static StackValue composedOrStatic(@NotNull StackValue prefix, @NotNull StackValue suffix) {
|
||||
// if (isStaticField(suffix)) {
|
||||
// return suffix;
|
||||
// }
|
||||
// return StackValue.composed(prefix, suffix);
|
||||
//}
|
||||
|
||||
private static boolean isStaticField(@NotNull StackValue value) {
|
||||
return value instanceof StackValue.Field && ((StackValue.Field) value).isStatic;
|
||||
return value instanceof StackValue.Field && ((StackValue.Field) value).isStaticPut;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,13 +26,13 @@ import org.jetbrains.org.objectweb.asm.Type;
|
||||
public final class EnclosedValueDescriptor {
|
||||
private final String fieldName;
|
||||
private final DeclarationDescriptor descriptor;
|
||||
private final StackValue innerValue;
|
||||
private final StackValue.StackValueWithSimpleReceiver innerValue;
|
||||
private final Type type;
|
||||
|
||||
public EnclosedValueDescriptor(
|
||||
@NotNull String fieldName,
|
||||
@Nullable DeclarationDescriptor descriptor,
|
||||
@Nullable StackValue innerValue,
|
||||
@NotNull StackValue.StackValueWithSimpleReceiver innerValue,
|
||||
@NotNull Type type
|
||||
) {
|
||||
this.fieldName = fieldName;
|
||||
@@ -51,8 +51,8 @@ public final class EnclosedValueDescriptor {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public StackValue getInnerValue() {
|
||||
@NotNull
|
||||
public StackValue.StackValueWithSimpleReceiver getInnerValue() {
|
||||
return innerValue;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.jet.codegen.binding.MutableClosure;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
@@ -42,7 +43,7 @@ public interface LocalLookup {
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue innerValue(
|
||||
public StackValue.StackValueWithSimpleReceiver innerValue(
|
||||
DeclarationDescriptor d,
|
||||
LocalLookup localLookup,
|
||||
GenerationState state,
|
||||
@@ -59,9 +60,10 @@ public interface LocalLookup {
|
||||
Type type = sharedVarType != null ? sharedVarType : localType;
|
||||
|
||||
String fieldName = "$" + vd.getName();
|
||||
StackValue innerValue = sharedVarType != null
|
||||
? StackValue.fieldForSharedVar(localType, classType, fieldName)
|
||||
: StackValue.field(type, classType, fieldName, false);
|
||||
StackValue.Local thiz = StackValue.local(0, AsmTypeConstants.OBJECT_TYPE);
|
||||
StackValue.StackValueWithSimpleReceiver innerValue = sharedVarType != null
|
||||
? StackValue.fieldForSharedVar(localType, classType, fieldName, thiz)
|
||||
: StackValue.field(type, classType, fieldName, false, thiz);
|
||||
|
||||
closure.recordField(fieldName, type);
|
||||
closure.captureVariable(new EnclosedValueDescriptor(fieldName, d, innerValue, type));
|
||||
@@ -77,7 +79,7 @@ public interface LocalLookup {
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue innerValue(
|
||||
public StackValue.StackValueWithSimpleReceiver innerValue(
|
||||
DeclarationDescriptor d,
|
||||
LocalLookup localLookup,
|
||||
GenerationState state,
|
||||
@@ -96,11 +98,11 @@ public interface LocalLookup {
|
||||
if (localFunClosure != null && JvmCodegenUtil.isConst(localFunClosure)) {
|
||||
// This is an optimization: we can obtain an instance of a const closure simply by GETSTATIC ...$instance
|
||||
// (instead of passing this instance to the constructor and storing as a field)
|
||||
return StackValue.field(localType, localType, JvmAbi.INSTANCE_FIELD, true);
|
||||
return StackValue.field(localType, localType, JvmAbi.INSTANCE_FIELD, true, StackValue.local(0, AsmTypeConstants.OBJECT_TYPE));
|
||||
}
|
||||
|
||||
String fieldName = "$" + vd.getName();
|
||||
StackValue innerValue = StackValue.field(localType, classType, fieldName, false);
|
||||
StackValue.StackValueWithSimpleReceiver innerValue = StackValue.field(localType, classType, fieldName, false, StackValue.local(0, AsmTypeConstants.OBJECT_TYPE));
|
||||
|
||||
closure.recordField(fieldName, localType);
|
||||
closure.captureVariable(new EnclosedValueDescriptor(fieldName, d, innerValue, localType));
|
||||
@@ -116,7 +118,7 @@ public interface LocalLookup {
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue innerValue(
|
||||
public StackValue.StackValueWithSimpleReceiver innerValue(
|
||||
DeclarationDescriptor d,
|
||||
LocalLookup enclosingLocalLookup,
|
||||
GenerationState state,
|
||||
@@ -129,7 +131,7 @@ public interface LocalLookup {
|
||||
|
||||
JetType receiverType = closure.getEnclosingReceiverDescriptor().getType();
|
||||
Type type = state.getTypeMapper().mapType(receiverType);
|
||||
StackValue innerValue = StackValue.field(type, classType, CAPTURED_RECEIVER_FIELD, false);
|
||||
StackValue.StackValueWithSimpleReceiver innerValue = StackValue.field(type, classType, CAPTURED_RECEIVER_FIELD, false, StackValue.local(0, AsmTypeConstants.OBJECT_TYPE));
|
||||
closure.setCaptureReceiver();
|
||||
|
||||
return innerValue;
|
||||
@@ -145,7 +147,7 @@ public interface LocalLookup {
|
||||
|
||||
public abstract boolean isCase(DeclarationDescriptor d);
|
||||
|
||||
public abstract StackValue innerValue(
|
||||
public abstract StackValue.StackValueWithSimpleReceiver innerValue(
|
||||
DeclarationDescriptor d,
|
||||
LocalLookup localLookup,
|
||||
GenerationState state,
|
||||
|
||||
@@ -116,14 +116,4 @@ public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
|
||||
return isInliningLambda;
|
||||
}
|
||||
|
||||
public boolean isSpecialStackValue(StackValue stackValue) {
|
||||
if (isInliningLambda && stackValue instanceof StackValue.Composed) {
|
||||
StackValue prefix = ((StackValue.Composed) stackValue).prefix;
|
||||
StackValue suffix = ((StackValue.Composed) stackValue).suffix;
|
||||
if (prefix instanceof StackValue.Local && ((StackValue.Local) prefix).index == 0) {
|
||||
return suffix instanceof StackValue.Field;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -250,11 +250,11 @@ public class AnonymousObjectTransformer {
|
||||
|
||||
if (fake.getLambda() != null) {
|
||||
//set remap value to skip this fake (captured with lambda already skipped)
|
||||
StackValue composed = StackValue.composed(StackValue.local(0, oldObjectType),
|
||||
StackValue.field(fake.getType(),
|
||||
oldObjectType,
|
||||
fake.getNewFieldName(), false)
|
||||
);
|
||||
StackValue composed = StackValue.field(fake.getType(),
|
||||
oldObjectType,
|
||||
fake.getNewFieldName(),
|
||||
false,
|
||||
StackValue.local(0, oldObjectType));
|
||||
fake.setRemapValue(composed);
|
||||
}
|
||||
}
|
||||
@@ -393,11 +393,11 @@ public class AnonymousObjectTransformer {
|
||||
for (LambdaInfo info : capturedLambdas) {
|
||||
for (CapturedParamDesc desc : info.getCapturedVars()) {
|
||||
CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, getNewFieldName(desc.getFieldName()));
|
||||
StackValue composed = StackValue.composed(StackValue.local(0, oldObjectType),
|
||||
StackValue.field(desc.getType(),
|
||||
oldObjectType, /*TODO owner type*/
|
||||
recapturedParamInfo.getNewFieldName(), false)
|
||||
);
|
||||
StackValue composed = StackValue.field(desc.getType(),
|
||||
oldObjectType, /*TODO owner type*/
|
||||
recapturedParamInfo.getNewFieldName(),
|
||||
false,
|
||||
StackValue.local(0, oldObjectType));
|
||||
recapturedParamInfo.setRemapValue(composed);
|
||||
allRecapturedParameters.add(desc);
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.jetbrains.jet.codegen.inline;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.*;
|
||||
@@ -336,16 +335,20 @@ public class InlineCodegen implements CallGenerator {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stackValue instanceof StackValue.Composed) {
|
||||
//see: Method.isSpecialStackValue: go through aload 0
|
||||
if (codegen.getContext().isInliningLambda() && codegen.getContext().getContextDescriptor() instanceof AnonymousFunctionDescriptor) {
|
||||
if (descriptor != null && !InlineUtil.hasNoinlineAnnotation(descriptor)) {
|
||||
//TODO: check type of context
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//skip direct capturing fields
|
||||
StackValue receiver = null;
|
||||
if (stackValue instanceof StackValue.Field) {
|
||||
receiver = ((StackValue.Field) stackValue).receiver;
|
||||
} else if(stackValue instanceof StackValue.FieldForSharedVar) {
|
||||
receiver = ((StackValue.Field) ((StackValue.FieldForSharedVar) stackValue).receiver).receiver;
|
||||
}
|
||||
return true;
|
||||
|
||||
if (!(receiver instanceof StackValue.Local)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//TODO: check type of context
|
||||
return !(codegen.getContext().isInliningLambda() && descriptor != null && !InlineUtil.hasNoinlineAnnotation(descriptor));
|
||||
}
|
||||
|
||||
private void putParameterOnStack(ParameterInfo... infos) {
|
||||
@@ -364,7 +367,7 @@ public class InlineCodegen implements CallGenerator {
|
||||
ParameterInfo info = infos[i];
|
||||
if (!info.isSkippedOrRemapped()) {
|
||||
Type type = info.type;
|
||||
StackValue.local(index[i], type).store(type, codegen.v);
|
||||
StackValue.local(index[i], type).store(StackValue.onStack(type), codegen.v, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.jet.codegen.inline;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.AsmUtil;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
||||
import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor;
|
||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||
@@ -106,12 +107,25 @@ public class LambdaInfo implements CapturedParamOwner, LabelOwner {
|
||||
capturedVars = new ArrayList<CapturedParamDesc>();
|
||||
|
||||
if (closure.getCaptureThis() != null) {
|
||||
EnclosedValueDescriptor descriptor = new EnclosedValueDescriptor(AsmUtil.CAPTURED_THIS_FIELD, null, null, typeMapper.mapType(closure.getCaptureThis()));
|
||||
Type type = typeMapper.mapType(closure.getCaptureThis());
|
||||
EnclosedValueDescriptor descriptor =
|
||||
new EnclosedValueDescriptor(AsmUtil.CAPTURED_THIS_FIELD,
|
||||
null,
|
||||
StackValue.field(type, closureClassType, AsmUtil.CAPTURED_THIS_FIELD, false,
|
||||
StackValue.local(0, AsmTypeConstants.OBJECT_TYPE)),
|
||||
type);
|
||||
capturedVars.add(getCapturedParamInfo(descriptor));
|
||||
}
|
||||
|
||||
if (closure.getCaptureReceiverType() != null) {
|
||||
EnclosedValueDescriptor descriptor = new EnclosedValueDescriptor(AsmUtil.CAPTURED_RECEIVER_FIELD, null, null, typeMapper.mapType(closure.getCaptureReceiverType()));
|
||||
Type type = typeMapper.mapType(closure.getCaptureReceiverType());
|
||||
EnclosedValueDescriptor descriptor =
|
||||
new EnclosedValueDescriptor(
|
||||
AsmUtil.CAPTURED_RECEIVER_FIELD,
|
||||
null,
|
||||
StackValue.field(type, closureClassType, AsmUtil.CAPTURED_RECEIVER_FIELD, false,
|
||||
StackValue.local(0, AsmTypeConstants.OBJECT_TYPE)),
|
||||
type);
|
||||
capturedVars.add(getCapturedParamInfo(descriptor));
|
||||
}
|
||||
|
||||
|
||||
+4
-6
@@ -91,12 +91,10 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
|
||||
}
|
||||
}
|
||||
|
||||
StackValue result =
|
||||
StackValue.composed(prefix == null ? StackValue.local(0, Type.getObjectType(getLambdaInternalName())) : prefix,
|
||||
StackValue.field(field.getType(),
|
||||
Type.getObjectType(newOwnerType), /*TODO owner type*/
|
||||
field.getNewFieldName(), false)
|
||||
);
|
||||
StackValue result = StackValue.field(field.getType(),
|
||||
Type.getObjectType(newOwnerType), /*TODO owner type*/
|
||||
field.getNewFieldName(), false,
|
||||
prefix == null ? StackValue.local(0, Type.getObjectType(getLambdaInternalName())) : prefix);
|
||||
|
||||
return searchInParent ? parent.getFieldForInline(node, result) : result;
|
||||
}
|
||||
|
||||
@@ -45,18 +45,15 @@ public class Equals extends IntrinsicMethod {
|
||||
StackValue leftExpr;
|
||||
JetExpression rightExpr;
|
||||
if (element instanceof JetCallExpression) {
|
||||
leftExpr = receiver;
|
||||
leftExpr = StackValue.lazyCast(receiver, OBJECT_TYPE);
|
||||
rightExpr = arguments.get(0);
|
||||
}
|
||||
else {
|
||||
leftExpr = codegen.gen(arguments.get(0));
|
||||
leftExpr = codegen.genLazy(arguments.get(0), OBJECT_TYPE);
|
||||
rightExpr = arguments.get(1);
|
||||
}
|
||||
|
||||
leftExpr.put(OBJECT_TYPE, v);
|
||||
codegen.gen(rightExpr).put(OBJECT_TYPE, v);
|
||||
|
||||
genEqualsForExpressionsOnStack(v, JetTokens.EQEQ, OBJECT_TYPE, OBJECT_TYPE).put(returnType, v);
|
||||
genEqualsForExpressionsOnStack(JetTokens.EQEQ, leftExpr, codegen.genLazy(rightExpr, OBJECT_TYPE)).put(returnType, v);
|
||||
return returnType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,17 +42,19 @@ public class IdentityEquals extends IntrinsicMethod {
|
||||
List<JetExpression> arguments,
|
||||
StackValue receiver
|
||||
) {
|
||||
StackValue left;
|
||||
StackValue right;
|
||||
if (element instanceof JetCallExpression) {
|
||||
receiver.put(OBJECT_TYPE, v);
|
||||
codegen.gen(arguments.get(0)).put(OBJECT_TYPE, v);
|
||||
left = StackValue.lazyCast(receiver, OBJECT_TYPE);
|
||||
right = codegen.genLazy(arguments.get(0), OBJECT_TYPE);
|
||||
}
|
||||
else {
|
||||
assert element instanceof JetBinaryExpression;
|
||||
JetBinaryExpression e = (JetBinaryExpression) element;
|
||||
codegen.gen(e.getLeft()).put(OBJECT_TYPE, v);
|
||||
codegen.gen(e.getRight()).put(OBJECT_TYPE, v);
|
||||
left = codegen.genLazy(e.getLeft(), OBJECT_TYPE);
|
||||
right = codegen.genLazy(e.getRight(), OBJECT_TYPE);
|
||||
}
|
||||
StackValue.cmp(JetTokens.EQEQEQ, OBJECT_TYPE).put(returnType, v);
|
||||
StackValue.cmp(JetTokens.EQEQEQ, OBJECT_TYPE, left, right).put(returnType, v);
|
||||
return returnType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,13 +66,13 @@ public class Increment extends IntrinsicMethod {
|
||||
}
|
||||
}
|
||||
StackValue value = codegen.genQualified(receiver, operand);
|
||||
value.dupReceiver(v);
|
||||
value.dupReceiver(v);
|
||||
value = StackValue.complexReceiver(value, StackValue.RECEIVER_READ, StackValue.RECEIVER_WRITE, StackValue.RECEIVER_READ);
|
||||
//value.putReadWriteReadReceiver(v);
|
||||
|
||||
value.put(returnType, v);
|
||||
genIncrement(returnType, myDelta, v);
|
||||
value.store(returnType, v);
|
||||
value.put(returnType, v);
|
||||
StackValue.putNoReceiver(value, returnType, v);
|
||||
}
|
||||
else {
|
||||
receiver.put(returnType, v);
|
||||
|
||||
@@ -17,28 +17,37 @@
|
||||
package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import kotlin.Function1;
|
||||
import kotlin.Unit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.jetbrains.jet.codegen.Callable;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class IntrinsicMethod implements Callable {
|
||||
public final void generate(
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@NotNull InstructionAdapter v,
|
||||
@NotNull Type returnType,
|
||||
@Nullable PsiElement element,
|
||||
@Nullable List<JetExpression> arguments,
|
||||
@Nullable StackValue receiver
|
||||
public final StackValue generate(
|
||||
@NotNull final ExpressionCodegen codegen,
|
||||
@NotNull final InstructionAdapter v,
|
||||
@NotNull final Type returnType,
|
||||
@Nullable final PsiElement element,
|
||||
@Nullable final List<JetExpression> arguments,
|
||||
@Nullable final StackValue receiver
|
||||
) {
|
||||
Type actualType = generateImpl(codegen, v, returnType, element, arguments, receiver);
|
||||
StackValue.coerce(actualType, returnType, v);
|
||||
return StackValue.operation(returnType, new Function1<InstructionAdapter, Unit>() {
|
||||
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter adapter) {
|
||||
Type actualType = generateImpl(codegen, v, returnType, element, arguments, receiver);
|
||||
StackValue.coerce(actualType, returnType, v);
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -38,7 +38,7 @@ public class NewArray extends IntrinsicMethod {
|
||||
List<JetExpression> arguments,
|
||||
StackValue receiver
|
||||
) {
|
||||
codegen.generateNewArray((JetCallExpression) element);
|
||||
codegen.generateNewArray((JetCallExpression) element).put(returnType, v);
|
||||
return returnType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +44,7 @@ public class Not extends IntrinsicMethod {
|
||||
else {
|
||||
stackValue = receiver;
|
||||
}
|
||||
stackValue.put(Type.BOOLEAN_TYPE, v);
|
||||
StackValue.not(StackValue.onStack(Type.BOOLEAN_TYPE)).put(returnType, v);
|
||||
StackValue.not(StackValue.lazyCast(stackValue, Type.BOOLEAN_TYPE)).put(returnType, v);
|
||||
return returnType;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user