Implement inlining of Array constructor in JS BE
See KT-15456
This commit is contained in:
@@ -1,6 +1,3 @@
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
fun testArray() {
|
||||
Array<String>(5) { i ->
|
||||
if (i == 3) return
|
||||
@@ -17,8 +14,44 @@ fun testIntArray() {
|
||||
throw AssertionError()
|
||||
}
|
||||
|
||||
fun testLongArray() {
|
||||
LongArray(5) { i ->
|
||||
if (i == 3) return
|
||||
i.toLong()
|
||||
}
|
||||
throw AssertionError()
|
||||
}
|
||||
|
||||
fun testBooleanArray() {
|
||||
BooleanArray(5) { i ->
|
||||
if (i == 3) return
|
||||
i % 2 == 0
|
||||
}
|
||||
throw AssertionError()
|
||||
}
|
||||
|
||||
fun testCharArray() {
|
||||
CharArray(5) { i ->
|
||||
if (i == 3) return
|
||||
i.toChar()
|
||||
}
|
||||
throw AssertionError()
|
||||
}
|
||||
|
||||
fun testFloatArray() {
|
||||
FloatArray(5) { i ->
|
||||
if (i == 3) return
|
||||
i.toFloat()
|
||||
}
|
||||
throw AssertionError()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
testArray()
|
||||
testIntArray()
|
||||
testLongArray()
|
||||
testBooleanArray()
|
||||
testCharArray()
|
||||
testFloatArray()
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.js.inline.util.IdentitySet
|
||||
import org.jetbrains.kotlin.js.inline.util.isCallInvocation
|
||||
import org.jetbrains.kotlin.js.parser.parseFunction
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.reference.CallExpressionTranslator
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getModuleName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineStrategy
|
||||
@@ -143,7 +142,7 @@ class FunctionReader(private val config: JsConfig, private val currentModuleName
|
||||
|
||||
private fun readFunctionFromSource(descriptor: CallableDescriptor, info: ModuleInfo): JsFunction? {
|
||||
val source = info.fileContent
|
||||
val tag = Namer.getFunctionTag(descriptor)
|
||||
val tag = Namer.getFunctionTag(descriptor, config)
|
||||
val index = source.indexOf(tag)
|
||||
if (index < 0) return null
|
||||
|
||||
@@ -174,8 +173,6 @@ private fun JsFunction.markInlineArguments(descriptor: CallableDescriptor) {
|
||||
val offset = if (descriptor.isExtension) 1 else 0
|
||||
|
||||
for ((i, param) in params.withIndex()) {
|
||||
if (!CallExpressionTranslator.shouldBeInlined(descriptor)) continue
|
||||
|
||||
val type = param.type
|
||||
if (!type.isFunctionTypeOrSubtype) continue
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.flattenStatemen
|
||||
|
||||
public class JsInliner extends JsVisitorWithContextImpl {
|
||||
|
||||
private final JsConfig config;
|
||||
private final Map<JsName, JsFunction> functions;
|
||||
private final Map<String, JsFunction> accessors;
|
||||
private final Stack<JsInliningContext> inliningContexts = new Stack<>();
|
||||
@@ -76,7 +77,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
||||
accessorInvocationTransformer.accept(fragment.getInitializerBlock());
|
||||
}
|
||||
FunctionReader functionReader = new FunctionReader(config, currentModuleName, fragments);
|
||||
JsInliner inliner = new JsInliner(functions, accessors, functionReader, trace);
|
||||
JsInliner inliner = new JsInliner(config, functions, accessors, functionReader, trace);
|
||||
for (JsProgramFragment fragment : fragmentsToProcess) {
|
||||
inliner.inliningContexts.push(inliner.new JsInliningContext());
|
||||
inliner.accept(fragment.getDeclarationBlock());
|
||||
@@ -92,11 +93,13 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
||||
}
|
||||
|
||||
private JsInliner(
|
||||
@NotNull JsConfig config,
|
||||
@NotNull Map<JsName, JsFunction> functions,
|
||||
@NotNull Map<String, JsFunction> accessors,
|
||||
@NotNull FunctionReader functionReader,
|
||||
@NotNull DiagnosticSink trace
|
||||
) {
|
||||
this.config = config;
|
||||
this.functions = functions;
|
||||
this.accessors = accessors;
|
||||
this.functionReader = functionReader;
|
||||
@@ -285,7 +288,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
||||
private final FunctionContext functionContext;
|
||||
|
||||
JsInliningContext() {
|
||||
functionContext = new FunctionContext(functionReader) {
|
||||
functionContext = new FunctionContext(functionReader, config) {
|
||||
@Nullable
|
||||
@Override
|
||||
protected JsFunction lookUpStaticFunction(@Nullable JsName functionName) {
|
||||
|
||||
@@ -19,11 +19,12 @@ package org.jetbrains.kotlin.js.inline.context
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.isCallableReference
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.descriptor
|
||||
import org.jetbrains.kotlin.js.config.JsConfig
|
||||
import org.jetbrains.kotlin.js.inline.FunctionReader
|
||||
import org.jetbrains.kotlin.js.inline.util.*
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
|
||||
abstract class FunctionContext(private val functionReader: FunctionReader) {
|
||||
abstract class FunctionContext(private val functionReader: FunctionReader, private val config: JsConfig) {
|
||||
protected abstract fun lookUpStaticFunction(functionName: JsName?): JsFunction?
|
||||
|
||||
protected abstract fun lookUpStaticFunctionByTag(functionTag: String): JsFunction?
|
||||
@@ -70,7 +71,7 @@ abstract class FunctionContext(private val functionReader: FunctionReader) {
|
||||
val descriptor = call.descriptor
|
||||
if (descriptor != null) {
|
||||
if (descriptor in functionReader) return functionReader[descriptor]
|
||||
lookUpStaticFunctionByTag(Namer.getFunctionTag(descriptor))?.let { return it }
|
||||
lookUpStaticFunctionByTag(Namer.getFunctionTag(descriptor, config))?.let { return it }
|
||||
}
|
||||
|
||||
/** remove ending `()` */
|
||||
|
||||
@@ -16,16 +16,17 @@
|
||||
|
||||
// a package is omitted to get declarations directly under the module
|
||||
|
||||
external private fun <T> Array(size: Int): Array<T>
|
||||
@PublishedApi
|
||||
external internal fun <T> Array(size: Int): Array<T>
|
||||
|
||||
@JsName("newArray")
|
||||
fun <T> newArray(size: Int, initValue: T) = fillArrayVal(Array<T>(size), initValue)
|
||||
|
||||
@JsName("newArrayF")
|
||||
fun <T> arrayWithFun(size: Int, init: (Int) -> T) = fillArrayFun(Array<T>(size), init)
|
||||
inline fun <T> arrayWithFun(size: Int, init: (Int) -> T) = fillArrayFun(Array<T>(size), init)
|
||||
|
||||
@JsName("fillArray")
|
||||
fun <T> fillArrayFun(array: Array<T>, init: (Int) -> T): Array<T> {
|
||||
inline fun <T> fillArrayFun(array: Array<T>, init: (Int) -> T): Array<T> {
|
||||
for (i in 0..array.size - 1) {
|
||||
array[i] = init(i)
|
||||
}
|
||||
@@ -43,6 +44,9 @@ fun booleanArray(size: Int, init: dynamic): Array<Boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
@JsName("booleanArrayF")
|
||||
inline fun booleanArrayWithFun(size: Int, init: (Int) -> Boolean): Array<Boolean> = fillArrayFun(booleanArray(size, false), init)
|
||||
|
||||
@JsName("charArray")
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun charArray(size: Int, init: dynamic): Array<Char> {
|
||||
@@ -54,6 +58,9 @@ fun charArray(size: Int, init: dynamic): Array<Char> {
|
||||
}
|
||||
}
|
||||
|
||||
@JsName("charArrayF")
|
||||
inline fun charArrayWithFun(size: Int, init: (Int) -> Char): Array<Char> = fillArrayFun(charArray(size, null), init)
|
||||
|
||||
@JsName("longArray")
|
||||
fun longArray(size: Int, init: dynamic): Array<Long> {
|
||||
val result: dynamic = Array<Long>(size)
|
||||
@@ -65,6 +72,9 @@ fun longArray(size: Int, init: dynamic): Array<Long> {
|
||||
}
|
||||
}
|
||||
|
||||
@JsName("longArrayF")
|
||||
inline fun longArrayWithFun(size: Int, init: (Int) -> Long): Array<Long> = fillArrayFun(longArray(size, false), init)
|
||||
|
||||
private fun <T> fillArrayVal(array: Array<T>, initValue: T): Array<T> {
|
||||
for (i in 0..array.size - 1) {
|
||||
array[i] = initValue
|
||||
|
||||
+1
-7
@@ -788,13 +788,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
@TestMetadata("nonLocalReturnArrayConstructor.kt")
|
||||
public void testNonLocalReturnArrayConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/nonLocalReturnArrayConstructor.kt");
|
||||
try {
|
||||
doTest(fileName);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return;
|
||||
}
|
||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nonNullArray.kt")
|
||||
|
||||
+1
-7
@@ -417,13 +417,7 @@ public class JsTypedArraysBoxTestGenerated extends AbstractJsTypedArraysBoxTest
|
||||
@TestMetadata("nonLocalReturnArrayConstructor.kt")
|
||||
public void testNonLocalReturnArrayConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/nonLocalReturnArrayConstructor.kt");
|
||||
try {
|
||||
doTest(fileName);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return;
|
||||
}
|
||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nonNullArray.kt")
|
||||
|
||||
@@ -30,9 +30,11 @@ import org.jetbrains.kotlin.js.backend.ast.*;
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties;
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind;
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.TypeCheck;
|
||||
import org.jetbrains.kotlin.js.config.JsConfig;
|
||||
import org.jetbrains.kotlin.js.naming.NameSuggestion;
|
||||
import org.jetbrains.kotlin.js.naming.SuggestedName;
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform;
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.ArrayFIF;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
@@ -114,7 +116,10 @@ public final class Namer {
|
||||
public static final String ENUM_ORDINAL_FIELD = "ordinal$";
|
||||
|
||||
@NotNull
|
||||
public static String getFunctionTag(@NotNull CallableDescriptor functionDescriptor) {
|
||||
public static String getFunctionTag(@NotNull CallableDescriptor functionDescriptor, @NotNull JsConfig config) {
|
||||
String intrinsicTag = ArrayFIF.INSTANCE.getTag(functionDescriptor, config);
|
||||
if (intrinsicTag != null) return intrinsicTag;
|
||||
|
||||
functionDescriptor = (CallableDescriptor) JsDescriptorUtils.findRealInlineDeclaration(functionDescriptor);
|
||||
String moduleName = getModuleName(functionDescriptor);
|
||||
FqNameUnsafe fqNameParent = DescriptorUtils.getFqName(functionDescriptor).parent();
|
||||
|
||||
@@ -782,7 +782,7 @@ public final class StaticContext {
|
||||
}
|
||||
|
||||
public void addInlineCall(@NotNull CallableDescriptor descriptor) {
|
||||
String tag = Namer.getFunctionTag(descriptor);
|
||||
String tag = Namer.getFunctionTag(descriptor, config);
|
||||
fragment.getInlineModuleMap().put(tag, getModuleExpressionFor(descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ abstract class AbstractDeclarationVisitor : TranslatorVisitor<Unit>() {
|
||||
function.body.statements += FunctionBodyTranslator.setDefaultValueForArguments(descriptor, innerContext)
|
||||
}
|
||||
innerContext.translateFunction(expression, function)
|
||||
return innerContext.wrapWithInlineMetadata(function, descriptor)
|
||||
return innerContext.wrapWithInlineMetadata(function, descriptor, context.config)
|
||||
}
|
||||
|
||||
protected abstract fun addFunction(
|
||||
|
||||
+3
-2
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.js.backend.ast.JsScope
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.descriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.functionDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.hasDefaultValue
|
||||
import org.jetbrains.kotlin.js.config.JsConfig
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.reference.CallExpressionTranslator.shouldBeInlined
|
||||
@@ -100,9 +101,9 @@ fun TranslationContext.translateFunction(declaration: KtDeclarationWithBody, fun
|
||||
function.functionDescriptor = descriptor
|
||||
}
|
||||
|
||||
fun TranslationContext.wrapWithInlineMetadata(function: JsFunction, descriptor: FunctionDescriptor): JsExpression {
|
||||
fun TranslationContext.wrapWithInlineMetadata(function: JsFunction, descriptor: FunctionDescriptor, config: JsConfig): JsExpression {
|
||||
return if (shouldBeInlined(descriptor, this) && descriptor.isEffectivelyPublicApi) {
|
||||
val metadata = InlineMetadata.compose(function, descriptor)
|
||||
val metadata = InlineMetadata.compose(function, descriptor, config)
|
||||
metadata.functionWithMetadata
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.js.translate.expression
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.config.JsConfig
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
|
||||
private val METADATA_PROPERTIES_COUNT = 2
|
||||
@@ -25,9 +26,9 @@ private val METADATA_PROPERTIES_COUNT = 2
|
||||
class InlineMetadata(val tag: JsStringLiteral, val function: JsFunction) {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun compose(function: JsFunction, descriptor: CallableDescriptor): InlineMetadata {
|
||||
fun compose(function: JsFunction, descriptor: CallableDescriptor, config: JsConfig): InlineMetadata {
|
||||
val program = function.scope.program
|
||||
val tag = program.getStringLiteral(Namer.getFunctionTag(descriptor))
|
||||
val tag = program.getStringLiteral(Namer.getFunctionTag(descriptor, config))
|
||||
return InlineMetadata(tag, function)
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -211,7 +211,7 @@ public final class PatternTranslator extends AbstractTranslator {
|
||||
}
|
||||
|
||||
if (isArray(type)) {
|
||||
if (ArrayFIF.typedArraysEnabled(context())) {
|
||||
if (ArrayFIF.typedArraysEnabled(context().getConfig())) {
|
||||
return namer().isArray();
|
||||
}
|
||||
else {
|
||||
@@ -255,7 +255,7 @@ public final class PatternTranslator extends AbstractTranslator {
|
||||
return namer().isTypeOf(program().getStringLiteral("number"));
|
||||
}
|
||||
|
||||
if (ArrayFIF.typedArraysEnabled(context())) {
|
||||
if (ArrayFIF.typedArraysEnabled(context().getConfig())) {
|
||||
if (KotlinBuiltIns.isPrimitiveArray(type)) {
|
||||
PrimitiveType arrayType = KotlinBuiltIns.getPrimitiveArrayElementType(type);
|
||||
assert arrayType != null;
|
||||
|
||||
+73
-32
@@ -20,33 +20,40 @@ import com.intellij.openapi.util.text.StringUtil.decapitalize
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType.*
|
||||
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.descriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.inlineStrategy
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.config.JsConfig
|
||||
import org.jetbrains.kotlin.js.patterns.NamePredicate
|
||||
import org.jetbrains.kotlin.js.patterns.PatternBuilder.pattern
|
||||
import org.jetbrains.kotlin.js.translate.callTranslator.CallInfo
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.BuiltInPropertyIntrinsic
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsicWithReceiverComputed
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineStrategy
|
||||
import java.util.*
|
||||
|
||||
object ArrayFIF : CompositeFIF() {
|
||||
@JvmField
|
||||
val GET_INTRINSIC = intrinsify { receiver, arguments, _ ->
|
||||
val GET_INTRINSIC = intrinsify { callInfo, arguments, _ ->
|
||||
assert(arguments.size == 1) { "Array get expression must have one argument." }
|
||||
val (indexExpression) = arguments
|
||||
JsArrayAccess(receiver!!, indexExpression)
|
||||
JsArrayAccess(callInfo.dispatchReceiver, indexExpression)
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val SET_INTRINSIC = intrinsify { receiver, arguments, _ ->
|
||||
val SET_INTRINSIC = intrinsify { callInfo, arguments, _ ->
|
||||
assert(arguments.size == 2) { "Array set expression must have two arguments." }
|
||||
val (indexExpression, value) = arguments
|
||||
val arrayAccess = JsArrayAccess(receiver!!, indexExpression)
|
||||
val arrayAccess = JsArrayAccess(callInfo.dispatchReceiver, indexExpression)
|
||||
JsAstUtils.assignment(arrayAccess, value)
|
||||
}
|
||||
|
||||
@@ -54,10 +61,10 @@ object ArrayFIF : CompositeFIF() {
|
||||
val LENGTH_PROPERTY_INTRINSIC = BuiltInPropertyIntrinsic("length")
|
||||
|
||||
@JvmStatic
|
||||
fun typedArraysEnabled(ctx: TranslationContext) = ctx.config.configuration.getBoolean(JSConfigurationKeys.TYPED_ARRAYS_ENABLED)
|
||||
fun typedArraysEnabled(config: JsConfig) = config.configuration.getBoolean(JSConfigurationKeys.TYPED_ARRAYS_ENABLED)
|
||||
|
||||
fun castOrCreatePrimitiveArray(ctx: TranslationContext, type: PrimitiveType?, arg: JsArrayLiteral): JsExpression {
|
||||
if (type == null || !typedArraysEnabled(ctx)) return arg
|
||||
if (type == null || !typedArraysEnabled(ctx.config)) return arg
|
||||
|
||||
if (type in TYPED_ARRAY_MAP) {
|
||||
return createTypedArray(type, arg)
|
||||
@@ -81,6 +88,30 @@ object ArrayFIF : CompositeFIF() {
|
||||
private val PrimitiveType.lowerCaseName
|
||||
get() = typeName.asString().toLowerCase()
|
||||
|
||||
fun getTag(descriptor: CallableDescriptor, config: JsConfig): String? {
|
||||
if (descriptor !is ConstructorDescriptor) return null
|
||||
val constructedClass = descriptor.constructedClass
|
||||
if (!KotlinBuiltIns.isArrayOrPrimitiveArray(constructedClass)) return null
|
||||
|
||||
if (descriptor.valueParameters.size != 2) return null
|
||||
val (sizeParam, functionParam) = descriptor.valueParameters
|
||||
if (!KotlinBuiltIns.isInt(sizeParam.type) || !functionParam.type.isBuiltinFunctionalType) return null
|
||||
if (functionParam.type.getValueParameterTypesFromFunctionType().size != 1) return null
|
||||
|
||||
val primitiveType = KotlinBuiltIns.getPrimitiveArrayElementType(constructedClass.defaultType)
|
||||
return if (typedArraysEnabled(config) && primitiveType != null) {
|
||||
if (primitiveType in TYPED_ARRAY_MAP) {
|
||||
"kotlin.fillArray"
|
||||
}
|
||||
else {
|
||||
"kotlin.${primitiveType.lowerCaseName}ArrayF"
|
||||
}
|
||||
}
|
||||
else {
|
||||
"kotlin.newArrayF"
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
val arrayName = KotlinBuiltIns.FQ_NAMES.array.shortName()
|
||||
|
||||
@@ -97,7 +128,7 @@ object ArrayFIF : CompositeFIF() {
|
||||
assert(arguments.size == 1) { "Array <init>(Int) expression must have one argument." }
|
||||
val (size) = arguments
|
||||
|
||||
if (typedArraysEnabled(context)) {
|
||||
if (typedArraysEnabled(context.config)) {
|
||||
if (type in TYPED_ARRAY_MAP) {
|
||||
createTypedArray(type, size)
|
||||
}
|
||||
@@ -116,24 +147,11 @@ object ArrayFIF : CompositeFIF() {
|
||||
}
|
||||
})
|
||||
|
||||
add(pattern(NamePredicate(type.arrayTypeName), "<init>(Int,Function1)"), intrinsify { _, arguments, context ->
|
||||
assert(arguments.size == 2) { "Array <init>(Int,Function1) expression must have two arguments." }
|
||||
val (size, fn) = arguments
|
||||
if (typedArraysEnabled(context)) {
|
||||
if (type in TYPED_ARRAY_MAP) {
|
||||
JsAstUtils.invokeKotlinFunction("fillArray", createTypedArray(type, size), fn)
|
||||
}
|
||||
else {
|
||||
JsAstUtils.invokeKotlinFunction("${type.lowerCaseName}Array", size, fn)
|
||||
}
|
||||
}
|
||||
else {
|
||||
JsAstUtils.invokeKotlinFunction("newArrayF", size, fn)
|
||||
}
|
||||
})
|
||||
add(pattern(NamePredicate(type.arrayTypeName), "<init>(Int,Function1)"), createConstructorIntrinsic(type))
|
||||
|
||||
add(pattern(NamePredicate(type.arrayTypeName), "iterator"), intrinsify { receiver, _, context ->
|
||||
if (typedArraysEnabled(context)) {
|
||||
add(pattern(NamePredicate(type.arrayTypeName), "iterator"), intrinsify { callInfo, _, context ->
|
||||
val receiver = callInfo.dispatchReceiver
|
||||
if (typedArraysEnabled(context.config)) {
|
||||
JsAstUtils.invokeKotlinFunction("${type.lowerCaseName}ArrayIterator", receiver!!)
|
||||
}
|
||||
else {
|
||||
@@ -143,7 +161,7 @@ object ArrayFIF : CompositeFIF() {
|
||||
})
|
||||
}
|
||||
|
||||
add(pattern(NamePredicate(arrayName), "<init>(Int,Function1)"), KotlinFunctionIntrinsic("newArrayF"))
|
||||
add(pattern(NamePredicate(arrayName), "<init>(Int,Function1)"), createConstructorIntrinsic(null))
|
||||
add(pattern(NamePredicate(arrayName), "iterator"), KotlinFunctionIntrinsic("arrayIterator"))
|
||||
|
||||
add(pattern(Namer.KOTLIN_LOWER_NAME, "arrayOfNulls"), KotlinFunctionIntrinsic("newArray", JsLiteral.NULL))
|
||||
@@ -153,10 +171,33 @@ object ArrayFIF : CompositeFIF() {
|
||||
add(arrayFactoryMethods, intrinsify { _, arguments, _ -> arguments[0] })
|
||||
}
|
||||
|
||||
private fun intrinsify(f: (receiver: JsExpression?, arguments: List<JsExpression>, context: TranslationContext) -> JsExpression)
|
||||
= object : FunctionIntrinsicWithReceiverComputed() {
|
||||
override fun apply(receiver: JsExpression?, arguments: List<JsExpression>, context: TranslationContext): JsExpression {
|
||||
return f(receiver, arguments, context)
|
||||
private fun createConstructorIntrinsic(type: PrimitiveType?): FunctionIntrinsic {
|
||||
return intrinsify { callInfo, arguments, context ->
|
||||
assert(arguments.size == 2) { "Array <init>(Int,Function1) expression must have two arguments." }
|
||||
val (size, fn) = arguments
|
||||
val invocation = if (typedArraysEnabled(context.config) && type != null) {
|
||||
if (type in TYPED_ARRAY_MAP) {
|
||||
JsAstUtils.invokeKotlinFunction("fillArray", createTypedArray(type, size), fn)
|
||||
}
|
||||
else {
|
||||
JsAstUtils.invokeKotlinFunction("${type.lowerCaseName}ArrayF", size, fn)
|
||||
}
|
||||
}
|
||||
else {
|
||||
JsAstUtils.invokeKotlinFunction("newArrayF", size, fn)
|
||||
}
|
||||
invocation.inlineStrategy = InlineStrategy.IN_PLACE
|
||||
val descriptor = callInfo.resolvedCall.resultingDescriptor.original
|
||||
invocation.descriptor = descriptor
|
||||
context.addInlineCall(descriptor)
|
||||
invocation
|
||||
}
|
||||
}
|
||||
|
||||
private fun intrinsify(f: (callInfo: CallInfo, arguments: List<JsExpression>, context: TranslationContext) -> JsExpression)
|
||||
= object : FunctionIntrinsic() {
|
||||
override fun apply(callInfo: CallInfo, arguments: List<JsExpression>, context: TranslationContext): JsExpression {
|
||||
return f(callInfo, arguments, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallsKt;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
@@ -147,6 +149,9 @@ public final class JsDescriptorUtils {
|
||||
@NotNull
|
||||
public static String getModuleName(@NotNull DeclarationDescriptor descriptor) {
|
||||
ModuleDescriptor moduleDescriptor = DescriptorUtils.getContainingModule(findRealInlineDeclaration(descriptor));
|
||||
if (DescriptorUtils.getContainingModule(descriptor) == moduleDescriptor.getBuiltIns().getBuiltInsModule()) {
|
||||
return Namer.KOTLIN_LOWER_NAME;
|
||||
}
|
||||
String moduleName = moduleDescriptor.getName().asString();
|
||||
return moduleName.substring(1, moduleName.length() - 1);
|
||||
}
|
||||
@@ -179,7 +184,7 @@ public final class JsDescriptorUtils {
|
||||
|
||||
public static boolean isImmediateSubtypeOfError(@NotNull ClassDescriptor descriptor) {
|
||||
if (!isExceptionClass(descriptor)) return false;
|
||||
ClassDescriptor superClass = org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getSuperClassOrAny(descriptor);
|
||||
ClassDescriptor superClass = DescriptorUtilsKt.getSuperClassOrAny(descriptor);
|
||||
return TypeUtilsKt.isThrowable(superClass.getDefaultType()) || AnnotationsUtils.isNativeObject(superClass);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ public final class TranslationUtils {
|
||||
@NotNull TranslationContext context) {
|
||||
JsExpression functionExpression = function;
|
||||
if (InlineUtil.isInline(descriptor)) {
|
||||
InlineMetadata metadata = InlineMetadata.compose(function, descriptor);
|
||||
InlineMetadata metadata = InlineMetadata.compose(function, descriptor, context.getConfig());
|
||||
functionExpression = metadata.getFunctionWithMetadata();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user