diff --git a/compiler/testData/codegen/box/arrays/nonLocalReturnArrayConstructor.kt b/compiler/testData/codegen/box/arrays/nonLocalReturnArrayConstructor.kt index 350d4cfe176..de43ac414e1 100644 --- a/compiler/testData/codegen/box/arrays/nonLocalReturnArrayConstructor.kt +++ b/compiler/testData/codegen/box/arrays/nonLocalReturnArrayConstructor.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - fun testArray() { Array(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" } diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt index 499251b0f4d..de201c476eb 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt @@ -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 diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java index c75dbcbe0fb..dfd4f81df73 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java @@ -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 functions; private final Map accessors; private final Stack 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 functions, @NotNull Map 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) { diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/FunctionContext.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/FunctionContext.kt index a9ecc7d75b9..d207c80d0b7 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/FunctionContext.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/FunctionContext.kt @@ -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 `()` */ diff --git a/js/js.libraries/src/builtins/arrayUtils.kt b/js/js.libraries/src/builtins/arrayUtils.kt index 3b4ea7c2be9..189eb079e5e 100644 --- a/js/js.libraries/src/builtins/arrayUtils.kt +++ b/js/js.libraries/src/builtins/arrayUtils.kt @@ -16,16 +16,17 @@ // a package is omitted to get declarations directly under the module -external private fun Array(size: Int): Array +@PublishedApi +external internal fun Array(size: Int): Array @JsName("newArray") fun newArray(size: Int, initValue: T) = fillArrayVal(Array(size), initValue) @JsName("newArrayF") -fun arrayWithFun(size: Int, init: (Int) -> T) = fillArrayFun(Array(size), init) +inline fun arrayWithFun(size: Int, init: (Int) -> T) = fillArrayFun(Array(size), init) @JsName("fillArray") -fun fillArrayFun(array: Array, init: (Int) -> T): Array { +inline fun fillArrayFun(array: Array, init: (Int) -> T): Array { for (i in 0..array.size - 1) { array[i] = init(i) } @@ -43,6 +44,9 @@ fun booleanArray(size: Int, init: dynamic): Array { } } +@JsName("booleanArrayF") +inline fun booleanArrayWithFun(size: Int, init: (Int) -> Boolean): Array = fillArrayFun(booleanArray(size, false), init) + @JsName("charArray") @Suppress("UNUSED_PARAMETER") fun charArray(size: Int, init: dynamic): Array { @@ -54,6 +58,9 @@ fun charArray(size: Int, init: dynamic): Array { } } +@JsName("charArrayF") +inline fun charArrayWithFun(size: Int, init: (Int) -> Char): Array = fillArrayFun(charArray(size, null), init) + @JsName("longArray") fun longArray(size: Int, init: dynamic): Array { val result: dynamic = Array(size) @@ -65,6 +72,9 @@ fun longArray(size: Int, init: dynamic): Array { } } +@JsName("longArrayF") +inline fun longArrayWithFun(size: Int, init: (Int) -> Long): Array = fillArrayFun(longArray(size, false), init) + private fun fillArrayVal(array: Array, initValue: T): Array { for (i in 0..array.size - 1) { array[i] = initValue diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index a8990d2d0e3..b236cb860e7 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -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") diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsTypedArraysBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsTypedArraysBoxTestGenerated.java index a94def3cac2..4806644ee10 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsTypedArraysBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsTypedArraysBoxTestGenerated.java @@ -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") diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java index 26d73003077..70703b6a594 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java @@ -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(); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java index 1b7fd5bb0c2..fa871aac83c 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java @@ -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)); } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/AbstractDeclarationVisitor.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/AbstractDeclarationVisitor.kt index c48c5cb5d1f..eb25239ea80 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/AbstractDeclarationVisitor.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/AbstractDeclarationVisitor.kt @@ -110,7 +110,7 @@ abstract class AbstractDeclarationVisitor : TranslatorVisitor() { 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( diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.kt index e28604de13c..cf6e8904ac1 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.kt @@ -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 { diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/InlineMetadata.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/InlineMetadata.kt index 8848c4387ea..33d2566d924 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/InlineMetadata.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/InlineMetadata.kt @@ -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) } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/PatternTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/PatternTranslator.java index 545dbab3cb5..e51285a5e00 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/PatternTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/PatternTranslator.java @@ -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; diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/ArrayFIF.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/ArrayFIF.kt index 1347ce05388..ad63630be80 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/ArrayFIF.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/ArrayFIF.kt @@ -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 (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), "(Int,Function1)"), intrinsify { _, arguments, context -> - assert(arguments.size == 2) { "Array (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), "(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), "(Int,Function1)"), KotlinFunctionIntrinsic("newArrayF")) + add(pattern(NamePredicate(arrayName), "(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, context: TranslationContext) -> JsExpression) - = object : FunctionIntrinsicWithReceiverComputed() { - override fun apply(receiver: JsExpression?, arguments: List, context: TranslationContext): JsExpression { - return f(receiver, arguments, context) + private fun createConstructorIntrinsic(type: PrimitiveType?): FunctionIntrinsic { + return intrinsify { callInfo, arguments, context -> + assert(arguments.size == 2) { "Array (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, context: TranslationContext) -> JsExpression) + = object : FunctionIntrinsic() { + override fun apply(callInfo: CallInfo, arguments: List, context: TranslationContext): JsExpression { + return f(callInfo, arguments, context) + } + } } \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java index eace25b3328..9ba2c1c98d8 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java @@ -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); } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java index 94e9f5d86cc..8692089fea6 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/TranslationUtils.java @@ -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(); }