From 275c758da12553f4140967698a8f0123f118664b Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Thu, 13 Jul 2017 14:01:37 +0300 Subject: [PATCH] Cleanup and move code around in BranchedValue - Cleanup inspections - Move optimized boxed-vs-primitive comparisons to a separate file --- .../codegen/BoxedVsPrimitiveBranchedValues.kt | 114 ++++++++++++++ .../jetbrains/kotlin/codegen/BranchedValue.kt | 144 +++--------------- 2 files changed, 136 insertions(+), 122 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/BoxedVsPrimitiveBranchedValues.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/BoxedVsPrimitiveBranchedValues.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/BoxedVsPrimitiveBranchedValues.kt new file mode 100644 index 00000000000..6b56fd6ea26 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/BoxedVsPrimitiveBranchedValues.kt @@ -0,0 +1,114 @@ +/* + * Copyright 2010-2017 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.kotlin.codegen + +import com.intellij.psi.tree.IElementType +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.org.objectweb.asm.Label +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter + +abstract class SafeCallFusedWithPrimitiveEqualityBase( + private val opToken: IElementType, + operandType: Type, + left: StackValue, + right: StackValue +) : BranchedValue(left, right, operandType, NumberCompare.getNumberCompareOpcode(opToken)) { + private val trueIfEqual = opToken == KtTokens.EQEQ || opToken == KtTokens.EQEQEQ + + protected abstract fun cleanupOnNullReceiver(v: InstructionAdapter) + + override fun patchOpcode(opcode: Int, v: InstructionAdapter): Int = + NumberCompare.patchOpcode(opcode, v, opToken, operandType) + + override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) { + val endLabel = Label() + + arg1.put(operandType, v) + arg2!!.put(operandType, v) + v.visitJumpInsn(patchOpcode(if (jumpIfFalse) opcode else negatedOperations[opcode]!!, v), jumpLabel) + v.goTo(endLabel) + + cleanupOnNullReceiver(v) + if (jumpIfFalse == trueIfEqual) { + v.goTo(jumpLabel) + } + + v.mark(endLabel) + } + + override fun putSelector(type: Type, v: InstructionAdapter) { + val falseLabel = Label() + val endLabel = Label() + + arg1.put(operandType, v) + arg2!!.put(operandType, v) + v.visitJumpInsn(patchOpcode(opcode, v), falseLabel) + + if (!trueIfEqual) { + val trueLabel = Label() + v.goTo(trueLabel) + cleanupOnNullReceiver(v) + v.mark(trueLabel) + } + + v.iconst(1) + v.goTo(endLabel) + + if (trueIfEqual) { + cleanupOnNullReceiver(v) + } + + v.mark(falseLabel) + v.iconst(0) + + v.mark(endLabel) + coerceTo(type, v) + } +} + + +class SafeCallToPrimitiveEquality( + opToken: IElementType, + operandType: Type, + left: StackValue, + right: StackValue, + private val safeReceiverType: Type, + private val safeReceiverIsNull: Label +) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) { + override fun cleanupOnNullReceiver(v: InstructionAdapter) { + v.mark(safeReceiverIsNull) + AsmUtil.pop(v, safeReceiverType) + } +} + + +class PrimitiveToSafeCallEquality( + opToken: IElementType, + operandType: Type, + left: StackValue, + right: StackValue, + private val safeReceiverType: Type, + private val safeReceiverIsNull: Label +) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) { + override fun cleanupOnNullReceiver(v: InstructionAdapter) { + v.mark(safeReceiverIsNull) + AsmUtil.pop(v, safeReceiverType) + AsmUtil.pop(v, arg1.type) + } +} + diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/BranchedValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/BranchedValue.kt index 4c3257aba02..4d76cbe09b1 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/BranchedValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/BranchedValue.kt @@ -54,9 +54,7 @@ open class BranchedValue( condJump(jumpLabel, v, jumpIfFalse) } - protected open fun patchOpcode(opcode: Int, v: InstructionAdapter): Int { - return opcode - } + protected open fun patchOpcode(opcode: Int, v: InstructionAdapter): Int = opcode companion object { val negatedOperations = hashMapOf() @@ -120,13 +118,9 @@ open class BranchedValue( negatedOperations.put(negatedOp, op) } - fun booleanConstant(value: Boolean): BranchedValue { - return if (value) TRUE else FALSE - } + fun booleanConstant(value: Boolean): BranchedValue = if (value) TRUE else FALSE - fun createInvertValue(argument: StackValue): StackValue { - return Invert(condJump(argument)) - } + fun createInvertValue(argument: StackValue): StackValue = Invert(condJump(argument)) fun condJump(condition: StackValue, label: Label, jumpIfFalse: Boolean, iv: InstructionAdapter) { condJump(condition).condJump(label, iv, jumpIfFalse) @@ -136,14 +130,11 @@ open class BranchedValue( condJump(condition).loopJump(label, iv, jumpIfFalse) } - fun condJump(condition: StackValue): CondJump { - return CondJump(if (condition is BranchedValue) { - condition - } - else { - BranchedValue(condition, null, Type.BOOLEAN_TYPE, IFEQ) - }, IFEQ) - } + fun condJump(condition: StackValue): CondJump = + CondJump( + condition as? BranchedValue ?: BranchedValue(condition, null, Type.BOOLEAN_TYPE, IFEQ), + IFEQ + ) fun cmp(opToken: IElementType, operandType: Type, left: StackValue, right: StackValue): StackValue = if (operandType.sort == Type.OBJECT) @@ -203,7 +194,7 @@ class CondJump(val condition: BranchedValue, op: Int) : BranchedValue(condition, } class NumberCompare( - val opToken: IElementType, + private val opToken: IElementType, operandType: Type, left: StackValue, right: StackValue @@ -213,17 +204,15 @@ class NumberCompare( patchOpcode(opcode, v, opToken, operandType) companion object { - fun getNumberCompareOpcode(opToken: IElementType): Int { - return when (opToken) { - KtTokens.EQEQ, KtTokens.EQEQEQ -> IFNE - KtTokens.EXCLEQ, KtTokens.EXCLEQEQEQ -> IFEQ - KtTokens.GT -> IFLE - KtTokens.GTEQ -> IFLT - KtTokens.LT -> IFGE - KtTokens.LTEQ -> IFGT - else -> { - throw UnsupportedOperationException("Don't know how to generate this condJump: " + opToken) - } + fun getNumberCompareOpcode(opToken: IElementType): Int = when (opToken) { + KtTokens.EQEQ, KtTokens.EQEQEQ -> IFNE + KtTokens.EXCLEQ, KtTokens.EXCLEQEQEQ -> IFEQ + KtTokens.GT -> IFLE + KtTokens.GTEQ -> IFLT + KtTokens.LT -> IFGE + KtTokens.LTEQ -> IFGT + else -> { + throw UnsupportedOperationException("Don't know how to generate this condJump: " + opToken) } } @@ -258,100 +247,11 @@ class ObjectCompare( ) : BranchedValue(left, right, operandType, ObjectCompare.getObjectCompareOpcode(opToken)) { companion object { - fun getObjectCompareOpcode(opToken: IElementType): Int { - return when (opToken) { - KtTokens.EQEQEQ -> IF_ACMPNE - KtTokens.EXCLEQEQEQ -> IF_ACMPEQ - else -> throw UnsupportedOperationException("don't know how to generate this condjump") - } + fun getObjectCompareOpcode(opToken: IElementType): Int = when (opToken) { + KtTokens.EQEQEQ -> IF_ACMPNE + KtTokens.EXCLEQEQEQ -> IF_ACMPEQ + else -> throw UnsupportedOperationException("don't know how to generate this condjump") } } } -abstract class SafeCallFusedWithPrimitiveEqualityBase( - val opToken: IElementType, - operandType: Type, - left: StackValue, - right: StackValue -) : BranchedValue(left, right, operandType, NumberCompare.getNumberCompareOpcode(opToken)) { - private val trueIfEqual = opToken == KtTokens.EQEQ || opToken == KtTokens.EQEQEQ - - protected abstract fun cleanupOnNullReceiver(v: InstructionAdapter) - - override fun patchOpcode(opcode: Int, v: InstructionAdapter): Int = - NumberCompare.patchOpcode(opcode, v, opToken, operandType) - - override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) { - val endLabel = Label() - - arg1.put(operandType, v) - arg2!!.put(operandType, v) - v.visitJumpInsn(patchOpcode(if (jumpIfFalse) opcode else negatedOperations[opcode]!!, v), jumpLabel) - v.goTo(endLabel) - - cleanupOnNullReceiver(v) - if (jumpIfFalse == trueIfEqual) { - v.goTo(jumpLabel) - } - - v.mark(endLabel) - } - - override fun putSelector(type: Type, v: InstructionAdapter) { - val falseLabel = Label() - val endLabel = Label() - - arg1.put(operandType, v) - arg2!!.put(operandType, v) - v.visitJumpInsn(patchOpcode(opcode, v), falseLabel) - - if (!trueIfEqual) { - val trueLabel = Label() - v.goTo(trueLabel) - cleanupOnNullReceiver(v) - v.mark(trueLabel) - } - - v.iconst(1) - v.goTo(endLabel) - - if (trueIfEqual) { - cleanupOnNullReceiver(v) - } - - v.mark(falseLabel) - v.iconst(0) - - v.mark(endLabel) - coerceTo(type, v) - } -} - -class SafeCallToPrimitiveEquality( - opToken: IElementType, - operandType: Type, - left: StackValue, - right: StackValue, - val safeReceiverType: Type, - val safeReceiverIsNull: Label -) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) { - override fun cleanupOnNullReceiver(v: InstructionAdapter) { - v.mark(safeReceiverIsNull) - AsmUtil.pop(v, safeReceiverType) - } -} - -class PrimitiveToSafeCallEquality( - opToken: IElementType, - operandType: Type, - left: StackValue, - right: StackValue, - val safeReceiverType: Type, - val safeReceiverIsNull: Label -) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) { - override fun cleanupOnNullReceiver(v: InstructionAdapter) { - v.mark(safeReceiverIsNull) - AsmUtil.pop(v, safeReceiverType) - AsmUtil.pop(v, arg1.type) - } -} \ No newline at end of file