JS: save function descriptor for inline calls
This commit is contained in:
+3
@@ -19,11 +19,14 @@ package com.google.dart.compiler.backend.js.ast.metadata
|
||||
import com.google.dart.compiler.backend.js.ast.*
|
||||
import org.jetbrains.kotlin.builtins.InlineStrategy
|
||||
import kotlin.properties.Delegates
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
|
||||
public var JsName.staticRef: JsNode? by MetadataProperty(default = null)
|
||||
|
||||
public var JsInvocation.inlineStrategy: InlineStrategy? by MetadataProperty(default = null)
|
||||
|
||||
public var JsInvocation.descriptor: CallableDescriptor? by MetadataProperty(default = null)
|
||||
|
||||
public var JsFunction.isLocal: Boolean by MetadataProperty(default = false)
|
||||
|
||||
public var JsParameter.hasDefaultValue: Boolean by MetadataProperty(default = false)
|
||||
|
||||
+20
-17
@@ -17,13 +17,11 @@
|
||||
package org.jetbrains.kotlin.js.translate.reference;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.google.dart.compiler.backend.js.ast.metadata.MetadataPackage;
|
||||
import com.google.dart.compiler.common.SourceInfoImpl;
|
||||
import com.google.gwt.dev.js.JsParser;
|
||||
import com.google.gwt.dev.js.ThrowExceptionOnErrorReporter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.InlineStrategy;
|
||||
import org.jetbrains.kotlin.builtins.InlineUtil;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
@@ -47,6 +45,7 @@ import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.js.translate.utils.UtilsPackage.setInlineCallMetadata;
|
||||
import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getFunctionResolvedCallWithAssert;
|
||||
import static org.jetbrains.kotlin.js.resolve.diagnostics.JsCallChecker.isJsCall;
|
||||
|
||||
@@ -65,11 +64,10 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
|
||||
}
|
||||
|
||||
JsExpression callExpression = (new CallExpressionTranslator(expression, receiver, context)).translate();
|
||||
CallableDescriptor descriptor = getFunctionDescriptor(expression, context);
|
||||
|
||||
if (shouldBeInlined(expression, context)
|
||||
&& callExpression instanceof JsInvocation) {
|
||||
|
||||
MetadataPackage.setInlineStrategy((JsInvocation) callExpression, InlineStrategy.IN_PLACE);
|
||||
if (shouldBeInlined(expression, context)) {
|
||||
setInlineCallMetadata(callExpression, descriptor, context);
|
||||
}
|
||||
|
||||
return callExpression;
|
||||
@@ -78,17 +76,7 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
|
||||
public static boolean shouldBeInlined(@NotNull JetCallExpression expression, @NotNull TranslationContext context) {
|
||||
if (!context.getConfig().isInlineEnabled()) return false;
|
||||
|
||||
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(expression, context.bindingContext());
|
||||
assert resolvedCall != null;
|
||||
|
||||
CallableDescriptor descriptor;
|
||||
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
descriptor = ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall().getCandidateDescriptor();
|
||||
} else {
|
||||
descriptor = resolvedCall.getCandidateDescriptor();
|
||||
}
|
||||
|
||||
CallableDescriptor descriptor = getFunctionDescriptor(expression, context);
|
||||
return shouldBeInlined(descriptor);
|
||||
}
|
||||
|
||||
@@ -106,6 +94,21 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static CallableDescriptor getFunctionDescriptor(
|
||||
@NotNull JetCallExpression expression,
|
||||
@NotNull TranslationContext context
|
||||
) {
|
||||
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(expression, context.bindingContext());
|
||||
assert resolvedCall != null;
|
||||
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
return ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall().getCandidateDescriptor();
|
||||
}
|
||||
|
||||
return resolvedCall.getCandidateDescriptor();
|
||||
}
|
||||
|
||||
private CallExpressionTranslator(
|
||||
@NotNull JetCallExpression expression,
|
||||
@Nullable JsExpression receiver,
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.js.translate.utils
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*
|
||||
import com.google.dart.compiler.backend.js.ast.metadata.*
|
||||
import org.jetbrains.kotlin.builtins.InlineStrategy
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.js.inline.util.isCallInvocation
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.reference.CallExpressionTranslator
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
|
||||
/**
|
||||
* Recursively walks expression and sets metadata for all invocations of descriptor.
|
||||
*
|
||||
* When JetExpression is compiled, the resulting JsExpression
|
||||
* might not be JsInvocation.
|
||||
*
|
||||
* For example, extension call with nullable receiver:
|
||||
* x?.fn(y)
|
||||
* will compile to:
|
||||
* (x != null) ? fn.call(x, y) : null
|
||||
*/
|
||||
fun setInlineCallMetadata(
|
||||
expression: JsExpression,
|
||||
descriptor: CallableDescriptor,
|
||||
context: TranslationContext
|
||||
) {
|
||||
assert(CallExpressionTranslator.shouldBeInlined(descriptor)) {
|
||||
"Expected descriptor of callable, that should be inlined, but got: $descriptor"
|
||||
}
|
||||
|
||||
val name = context.aliasedName(descriptor)
|
||||
|
||||
val visitor = object : RecursiveJsVisitor() {
|
||||
override fun visitInvocation(invocation: JsInvocation?) {
|
||||
if (invocation == null) return
|
||||
|
||||
super.visitInvocation(invocation)
|
||||
|
||||
if (name == invocation.name) {
|
||||
invocation.descriptor = descriptor
|
||||
invocation.inlineStrategy = InlineStrategy.IN_PLACE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitor.accept(expression)
|
||||
}
|
||||
|
||||
fun TranslationContext.aliasedName(descriptor: CallableDescriptor): JsName {
|
||||
val alias = getAliasForDescriptor(descriptor)
|
||||
val aliasName = (alias as? JsNameRef)?.getName()
|
||||
|
||||
return aliasName ?: getNameForDescriptor(descriptor)
|
||||
}
|
||||
|
||||
val JsExpression?.name: JsName?
|
||||
get() = when (this) {
|
||||
is JsInvocation -> {
|
||||
val qualifier = this.getQualifier()
|
||||
|
||||
when {
|
||||
isCallInvocation(this) -> (qualifier as JsNameRef).getQualifier().name
|
||||
else -> qualifier.name
|
||||
}
|
||||
}
|
||||
is JsNameRef -> this.getName()
|
||||
else -> null
|
||||
}
|
||||
Reference in New Issue
Block a user