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 com.google.dart.compiler.backend.js.ast.*
|
||||||
import org.jetbrains.kotlin.builtins.InlineStrategy
|
import org.jetbrains.kotlin.builtins.InlineStrategy
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
|
|
||||||
public var JsName.staticRef: JsNode? by MetadataProperty(default = null)
|
public var JsName.staticRef: JsNode? by MetadataProperty(default = null)
|
||||||
|
|
||||||
public var JsInvocation.inlineStrategy: InlineStrategy? 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 JsFunction.isLocal: Boolean by MetadataProperty(default = false)
|
||||||
|
|
||||||
public var JsParameter.hasDefaultValue: 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;
|
package org.jetbrains.kotlin.js.translate.reference;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*;
|
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.dart.compiler.common.SourceInfoImpl;
|
||||||
import com.google.gwt.dev.js.JsParser;
|
import com.google.gwt.dev.js.JsParser;
|
||||||
import com.google.gwt.dev.js.ThrowExceptionOnErrorReporter;
|
import com.google.gwt.dev.js.ThrowExceptionOnErrorReporter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.builtins.InlineStrategy;
|
|
||||||
import org.jetbrains.kotlin.builtins.InlineUtil;
|
import org.jetbrains.kotlin.builtins.InlineUtil;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
@@ -47,6 +45,7 @@ import java.io.StringReader;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
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.resolve.calls.callUtil.CallUtilPackage.getFunctionResolvedCallWithAssert;
|
||||||
import static org.jetbrains.kotlin.js.resolve.diagnostics.JsCallChecker.isJsCall;
|
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();
|
JsExpression callExpression = (new CallExpressionTranslator(expression, receiver, context)).translate();
|
||||||
|
CallableDescriptor descriptor = getFunctionDescriptor(expression, context);
|
||||||
|
|
||||||
if (shouldBeInlined(expression, context)
|
if (shouldBeInlined(expression, context)) {
|
||||||
&& callExpression instanceof JsInvocation) {
|
setInlineCallMetadata(callExpression, descriptor, context);
|
||||||
|
|
||||||
MetadataPackage.setInlineStrategy((JsInvocation) callExpression, InlineStrategy.IN_PLACE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return callExpression;
|
return callExpression;
|
||||||
@@ -78,17 +76,7 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
|
|||||||
public static boolean shouldBeInlined(@NotNull JetCallExpression expression, @NotNull TranslationContext context) {
|
public static boolean shouldBeInlined(@NotNull JetCallExpression expression, @NotNull TranslationContext context) {
|
||||||
if (!context.getConfig().isInlineEnabled()) return false;
|
if (!context.getConfig().isInlineEnabled()) return false;
|
||||||
|
|
||||||
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(expression, context.bindingContext());
|
CallableDescriptor descriptor = getFunctionDescriptor(expression, context);
|
||||||
assert resolvedCall != null;
|
|
||||||
|
|
||||||
CallableDescriptor descriptor;
|
|
||||||
|
|
||||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
|
||||||
descriptor = ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall().getCandidateDescriptor();
|
|
||||||
} else {
|
|
||||||
descriptor = resolvedCall.getCandidateDescriptor();
|
|
||||||
}
|
|
||||||
|
|
||||||
return shouldBeInlined(descriptor);
|
return shouldBeInlined(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +94,21 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
|
|||||||
return false;
|
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(
|
private CallExpressionTranslator(
|
||||||
@NotNull JetCallExpression expression,
|
@NotNull JetCallExpression expression,
|
||||||
@Nullable JsExpression receiver,
|
@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