Minor: reformat code
This commit is contained in:
+86
-87
@@ -13,20 +13,20 @@ import org.jetbrains.org.objectweb.asm.Type
|
|||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
abstract class NumberLikeCompare(
|
abstract class NumberLikeCompare(
|
||||||
left: StackValue,
|
left: StackValue,
|
||||||
right: StackValue,
|
right: StackValue,
|
||||||
operandType: Type,
|
operandType: Type,
|
||||||
private val opToken: IElementType
|
private val opToken: IElementType
|
||||||
) : BranchedValue(left, right, operandType, NumberCompare.getNumberCompareOpcode(opToken)) {
|
) : BranchedValue(left, right, operandType, NumberCompare.getNumberCompareOpcode(opToken)) {
|
||||||
override fun patchOpcode(opcode: Int, v: InstructionAdapter): Int =
|
override fun patchOpcode(opcode: Int, v: InstructionAdapter): Int =
|
||||||
NumberCompare.patchOpcode(opcode, v, opToken, operandType)
|
NumberCompare.patchOpcode(opcode, v, opToken, operandType)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class SafeCallFusedWithPrimitiveEqualityBase(
|
abstract class SafeCallFusedWithPrimitiveEqualityBase(
|
||||||
opToken: IElementType,
|
opToken: IElementType,
|
||||||
operandType: Type,
|
operandType: Type,
|
||||||
left: StackValue,
|
left: StackValue,
|
||||||
right: StackValue
|
right: StackValue
|
||||||
) : NumberLikeCompare(left, right, operandType, opToken) {
|
) : NumberLikeCompare(left, right, operandType, opToken) {
|
||||||
private val trueIfEqual = opToken == KtTokens.EQEQ || opToken == KtTokens.EQEQEQ
|
private val trueIfEqual = opToken == KtTokens.EQEQ || opToken == KtTokens.EQEQEQ
|
||||||
|
|
||||||
@@ -80,12 +80,12 @@ abstract class SafeCallFusedWithPrimitiveEqualityBase(
|
|||||||
|
|
||||||
|
|
||||||
class SafeCallToPrimitiveEquality(
|
class SafeCallToPrimitiveEquality(
|
||||||
opToken: IElementType,
|
opToken: IElementType,
|
||||||
operandType: Type,
|
operandType: Type,
|
||||||
left: StackValue,
|
left: StackValue,
|
||||||
right: StackValue,
|
right: StackValue,
|
||||||
private val safeReceiverType: Type,
|
private val safeReceiverType: Type,
|
||||||
private val safeReceiverIsNull: Label
|
private val safeReceiverIsNull: Label
|
||||||
) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) {
|
) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) {
|
||||||
override fun cleanupOnNullReceiver(v: InstructionAdapter) {
|
override fun cleanupOnNullReceiver(v: InstructionAdapter) {
|
||||||
v.mark(safeReceiverIsNull)
|
v.mark(safeReceiverIsNull)
|
||||||
@@ -95,12 +95,12 @@ class SafeCallToPrimitiveEquality(
|
|||||||
|
|
||||||
|
|
||||||
class PrimitiveToSafeCallEquality(
|
class PrimitiveToSafeCallEquality(
|
||||||
opToken: IElementType,
|
opToken: IElementType,
|
||||||
operandType: Type,
|
operandType: Type,
|
||||||
left: StackValue,
|
left: StackValue,
|
||||||
right: StackValue,
|
right: StackValue,
|
||||||
private val safeReceiverType: Type,
|
private val safeReceiverType: Type,
|
||||||
private val safeReceiverIsNull: Label
|
private val safeReceiverIsNull: Label
|
||||||
) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) {
|
) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) {
|
||||||
override fun cleanupOnNullReceiver(v: InstructionAdapter) {
|
override fun cleanupOnNullReceiver(v: InstructionAdapter) {
|
||||||
v.mark(safeReceiverIsNull)
|
v.mark(safeReceiverIsNull)
|
||||||
@@ -111,10 +111,10 @@ class PrimitiveToSafeCallEquality(
|
|||||||
|
|
||||||
|
|
||||||
class BoxedToPrimitiveEquality private constructor(
|
class BoxedToPrimitiveEquality private constructor(
|
||||||
leftBoxed: StackValue,
|
leftBoxed: StackValue,
|
||||||
rightPrimitive: StackValue,
|
rightPrimitive: StackValue,
|
||||||
primitiveType: Type,
|
primitiveType: Type,
|
||||||
private val frameMap: FrameMap
|
private val frameMap: FrameMap
|
||||||
) : NumberLikeCompare(leftBoxed, rightPrimitive, primitiveType, KtTokens.EQEQ) {
|
) : NumberLikeCompare(leftBoxed, rightPrimitive, primitiveType, KtTokens.EQEQ) {
|
||||||
private val boxedType = arg1.type
|
private val boxedType = arg1.type
|
||||||
|
|
||||||
@@ -122,31 +122,30 @@ class BoxedToPrimitiveEquality private constructor(
|
|||||||
if (arg2!!.canHaveSideEffects()) {
|
if (arg2!!.canHaveSideEffects()) {
|
||||||
val tmp = frameMap.enterTemp(operandType)
|
val tmp = frameMap.enterTemp(operandType)
|
||||||
doJump(
|
doJump(
|
||||||
v, jumpLabel, jumpIfFalse,
|
v, jumpLabel, jumpIfFalse,
|
||||||
{
|
{
|
||||||
arg1.put(boxedType, v)
|
arg1.put(boxedType, v)
|
||||||
arg2.put(operandType, v)
|
arg2.put(operandType, v)
|
||||||
v.store(tmp, operandType)
|
v.store(tmp, operandType)
|
||||||
},
|
},
|
||||||
{ v.load(tmp, operandType) }
|
{ v.load(tmp, operandType) }
|
||||||
)
|
)
|
||||||
frameMap.leaveTemp(operandType)
|
frameMap.leaveTemp(operandType)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
doJump(
|
doJump(
|
||||||
v, jumpLabel, jumpIfFalse,
|
v, jumpLabel, jumpIfFalse,
|
||||||
{ arg1.put(boxedType, v) },
|
{ arg1.put(boxedType, v) },
|
||||||
{ arg2.put(operandType, v) }
|
{ arg2.put(operandType, v) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun doJump(
|
private inline fun doJump(
|
||||||
v: InstructionAdapter,
|
v: InstructionAdapter,
|
||||||
jumpLabel: Label,
|
jumpLabel: Label,
|
||||||
jumpIfFalse: Boolean,
|
jumpIfFalse: Boolean,
|
||||||
putArg1: () -> Unit,
|
putArg1: () -> Unit,
|
||||||
putArg2: () -> Unit
|
putArg2: () -> Unit
|
||||||
) {
|
) {
|
||||||
val notNullLabel = Label()
|
val notNullLabel = Label()
|
||||||
val endLabel = Label()
|
val endLabel = Label()
|
||||||
@@ -169,34 +168,34 @@ class BoxedToPrimitiveEquality private constructor(
|
|||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun create(
|
fun create(
|
||||||
opToken: IElementType,
|
opToken: IElementType,
|
||||||
left: StackValue,
|
left: StackValue,
|
||||||
leftType: Type,
|
leftType: Type,
|
||||||
right: StackValue,
|
right: StackValue,
|
||||||
rightType: Type,
|
rightType: Type,
|
||||||
frameMap: FrameMap
|
frameMap: FrameMap
|
||||||
): BranchedValue =
|
): BranchedValue =
|
||||||
if (!isApplicable(opToken, leftType, rightType))
|
if (!isApplicable(opToken, leftType, rightType))
|
||||||
throw IllegalArgumentException("Not applicable for $opToken, $leftType, $rightType")
|
throw IllegalArgumentException("Not applicable for $opToken, $leftType, $rightType")
|
||||||
else when (opToken) {
|
else when (opToken) {
|
||||||
KtTokens.EQEQ -> BoxedToPrimitiveEquality(left, right, rightType, frameMap)
|
KtTokens.EQEQ -> BoxedToPrimitiveEquality(left, right, rightType, frameMap)
|
||||||
KtTokens.EXCLEQ -> Invert(BoxedToPrimitiveEquality(left, right, rightType, frameMap))
|
KtTokens.EXCLEQ -> Invert(BoxedToPrimitiveEquality(left, right, rightType, frameMap))
|
||||||
else -> throw AssertionError("Unexpected opToken: $opToken")
|
else -> throw AssertionError("Unexpected opToken: $opToken")
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun isApplicable(opToken: IElementType, leftType: Type, rightType: Type) =
|
fun isApplicable(opToken: IElementType, leftType: Type, rightType: Type) =
|
||||||
(opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) &&
|
(opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) &&
|
||||||
AsmUtil.isIntOrLongPrimitive(rightType) &&
|
AsmUtil.isIntOrLongPrimitive(rightType) &&
|
||||||
AsmUtil.isBoxedTypeOf(leftType, rightType)
|
AsmUtil.isBoxedTypeOf(leftType, rightType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class PrimitiveToSomethingEquality
|
abstract class PrimitiveToSomethingEquality
|
||||||
protected constructor(
|
protected constructor(
|
||||||
leftPrimitive: StackValue,
|
leftPrimitive: StackValue,
|
||||||
right: StackValue,
|
right: StackValue,
|
||||||
primitiveType: Type
|
primitiveType: Type
|
||||||
) : NumberLikeCompare(leftPrimitive, right, primitiveType, KtTokens.EQEQ) {
|
) : NumberLikeCompare(leftPrimitive, right, primitiveType, KtTokens.EQEQ) {
|
||||||
protected val primitiveType = leftPrimitive.type
|
protected val primitiveType = leftPrimitive.type
|
||||||
protected val rightType = right.type
|
protected val rightType = right.type
|
||||||
@@ -227,9 +226,9 @@ protected constructor(
|
|||||||
|
|
||||||
|
|
||||||
class PrimitiveToBoxedEquality private constructor(
|
class PrimitiveToBoxedEquality private constructor(
|
||||||
leftPrimitive: StackValue,
|
leftPrimitive: StackValue,
|
||||||
rightBoxed: StackValue,
|
rightBoxed: StackValue,
|
||||||
primitiveType: Type
|
primitiveType: Type
|
||||||
) : PrimitiveToSomethingEquality(leftPrimitive, rightBoxed, primitiveType) {
|
) : PrimitiveToSomethingEquality(leftPrimitive, rightBoxed, primitiveType) {
|
||||||
private val boxedType = rightBoxed.type
|
private val boxedType = rightBoxed.type
|
||||||
|
|
||||||
@@ -244,27 +243,27 @@ class PrimitiveToBoxedEquality private constructor(
|
|||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun create(opToken: IElementType, left: StackValue, leftType: Type, right: StackValue, rightType: Type): BranchedValue =
|
fun create(opToken: IElementType, left: StackValue, leftType: Type, right: StackValue, rightType: Type): BranchedValue =
|
||||||
if (!isApplicable(opToken, leftType, rightType))
|
if (!isApplicable(opToken, leftType, rightType))
|
||||||
throw IllegalArgumentException("Not applicable for $opToken, $leftType, $rightType")
|
throw IllegalArgumentException("Not applicable for $opToken, $leftType, $rightType")
|
||||||
else when (opToken) {
|
else when (opToken) {
|
||||||
KtTokens.EQEQ -> PrimitiveToBoxedEquality(left, right, leftType)
|
KtTokens.EQEQ -> PrimitiveToBoxedEquality(left, right, leftType)
|
||||||
KtTokens.EXCLEQ -> Invert(PrimitiveToBoxedEquality(left, right, leftType))
|
KtTokens.EXCLEQ -> Invert(PrimitiveToBoxedEquality(left, right, leftType))
|
||||||
else -> throw AssertionError("Unexpected opToken: $opToken")
|
else -> throw AssertionError("Unexpected opToken: $opToken")
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun isApplicable(opToken: IElementType, leftType: Type, rightType: Type) =
|
fun isApplicable(opToken: IElementType, leftType: Type, rightType: Type) =
|
||||||
(opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) &&
|
(opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) &&
|
||||||
AsmUtil.isIntOrLongPrimitive(leftType) &&
|
AsmUtil.isIntOrLongPrimitive(leftType) &&
|
||||||
AsmUtil.isBoxedTypeOf(rightType, leftType)
|
AsmUtil.isBoxedTypeOf(rightType, leftType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PrimitiveToObjectEquality private constructor(
|
class PrimitiveToObjectEquality private constructor(
|
||||||
leftPrimitive: StackValue,
|
leftPrimitive: StackValue,
|
||||||
rightObject: StackValue,
|
rightObject: StackValue,
|
||||||
primitiveType: Type
|
primitiveType: Type
|
||||||
) : PrimitiveToSomethingEquality(leftPrimitive, rightObject, primitiveType) {
|
) : PrimitiveToSomethingEquality(leftPrimitive, rightObject, primitiveType) {
|
||||||
private val boxedType = AsmUtil.boxType(primitiveType)
|
private val boxedType = AsmUtil.boxType(primitiveType)
|
||||||
|
|
||||||
@@ -281,18 +280,18 @@ class PrimitiveToObjectEquality private constructor(
|
|||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun create(opToken: IElementType, left: StackValue, leftType: Type, right: StackValue, rightType: Type): BranchedValue =
|
fun create(opToken: IElementType, left: StackValue, leftType: Type, right: StackValue, rightType: Type): BranchedValue =
|
||||||
if (!isApplicable(opToken, leftType, rightType))
|
if (!isApplicable(opToken, leftType, rightType))
|
||||||
throw IllegalArgumentException("Not applicable for $opToken, $leftType, $rightType")
|
throw IllegalArgumentException("Not applicable for $opToken, $leftType, $rightType")
|
||||||
else when (opToken) {
|
else when (opToken) {
|
||||||
KtTokens.EQEQ -> PrimitiveToObjectEquality(left, right, leftType)
|
KtTokens.EQEQ -> PrimitiveToObjectEquality(left, right, leftType)
|
||||||
KtTokens.EXCLEQ -> Invert(PrimitiveToObjectEquality(left, right, leftType))
|
KtTokens.EXCLEQ -> Invert(PrimitiveToObjectEquality(left, right, leftType))
|
||||||
else -> throw AssertionError("Unexpected opToken: $opToken")
|
else -> throw AssertionError("Unexpected opToken: $opToken")
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun isApplicable(opToken: IElementType, leftType: Type, rightType: Type) =
|
fun isApplicable(opToken: IElementType, leftType: Type, rightType: Type) =
|
||||||
(opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) &&
|
(opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) &&
|
||||||
AsmUtil.isIntOrLongPrimitive(leftType) &&
|
AsmUtil.isIntOrLongPrimitive(leftType) &&
|
||||||
rightType.sort == Type.OBJECT
|
rightType.sort == Type.OBJECT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,10 +16,10 @@ import org.jetbrains.org.objectweb.asm.Type
|
|||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
open class BranchedValue(
|
open class BranchedValue(
|
||||||
val arg1: StackValue,
|
val arg1: StackValue,
|
||||||
val arg2: StackValue? = null,
|
val arg2: StackValue? = null,
|
||||||
val operandType: Type,
|
val operandType: Type,
|
||||||
val opcode: Int
|
val opcode: Int
|
||||||
) : StackValue(Type.BOOLEAN_TYPE) {
|
) : StackValue(Type.BOOLEAN_TYPE) {
|
||||||
|
|
||||||
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
|
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
|
||||||
@@ -59,8 +59,7 @@ open class BranchedValue(
|
|||||||
override fun loopJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
override fun loopJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||||
if (!jumpIfFalse) {
|
if (!jumpIfFalse) {
|
||||||
v.fakeAlwaysTrueIfeq(jumpLabel)
|
v.fakeAlwaysTrueIfeq(jumpLabel)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
v.fakeAlwaysFalseIfeq(jumpLabel)
|
v.fakeAlwaysFalseIfeq(jumpLabel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,8 +80,7 @@ open class BranchedValue(
|
|||||||
override fun loopJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
override fun loopJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||||
if (jumpIfFalse) {
|
if (jumpIfFalse) {
|
||||||
v.fakeAlwaysTrueIfeq(jumpLabel)
|
v.fakeAlwaysTrueIfeq(jumpLabel)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
v.fakeAlwaysFalseIfeq(jumpLabel)
|
v.fakeAlwaysFalseIfeq(jumpLabel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,23 +119,23 @@ open class BranchedValue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun condJump(condition: StackValue): CondJump =
|
fun condJump(condition: StackValue): CondJump =
|
||||||
CondJump(
|
CondJump(
|
||||||
condition as? BranchedValue ?: BranchedValue(condition, null, Type.BOOLEAN_TYPE, IFEQ),
|
condition as? BranchedValue ?: BranchedValue(condition, null, Type.BOOLEAN_TYPE, IFEQ),
|
||||||
IFEQ
|
IFEQ
|
||||||
)
|
)
|
||||||
|
|
||||||
fun cmp(opToken: IElementType, operandType: Type, left: StackValue, right: StackValue): StackValue =
|
fun cmp(opToken: IElementType, operandType: Type, left: StackValue, right: StackValue): StackValue =
|
||||||
if (operandType.sort == Type.OBJECT)
|
if (operandType.sort == Type.OBJECT)
|
||||||
ObjectCompare(opToken, operandType, left, right)
|
ObjectCompare(opToken, operandType, left, right)
|
||||||
else
|
else
|
||||||
NumberCompare(opToken, operandType, left, right)
|
NumberCompare(opToken, operandType, left, right)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class And(
|
class And(
|
||||||
arg1: StackValue,
|
arg1: StackValue,
|
||||||
arg2: StackValue
|
arg2: StackValue
|
||||||
) : BranchedValue(BranchedValue.condJump(arg1), BranchedValue.condJump(arg2), Type.BOOLEAN_TYPE, IFEQ) {
|
) : BranchedValue(BranchedValue.condJump(arg1), BranchedValue.condJump(arg2), Type.BOOLEAN_TYPE, IFEQ) {
|
||||||
|
|
||||||
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||||
@@ -149,8 +147,8 @@ class And(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Or(
|
class Or(
|
||||||
arg1: StackValue,
|
arg1: StackValue,
|
||||||
arg2: StackValue
|
arg2: StackValue
|
||||||
) : BranchedValue(BranchedValue.condJump(arg1), BranchedValue.condJump(arg2), Type.BOOLEAN_TYPE, IFEQ) {
|
) : BranchedValue(BranchedValue.condJump(arg1), BranchedValue.condJump(arg2), Type.BOOLEAN_TYPE, IFEQ) {
|
||||||
|
|
||||||
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||||
@@ -184,14 +182,14 @@ class CondJump(val condition: BranchedValue, op: Int) : BranchedValue(condition,
|
|||||||
}
|
}
|
||||||
|
|
||||||
class NumberCompare(
|
class NumberCompare(
|
||||||
private val opToken: IElementType,
|
private val opToken: IElementType,
|
||||||
operandType: Type,
|
operandType: Type,
|
||||||
left: StackValue,
|
left: StackValue,
|
||||||
right: StackValue
|
right: StackValue
|
||||||
) : BranchedValue(left, right, operandType, NumberCompare.getNumberCompareOpcode(opToken)) {
|
) : BranchedValue(left, right, operandType, NumberCompare.getNumberCompareOpcode(opToken)) {
|
||||||
|
|
||||||
override fun patchOpcode(opcode: Int, v: InstructionAdapter): Int =
|
override fun patchOpcode(opcode: Int, v: InstructionAdapter): Int =
|
||||||
patchOpcode(opcode, v, opToken, operandType)
|
patchOpcode(opcode, v, opToken, operandType)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getNumberCompareOpcode(opToken: IElementType): Int = when (opToken) {
|
fun getNumberCompareOpcode(opToken: IElementType): Int = when (opToken) {
|
||||||
@@ -230,10 +228,10 @@ class NumberCompare(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ObjectCompare(
|
class ObjectCompare(
|
||||||
opToken: IElementType,
|
opToken: IElementType,
|
||||||
operandType: Type,
|
operandType: Type,
|
||||||
left: StackValue,
|
left: StackValue,
|
||||||
right: StackValue
|
right: StackValue
|
||||||
) : BranchedValue(left, right, operandType, ObjectCompare.getObjectCompareOpcode(opToken)) {
|
) : BranchedValue(left, right, operandType, ObjectCompare.getObjectCompareOpcode(opToken)) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -57,9 +57,9 @@ import org.jetbrains.org.objectweb.asm.commons.Method
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
fun generateIsCheck(
|
fun generateIsCheck(
|
||||||
v: InstructionAdapter,
|
v: InstructionAdapter,
|
||||||
kotlinType: KotlinType,
|
kotlinType: KotlinType,
|
||||||
asmType: Type
|
asmType: Type
|
||||||
) {
|
) {
|
||||||
if (TypeUtils.isNullableType(kotlinType)) {
|
if (TypeUtils.isNullableType(kotlinType)) {
|
||||||
val nope = Label()
|
val nope = Label()
|
||||||
@@ -80,24 +80,22 @@ fun generateIsCheck(
|
|||||||
|
|
||||||
mark(end)
|
mark(end)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
TypeIntrinsics.instanceOf(v, kotlinType, asmType)
|
TypeIntrinsics.instanceOf(v, kotlinType, asmType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateAsCast(
|
fun generateAsCast(
|
||||||
v: InstructionAdapter,
|
v: InstructionAdapter,
|
||||||
kotlinType: KotlinType,
|
kotlinType: KotlinType,
|
||||||
asmType: Type,
|
asmType: Type,
|
||||||
isSafe: Boolean
|
isSafe: Boolean
|
||||||
) {
|
) {
|
||||||
if (!isSafe) {
|
if (!isSafe) {
|
||||||
if (!TypeUtils.isNullableType(kotlinType)) {
|
if (!TypeUtils.isNullableType(kotlinType)) {
|
||||||
generateNullCheckForNonSafeAs(v, kotlinType)
|
generateNullCheckForNonSafeAs(v, kotlinType)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
with(v) {
|
with(v) {
|
||||||
dup()
|
dup()
|
||||||
TypeIntrinsics.instanceOf(v, kotlinType, asmType)
|
TypeIntrinsics.instanceOf(v, kotlinType, asmType)
|
||||||
@@ -113,22 +111,30 @@ fun generateAsCast(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateNullCheckForNonSafeAs(
|
private fun generateNullCheckForNonSafeAs(
|
||||||
v: InstructionAdapter,
|
v: InstructionAdapter,
|
||||||
type: KotlinType
|
type: KotlinType
|
||||||
) {
|
) {
|
||||||
with(v) {
|
with(v) {
|
||||||
dup()
|
dup()
|
||||||
val nonnull = Label()
|
val nonnull = Label()
|
||||||
ifnonnull(nonnull)
|
ifnonnull(nonnull)
|
||||||
AsmUtil.genThrow(v, "kotlin/TypeCastException", "null cannot be cast to non-null type " + DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type))
|
AsmUtil.genThrow(
|
||||||
|
v,
|
||||||
|
"kotlin/TypeCastException",
|
||||||
|
"null cannot be cast to non-null type " + DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type)
|
||||||
|
)
|
||||||
mark(nonnull)
|
mark(nonnull)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SpecialSignatureInfo.replaceValueParametersIn(sourceSignature: String?): String?
|
fun SpecialSignatureInfo.replaceValueParametersIn(sourceSignature: String?): String? =
|
||||||
= valueParametersSignature?.let { sourceSignature?.replace("^\\(.*\\)".toRegex(), "($it)") }
|
valueParametersSignature?.let { sourceSignature?.replace("^\\(.*\\)".toRegex(), "($it)") }
|
||||||
|
|
||||||
fun populateCompanionBackingFieldNamesToOuterContextIfNeeded(companion: KtObjectDeclaration, outerContext: FieldOwnerContext<*>, state: GenerationState) {
|
fun populateCompanionBackingFieldNamesToOuterContextIfNeeded(
|
||||||
|
companion: KtObjectDeclaration,
|
||||||
|
outerContext: FieldOwnerContext<*>,
|
||||||
|
state: GenerationState
|
||||||
|
) {
|
||||||
val descriptor = state.bindingContext.get(BindingContext.CLASS, companion)
|
val descriptor = state.bindingContext.get(BindingContext.CLASS, companion)
|
||||||
|
|
||||||
if (descriptor == null || ErrorUtils.isError(descriptor)) {
|
if (descriptor == null || ErrorUtils.isError(descriptor)) {
|
||||||
@@ -150,16 +156,20 @@ fun populateCompanionBackingFieldNamesToOuterContextIfNeeded(companion: KtObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: inline and remove then ScriptCodegen is converted to Kotlin
|
// TODO: inline and remove then ScriptCodegen is converted to Kotlin
|
||||||
fun mapSupertypesNames(typeMapper: KotlinTypeMapper, supertypes: List<ClassDescriptor>, signatureVisitor: JvmSignatureWriter?): Array<String> =
|
fun mapSupertypesNames(
|
||||||
supertypes.map { typeMapper.mapSupertype(it.defaultType, signatureVisitor).internalName }.toTypedArray()
|
typeMapper: KotlinTypeMapper,
|
||||||
|
supertypes: List<ClassDescriptor>,
|
||||||
|
signatureVisitor: JvmSignatureWriter?
|
||||||
|
): Array<String> =
|
||||||
|
supertypes.map { typeMapper.mapSupertype(it.defaultType, signatureVisitor).internalName }.toTypedArray()
|
||||||
|
|
||||||
|
|
||||||
// Top level subclasses of a sealed class should be generated before that sealed class,
|
// Top level subclasses of a sealed class should be generated before that sealed class,
|
||||||
// so that we'd generate the necessary accessor for its constructor afterwards
|
// so that we'd generate the necessary accessor for its constructor afterwards
|
||||||
fun sortTopLevelClassesAndPrepareContextForSealedClasses(
|
fun sortTopLevelClassesAndPrepareContextForSealedClasses(
|
||||||
classOrObjects: List<KtClassOrObject>,
|
classOrObjects: List<KtClassOrObject>,
|
||||||
packagePartContext: PackageContext,
|
packagePartContext: PackageContext,
|
||||||
state: GenerationState
|
state: GenerationState
|
||||||
): List<KtClassOrObject> {
|
): List<KtClassOrObject> {
|
||||||
fun prepareContextIfNeeded(descriptor: ClassDescriptor?) {
|
fun prepareContextIfNeeded(descriptor: ClassDescriptor?) {
|
||||||
if (DescriptorUtils.isSealedClass(descriptor)) {
|
if (DescriptorUtils.isSealedClass(descriptor)) {
|
||||||
@@ -183,8 +193,7 @@ fun sortTopLevelClassesAndPrepareContextForSealedClasses(
|
|||||||
val descriptor = state.bindingContext.get(BindingContext.CLASS, classOrObject)
|
val descriptor = state.bindingContext.get(BindingContext.CLASS, classOrObject)
|
||||||
if (descriptor == null) {
|
if (descriptor == null) {
|
||||||
result.add(classOrObject)
|
result.add(classOrObject)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
prepareContextIfNeeded(descriptor)
|
prepareContextIfNeeded(descriptor)
|
||||||
descriptorToPsi[descriptor] = classOrObject
|
descriptorToPsi[descriptor] = classOrObject
|
||||||
}
|
}
|
||||||
@@ -199,17 +208,17 @@ fun sortTopLevelClassesAndPrepareContextForSealedClasses(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun CallableMemberDescriptor.isDefinitelyNotDefaultImplsMethod() =
|
fun CallableMemberDescriptor.isDefinitelyNotDefaultImplsMethod() =
|
||||||
this is JavaCallableMemberDescriptor || this.annotations.hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME)
|
this is JavaCallableMemberDescriptor || this.annotations.hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME)
|
||||||
|
|
||||||
|
|
||||||
fun ClassBuilder.generateMethod(
|
fun ClassBuilder.generateMethod(
|
||||||
debugString: String,
|
debugString: String,
|
||||||
access: Int,
|
access: Int,
|
||||||
method: Method,
|
method: Method,
|
||||||
element: PsiElement?,
|
element: PsiElement?,
|
||||||
origin: JvmDeclarationOrigin,
|
origin: JvmDeclarationOrigin,
|
||||||
state: GenerationState,
|
state: GenerationState,
|
||||||
generate: InstructionAdapter.() -> Unit
|
generate: InstructionAdapter.() -> Unit
|
||||||
) {
|
) {
|
||||||
val mv = this.newMethod(origin, access, method.name, method.descriptor, null, null)
|
val mv = this.newMethod(origin, access, method.name, method.descriptor, null, null)
|
||||||
|
|
||||||
@@ -224,44 +233,44 @@ fun ClassBuilder.generateMethod(
|
|||||||
|
|
||||||
|
|
||||||
fun reportTarget6InheritanceErrorIfNeeded(
|
fun reportTarget6InheritanceErrorIfNeeded(
|
||||||
classDescriptor: ClassDescriptor, classElement: PsiElement, restrictedInheritance: List<FunctionDescriptor>, state:GenerationState
|
classDescriptor: ClassDescriptor, classElement: PsiElement, restrictedInheritance: List<FunctionDescriptor>, state: GenerationState
|
||||||
) {
|
) {
|
||||||
if (!restrictedInheritance.isEmpty()) {
|
if (!restrictedInheritance.isEmpty()) {
|
||||||
val groupBy = restrictedInheritance.groupBy { descriptor -> descriptor.containingDeclaration as ClassDescriptor }
|
val groupBy = restrictedInheritance.groupBy { descriptor -> descriptor.containingDeclaration as ClassDescriptor }
|
||||||
|
|
||||||
for ((key, value) in groupBy) {
|
for ((key, value) in groupBy) {
|
||||||
state.diagnostics.report(
|
state.diagnostics.report(
|
||||||
ErrorsJvm.TARGET6_INTERFACE_INHERITANCE.on(
|
ErrorsJvm.TARGET6_INTERFACE_INHERITANCE.on(
|
||||||
classElement, classDescriptor, key,
|
classElement, classDescriptor, key,
|
||||||
value.joinToString(separator = "\n", prefix = "\n") {
|
value.joinToString(separator = "\n", prefix = "\n") {
|
||||||
Renderers.COMPACT.render(JvmCodegenUtil.getDirectMember(it), RenderingContext.Empty)
|
Renderers.COMPACT.render(JvmCodegenUtil.getDirectMember(it), RenderingContext.Empty)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CallableDescriptor.isJvmStaticInObjectOrClassOrInterface(): Boolean =
|
fun CallableDescriptor.isJvmStaticInObjectOrClassOrInterface(): Boolean =
|
||||||
isJvmStaticIn {
|
isJvmStaticIn {
|
||||||
DescriptorUtils.isNonCompanionObject(it) ||
|
DescriptorUtils.isNonCompanionObject(it) ||
|
||||||
// This is necessary because for generation of @JvmStatic methods from companion of class A
|
// This is necessary because for generation of @JvmStatic methods from companion of class A
|
||||||
// we create a synthesized descriptor containing in class A
|
// we create a synthesized descriptor containing in class A
|
||||||
DescriptorUtils.isClassOrEnumClass(it) || DescriptorUtils.isInterface(it)
|
DescriptorUtils.isClassOrEnumClass(it) || DescriptorUtils.isInterface(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CallableDescriptor.isJvmStaticInCompanionObject(): Boolean =
|
fun CallableDescriptor.isJvmStaticInCompanionObject(): Boolean =
|
||||||
isJvmStaticIn { DescriptorUtils.isCompanionObject(it) }
|
isJvmStaticIn { DescriptorUtils.isCompanionObject(it) }
|
||||||
|
|
||||||
private fun CallableDescriptor.isJvmStaticIn(predicate: (DeclarationDescriptor) -> Boolean): Boolean =
|
private fun CallableDescriptor.isJvmStaticIn(predicate: (DeclarationDescriptor) -> Boolean): Boolean =
|
||||||
when (this) {
|
when (this) {
|
||||||
is PropertyAccessorDescriptor -> {
|
is PropertyAccessorDescriptor -> {
|
||||||
val propertyDescriptor = correspondingProperty
|
val propertyDescriptor = correspondingProperty
|
||||||
predicate(propertyDescriptor.containingDeclaration) &&
|
predicate(propertyDescriptor.containingDeclaration) &&
|
||||||
(hasJvmStaticAnnotation() || propertyDescriptor.hasJvmStaticAnnotation())
|
(hasJvmStaticAnnotation() || propertyDescriptor.hasJvmStaticAnnotation())
|
||||||
}
|
|
||||||
else -> predicate(containingDeclaration) && hasJvmStaticAnnotation()
|
|
||||||
}
|
}
|
||||||
|
else -> predicate(containingDeclaration) && hasJvmStaticAnnotation()
|
||||||
|
}
|
||||||
|
|
||||||
fun Collection<VariableDescriptor>.filterOutDescriptorsWithSpecialNames() = filterNot { it.name.isSpecial }
|
fun Collection<VariableDescriptor>.filterOutDescriptorsWithSpecialNames() = filterNot { it.name.isSpecial }
|
||||||
|
|
||||||
@@ -271,10 +280,10 @@ class TypeAndNullability(@JvmField val type: Type, @JvmField val isNullable: Boo
|
|||||||
class JvmKotlinType(val type: Type, val kotlinType: KotlinType?)
|
class JvmKotlinType(val type: Type, val kotlinType: KotlinType?)
|
||||||
|
|
||||||
fun calcTypeForIEEE754ArithmeticIfNeeded(
|
fun calcTypeForIEEE754ArithmeticIfNeeded(
|
||||||
expression: KtExpression?,
|
expression: KtExpression?,
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
descriptor: DeclarationDescriptor,
|
descriptor: DeclarationDescriptor,
|
||||||
languageVersionSettings: LanguageVersionSettings
|
languageVersionSettings: LanguageVersionSettings
|
||||||
): TypeAndNullability? {
|
): TypeAndNullability? {
|
||||||
val ktType = expression.kotlinType(bindingContext) ?: return null
|
val ktType = expression.kotlinType(bindingContext) ?: return null
|
||||||
|
|
||||||
@@ -300,7 +309,7 @@ fun calcTypeForIEEE754ArithmeticIfNeeded(
|
|||||||
fun KotlinType.asmType(typeMapper: KotlinTypeMapper) = typeMapper.mapType(this)
|
fun KotlinType.asmType(typeMapper: KotlinTypeMapper) = typeMapper.mapType(this)
|
||||||
|
|
||||||
fun KtExpression?.asmType(typeMapper: KotlinTypeMapper, bindingContext: BindingContext): Type =
|
fun KtExpression?.asmType(typeMapper: KotlinTypeMapper, bindingContext: BindingContext): Type =
|
||||||
this.kotlinType(bindingContext)?.asmType(typeMapper) ?: Type.VOID_TYPE
|
this.kotlinType(bindingContext)?.asmType(typeMapper) ?: Type.VOID_TYPE
|
||||||
|
|
||||||
fun KtExpression?.kotlinType(bindingContext: BindingContext) = this?.let(bindingContext::getType)
|
fun KtExpression?.kotlinType(bindingContext: BindingContext) = this?.let(bindingContext::getType)
|
||||||
|
|
||||||
@@ -322,7 +331,7 @@ fun FunctionDescriptor.isGenericToArray(): Boolean {
|
|||||||
|
|
||||||
val elementType = typeParameters[0].defaultType
|
val elementType = typeParameters[0].defaultType
|
||||||
return KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(returnType)) &&
|
return KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(returnType)) &&
|
||||||
KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(paramType))
|
KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(paramType))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FunctionDescriptor.isNonGenericToArray(): Boolean {
|
fun FunctionDescriptor.isNonGenericToArray(): Boolean {
|
||||||
@@ -361,13 +370,13 @@ fun initializeVariablesForDestructuredLambdaParameters(codegen: ExpressionCodege
|
|||||||
}
|
}
|
||||||
|
|
||||||
val destructuringDeclaration =
|
val destructuringDeclaration =
|
||||||
(DescriptorToSourceUtils.descriptorToDeclaration(parameterDescriptor) as? KtParameter)?.destructuringDeclaration
|
(DescriptorToSourceUtils.descriptorToDeclaration(parameterDescriptor) as? KtParameter)?.destructuringDeclaration
|
||||||
?: error("Destructuring declaration for descriptor $parameterDescriptor not found")
|
?: error("Destructuring declaration for descriptor $parameterDescriptor not found")
|
||||||
|
|
||||||
codegen.initializeDestructuringDeclarationVariables(
|
codegen.initializeDestructuringDeclarationVariables(
|
||||||
destructuringDeclaration,
|
destructuringDeclaration,
|
||||||
TransientReceiver(parameterDescriptor.type),
|
TransientReceiver(parameterDescriptor.type),
|
||||||
codegen.findLocalOrCapturedValue(parameterDescriptor) ?: error("Local var not found for parameter $parameterDescriptor")
|
codegen.findLocalOrCapturedValue(parameterDescriptor) ?: error("Local var not found for parameter $parameterDescriptor")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,9 +392,9 @@ inline fun FrameMap.useTmpVar(type: Type, block: (index: Int) -> Unit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun InstructionAdapter.generateNewInstanceDupAndPlaceBeforeStackTop(
|
fun InstructionAdapter.generateNewInstanceDupAndPlaceBeforeStackTop(
|
||||||
frameMap: FrameMap,
|
frameMap: FrameMap,
|
||||||
topStackType: Type,
|
topStackType: Type,
|
||||||
newInstanceInternalName: String
|
newInstanceInternalName: String
|
||||||
) {
|
) {
|
||||||
frameMap.useTmpVar(topStackType) { index ->
|
frameMap.useTmpVar(topStackType) { index ->
|
||||||
store(index, topStackType)
|
store(index, topStackType)
|
||||||
@@ -410,17 +419,17 @@ fun extractReificationArgument(type: KotlinType): Pair<TypeParameterDescriptor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun unwrapInitialSignatureDescriptor(function: FunctionDescriptor): FunctionDescriptor =
|
fun unwrapInitialSignatureDescriptor(function: FunctionDescriptor): FunctionDescriptor =
|
||||||
function.initialSignatureDescriptor ?: function
|
function.initialSignatureDescriptor ?: function
|
||||||
|
|
||||||
fun ExpressionCodegen.generateCallReceiver(call: ResolvedCall<out CallableDescriptor>): StackValue =
|
fun ExpressionCodegen.generateCallReceiver(call: ResolvedCall<out CallableDescriptor>): StackValue =
|
||||||
generateReceiverValue(call.extensionReceiver ?: call.dispatchReceiver!!, false)
|
generateReceiverValue(call.extensionReceiver ?: call.dispatchReceiver!!, false)
|
||||||
|
|
||||||
fun ExpressionCodegen.generateCallSingleArgument(call: ResolvedCall<out CallableDescriptor>): StackValue =
|
fun ExpressionCodegen.generateCallSingleArgument(call: ResolvedCall<out CallableDescriptor>): StackValue =
|
||||||
gen(call.getFirstArgumentExpression()!!)
|
gen(call.getFirstArgumentExpression()!!)
|
||||||
|
|
||||||
fun ClassDescriptor.isPossiblyUninitializedSingleton() =
|
fun ClassDescriptor.isPossiblyUninitializedSingleton() =
|
||||||
DescriptorUtils.isEnumEntry(this) ||
|
DescriptorUtils.isEnumEntry(this) ||
|
||||||
DescriptorUtils.isCompanionObject(this) && JvmCodegenUtil.isJvmInterface(this.containingDeclaration)
|
DescriptorUtils.isCompanionObject(this) && JvmCodegenUtil.isJvmInterface(this.containingDeclaration)
|
||||||
|
|
||||||
val CodegenContext<*>.parentContextsWithSelf
|
val CodegenContext<*>.parentContextsWithSelf
|
||||||
get() = generateSequence(this) { it.parentContext }
|
get() = generateSequence(this) { it.parentContext }
|
||||||
|
|||||||
Reference in New Issue
Block a user