001 /* 002 * Copyright 2010-2015 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.kotlin.codegen; 018 019 import com.google.common.collect.Lists; 020 import com.google.common.collect.Maps; 021 import com.intellij.openapi.progress.ProcessCanceledException; 022 import com.intellij.openapi.util.Ref; 023 import com.intellij.psi.PsiElement; 024 import com.intellij.psi.tree.IElementType; 025 import com.intellij.util.ArrayUtil; 026 import com.intellij.util.Function; 027 import com.intellij.util.containers.Stack; 028 import kotlin.Pair; 029 import kotlin.Unit; 030 import kotlin.collections.CollectionsKt; 031 import kotlin.jvm.functions.Function1; 032 import org.jetbrains.annotations.NotNull; 033 import org.jetbrains.annotations.Nullable; 034 import org.jetbrains.kotlin.backend.common.CodegenUtil; 035 import org.jetbrains.kotlin.builtins.KotlinBuiltIns; 036 import org.jetbrains.kotlin.codegen.binding.CalculatedClosure; 037 import org.jetbrains.kotlin.codegen.binding.CodegenBinding; 038 import org.jetbrains.kotlin.codegen.context.*; 039 import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension; 040 import org.jetbrains.kotlin.codegen.inline.*; 041 import org.jetbrains.kotlin.codegen.intrinsics.*; 042 import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsnsKt; 043 import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter; 044 import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter; 045 import org.jetbrains.kotlin.codegen.state.GenerationState; 046 import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; 047 import org.jetbrains.kotlin.codegen.when.SwitchCodegen; 048 import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil; 049 import org.jetbrains.kotlin.descriptors.*; 050 import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor; 051 import org.jetbrains.kotlin.diagnostics.DiagnosticUtils; 052 import org.jetbrains.kotlin.diagnostics.Errors; 053 import org.jetbrains.kotlin.incremental.components.NoLookupLocation; 054 import org.jetbrains.kotlin.lexer.KtTokens; 055 import org.jetbrains.kotlin.load.java.JvmAbi; 056 import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor; 057 import org.jetbrains.kotlin.name.Name; 058 import org.jetbrains.kotlin.psi.*; 059 import org.jetbrains.kotlin.resolve.BindingContext; 060 import org.jetbrains.kotlin.resolve.BindingContextUtils; 061 import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; 062 import org.jetbrains.kotlin.resolve.DescriptorUtils; 063 import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt; 064 import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt; 065 import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt; 066 import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; 067 import org.jetbrains.kotlin.resolve.calls.model.*; 068 import org.jetbrains.kotlin.resolve.calls.util.CallMaker; 069 import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject; 070 import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; 071 import org.jetbrains.kotlin.resolve.constants.ConstantValue; 072 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; 073 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluatorKt; 074 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; 075 import org.jetbrains.kotlin.resolve.inline.InlineUtil; 076 import org.jetbrains.kotlin.resolve.jvm.JvmBindingContextSlices; 077 import org.jetbrains.kotlin.resolve.jvm.RuntimeAssertionInfo; 078 import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt; 079 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind; 080 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature; 081 import org.jetbrains.kotlin.resolve.scopes.receivers.*; 082 import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor; 083 import org.jetbrains.kotlin.types.KotlinType; 084 import org.jetbrains.kotlin.types.TypeProjection; 085 import org.jetbrains.kotlin.types.TypeUtils; 086 import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; 087 import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt; 088 import org.jetbrains.org.objectweb.asm.Label; 089 import org.jetbrains.org.objectweb.asm.MethodVisitor; 090 import org.jetbrains.org.objectweb.asm.Opcodes; 091 import org.jetbrains.org.objectweb.asm.Type; 092 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; 093 import org.jetbrains.org.objectweb.asm.commons.Method; 094 095 import java.util.*; 096 097 import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isInt; 098 import static org.jetbrains.kotlin.codegen.AsmUtil.*; 099 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*; 100 import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*; 101 import static org.jetbrains.kotlin.resolve.BindingContext.*; 102 import static org.jetbrains.kotlin.resolve.BindingContextUtils.*; 103 import static org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry; 104 import static org.jetbrains.kotlin.resolve.DescriptorUtils.isObject; 105 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*; 106 import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression; 107 import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral; 108 import static org.jetbrains.org.objectweb.asm.Opcodes.*; 109 110 public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> implements LocalLookup { 111 private final GenerationState state; 112 final KotlinTypeMapper typeMapper; 113 private final BindingContext bindingContext; 114 115 public final InstructionAdapter v; 116 public final FrameMap myFrameMap; 117 private final MethodContext context; 118 private final Type returnType; 119 120 private final CodegenStatementVisitor statementVisitor = new CodegenStatementVisitor(this); 121 private final MemberCodegen<?> parentCodegen; 122 private final TailRecursionCodegen tailRecursionCodegen; 123 public final CallGenerator defaultCallGenerator = new CallGenerator.DefaultCallGenerator(this); 124 125 private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>(); 126 127 /* 128 * When we create a temporary variable to hold some value not to compute it many times 129 * we put it into this map to emit access to that variable instead of evaluating the whole expression 130 */ 131 public final Map<KtElement, StackValue> tempVariables = Maps.newHashMap(); 132 133 private int myLastLineNumber = -1; 134 private boolean shouldMarkLineNumbers = true; 135 private int finallyDepth = 0; 136 137 public ExpressionCodegen( 138 @NotNull MethodVisitor mv, 139 @NotNull FrameMap frameMap, 140 @NotNull Type returnType, 141 @NotNull MethodContext context, 142 @NotNull GenerationState state, 143 @NotNull MemberCodegen<?> parentCodegen 144 ) { 145 this.state = state; 146 this.typeMapper = state.getTypeMapper(); 147 this.bindingContext = state.getBindingContext(); 148 this.v = new InstructionAdapter(mv); 149 this.myFrameMap = frameMap; 150 this.context = context; 151 this.returnType = returnType; 152 this.parentCodegen = parentCodegen; 153 this.tailRecursionCodegen = new TailRecursionCodegen(context, this, this.v, state); 154 } 155 156 static class BlockStackElement { 157 } 158 159 static class LoopBlockStackElement extends BlockStackElement { 160 final Label continueLabel; 161 final Label breakLabel; 162 public final KtSimpleNameExpression targetLabel; 163 164 LoopBlockStackElement(Label breakLabel, Label continueLabel, KtSimpleNameExpression targetLabel) { 165 this.breakLabel = breakLabel; 166 this.continueLabel = continueLabel; 167 this.targetLabel = targetLabel; 168 } 169 } 170 171 static class FinallyBlockStackElement extends BlockStackElement { 172 List<Label> gaps = new ArrayList<Label>(); 173 174 final KtTryExpression expression; 175 176 FinallyBlockStackElement(KtTryExpression expression) { 177 this.expression = expression; 178 } 179 180 private void addGapLabel(Label label){ 181 gaps.add(label); 182 } 183 } 184 185 @NotNull 186 public GenerationState getState() { 187 return state; 188 } 189 190 @NotNull 191 public BindingContext getBindingContext() { 192 return bindingContext; 193 } 194 195 @NotNull 196 public MemberCodegen<?> getParentCodegen() { 197 return parentCodegen; 198 } 199 200 @NotNull 201 public ObjectLiteralResult generateObjectLiteral(@NotNull KtObjectLiteralExpression literal) { 202 KtObjectDeclaration objectDeclaration = literal.getObjectDeclaration(); 203 204 ClassDescriptor classDescriptor = bindingContext.get(CLASS, objectDeclaration); 205 assert classDescriptor != null; 206 207 Type asmType = asmTypeForAnonymousClass(bindingContext, objectDeclaration); 208 ClassBuilder classBuilder = state.getFactory().newVisitor( 209 JvmDeclarationOriginKt.OtherOrigin(objectDeclaration, classDescriptor), 210 asmType, 211 literal.getContainingFile() 212 ); 213 214 ClassContext objectContext = context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION); 215 216 MemberCodegen literalCodegen = new ImplementationBodyCodegen( 217 objectDeclaration, objectContext, classBuilder, state, getParentCodegen(), 218 /* isLocal = */ true); 219 literalCodegen.generate(); 220 221 addReifiedParametersFromSignature(literalCodegen, classDescriptor); 222 propagateChildReifiedTypeParametersUsages(literalCodegen.getReifiedTypeParametersUsages()); 223 224 return new ObjectLiteralResult( 225 literalCodegen.getReifiedTypeParametersUsages().wereUsedReifiedParameters(), 226 classDescriptor 227 ); 228 } 229 230 private static void addReifiedParametersFromSignature(@NotNull MemberCodegen member, @NotNull ClassDescriptor descriptor) { 231 for (KotlinType type : descriptor.getTypeConstructor().getSupertypes()) { 232 for (TypeProjection supertypeArgument : type.getArguments()) { 233 TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(supertypeArgument.getType()); 234 if (parameterDescriptor != null && parameterDescriptor.isReified()) { 235 member.getReifiedTypeParametersUsages().addUsedReifiedParameter(parameterDescriptor.getName().asString()); 236 } 237 } 238 } 239 } 240 241 private static class ObjectLiteralResult { 242 private final boolean wereReifiedMarkers; 243 private final ClassDescriptor classDescriptor; 244 245 public ObjectLiteralResult(boolean wereReifiedMarkers, @NotNull ClassDescriptor classDescriptor) { 246 this.wereReifiedMarkers = wereReifiedMarkers; 247 this.classDescriptor = classDescriptor; 248 } 249 } 250 251 @NotNull 252 private StackValue castToRequiredTypeOfInterfaceIfNeeded( 253 StackValue inner, 254 @NotNull ClassDescriptor provided, 255 @NotNull ClassDescriptor required 256 ) { 257 if (!isJvmInterface(provided) && isJvmInterface(required)) { 258 return StackValue.coercion(inner, asmType(required.getDefaultType())); 259 } 260 261 return inner; 262 } 263 264 public StackValue genQualified(StackValue receiver, KtElement selector) { 265 return genQualified(receiver, selector, this); 266 } 267 268 private StackValue genQualified(StackValue receiver, KtElement selector, KtVisitor<StackValue, StackValue> visitor) { 269 if (tempVariables.containsKey(selector)) { 270 throw new IllegalStateException("Inconsistent state: expression saved to a temporary variable is a selector"); 271 } 272 if (!(selector instanceof KtBlockExpression)) { 273 markStartLineNumber(selector); 274 } 275 try { 276 if (selector instanceof KtExpression) { 277 StackValue samValue = genSamInterfaceValue((KtExpression) selector, visitor); 278 if (samValue != null) { 279 return samValue; 280 } 281 } 282 283 StackValue stackValue = selector.accept(visitor, receiver); 284 285 RuntimeAssertionInfo runtimeAssertionInfo = null; 286 if (selector instanceof KtExpression) { 287 runtimeAssertionInfo = bindingContext.get(JvmBindingContextSlices.RUNTIME_ASSERTION_INFO, (KtExpression) selector); 288 } 289 290 if (BuiltinSpecialBridgesKt.isValueArgumentForCallToMethodWithTypeCheckBarrier(selector, bindingContext)) return stackValue; 291 292 return genNotNullAssertions(state, stackValue, runtimeAssertionInfo); 293 } 294 catch (ProcessCanceledException e) { 295 throw e; 296 } 297 catch (CompilationException e) { 298 throw e; 299 } 300 catch (Throwable error) { 301 String message = error.getMessage(); 302 throw new CompilationException(message != null ? message : "null", error, selector); 303 } 304 } 305 306 public StackValue gen(KtElement expr) { 307 StackValue tempVar = tempVariables.get(expr); 308 return tempVar != null ? tempVar : genQualified(StackValue.none(), expr); 309 } 310 311 public void gen(KtElement expr, Type type) { 312 StackValue value = Type.VOID_TYPE.equals(type) ? genStatement(expr) : gen(expr); 313 // for repl store the result of the last line into special field 314 if (value.type != Type.VOID_TYPE && state.getReplSpecific().getShouldGenerateScriptResultValue()) { 315 ScriptContext context = getScriptContext(); 316 if (expr == context.getLastStatement()) { 317 StackValue.Field resultValue = StackValue.field(context.getResultFieldInfo(), StackValue.LOCAL_0); 318 resultValue.store(value, v); 319 state.getReplSpecific().setHasResult(true); 320 return; 321 } 322 } 323 324 value.put(type, v); 325 } 326 327 @NotNull 328 private ScriptContext getScriptContext() { 329 CodegenContext context = getContext(); 330 while (!(context instanceof ScriptContext)) { 331 context = context.getParentContext(); 332 } 333 return (ScriptContext) context; 334 } 335 336 public StackValue genLazy(KtElement expr, Type type) { 337 StackValue value = gen(expr); 338 return StackValue.coercion(value, type); 339 } 340 341 private StackValue genStatement(KtElement statement) { 342 return genQualified(StackValue.none(), statement, statementVisitor); 343 } 344 345 @Override 346 public StackValue visitClass(@NotNull KtClass klass, StackValue data) { 347 return visitClassOrObject(klass); 348 } 349 350 private StackValue visitClassOrObject(KtClassOrObject declaration) { 351 ClassDescriptor descriptor = bindingContext.get(CLASS, declaration); 352 assert descriptor != null; 353 354 Type asmType = asmTypeForAnonymousClass(bindingContext, declaration); 355 ClassBuilder classBuilder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(declaration, descriptor), asmType, declaration.getContainingFile()); 356 357 ClassContext objectContext = context.intoAnonymousClass(descriptor, this, OwnerKind.IMPLEMENTATION); 358 new ImplementationBodyCodegen(declaration, objectContext, classBuilder, state, getParentCodegen(), /* isLocal = */ true).generate(); 359 360 if (declaration instanceof KtClass && ((KtClass) declaration).isInterface()) { 361 Type traitImplType = state.getTypeMapper().mapDefaultImpls(descriptor); 362 ClassBuilder traitImplBuilder = state.getFactory().newVisitor(JvmDeclarationOriginKt.TraitImpl(declaration, descriptor), traitImplType, declaration.getContainingFile()); 363 ClassContext traitImplContext = context.intoAnonymousClass(descriptor, this, OwnerKind.DEFAULT_IMPLS); 364 new InterfaceImplBodyCodegen(declaration, traitImplContext, traitImplBuilder, state, parentCodegen).generate(); 365 } 366 367 return StackValue.none(); 368 } 369 370 @Override 371 public StackValue visitObjectDeclaration(@NotNull KtObjectDeclaration declaration, StackValue data) { 372 return visitClassOrObject(declaration); 373 } 374 375 @Override 376 public StackValue visitExpression(@NotNull KtExpression expression, StackValue receiver) { 377 throw new UnsupportedOperationException("Codegen for " + expression + " is not yet implemented"); 378 } 379 380 @Override 381 public StackValue visitSuperExpression(@NotNull KtSuperExpression expression, StackValue data) { 382 return StackValue.thisOrOuter(this, getSuperCallLabelTarget(context, expression), true, false); 383 } 384 385 @NotNull 386 public static ClassDescriptor getSuperCallLabelTarget( 387 @NotNull CodegenContext<?> context, 388 @NotNull KtSuperExpression expression 389 ) { 390 KotlinType thisTypeForSuperCall = context.getState().getBindingContext().get(BindingContext.THIS_TYPE_FOR_SUPER_EXPRESSION, expression); 391 assert thisTypeForSuperCall != null : "This type for superCall ''" + expression.getText() + "'' should be not null!"; 392 ClassifierDescriptor descriptor = thisTypeForSuperCall.getConstructor().getDeclarationDescriptor(); 393 assert descriptor instanceof ClassDescriptor : 394 "'This' reference target for ''" + expression.getText() + "''should be class descriptor, but was " + descriptor; 395 return (ClassDescriptor) descriptor; 396 } 397 398 @NotNull 399 private Type asmType(@NotNull KotlinType type) { 400 return typeMapper.mapType(type); 401 } 402 403 @NotNull 404 public Type expressionType(@Nullable KtExpression expression) { 405 KotlinType type = expressionJetType(expression); 406 return type == null ? Type.VOID_TYPE : asmType(type); 407 } 408 409 @Nullable 410 public KotlinType expressionJetType(@Nullable KtExpression expression) { 411 return expression != null ? bindingContext.getType(expression) : null; 412 } 413 414 @Override 415 public StackValue visitParenthesizedExpression(@NotNull KtParenthesizedExpression expression, StackValue receiver) { 416 return genQualified(receiver, expression.getExpression()); 417 } 418 419 @Override 420 public StackValue visitAnnotatedExpression(@NotNull KtAnnotatedExpression expression, StackValue receiver) { 421 return genQualified(receiver, expression.getBaseExpression()); 422 } 423 424 private static boolean isEmptyExpression(@Nullable KtElement expr) { 425 if (expr == null) { 426 return true; 427 } 428 if (expr instanceof KtBlockExpression) { 429 KtBlockExpression blockExpression = (KtBlockExpression) expr; 430 List<KtExpression> statements = blockExpression.getStatements(); 431 if (statements.size() == 0 || statements.size() == 1 && isEmptyExpression(statements.get(0))) { 432 return true; 433 } 434 } 435 return false; 436 } 437 438 @Override 439 public StackValue visitIfExpression(@NotNull KtIfExpression expression, StackValue receiver) { 440 return generateIfExpression(expression, false); 441 } 442 443 /* package */ StackValue generateIfExpression(@NotNull final KtIfExpression expression, final boolean isStatement) { 444 final Type asmType = isStatement ? Type.VOID_TYPE : expressionType(expression); 445 final StackValue condition = gen(expression.getCondition()); 446 447 final KtExpression thenExpression = expression.getThen(); 448 final KtExpression elseExpression = expression.getElse(); 449 450 if (isEmptyExpression(thenExpression)) { 451 if (isEmptyExpression(elseExpression)) { 452 return StackValue.coercion(condition, asmType); 453 } 454 return generateSingleBranchIf(condition, expression, elseExpression, false, isStatement); 455 } 456 else { 457 if (isEmptyExpression(elseExpression)) { 458 return generateSingleBranchIf(condition, expression, thenExpression, true, isStatement); 459 } 460 } 461 462 return StackValue.operation(asmType, new Function1<InstructionAdapter, Unit>() { 463 @Override 464 public Unit invoke(InstructionAdapter v) { 465 Label elseLabel = new Label(); 466 BranchedValue.Companion.condJump(condition, elseLabel, true, v); 467 468 Label end = new Label(); 469 470 gen(thenExpression, asmType); 471 472 v.goTo(end); 473 v.mark(elseLabel); 474 475 gen(elseExpression, asmType); 476 477 markLineNumber(expression, isStatement); 478 v.mark(end); 479 return Unit.INSTANCE; 480 } 481 }); 482 } 483 484 @Override 485 public StackValue visitWhileExpression(@NotNull KtWhileExpression expression, StackValue receiver) { 486 Label condition = new Label(); 487 v.mark(condition); 488 489 Label end = new Label(); 490 blockStackElements.push(new LoopBlockStackElement(end, condition, targetLabel(expression))); 491 492 StackValue conditionValue = gen(expression.getCondition()); 493 BranchedValue.Companion.loopJump(conditionValue, end, true, v); 494 495 generateLoopBody(expression.getBody()); 496 497 markStartLineNumber(expression); 498 v.goTo(condition); 499 500 v.mark(end); 501 502 blockStackElements.pop(); 503 504 return StackValue.onStack(Type.VOID_TYPE); 505 } 506 507 508 @Override 509 public StackValue visitDoWhileExpression(@NotNull KtDoWhileExpression expression, StackValue receiver) { 510 Label beginLoopLabel = new Label(); 511 v.mark(beginLoopLabel); 512 513 Label breakLabel = new Label(); 514 Label continueLabel = new Label(); 515 516 blockStackElements.push(new LoopBlockStackElement(breakLabel, continueLabel, targetLabel(expression))); 517 518 PseudoInsnsKt.fakeAlwaysFalseIfeq(v, continueLabel); 519 520 KtExpression body = expression.getBody(); 521 KtExpression condition = expression.getCondition(); 522 StackValue conditionValue; 523 524 StackValueWithLeaveTask leaveTask = null; 525 if (body instanceof KtBlockExpression) { 526 // If body's a block, it can contain variable declarations which may be used in the condition of a do-while loop. 527 // We handle this case separately because otherwise such variable will be out of the frame map after the block ends 528 List<KtExpression> doWhileStatements = ((KtBlockExpression) body).getStatements(); 529 530 List<KtExpression> statements = new ArrayList<KtExpression>(doWhileStatements.size() + 1); 531 statements.addAll(doWhileStatements); 532 statements.add(condition); 533 534 //Need to split leave task and condition cause otherwise BranchedValue optimizations wouldn't work 535 leaveTask = generateBlock(statements, false, continueLabel, null); 536 conditionValue = leaveTask.getStackValue(); 537 } 538 else { 539 if (body != null) { 540 gen(body, Type.VOID_TYPE); 541 } 542 v.mark(continueLabel); 543 conditionValue = gen(condition); 544 } 545 546 BranchedValue.Companion.loopJump(conditionValue, beginLoopLabel, false, v); 547 if (leaveTask != null) { 548 leaveTask.getLeaveTasks().invoke(conditionValue); 549 } 550 v.mark(breakLabel); 551 552 blockStackElements.pop(); 553 return StackValue.none(); 554 } 555 556 @Override 557 public StackValue visitForExpression(@NotNull KtForExpression forExpression, StackValue receiver) { 558 ResolvedCall<? extends CallableDescriptor> loopRangeCall = RangeCodegenUtil.getLoopRangeResolvedCall(forExpression, bindingContext); 559 if (loopRangeCall != null) { 560 AbstractForLoopGenerator optimizedForLoopGenerator = createOptimizedForLoopGeneratorOrNull(forExpression, loopRangeCall); 561 if (optimizedForLoopGenerator != null) { 562 generateForLoop(optimizedForLoopGenerator); 563 return StackValue.none(); 564 } 565 } 566 567 KtExpression loopRange = forExpression.getLoopRange(); 568 assert loopRange != null; 569 KotlinType loopRangeType = bindingContext.getType(loopRange); 570 assert loopRangeType != null; 571 Type asmLoopRangeType = asmType(loopRangeType); 572 if (asmLoopRangeType.getSort() == Type.ARRAY) { 573 generateForLoop(new ForInArrayLoopGenerator(forExpression)); 574 return StackValue.none(); 575 } 576 577 if (RangeCodegenUtil.isRange(loopRangeType)) { 578 generateForLoop(new ForInRangeInstanceLoopGenerator(forExpression)); 579 return StackValue.none(); 580 } 581 582 if (RangeCodegenUtil.isProgression(loopRangeType)) { 583 generateForLoop(new ForInProgressionExpressionLoopGenerator(forExpression)); 584 return StackValue.none(); 585 } 586 587 generateForLoop(new IteratorForLoopGenerator(forExpression)); 588 return StackValue.none(); 589 } 590 591 @Nullable 592 private AbstractForLoopGenerator createOptimizedForLoopGeneratorOrNull( 593 @NotNull KtForExpression forExpression, 594 @NotNull ResolvedCall<? extends CallableDescriptor> loopRangeCall 595 ) { 596 CallableDescriptor loopRangeCallee = loopRangeCall.getResultingDescriptor(); 597 if (RangeCodegenUtil.isOptimizableRangeTo(loopRangeCallee)) { 598 return new ForInRangeLiteralLoopGenerator(forExpression, loopRangeCall); 599 } 600 else if (RangeCodegenUtil.isOptimizableDownTo(loopRangeCallee)) { 601 return new ForInDownToProgressionLoopGenerator(forExpression, loopRangeCall); 602 } 603 else if (RangeCodegenUtil.isArrayOrPrimitiveArrayIndices(loopRangeCallee)) { 604 return new ForInArrayIndicesRangeLoopGenerator(forExpression, loopRangeCall); 605 } 606 else if (RangeCodegenUtil.isCollectionIndices(loopRangeCallee)) { 607 return new ForInCollectionIndicesRangeLoopGenerator(forExpression, loopRangeCall); 608 } 609 610 return null; 611 } 612 613 @NotNull 614 private static KotlinType getExpectedReceiverType(@NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall) { 615 ReceiverParameterDescriptor extensionReceiver = resolvedCall.getResultingDescriptor().getExtensionReceiverParameter(); 616 assert extensionReceiver != null : "Extension receiver should be non-null"; 617 return extensionReceiver.getType(); 618 } 619 620 @Nullable 621 private static KtExpression getSingleArgumentExpression(@NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall) { 622 List<ResolvedValueArgument> resolvedValueArguments = resolvedCall.getValueArgumentsByIndex(); 623 if (resolvedValueArguments == null) return null; 624 if (resolvedValueArguments.size() != 1) return null; 625 List<ValueArgument> valueArguments = resolvedValueArguments.get(0).getArguments(); 626 if (valueArguments.size() != 1) return null; 627 return valueArguments.get(0).getArgumentExpression(); 628 } 629 630 private OwnerKind contextKind() { 631 return context.getContextKind(); 632 } 633 634 private void generateForLoop(AbstractForLoopGenerator generator) { 635 Label loopExit = new Label(); 636 Label loopEntry = new Label(); 637 Label continueLabel = new Label(); 638 639 generator.beforeLoop(); 640 generator.checkEmptyLoop(loopExit); 641 642 v.mark(loopEntry); 643 generator.checkPreCondition(loopExit); 644 645 // Some forms of for-loop can be optimized as post-condition loops. 646 PseudoInsnsKt.fakeAlwaysFalseIfeq(v, continueLabel); 647 648 generator.beforeBody(); 649 blockStackElements.push(new LoopBlockStackElement(loopExit, continueLabel, targetLabel(generator.forExpression))); 650 generator.body(); 651 blockStackElements.pop(); 652 v.mark(continueLabel); 653 generator.afterBody(loopExit); 654 655 v.goTo(loopEntry); 656 657 v.mark(loopExit); 658 generator.afterLoop(); 659 } 660 661 private abstract class AbstractForLoopGenerator { 662 663 // for (e : E in c) {...} 664 protected final KtForExpression forExpression; 665 private final Label loopParameterStartLabel = new Label(); 666 private final Label bodyEnd = new Label(); 667 private final List<Runnable> leaveVariableTasks = Lists.newArrayList(); 668 669 protected final KotlinType elementType; 670 protected final Type asmElementType; 671 672 protected int loopParameterVar; 673 protected Type loopParameterType; 674 675 private AbstractForLoopGenerator(@NotNull KtForExpression forExpression) { 676 this.forExpression = forExpression; 677 this.elementType = getElementType(forExpression); 678 this.asmElementType = asmType(elementType); 679 } 680 681 @NotNull 682 private KotlinType getElementType(KtForExpression forExpression) { 683 KtExpression loopRange = forExpression.getLoopRange(); 684 assert loopRange != null; 685 ResolvedCall<FunctionDescriptor> nextCall = getNotNull(bindingContext, 686 LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange, 687 "No next() function " + DiagnosticUtils.atLocation(loopRange)); 688 //noinspection ConstantConditions 689 return nextCall.getResultingDescriptor().getReturnType(); 690 } 691 692 public void beforeLoop() { 693 KtParameter loopParameter = forExpression.getLoopParameter(); 694 if (loopParameter != null) { 695 // E e = tmp<iterator>.next() 696 final VariableDescriptor parameterDescriptor = bindingContext.get(VALUE_PARAMETER, loopParameter); 697 loopParameterType = asmType(parameterDescriptor.getType()); 698 loopParameterVar = myFrameMap.enter(parameterDescriptor, loopParameterType); 699 scheduleLeaveVariable(new Runnable() { 700 @Override 701 public void run() { 702 myFrameMap.leave(parameterDescriptor); 703 v.visitLocalVariable(parameterDescriptor.getName().asString(), 704 loopParameterType.getDescriptor(), null, 705 loopParameterStartLabel, bodyEnd, 706 loopParameterVar); 707 } 708 }); 709 } 710 else { 711 KtDestructuringDeclaration multiParameter = forExpression.getDestructuringParameter(); 712 assert multiParameter != null; 713 714 // E tmp<e> = tmp<iterator>.next() 715 loopParameterType = asmElementType; 716 loopParameterVar = createLoopTempVariable(asmElementType); 717 } 718 } 719 720 public abstract void checkEmptyLoop(@NotNull Label loopExit); 721 722 public abstract void checkPreCondition(@NotNull Label loopExit); 723 724 public void beforeBody() { 725 assignToLoopParameter(); 726 v.mark(loopParameterStartLabel); 727 728 if (forExpression.getLoopParameter() == null) { 729 KtDestructuringDeclaration multiParameter = forExpression.getDestructuringParameter(); 730 assert multiParameter != null; 731 732 generateMultiVariables(multiParameter.getEntries()); 733 } 734 } 735 736 private void generateMultiVariables(List<KtDestructuringDeclarationEntry> entries) { 737 for (KtDestructuringDeclarationEntry variableDeclaration : entries) { 738 final VariableDescriptor componentDescriptor = bindingContext.get(VARIABLE, variableDeclaration); 739 740 @SuppressWarnings("ConstantConditions") final Type componentAsmType = asmType(componentDescriptor.getReturnType()); 741 final int componentVarIndex = myFrameMap.enter(componentDescriptor, componentAsmType); 742 final Label variableStartLabel = new Label(); 743 scheduleLeaveVariable(new Runnable() { 744 @Override 745 public void run() { 746 myFrameMap.leave(componentDescriptor); 747 v.visitLocalVariable(componentDescriptor.getName().asString(), 748 componentAsmType.getDescriptor(), null, 749 variableStartLabel, bodyEnd, 750 componentVarIndex); 751 } 752 }); 753 754 ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(COMPONENT_RESOLVED_CALL, variableDeclaration); 755 assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText(); 756 Call call = makeFakeCall(new TransientReceiver(elementType)); 757 758 StackValue value = invokeFunction(call, resolvedCall, StackValue.local(loopParameterVar, asmElementType)); 759 StackValue.local(componentVarIndex, componentAsmType).store(value, v); 760 v.visitLabel(variableStartLabel); 761 } 762 } 763 764 protected abstract void assignToLoopParameter(); 765 766 protected abstract void increment(@NotNull Label loopExit); 767 768 public void body() { 769 generateLoopBody(forExpression.getBody()); 770 } 771 772 private void scheduleLeaveVariable(Runnable runnable) { 773 leaveVariableTasks.add(runnable); 774 } 775 776 protected int createLoopTempVariable(final Type type) { 777 int varIndex = myFrameMap.enterTemp(type); 778 scheduleLeaveVariable(new Runnable() { 779 @Override 780 public void run() { 781 myFrameMap.leaveTemp(type); 782 } 783 }); 784 return varIndex; 785 } 786 787 public void afterBody(@NotNull Label loopExit) { 788 markStartLineNumber(forExpression); 789 790 increment(loopExit); 791 792 v.mark(bodyEnd); 793 } 794 795 public void afterLoop() { 796 for (Runnable task : Lists.reverse(leaveVariableTasks)) { 797 task.run(); 798 } 799 } 800 801 // This method consumes range/progression from stack 802 // The result is stored to local variable 803 protected void generateRangeOrProgressionProperty( 804 @NotNull Type loopRangeType, 805 @NotNull String getterName, 806 @NotNull Type getterReturnType, 807 @NotNull Type varType, 808 int varToStore 809 ) { 810 v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + getterReturnType.getDescriptor(), false); 811 StackValue.local(varToStore, varType).store(StackValue.onStack(getterReturnType), v); 812 } 813 } 814 815 private void generateLoopBody(@Nullable KtExpression body) { 816 if (body != null) { 817 gen(body, Type.VOID_TYPE); 818 } 819 } 820 821 private class IteratorForLoopGenerator extends AbstractForLoopGenerator { 822 823 private int iteratorVarIndex; 824 private final ResolvedCall<FunctionDescriptor> iteratorCall; 825 private final ResolvedCall<FunctionDescriptor> nextCall; 826 private final Type asmTypeForIterator; 827 828 private IteratorForLoopGenerator(@NotNull KtForExpression forExpression) { 829 super(forExpression); 830 831 KtExpression loopRange = forExpression.getLoopRange(); 832 assert loopRange != null; 833 this.iteratorCall = getNotNull(bindingContext, 834 LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange, 835 "No .iterator() function " + DiagnosticUtils.atLocation(loopRange)); 836 837 KotlinType iteratorType = iteratorCall.getResultingDescriptor().getReturnType(); 838 assert iteratorType != null; 839 this.asmTypeForIterator = asmType(iteratorType); 840 841 this.nextCall = getNotNull(bindingContext, 842 LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange, 843 "No next() function " + DiagnosticUtils.atLocation(loopRange)); 844 } 845 846 @Override 847 public void beforeLoop() { 848 super.beforeLoop(); 849 850 // Iterator<E> tmp<iterator> = c.iterator() 851 852 iteratorVarIndex = createLoopTempVariable(asmTypeForIterator); 853 854 StackValue.local(iteratorVarIndex, asmTypeForIterator).store(invokeFunction(iteratorCall, StackValue.none()), v); 855 } 856 857 @Override 858 public void checkEmptyLoop(@NotNull Label loopExit) { 859 } 860 861 @Override 862 public void checkPreCondition(@NotNull Label loopExit) { 863 // tmp<iterator>.hasNext() 864 865 KtExpression loopRange = forExpression.getLoopRange(); 866 @SuppressWarnings("ConstantConditions") ResolvedCall<FunctionDescriptor> hasNextCall = getNotNull(bindingContext, 867 LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, loopRange, 868 "No hasNext() function " + DiagnosticUtils.atLocation(loopRange)); 869 @SuppressWarnings("ConstantConditions") Call fakeCall = makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType())); 870 StackValue result = invokeFunction(fakeCall, hasNextCall, StackValue.local(iteratorVarIndex, asmTypeForIterator)); 871 result.put(result.type, v); 872 873 FunctionDescriptor hasNext = hasNextCall.getResultingDescriptor(); 874 KotlinType type = hasNext.getReturnType(); 875 assert type != null && KotlinTypeChecker.DEFAULT.isSubtypeOf(type, DescriptorUtilsKt.getBuiltIns(hasNext).getBooleanType()); 876 877 Type asmType = asmType(type); 878 StackValue.coerce(asmType, Type.BOOLEAN_TYPE, v); 879 v.ifeq(loopExit); 880 } 881 882 @Override 883 protected void assignToLoopParameter() { 884 @SuppressWarnings("ConstantConditions") Call fakeCall = 885 makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType())); 886 StackValue value = invokeFunction(fakeCall, nextCall, StackValue.local(iteratorVarIndex, asmTypeForIterator)); 887 //noinspection ConstantConditions 888 StackValue.local(loopParameterVar, loopParameterType).store(value, v); 889 } 890 891 @Override 892 protected void increment(@NotNull Label loopExit) { 893 } 894 } 895 896 private class ForInArrayLoopGenerator extends AbstractForLoopGenerator { 897 private int indexVar; 898 private int arrayVar; 899 private final KotlinType loopRangeType; 900 901 private ForInArrayLoopGenerator(@NotNull KtForExpression forExpression) { 902 super(forExpression); 903 loopRangeType = bindingContext.getType(forExpression.getLoopRange()); 904 } 905 906 @Override 907 public void beforeLoop() { 908 super.beforeLoop(); 909 910 indexVar = createLoopTempVariable(Type.INT_TYPE); 911 912 KtExpression loopRange = forExpression.getLoopRange(); 913 StackValue value = gen(loopRange); 914 Type asmLoopRangeType = asmType(loopRangeType); 915 if (value instanceof StackValue.Local && value.type.equals(asmLoopRangeType)) { 916 arrayVar = ((StackValue.Local) value).index; // no need to copy local variable into another variable 917 } 918 else { 919 arrayVar = createLoopTempVariable(OBJECT_TYPE); 920 value.put(asmLoopRangeType, v); 921 v.store(arrayVar, OBJECT_TYPE); 922 } 923 924 v.iconst(0); 925 v.store(indexVar, Type.INT_TYPE); 926 } 927 928 @Override 929 public void checkEmptyLoop(@NotNull Label loopExit) { 930 } 931 932 @Override 933 public void checkPreCondition(@NotNull Label loopExit) { 934 v.load(indexVar, Type.INT_TYPE); 935 v.load(arrayVar, OBJECT_TYPE); 936 v.arraylength(); 937 v.ificmpge(loopExit); 938 } 939 940 @Override 941 protected void assignToLoopParameter() { 942 Type arrayElParamType; 943 if (KotlinBuiltIns.isArray(loopRangeType)) { 944 arrayElParamType = boxType(asmElementType); 945 } 946 else { 947 arrayElParamType = asmElementType; 948 } 949 950 v.load(arrayVar, OBJECT_TYPE); 951 v.load(indexVar, Type.INT_TYPE); 952 v.aload(arrayElParamType); 953 StackValue.onStack(arrayElParamType).put(asmElementType, v); 954 v.store(loopParameterVar, asmElementType); 955 } 956 957 @Override 958 protected void increment(@NotNull Label loopExit) { 959 v.iinc(indexVar, 1); 960 } 961 } 962 963 private abstract class AbstractForInProgressionOrRangeLoopGenerator extends AbstractForLoopGenerator { 964 protected int endVar; 965 966 private StackValue loopParameter; 967 968 private AbstractForInProgressionOrRangeLoopGenerator(@NotNull KtForExpression forExpression) { 969 super(forExpression); 970 971 switch (asmElementType.getSort()) { 972 case Type.INT: 973 case Type.BYTE: 974 case Type.SHORT: 975 case Type.CHAR: 976 case Type.LONG: 977 break; 978 979 default: 980 throw new IllegalStateException("Unexpected range element type: " + asmElementType); 981 } 982 } 983 984 @Override 985 public void beforeLoop() { 986 super.beforeLoop(); 987 988 endVar = createLoopTempVariable(asmElementType); 989 } 990 991 protected void checkPostCondition(@NotNull Label loopExit) { 992 assert endVar != -1 : 993 "endVar must be allocated, endVar = " + endVar; 994 loopParameter().put(asmElementType, v); 995 v.load(endVar, asmElementType); 996 if (asmElementType.getSort() == Type.LONG) { 997 v.lcmp(); 998 v.ifeq(loopExit); 999 } 1000 else { 1001 v.ificmpeq(loopExit); 1002 } 1003 } 1004 1005 @Override 1006 public void checkPreCondition(@NotNull Label loopExit) { 1007 } 1008 1009 @NotNull 1010 protected StackValue loopParameter() { 1011 if (loopParameter == null) { 1012 loopParameter = StackValue.local(loopParameterVar, loopParameterType); 1013 } 1014 return loopParameter; 1015 } 1016 } 1017 1018 private abstract class AbstractForInRangeLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator { 1019 private final int step; 1020 1021 private AbstractForInRangeLoopGenerator(@NotNull KtForExpression forExpression, int step) { 1022 super(forExpression); 1023 this.step = step; 1024 assert step == 1 || step == -1 : "'step' should be either 1 or -1: " + step; 1025 } 1026 1027 private AbstractForInRangeLoopGenerator(@NotNull KtForExpression forExpression) { 1028 this(forExpression, 1); 1029 } 1030 1031 @Override 1032 public void beforeLoop() { 1033 super.beforeLoop(); 1034 1035 storeRangeStartAndEnd(); 1036 } 1037 1038 protected abstract void storeRangeStartAndEnd(); 1039 1040 @Override 1041 public void checkEmptyLoop(@NotNull Label loopExit) { 1042 loopParameter().put(asmElementType, v); 1043 v.load(endVar, asmElementType); 1044 if (asmElementType.getSort() == Type.LONG) { 1045 v.lcmp(); 1046 if (step > 0) { 1047 v.ifgt(loopExit); 1048 } 1049 else { 1050 v.iflt(loopExit); 1051 } 1052 } 1053 else { 1054 if (step > 0) { 1055 v.ificmpgt(loopExit); 1056 } 1057 else { 1058 v.ificmplt(loopExit); 1059 } 1060 } 1061 } 1062 1063 @Override 1064 protected void assignToLoopParameter() { 1065 } 1066 1067 @Override 1068 protected void increment(@NotNull Label loopExit) { 1069 checkPostCondition(loopExit); 1070 1071 if (loopParameterType == Type.INT_TYPE) { 1072 v.iinc(loopParameterVar, step); 1073 } 1074 else { 1075 StackValue loopParameter = loopParameter(); 1076 loopParameter.put(asmElementType, v); 1077 genIncrement(asmElementType, step, v); 1078 loopParameter.store(StackValue.onStack(asmElementType), v); 1079 } 1080 } 1081 } 1082 1083 private class ForInRangeLiteralLoopGenerator extends AbstractForInRangeLoopGenerator { 1084 private final ReceiverValue from; 1085 private final KtExpression to; 1086 1087 private ForInRangeLiteralLoopGenerator(@NotNull KtForExpression forExpression, @NotNull ResolvedCall<?> loopRangeCall) { 1088 super(forExpression); 1089 this.from = loopRangeCall.getDispatchReceiver(); 1090 this.to = getSingleArgumentExpression(loopRangeCall); 1091 } 1092 1093 @Override 1094 protected void storeRangeStartAndEnd() { 1095 loopParameter().store(generateReceiverValue(from, false), v); 1096 StackValue.local(endVar, asmElementType).store(gen(to), v); 1097 } 1098 } 1099 1100 private class ForInDownToProgressionLoopGenerator extends AbstractForInRangeLoopGenerator { 1101 private final ReceiverValue from; 1102 private final KtExpression to; 1103 1104 private ForInDownToProgressionLoopGenerator(@NotNull KtForExpression forExpression, @NotNull ResolvedCall<?> loopRangeCall) { 1105 super(forExpression, -1); 1106 this.from = loopRangeCall.getExtensionReceiver(); 1107 this.to = getSingleArgumentExpression(loopRangeCall); 1108 } 1109 1110 @Override 1111 protected void storeRangeStartAndEnd() { 1112 loopParameter().store(generateReceiverValue(from, false), v); 1113 StackValue.local(endVar, asmElementType).store(gen(to), v); 1114 } 1115 } 1116 1117 private class ForInRangeInstanceLoopGenerator extends AbstractForInRangeLoopGenerator { 1118 private ForInRangeInstanceLoopGenerator(@NotNull KtForExpression forExpression) { 1119 super(forExpression); 1120 } 1121 1122 @Override 1123 protected void storeRangeStartAndEnd() { 1124 KotlinType loopRangeType = bindingContext.getType(forExpression.getLoopRange()); 1125 assert loopRangeType != null; 1126 Type asmLoopRangeType = asmType(loopRangeType); 1127 gen(forExpression.getLoopRange(), asmLoopRangeType); 1128 v.dup(); 1129 1130 // ranges inherit first and last from corresponding progressions 1131 generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar); 1132 generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar); 1133 } 1134 } 1135 1136 private abstract class ForInOptimizedIndicesLoopGenerator extends AbstractForInRangeLoopGenerator { 1137 protected final ReceiverValue receiverValue; 1138 protected final KotlinType expectedReceiverType; 1139 1140 private ForInOptimizedIndicesLoopGenerator(@NotNull KtForExpression forExpression, @NotNull ResolvedCall<?> loopRangeCall) { 1141 super(forExpression); 1142 this.receiverValue = loopRangeCall.getExtensionReceiver(); 1143 this.expectedReceiverType = getExpectedReceiverType(loopRangeCall); 1144 } 1145 1146 @Override 1147 protected void storeRangeStartAndEnd() { 1148 loopParameter().store(StackValue.constant(0, asmElementType), v); 1149 1150 StackValue receiver = generateReceiverValue(receiverValue, false); 1151 Type receiverType = asmType(expectedReceiverType); 1152 receiver.put(receiverType, v); 1153 getReceiverSizeAsInt(); 1154 v.iconst(1); 1155 v.sub(Type.INT_TYPE); 1156 StackValue.local(endVar, asmElementType).store(StackValue.onStack(Type.INT_TYPE), v); 1157 } 1158 1159 /** 1160 * <code>(receiver -> size:I)</code> 1161 */ 1162 protected abstract void getReceiverSizeAsInt(); 1163 } 1164 1165 private class ForInCollectionIndicesRangeLoopGenerator extends ForInOptimizedIndicesLoopGenerator { 1166 private ForInCollectionIndicesRangeLoopGenerator(@NotNull KtForExpression forExpression, @NotNull ResolvedCall<?> loopRangeCall) { 1167 super(forExpression, loopRangeCall); 1168 } 1169 1170 @Override 1171 protected void getReceiverSizeAsInt() { 1172 v.invokeinterface("java/util/Collection", "size", "()I"); 1173 } 1174 } 1175 1176 private class ForInArrayIndicesRangeLoopGenerator extends ForInOptimizedIndicesLoopGenerator { 1177 private ForInArrayIndicesRangeLoopGenerator(@NotNull KtForExpression forExpression, @NotNull ResolvedCall<?> loopRangeCall) { 1178 super(forExpression, loopRangeCall); 1179 } 1180 1181 @Override 1182 protected void getReceiverSizeAsInt() { 1183 v.arraylength(); 1184 } 1185 } 1186 1187 private class ForInProgressionExpressionLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator { 1188 private int incrementVar; 1189 private Type incrementType; 1190 1191 private ForInProgressionExpressionLoopGenerator(@NotNull KtForExpression forExpression) { 1192 super(forExpression); 1193 } 1194 1195 @Override 1196 public void beforeLoop() { 1197 super.beforeLoop(); 1198 1199 incrementVar = createLoopTempVariable(asmElementType); 1200 1201 KotlinType loopRangeType = bindingContext.getType(forExpression.getLoopRange()); 1202 assert loopRangeType != null; 1203 Type asmLoopRangeType = asmType(loopRangeType); 1204 1205 Collection<PropertyDescriptor> incrementProp = 1206 loopRangeType.getMemberScope().getContributedVariables(Name.identifier("step"), NoLookupLocation.FROM_BACKEND); 1207 assert incrementProp.size() == 1 : loopRangeType + " " + incrementProp.size(); 1208 incrementType = asmType(incrementProp.iterator().next().getType()); 1209 1210 gen(forExpression.getLoopRange(), asmLoopRangeType); 1211 v.dup(); 1212 v.dup(); 1213 1214 generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar); 1215 generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar); 1216 generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementType, incrementVar); 1217 } 1218 1219 @Override 1220 public void checkEmptyLoop(@NotNull Label loopExit) { 1221 loopParameter().put(asmElementType, v); 1222 v.load(endVar, asmElementType); 1223 v.load(incrementVar, incrementType); 1224 1225 Label negativeIncrement = new Label(); 1226 Label afterIf = new Label(); 1227 1228 if (asmElementType.getSort() == Type.LONG) { 1229 v.lconst(0L); 1230 v.lcmp(); 1231 v.ifle(negativeIncrement); // if increment < 0, jump 1232 1233 // increment > 0 1234 v.lcmp(); 1235 v.ifgt(loopExit); 1236 v.goTo(afterIf); 1237 1238 // increment < 0 1239 v.mark(negativeIncrement); 1240 v.lcmp(); 1241 v.iflt(loopExit); 1242 v.mark(afterIf); 1243 } 1244 else { 1245 v.ifle(negativeIncrement); // if increment < 0, jump 1246 1247 // increment > 0 1248 v.ificmpgt(loopExit); 1249 v.goTo(afterIf); 1250 1251 // increment < 0 1252 v.mark(negativeIncrement); 1253 v.ificmplt(loopExit); 1254 v.mark(afterIf); 1255 } 1256 } 1257 1258 @Override 1259 protected void assignToLoopParameter() { 1260 } 1261 1262 @Override 1263 protected void increment(@NotNull Label loopExit) { 1264 checkPostCondition(loopExit); 1265 1266 StackValue loopParameter = loopParameter(); 1267 loopParameter.put(asmElementType, v); 1268 v.load(incrementVar, asmElementType); 1269 v.add(asmElementType); 1270 1271 if (asmElementType == Type.BYTE_TYPE || asmElementType == Type.SHORT_TYPE || asmElementType == Type.CHAR_TYPE) { 1272 StackValue.coerce(Type.INT_TYPE, asmElementType, v); 1273 } 1274 1275 loopParameter.store(StackValue.onStack(asmElementType), v); 1276 } 1277 } 1278 1279 1280 @Override 1281 public StackValue visitBreakExpression(@NotNull KtBreakExpression expression, StackValue receiver) { 1282 return generateBreakOrContinueExpression(expression, true, new Label()); 1283 } 1284 1285 @Override 1286 public StackValue visitContinueExpression(@NotNull KtContinueExpression expression, StackValue receiver) { 1287 return generateBreakOrContinueExpression(expression, false, new Label()); 1288 } 1289 1290 @NotNull 1291 private StackValue generateBreakOrContinueExpression( 1292 @NotNull KtExpressionWithLabel expression, 1293 boolean isBreak, 1294 final @NotNull Label afterBreakContinueLabel 1295 ) { 1296 assert expression instanceof KtContinueExpression || expression instanceof KtBreakExpression; 1297 1298 if (blockStackElements.isEmpty()) { 1299 throw new UnsupportedOperationException("Target label for break/continue not found"); 1300 } 1301 1302 BlockStackElement stackElement = blockStackElements.peek(); 1303 1304 if (stackElement instanceof FinallyBlockStackElement) { 1305 FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement; 1306 //noinspection ConstantConditions 1307 genFinallyBlockOrGoto(finallyBlockStackElement, null, afterBreakContinueLabel); 1308 } 1309 else if (stackElement instanceof LoopBlockStackElement) { 1310 LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement; 1311 KtSimpleNameExpression labelElement = expression.getTargetLabel(); 1312 //noinspection ConstantConditions 1313 if (labelElement == null || 1314 loopBlockStackElement.targetLabel != null && 1315 labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) { 1316 final Label label = isBreak ? loopBlockStackElement.breakLabel : loopBlockStackElement.continueLabel; 1317 return StackValue.operation(Type.VOID_TYPE, new Function1<InstructionAdapter, Unit>() { 1318 @Override 1319 public Unit invoke(InstructionAdapter adapter) { 1320 PseudoInsnsKt.fixStackAndJump(v, label); 1321 v.mark(afterBreakContinueLabel); 1322 return Unit.INSTANCE; 1323 } 1324 } 1325 ); 1326 } 1327 } 1328 else { 1329 throw new UnsupportedOperationException("Wrong BlockStackElement in processing stack"); 1330 } 1331 1332 blockStackElements.pop(); 1333 StackValue result = generateBreakOrContinueExpression(expression, isBreak, afterBreakContinueLabel); 1334 blockStackElements.push(stackElement); 1335 return result; 1336 } 1337 1338 private StackValue generateSingleBranchIf( 1339 final StackValue condition, 1340 final KtIfExpression ifExpression, 1341 final KtExpression expression, 1342 final boolean inverse, 1343 final boolean isStatement 1344 ) { 1345 Type targetType = isStatement ? Type.VOID_TYPE : expressionType(ifExpression); 1346 return StackValue.operation(targetType, new Function1<InstructionAdapter, Unit>() { 1347 @Override 1348 public Unit invoke(InstructionAdapter v) { 1349 Label elseLabel = new Label(); 1350 BranchedValue.Companion.condJump(condition, elseLabel, inverse, v); 1351 1352 if (isStatement) { 1353 gen(expression, Type.VOID_TYPE); 1354 v.mark(elseLabel); 1355 } 1356 else { 1357 Type targetType = expressionType(ifExpression); 1358 gen(expression, targetType); 1359 Label end = new Label(); 1360 v.goTo(end); 1361 1362 v.mark(elseLabel); 1363 StackValue.putUnitInstance(v); 1364 1365 markStartLineNumber(ifExpression); 1366 v.mark(end); 1367 } 1368 return null; 1369 } 1370 }); 1371 } 1372 1373 @Override 1374 public StackValue visitConstantExpression(@NotNull KtConstantExpression expression, StackValue receiver) { 1375 ConstantValue<?> compileTimeValue = getPrimitiveOrStringCompileTimeConstant(expression, bindingContext); 1376 assert compileTimeValue != null; 1377 return StackValue.constant(compileTimeValue.getValue(), expressionType(expression)); 1378 } 1379 1380 @Nullable 1381 public static ConstantValue<?> getPrimitiveOrStringCompileTimeConstant(@NotNull KtExpression expression, @NotNull BindingContext bindingContext) { 1382 ConstantValue<?> constant = getCompileTimeConstant(expression, bindingContext, false); 1383 if (constant == null || ConstantExpressionEvaluatorKt.isStandaloneOnlyConstant(constant)) { 1384 return null; 1385 } 1386 return constant; 1387 } 1388 1389 @Nullable 1390 public static ConstantValue<?> getCompileTimeConstant(@NotNull KtExpression expression, @NotNull BindingContext bindingContext) { 1391 return getCompileTimeConstant(expression, bindingContext, false); 1392 } 1393 1394 @Nullable 1395 public static ConstantValue<?> getCompileTimeConstant( 1396 @NotNull KtExpression expression, 1397 @NotNull final BindingContext bindingContext, 1398 boolean takeUpConstValsAsConst 1399 ) { 1400 CompileTimeConstant<?> compileTimeValue = ConstantExpressionEvaluator.getConstant(expression, bindingContext); 1401 if (compileTimeValue == null || compileTimeValue.getUsesNonConstValAsConstant()) { 1402 return null; 1403 } 1404 1405 if (!takeUpConstValsAsConst && compileTimeValue.getUsesVariableAsConstant()) { 1406 final Ref<Boolean> containsNonInlinedVals = new Ref<Boolean>(false); 1407 KtVisitor constantChecker = new KtVisitor() { 1408 @Override 1409 public Object visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, Object data) { 1410 ResolvedCall resolvedCall = CallUtilKt.getResolvedCall(expression, bindingContext); 1411 if (resolvedCall != null) { 1412 CallableDescriptor callableDescriptor = resolvedCall.getResultingDescriptor(); 1413 if (callableDescriptor instanceof PropertyDescriptor && 1414 !JvmCodegenUtil.isInlinedJavaConstProperty((VariableDescriptor) callableDescriptor)) { 1415 containsNonInlinedVals.set(true); 1416 } 1417 } 1418 return null; 1419 } 1420 1421 @Override 1422 public Object visitKtElement(@NotNull KtElement element, Object data) { 1423 if (!containsNonInlinedVals.get()) { 1424 element.acceptChildren(this); 1425 } 1426 return null; 1427 } 1428 }; 1429 1430 expression.accept(constantChecker); 1431 1432 if (containsNonInlinedVals.get()) { 1433 return null; 1434 } 1435 } 1436 1437 KotlinType expectedType = bindingContext.getType(expression); 1438 return compileTimeValue.toConstantValue(expectedType); 1439 } 1440 1441 @Override 1442 public StackValue visitStringTemplateExpression(@NotNull KtStringTemplateExpression expression, StackValue receiver) { 1443 StringBuilder constantValue = new StringBuilder(""); 1444 final KtStringTemplateEntry[] entries = expression.getEntries(); 1445 1446 if (entries.length == 1 && entries[0] instanceof KtStringTemplateEntryWithExpression) { 1447 KtExpression expr = entries[0].getExpression(); 1448 return genToString(gen(expr), expressionType(expr)); 1449 } 1450 1451 for (KtStringTemplateEntry entry : entries) { 1452 if (entry instanceof KtLiteralStringTemplateEntry) { 1453 constantValue.append(entry.getText()); 1454 } 1455 else if (entry instanceof KtEscapeStringTemplateEntry) { 1456 constantValue.append(((KtEscapeStringTemplateEntry) entry).getUnescapedValue()); 1457 } 1458 else { 1459 constantValue = null; 1460 break; 1461 } 1462 } 1463 if (constantValue != null) { 1464 Type type = expressionType(expression); 1465 return StackValue.constant(constantValue.toString(), type); 1466 } 1467 else { 1468 return StackValue.operation(JAVA_STRING_TYPE, new Function1<InstructionAdapter, Unit>() { 1469 @Override 1470 public Unit invoke(InstructionAdapter v) { 1471 genStringBuilderConstructor(v); 1472 for (KtStringTemplateEntry entry : entries) { 1473 if (entry instanceof KtStringTemplateEntryWithExpression) { 1474 invokeAppend(entry.getExpression()); 1475 } 1476 else { 1477 String text = entry instanceof KtEscapeStringTemplateEntry 1478 ? ((KtEscapeStringTemplateEntry) entry).getUnescapedValue() 1479 : entry.getText(); 1480 v.aconst(text); 1481 genInvokeAppendMethod(v, JAVA_STRING_TYPE); 1482 } 1483 } 1484 v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); 1485 return Unit.INSTANCE; 1486 } 1487 }); 1488 } 1489 } 1490 1491 @Override 1492 public StackValue visitBlockExpression(@NotNull KtBlockExpression expression, StackValue receiver) { 1493 return generateBlock(expression, false); 1494 } 1495 1496 @Override 1497 public StackValue visitNamedFunction(@NotNull KtNamedFunction function, StackValue data) { 1498 return visitNamedFunction(function, data, false); 1499 } 1500 1501 public StackValue visitNamedFunction(@NotNull KtNamedFunction function, StackValue data, boolean isStatement) { 1502 assert data == StackValue.none(); 1503 1504 if (KtPsiUtil.isScriptDeclaration(function)) { 1505 return StackValue.none(); 1506 } 1507 1508 StackValue closure = genClosure(function, null); 1509 if (isStatement) { 1510 DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, function); 1511 int index = lookupLocalIndex(descriptor); 1512 closure.put(OBJECT_TYPE, v); 1513 v.store(index, OBJECT_TYPE); 1514 return StackValue.none(); 1515 } 1516 else { 1517 return closure; 1518 } 1519 } 1520 1521 @Override 1522 public StackValue visitLambdaExpression(@NotNull KtLambdaExpression expression, StackValue receiver) { 1523 if (Boolean.TRUE.equals(bindingContext.get(BLOCK, expression))) { 1524 return gen(expression.getFunctionLiteral().getBodyExpression()); 1525 } 1526 else { 1527 return genClosure(expression.getFunctionLiteral(), null); 1528 } 1529 } 1530 1531 @NotNull 1532 private StackValue genClosure(KtDeclarationWithBody declaration, @Nullable SamType samType) { 1533 FunctionDescriptor descriptor = bindingContext.get(FUNCTION, declaration); 1534 assert descriptor != null : "Function is not resolved to descriptor: " + declaration.getText(); 1535 1536 return genClosure( 1537 declaration, descriptor, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), samType, null 1538 ); 1539 } 1540 1541 @NotNull 1542 private StackValue genClosure( 1543 @NotNull KtElement declaration, 1544 @NotNull FunctionDescriptor descriptor, 1545 @NotNull FunctionGenerationStrategy strategy, 1546 @Nullable SamType samType, 1547 @Nullable FunctionDescriptor functionReferenceTarget 1548 ) { 1549 ClassBuilder cv = state.getFactory().newVisitor( 1550 JvmDeclarationOriginKt.OtherOrigin(declaration, descriptor), 1551 asmTypeForAnonymousClass(bindingContext, descriptor), 1552 declaration.getContainingFile() 1553 ); 1554 1555 ClosureCodegen closureCodegen = new ClosureCodegen( 1556 state, declaration, samType, context.intoClosure(descriptor, this, typeMapper), 1557 functionReferenceTarget, strategy, parentCodegen, cv 1558 ); 1559 1560 closureCodegen.generate(); 1561 1562 if (closureCodegen.getReifiedTypeParametersUsages().wereUsedReifiedParameters()) { 1563 ReifiedTypeInliner.putNeedClassReificationMarker(v); 1564 propagateChildReifiedTypeParametersUsages(closureCodegen.getReifiedTypeParametersUsages()); 1565 } 1566 1567 return closureCodegen.putInstanceOnStack(this); 1568 } 1569 1570 @Override 1571 public StackValue visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression, StackValue receiver) { 1572 final ObjectLiteralResult objectLiteralResult = generateObjectLiteral(expression); 1573 final ClassDescriptor classDescriptor = objectLiteralResult.classDescriptor; 1574 final Type type = typeMapper.mapType(classDescriptor); 1575 1576 return StackValue.operation(type, new Function1<InstructionAdapter, Unit>() { 1577 @Override 1578 public Unit invoke(InstructionAdapter v) { 1579 if (objectLiteralResult.wereReifiedMarkers) { 1580 ReifiedTypeInliner.putNeedClassReificationMarker(v); 1581 } 1582 v.anew(type); 1583 v.dup(); 1584 1585 pushClosureOnStack(classDescriptor, true, defaultCallGenerator); 1586 1587 ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); 1588 assert primaryConstructor != null : "There should be primary constructor for object literal"; 1589 ResolvedCall<ConstructorDescriptor> superCall = getDelegationConstructorCall(bindingContext, primaryConstructor); 1590 if (superCall != null) { 1591 // For an anonymous object, we should also generate all non-default arguments that it captures for its super call 1592 ConstructorDescriptor superConstructor = superCall.getResultingDescriptor(); 1593 ConstructorDescriptor constructorToCall = SamCodegenUtil.resolveSamAdapter(superConstructor); 1594 List<ValueParameterDescriptor> superValueParameters = superConstructor.getValueParameters(); 1595 int params = superValueParameters.size(); 1596 List<Type> superMappedTypes = typeMapper.mapToCallableMethod(constructorToCall, false).getValueParameterTypes(); 1597 assert superMappedTypes.size() >= params : String 1598 .format("Incorrect number of mapped parameters vs arguments: %d < %d for %s", 1599 superMappedTypes.size(), params, classDescriptor); 1600 1601 List<ResolvedValueArgument> valueArguments = new ArrayList<ResolvedValueArgument>(params); 1602 List<ValueParameterDescriptor> valueParameters = new ArrayList<ValueParameterDescriptor>(params); 1603 List<Type> mappedTypes = new ArrayList<Type>(params); 1604 for (ValueParameterDescriptor parameter : superValueParameters) { 1605 ResolvedValueArgument argument = superCall.getValueArguments().get(parameter); 1606 if (!(argument instanceof DefaultValueArgument)) { 1607 valueArguments.add(argument); 1608 valueParameters.add(parameter); 1609 mappedTypes.add(superMappedTypes.get(parameter.getIndex())); 1610 } 1611 } 1612 ArgumentGenerator argumentGenerator = 1613 new CallBasedArgumentGenerator(ExpressionCodegen.this, defaultCallGenerator, valueParameters, mappedTypes); 1614 1615 argumentGenerator.generate(valueArguments, valueArguments); 1616 } 1617 1618 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors(); 1619 assert constructors.size() == 1 : "Unexpected number of constructors for class: " + classDescriptor + " " + constructors; 1620 ConstructorDescriptor constructorDescriptor = CollectionsKt.single(constructors); 1621 1622 Method constructor = typeMapper.mapAsmMethod(SamCodegenUtil.resolveSamAdapter(constructorDescriptor)); 1623 v.invokespecial(type.getInternalName(), "<init>", constructor.getDescriptor(), false); 1624 return Unit.INSTANCE; 1625 } 1626 }); 1627 } 1628 1629 public void pushClosureOnStack(@NotNull ClassDescriptor classDescriptor, boolean putThis, @NotNull CallGenerator callGenerator) { 1630 CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor); 1631 if (closure == null) return; 1632 1633 int paramIndex = 0; 1634 1635 if (putThis) { 1636 ClassDescriptor captureThis = closure.getCaptureThis(); 1637 if (captureThis != null) { 1638 StackValue thisOrOuter = generateThisOrOuter(captureThis, false); 1639 assert !isPrimitive(thisOrOuter.type) : "This or outer should be non primitive: " + thisOrOuter.type; 1640 callGenerator.putCapturedValueOnStack(thisOrOuter, thisOrOuter.type, paramIndex++); 1641 } 1642 } 1643 1644 KotlinType captureReceiver = closure.getCaptureReceiverType(); 1645 if (captureReceiver != null) { 1646 Type asmType = typeMapper.mapType(captureReceiver); 1647 StackValue.Local capturedReceiver = StackValue.local(AsmUtil.getReceiverIndex(context, context.getContextDescriptor()), asmType); 1648 callGenerator.putCapturedValueOnStack(capturedReceiver, capturedReceiver.type, paramIndex++); 1649 } 1650 1651 for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) { 1652 Type sharedVarType = typeMapper.getSharedVarType(entry.getKey()); 1653 if (sharedVarType == null) { 1654 sharedVarType = typeMapper.mapType((VariableDescriptor) entry.getKey()); 1655 } 1656 StackValue capturedVar = lookupOuterValue(entry.getValue()); 1657 callGenerator.putCapturedValueOnStack(capturedVar, sharedVarType, paramIndex++); 1658 } 1659 1660 1661 ClassDescriptor superClass = DescriptorUtilsKt.getSuperClassNotAny(classDescriptor); 1662 if (superClass != null) { 1663 pushClosureOnStack( 1664 superClass, 1665 putThis && closure.getCaptureThis() == null, 1666 callGenerator 1667 ); 1668 } 1669 } 1670 1671 /* package */ StackValue generateBlock(@NotNull KtBlockExpression expression, boolean isStatement) { 1672 if (expression.getParent() instanceof KtNamedFunction) { 1673 // For functions end of block should be end of function label 1674 return generateBlock(expression.getStatements(), isStatement, null, context.getMethodEndLabel()); 1675 } 1676 return generateBlock(expression.getStatements(), isStatement, null, null); 1677 } 1678 1679 @NotNull 1680 public StackValue lookupOuterValue(EnclosedValueDescriptor d) { 1681 DeclarationDescriptor descriptor = d.getDescriptor(); 1682 for (LocalLookup.LocalLookupCase aCase : LocalLookup.LocalLookupCase.values()) { 1683 if (aCase.isCase(descriptor)) { 1684 return aCase.outerValue(d, this); 1685 } 1686 } 1687 throw new IllegalStateException("Can't get outer value in " + this + " for " + d); 1688 } 1689 1690 private StackValueWithLeaveTask generateBlock( 1691 List<KtExpression> statements, 1692 boolean isStatement, 1693 Label labelBeforeLastExpression, 1694 @Nullable final Label labelBlockEnd 1695 ) { 1696 final Label blockEnd = labelBlockEnd != null ? labelBlockEnd : new Label(); 1697 1698 final List<Function<StackValue, Void>> leaveTasks = Lists.newArrayList(); 1699 1700 StackValue answer = StackValue.none(); 1701 1702 for (Iterator<KtExpression> iterator = statements.iterator(); iterator.hasNext(); ) { 1703 KtExpression possiblyLabeledStatement = iterator.next(); 1704 1705 KtElement statement = KtPsiUtil.safeDeparenthesize(possiblyLabeledStatement); 1706 1707 if (statement instanceof KtNamedDeclaration) { 1708 KtNamedDeclaration declaration = (KtNamedDeclaration) statement; 1709 if (KtPsiUtil.isScriptDeclaration(declaration)) { 1710 continue; 1711 } 1712 } 1713 1714 putDescriptorIntoFrameMap(statement); 1715 1716 boolean isExpression = !iterator.hasNext() && !isStatement; 1717 if (isExpression && labelBeforeLastExpression != null) { 1718 v.mark(labelBeforeLastExpression); 1719 } 1720 1721 StackValue result = isExpression ? gen(possiblyLabeledStatement) : genStatement(possiblyLabeledStatement); 1722 1723 if (!iterator.hasNext()) { 1724 answer = result; 1725 } 1726 else { 1727 result.put(Type.VOID_TYPE, v); 1728 } 1729 1730 addLeaveTaskToRemoveDescriptorFromFrameMap(statement, blockEnd, leaveTasks); 1731 } 1732 1733 return new StackValueWithLeaveTask(answer, new Function1<StackValue, Unit>() { 1734 @Override 1735 public Unit invoke(StackValue value) { 1736 if (labelBlockEnd == null) { 1737 v.mark(blockEnd); 1738 } 1739 for (Function<StackValue, Void> task : Lists.reverse(leaveTasks)) { 1740 task.fun(value); 1741 } 1742 return Unit.INSTANCE; 1743 } 1744 }); 1745 } 1746 1747 @NotNull 1748 private Type getVariableType(@NotNull VariableDescriptor variableDescriptor) { 1749 Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 1750 return sharedVarType != null ? sharedVarType : asmType(variableDescriptor.getType()); 1751 } 1752 1753 private static boolean isSharedVarType(@NotNull Type type) { 1754 return type.getSort() == Type.OBJECT && type.getInternalName().startsWith(REF_TYPE_PREFIX); 1755 } 1756 1757 1758 private void putDescriptorIntoFrameMap(@NotNull KtElement statement) { 1759 if (statement instanceof KtDestructuringDeclaration) { 1760 KtDestructuringDeclaration multiDeclaration = (KtDestructuringDeclaration) statement; 1761 for (KtDestructuringDeclarationEntry entry : multiDeclaration.getEntries()) { 1762 putLocalVariableIntoFrameMap(entry); 1763 } 1764 } 1765 1766 if (statement instanceof KtVariableDeclaration) { 1767 putLocalVariableIntoFrameMap((KtVariableDeclaration) statement); 1768 } 1769 1770 if (statement instanceof KtNamedFunction) { 1771 DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, statement); 1772 assert descriptor instanceof FunctionDescriptor : "Couldn't find function declaration in binding context " + statement.getText(); 1773 Type type = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor); 1774 myFrameMap.enter(descriptor, type); 1775 } 1776 } 1777 1778 private void putLocalVariableIntoFrameMap(@NotNull KtVariableDeclaration statement) { 1779 VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, statement); 1780 assert variableDescriptor != null : "Couldn't find variable declaration in binding context " + statement.getText(); 1781 1782 Type type = getVariableType(variableDescriptor); 1783 int index = myFrameMap.enter(variableDescriptor, type); 1784 1785 if (isSharedVarType(type)) { 1786 markLineNumber(statement, false); 1787 v.anew(type); 1788 v.dup(); 1789 v.invokespecial(type.getInternalName(), "<init>", "()V", false); 1790 v.store(index, OBJECT_TYPE); 1791 } 1792 } 1793 1794 private void addLeaveTaskToRemoveDescriptorFromFrameMap( 1795 @NotNull KtElement statement, 1796 @NotNull Label blockEnd, 1797 @NotNull List<Function<StackValue, Void>> leaveTasks 1798 ) { 1799 if (statement instanceof KtDestructuringDeclaration) { 1800 KtDestructuringDeclaration multiDeclaration = (KtDestructuringDeclaration) statement; 1801 for (KtDestructuringDeclarationEntry entry : multiDeclaration.getEntries()) { 1802 addLeaveTaskToRemoveLocalVariableFromFrameMap(entry, blockEnd, leaveTasks); 1803 } 1804 } 1805 1806 if (statement instanceof KtVariableDeclaration) { 1807 addLeaveTaskToRemoveLocalVariableFromFrameMap((KtVariableDeclaration) statement, blockEnd, leaveTasks); 1808 } 1809 1810 if (statement instanceof KtNamedFunction) { 1811 addLeaveTaskToRemoveNamedFunctionFromFrameMap((KtNamedFunction) statement, blockEnd, leaveTasks); 1812 } 1813 } 1814 1815 private void addLeaveTaskToRemoveLocalVariableFromFrameMap( 1816 @NotNull KtVariableDeclaration statement, 1817 final Label blockEnd, 1818 @NotNull List<Function<StackValue, Void>> leaveTasks 1819 ) { 1820 final VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, statement); 1821 assert variableDescriptor != null; 1822 1823 final Type type = getVariableType(variableDescriptor); 1824 1825 final Label scopeStart = new Label(); 1826 v.mark(scopeStart); 1827 1828 leaveTasks.add(new Function<StackValue, Void>() { 1829 @Override 1830 public Void fun(StackValue answer) { 1831 int index = myFrameMap.leave(variableDescriptor); 1832 1833 if (isSharedVarType(type)) { 1834 v.aconst(null); 1835 v.store(index, OBJECT_TYPE); 1836 } 1837 v.visitLocalVariable(variableDescriptor.getName().asString(), type.getDescriptor(), null, scopeStart, blockEnd, index); 1838 return null; 1839 } 1840 }); 1841 } 1842 1843 private void addLeaveTaskToRemoveNamedFunctionFromFrameMap( 1844 @NotNull final KtNamedFunction statement, 1845 final Label blockEnd, 1846 @NotNull List<Function<StackValue, Void>> leaveTasks 1847 ) { 1848 final FunctionDescriptor functionDescriptor = (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, statement); 1849 assert functionDescriptor != null; 1850 1851 final Type type = asmTypeForAnonymousClass(bindingContext, functionDescriptor); 1852 1853 final Label scopeStart = new Label(); 1854 v.mark(scopeStart); 1855 1856 leaveTasks.add(new Function<StackValue, Void>() { 1857 @Override 1858 public Void fun(StackValue answer) { 1859 int index = myFrameMap.leave(functionDescriptor); 1860 1861 assert !functionDescriptor.getName().isSpecial() : "Local variable should be generated only for function with name: " + statement.getText(); 1862 v.visitLocalVariable(functionDescriptor.getName().asString() + "$", type.getDescriptor(), null, scopeStart, blockEnd, index); 1863 return null; 1864 } 1865 }); 1866 } 1867 1868 public boolean isShouldMarkLineNumbers() { 1869 return shouldMarkLineNumbers; 1870 } 1871 1872 public void setShouldMarkLineNumbers(boolean shouldMarkLineNumbers) { 1873 this.shouldMarkLineNumbers = shouldMarkLineNumbers; 1874 } 1875 1876 public void markStartLineNumber(@NotNull KtElement element) { 1877 markLineNumber(element, false); 1878 } 1879 1880 public void markLineNumber(@NotNull KtElement statement, boolean markEndOffset) { 1881 if (!shouldMarkLineNumbers) return; 1882 1883 Integer lineNumber = CodegenUtil.getLineNumberForElement(statement, markEndOffset); 1884 if (lineNumber == null || lineNumber == myLastLineNumber) { 1885 return; 1886 } 1887 myLastLineNumber = lineNumber; 1888 1889 Label label = new Label(); 1890 v.visitLabel(label); 1891 v.visitLineNumber(lineNumber, label); 1892 } 1893 1894 //we should generate additional linenumber info after inline call only if it used as argument 1895 public void markLineNumberAfterInlineIfNeeded() { 1896 if (!shouldMarkLineNumbers) { 1897 //if it used as general argument 1898 if (myLastLineNumber > -1) { 1899 Label label = new Label(); 1900 v.visitLabel(label); 1901 v.visitLineNumber(myLastLineNumber, label); 1902 } 1903 } else { 1904 //if it used as argument of infix call (in this case lineNumber for simple inlineCall also would be reset) 1905 myLastLineNumber = -1; 1906 } 1907 } 1908 1909 public int getLastLineNumber() { 1910 return myLastLineNumber; 1911 } 1912 1913 private void doFinallyOnReturn(@NotNull Label afterReturnLabel) { 1914 if(!blockStackElements.isEmpty()) { 1915 BlockStackElement stackElement = blockStackElements.peek(); 1916 if (stackElement instanceof FinallyBlockStackElement) { 1917 FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement; 1918 genFinallyBlockOrGoto(finallyBlockStackElement, null, afterReturnLabel); 1919 } 1920 else if (stackElement instanceof LoopBlockStackElement) { 1921 1922 } else { 1923 throw new UnsupportedOperationException("Wrong BlockStackElement in processing stack"); 1924 } 1925 1926 blockStackElements.pop(); 1927 doFinallyOnReturn(afterReturnLabel); 1928 blockStackElements.push(stackElement); 1929 } 1930 } 1931 1932 public boolean hasFinallyBlocks() { 1933 for (BlockStackElement element : blockStackElements) { 1934 if (element instanceof FinallyBlockStackElement) { 1935 return true; 1936 } 1937 } 1938 return false; 1939 } 1940 1941 private void genFinallyBlockOrGoto( 1942 @Nullable FinallyBlockStackElement finallyBlockStackElement, 1943 @Nullable Label tryCatchBlockEnd, 1944 @Nullable Label afterJumpLabel 1945 ) { 1946 if (finallyBlockStackElement != null) { 1947 finallyDepth++; 1948 assert finallyBlockStackElement.gaps.size() % 2 == 0 : "Finally block gaps are inconsistent"; 1949 1950 BlockStackElement topOfStack = blockStackElements.pop(); 1951 assert topOfStack == finallyBlockStackElement : "Top element of stack doesn't equals processing finally block"; 1952 1953 KtTryExpression jetTryExpression = finallyBlockStackElement.expression; 1954 Label finallyStart = new Label(); 1955 v.mark(finallyStart); 1956 finallyBlockStackElement.addGapLabel(finallyStart); 1957 if (InlineCodegenUtil.isFinallyMarkerRequired(context)) { 1958 InlineCodegenUtil.generateFinallyMarker(v, finallyDepth, true); 1959 } 1960 //noinspection ConstantConditions 1961 gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE); 1962 1963 if (InlineCodegenUtil.isFinallyMarkerRequired(context)) { 1964 InlineCodegenUtil.generateFinallyMarker(v, finallyDepth, false); 1965 } 1966 } 1967 1968 if (tryCatchBlockEnd != null) { 1969 v.goTo(tryCatchBlockEnd); 1970 } 1971 1972 if (finallyBlockStackElement != null) { 1973 finallyDepth--; 1974 Label finallyEnd = afterJumpLabel != null ? afterJumpLabel : new Label(); 1975 if (afterJumpLabel == null) { 1976 v.mark(finallyEnd); 1977 } 1978 finallyBlockStackElement.addGapLabel(finallyEnd); 1979 1980 blockStackElements.push(finallyBlockStackElement); 1981 } 1982 } 1983 1984 @Override 1985 public StackValue visitReturnExpression(@NotNull final KtReturnExpression expression, StackValue receiver) { 1986 return StackValue.operation(Type.VOID_TYPE, new Function1<InstructionAdapter, Unit>() { 1987 @Override 1988 public Unit invoke(InstructionAdapter adapter) { 1989 KtExpression returnedExpression = expression.getReturnedExpression(); 1990 CallableMemberDescriptor descriptor = getContext().getContextDescriptor(); 1991 NonLocalReturnInfo nonLocalReturn = getNonLocalReturnInfo(descriptor, expression); 1992 boolean isNonLocalReturn = nonLocalReturn != null; 1993 if (isNonLocalReturn && !state.isInlineEnabled()) { 1994 state.getDiagnostics().report(Errors.NON_LOCAL_RETURN_IN_DISABLED_INLINE.on(expression)); 1995 genThrow(v, "java/lang/UnsupportedOperationException", 1996 "Non-local returns are not allowed with inlining disabled"); 1997 return Unit.INSTANCE; 1998 } 1999 2000 Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : ExpressionCodegen.this.returnType; 2001 if (returnedExpression != null) { 2002 gen(returnedExpression, returnType); 2003 } 2004 2005 Label afterReturnLabel = new Label(); 2006 generateFinallyBlocksIfNeeded(returnType, afterReturnLabel); 2007 2008 if (isNonLocalReturn) { 2009 InlineCodegenUtil.generateGlobalReturnFlag(v, nonLocalReturn.labelName); 2010 } 2011 v.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); 2012 v.mark(afterReturnLabel); 2013 return Unit.INSTANCE; 2014 } 2015 }); 2016 } 2017 2018 public void generateFinallyBlocksIfNeeded(Type returnType, @NotNull Label afterReturnLabel) { 2019 if (hasFinallyBlocks()) { 2020 if (!Type.VOID_TYPE.equals(returnType)) { 2021 int returnValIndex = myFrameMap.enterTemp(returnType); 2022 StackValue.Local localForReturnValue = StackValue.local(returnValIndex, returnType); 2023 localForReturnValue.store(StackValue.onStack(returnType), v); 2024 doFinallyOnReturn(afterReturnLabel); 2025 localForReturnValue.put(returnType, v); 2026 myFrameMap.leaveTemp(returnType); 2027 } 2028 else { 2029 doFinallyOnReturn(afterReturnLabel); 2030 } 2031 } 2032 } 2033 2034 @Nullable 2035 private NonLocalReturnInfo getNonLocalReturnInfo(@NotNull CallableMemberDescriptor descriptor, @NotNull KtReturnExpression expression) { 2036 //call inside lambda 2037 if (isFunctionLiteral(descriptor) || isFunctionExpression(descriptor)) { 2038 if (expression.getLabelName() == null) { 2039 if (isFunctionLiteral(descriptor)) { 2040 //non labeled return couldn't be local in lambda 2041 FunctionDescriptor containingFunction = 2042 BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst(); 2043 //FIRST_FUN_LABEL to prevent clashing with existing labels 2044 return new NonLocalReturnInfo(typeMapper.mapReturnType(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL); 2045 } else { 2046 //local 2047 return null; 2048 } 2049 } 2050 2051 PsiElement element = bindingContext.get(LABEL_TARGET, expression.getTargetLabel()); 2052 if (element != DescriptorToSourceUtils.getSourceFromDescriptor(context.getContextDescriptor())) { 2053 DeclarationDescriptor elementDescriptor = typeMapper.getBindingContext().get(DECLARATION_TO_DESCRIPTOR, element); 2054 assert element != null : "Expression should be not null " + expression.getText(); 2055 assert elementDescriptor != null : "Descriptor should be not null: " + element.getText(); 2056 return new NonLocalReturnInfo(typeMapper.mapReturnType((CallableDescriptor) elementDescriptor), expression.getLabelName()); 2057 } 2058 } 2059 return null; 2060 } 2061 2062 public void returnExpression(KtExpression expr) { 2063 boolean isBlockedNamedFunction = expr instanceof KtBlockExpression && expr.getParent() instanceof KtNamedFunction; 2064 2065 // If generating body for named block-bodied function, generate it as sequence of statements 2066 gen(expr, isBlockedNamedFunction ? Type.VOID_TYPE : returnType); 2067 2068 // If it does not end with return we should return something 2069 // because if we don't there can be VerifyError (specific cases with Nothing-typed expressions) 2070 if (!endsWithReturn(expr)) { 2071 markLineNumber(expr, true); 2072 2073 if (isLambdaVoidBody(expr, returnType)) { 2074 markLineNumber((KtFunctionLiteral) expr.getParent(), true); 2075 } 2076 2077 if (isBlockedNamedFunction && !Type.VOID_TYPE.equals(expressionType(expr))) { 2078 StackValue.none().put(returnType, v); 2079 } 2080 2081 v.areturn(returnType); 2082 } 2083 } 2084 2085 private static boolean endsWithReturn(KtElement bodyExpression) { 2086 if (bodyExpression instanceof KtBlockExpression) { 2087 List<KtExpression> statements = ((KtBlockExpression) bodyExpression).getStatements(); 2088 return statements.size() > 0 && statements.get(statements.size() - 1) instanceof KtReturnExpression; 2089 } 2090 2091 return bodyExpression instanceof KtReturnExpression; 2092 } 2093 2094 private static boolean isLambdaVoidBody(KtElement bodyExpression, Type returnType) { 2095 if (bodyExpression instanceof KtBlockExpression) { 2096 PsiElement parent = bodyExpression.getParent(); 2097 if (parent instanceof KtFunctionLiteral) { 2098 return Type.VOID_TYPE.equals(returnType); 2099 } 2100 } 2101 2102 return false; 2103 } 2104 2105 @Override 2106 public StackValue visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, @NotNull StackValue receiver) { 2107 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, bindingContext); 2108 2109 DeclarationDescriptor descriptor; 2110 if (resolvedCall == null) { 2111 descriptor = bindingContext.get(REFERENCE_TARGET, expression); 2112 } 2113 else { 2114 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 2115 VariableAsFunctionResolvedCall call = (VariableAsFunctionResolvedCall) resolvedCall; 2116 resolvedCall = call.getVariableCall(); 2117 } 2118 2119 descriptor = resolvedCall.getResultingDescriptor(); 2120 2121 //Check early if KCallableNameProperty is applicable to prevent closure generation 2122 StackValue intrinsicResult = applyIntrinsic(descriptor, KCallableNameProperty.class, resolvedCall, receiver); 2123 if (intrinsicResult != null) return intrinsicResult; 2124 2125 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 2126 if (descriptor instanceof FakeCallableDescriptorForObject) { 2127 descriptor = ((FakeCallableDescriptorForObject) descriptor).getReferencedDescriptor(); 2128 } 2129 } 2130 2131 assert descriptor != null : "Couldn't find descriptor for '" + expression.getText() + "'"; 2132 descriptor = descriptor.getOriginal(); 2133 2134 boolean isSyntheticField = descriptor instanceof SyntheticFieldDescriptor; 2135 if (isSyntheticField) { 2136 descriptor = ((SyntheticFieldDescriptor) descriptor).getPropertyDescriptor(); 2137 } 2138 2139 StackValue intrinsicResult = applyIntrinsic(descriptor, IntrinsicPropertyGetter.class, resolvedCall, receiver); 2140 if (intrinsicResult != null) return intrinsicResult; 2141 2142 if (descriptor instanceof PropertyDescriptor) { 2143 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 2144 2145 Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject()); 2146 if (!codegenExtensions.isEmpty() && resolvedCall != null) { 2147 ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v); 2148 KotlinType returnType = propertyDescriptor.getReturnType(); 2149 for (ExpressionCodegenExtension extension : codegenExtensions) { 2150 if (returnType != null) { 2151 StackValue value = extension.applyProperty(receiver, resolvedCall, context); 2152 if (value != null) return value; 2153 } 2154 } 2155 } 2156 2157 boolean directToField = isSyntheticField && contextKind() != OwnerKind.DEFAULT_IMPLS; 2158 ClassDescriptor superCallTarget = resolvedCall == null ? null : getSuperCallTarget(resolvedCall.getCall()); 2159 2160 if (directToField) { 2161 receiver = StackValue.receiverWithoutReceiverArgument(receiver); 2162 } 2163 2164 return intermediateValueForProperty(propertyDescriptor, directToField, directToField, superCallTarget, false, receiver); 2165 } 2166 2167 if (descriptor instanceof ClassDescriptor) { 2168 ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; 2169 if (isObject(classDescriptor)) { 2170 return StackValue.singleton(classDescriptor, typeMapper); 2171 } 2172 if (isEnumEntry(classDescriptor)) { 2173 return StackValue.enumEntry(classDescriptor, typeMapper); 2174 } 2175 ClassDescriptor companionObjectDescriptor = classDescriptor.getCompanionObjectDescriptor(); 2176 if (companionObjectDescriptor != null) { 2177 return StackValue.singleton(companionObjectDescriptor, typeMapper); 2178 } 2179 return StackValue.none(); 2180 } 2181 2182 StackValue localOrCaptured = findLocalOrCapturedValue(descriptor); 2183 if (localOrCaptured != null) { 2184 return localOrCaptured; 2185 } 2186 throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); 2187 } 2188 2189 @Nullable 2190 private StackValue applyIntrinsic( 2191 DeclarationDescriptor descriptor, 2192 Class<? extends IntrinsicPropertyGetter> intrinsicType, 2193 ResolvedCall<?> resolvedCall, 2194 @NotNull StackValue receiver 2195 ) { 2196 if (descriptor instanceof CallableMemberDescriptor) { 2197 CallableMemberDescriptor memberDescriptor = DescriptorUtils.unwrapFakeOverride((CallableMemberDescriptor) descriptor); 2198 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(memberDescriptor); 2199 if (intrinsicType.isInstance(intrinsic)) { 2200 //TODO: intrinsic properties (see intermediateValueForProperty) 2201 Type returnType = typeMapper.mapType(memberDescriptor); 2202 return ((IntrinsicPropertyGetter) intrinsic).generate(resolvedCall, this, returnType, receiver); 2203 } 2204 } 2205 return null; 2206 } 2207 2208 @Nullable 2209 private ClassDescriptor getSuperCallTarget(@NotNull Call call) { 2210 KtSuperExpression superExpression = CallResolverUtilKt.getSuperCallExpression(call); 2211 return superExpression == null ? null : getSuperCallLabelTarget(context, superExpression); 2212 } 2213 2214 @Nullable 2215 public StackValue findLocalOrCapturedValue(@NotNull DeclarationDescriptor descriptor) { 2216 int index = lookupLocalIndex(descriptor); 2217 if (index >= 0) { 2218 return stackValueForLocal(descriptor, index); 2219 } 2220 2221 return findCapturedValue(descriptor); 2222 } 2223 2224 @Nullable 2225 public StackValue findCapturedValue(@NotNull DeclarationDescriptor descriptor) { 2226 if (context instanceof ConstructorContext) { 2227 return lookupCapturedValueInConstructorParameters(descriptor); 2228 } 2229 2230 return context.lookupInContext(descriptor, StackValue.LOCAL_0, state, false); 2231 } 2232 2233 @Nullable 2234 private StackValue lookupCapturedValueInConstructorParameters(@NotNull DeclarationDescriptor descriptor) { 2235 StackValue parentResult = context.lookupInContext(descriptor, StackValue.LOCAL_0, state, false); 2236 if (context.closure == null || parentResult == null) return parentResult; 2237 2238 int parameterOffsetInConstructor = context.closure.getCapturedParameterOffsetInConstructor(descriptor); 2239 // when captured parameter is singleton 2240 // see compiler/testData/codegen/box/objects/objectInLocalAnonymousObject.kt (fun local() captured in A) 2241 if (parameterOffsetInConstructor == -1) return parentResult; 2242 2243 assert parentResult instanceof StackValue.Field || parentResult instanceof StackValue.FieldForSharedVar 2244 : "Part of closure should be either Field or FieldForSharedVar"; 2245 2246 if (parentResult instanceof StackValue.FieldForSharedVar) { 2247 return StackValue.shared(parameterOffsetInConstructor, parentResult.type); 2248 } 2249 2250 return StackValue.local(parameterOffsetInConstructor, parentResult.type); 2251 } 2252 2253 private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) { 2254 if (descriptor instanceof VariableDescriptor) { 2255 Type sharedVarType = typeMapper.getSharedVarType(descriptor); 2256 KotlinType outType = ((VariableDescriptor) descriptor).getType(); 2257 if (sharedVarType != null) { 2258 return StackValue.shared(index, asmType(outType)); 2259 } 2260 else { 2261 return StackValue.local(index, asmType(outType)); 2262 } 2263 } 2264 else { 2265 return StackValue.local(index, OBJECT_TYPE); 2266 } 2267 } 2268 2269 @Override 2270 public boolean lookupLocal(DeclarationDescriptor descriptor) { 2271 return lookupLocalIndex(descriptor) != -1; 2272 } 2273 2274 public int lookupLocalIndex(DeclarationDescriptor descriptor) { 2275 return myFrameMap.getIndex(descriptor); 2276 } 2277 2278 @Nullable 2279 private static KotlinType getPropertyDelegateType(@NotNull PropertyDescriptor descriptor, @NotNull BindingContext bindingContext) { 2280 PropertyGetterDescriptor getter = descriptor.getGetter(); 2281 if (getter != null) { 2282 Call call = bindingContext.get(DELEGATED_PROPERTY_CALL, getter); 2283 if (call != null) { 2284 assert call.getExplicitReceiver() != null : "No explicit receiver for call:" + call; 2285 return ((ReceiverValue) call.getExplicitReceiver()).getType(); 2286 } 2287 } 2288 return null; 2289 } 2290 2291 @NotNull 2292 public StackValue.Property intermediateValueForProperty( 2293 @NotNull PropertyDescriptor propertyDescriptor, 2294 boolean forceField, 2295 @Nullable ClassDescriptor superCallTarget, 2296 @NotNull StackValue receiver 2297 ) { 2298 return intermediateValueForProperty(propertyDescriptor, forceField, false, superCallTarget, false, receiver); 2299 } 2300 2301 private CodegenContext getBackingFieldContext( 2302 @NotNull FieldAccessorKind accessorKind, 2303 @NotNull DeclarationDescriptor containingDeclaration 2304 ) { 2305 switch (accessorKind) { 2306 case NORMAL: return context.getParentContext(); 2307 // For companion object property, backing field lives in object containing class 2308 // Otherwise, it lives in its containing declaration 2309 case IN_CLASS_COMPANION: return context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration()); 2310 case FIELD_FROM_LOCAL: return context.findParentContextWithDescriptor(containingDeclaration); 2311 default: throw new IllegalStateException(); 2312 } 2313 } 2314 2315 public StackValue.Property intermediateValueForProperty( 2316 @NotNull PropertyDescriptor propertyDescriptor, 2317 boolean forceField, 2318 boolean syntheticBackingField, 2319 @Nullable ClassDescriptor superCallTarget, 2320 boolean skipAccessorsForPrivateFieldInOuterClass, 2321 StackValue receiver 2322 ) { 2323 if (propertyDescriptor instanceof SyntheticJavaPropertyDescriptor) { 2324 return intermediateValueForSyntheticExtensionProperty((SyntheticJavaPropertyDescriptor) propertyDescriptor, receiver); 2325 } 2326 2327 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); 2328 2329 FieldAccessorKind fieldAccessorKind = FieldAccessorKind.NORMAL; 2330 boolean isBackingFieldInClassCompanion = JvmAbi.isPropertyWithBackingFieldInOuterClass(propertyDescriptor); 2331 if (isBackingFieldInClassCompanion && (forceField || propertyDescriptor.isConst() && Visibilities.isPrivate(propertyDescriptor.getVisibility()))) { 2332 fieldAccessorKind = FieldAccessorKind.IN_CLASS_COMPANION; 2333 } 2334 else if (syntheticBackingField && context.getFirstCrossInlineOrNonInlineContext().getParentContext().getContextDescriptor() != containingDeclaration) { 2335 fieldAccessorKind = FieldAccessorKind.FIELD_FROM_LOCAL; 2336 } 2337 boolean isStaticBackingField = DescriptorUtils.isStaticDeclaration(propertyDescriptor) || 2338 AsmUtil.isInstancePropertyWithStaticBackingField(propertyDescriptor); 2339 boolean isSuper = superCallTarget != null; 2340 boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null; 2341 2342 KotlinType delegateType = getPropertyDelegateType(propertyDescriptor, bindingContext); 2343 boolean isDelegatedProperty = delegateType != null; 2344 2345 CallableMethod callableGetter = null; 2346 CallableMethod callableSetter = null; 2347 2348 CodegenContext backingFieldContext = getBackingFieldContext(fieldAccessorKind, containingDeclaration); 2349 DeclarationDescriptor ownerDescriptor = containingDeclaration; 2350 boolean skipPropertyAccessors; 2351 2352 PropertyDescriptor originalPropertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor); 2353 if (fieldAccessorKind != FieldAccessorKind.NORMAL) { 2354 int flags = AsmUtil.getVisibilityForBackingField(propertyDescriptor, isDelegatedProperty); 2355 skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || skipAccessorsForPrivateFieldInOuterClass; 2356 if (!skipPropertyAccessors) { 2357 //noinspection ConstantConditions 2358 propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor( 2359 propertyDescriptor, fieldAccessorKind, delegateType, superCallTarget 2360 ); 2361 assert propertyDescriptor instanceof AccessorForPropertyBackingField : 2362 "Unexpected accessor descriptor: " + propertyDescriptor; 2363 ownerDescriptor = propertyDescriptor; 2364 } 2365 } 2366 else { 2367 if (!isBackingFieldInClassCompanion) { 2368 ownerDescriptor = propertyDescriptor; 2369 } 2370 skipPropertyAccessors = forceField; 2371 } 2372 2373 if (!skipPropertyAccessors) { 2374 if (!couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context)) { 2375 propertyDescriptor = context.getAccessorForSuperCallIfNeeded(propertyDescriptor, superCallTarget); 2376 2377 propertyDescriptor = context.accessibleDescriptor(propertyDescriptor, superCallTarget); 2378 2379 PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); 2380 if (getter != null && !isConstOrHasJvmFieldAnnotation(propertyDescriptor)) { 2381 callableGetter = typeMapper.mapToCallableMethod(getter, isSuper); 2382 } 2383 } 2384 2385 if (propertyDescriptor.isVar()) { 2386 PropertySetterDescriptor setter = propertyDescriptor.getSetter(); 2387 if (setter != null && 2388 !couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context) && 2389 !isConstOrHasJvmFieldAnnotation(propertyDescriptor)) { 2390 callableSetter = typeMapper.mapToCallableMethod(setter, isSuper); 2391 } 2392 } 2393 } 2394 2395 if (!isStaticBackingField) { 2396 propertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor); 2397 } 2398 2399 Type backingFieldOwner = typeMapper.mapOwner(ownerDescriptor); 2400 2401 String fieldName; 2402 if (isExtensionProperty && !isDelegatedProperty) { 2403 fieldName = null; 2404 } 2405 else if (originalPropertyDescriptor.getContainingDeclaration() == backingFieldContext.getContextDescriptor()) { 2406 assert backingFieldContext instanceof FieldOwnerContext 2407 : "Actual context is " + backingFieldContext + " but should be instance of FieldOwnerContext"; 2408 fieldName = ((FieldOwnerContext) backingFieldContext).getFieldName(propertyDescriptor, isDelegatedProperty); 2409 } 2410 else { 2411 fieldName = KotlinTypeMapper.mapDefaultFieldName(propertyDescriptor, isDelegatedProperty); 2412 } 2413 2414 return StackValue.property(propertyDescriptor, backingFieldOwner, 2415 typeMapper.mapType( 2416 isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()), 2417 isStaticBackingField, fieldName, callableGetter, callableSetter, state, receiver); 2418 } 2419 2420 @NotNull 2421 private StackValue.Property intermediateValueForSyntheticExtensionProperty( 2422 @NotNull SyntheticJavaPropertyDescriptor propertyDescriptor, 2423 StackValue receiver 2424 ) { 2425 Type type = typeMapper.mapType(propertyDescriptor.getOriginal().getType()); 2426 CallableMethod callableGetter = 2427 typeMapper.mapToCallableMethod(context.accessibleDescriptor(propertyDescriptor.getGetMethod(), null), false); 2428 FunctionDescriptor setMethod = propertyDescriptor.getSetMethod(); 2429 CallableMethod callableSetter = 2430 setMethod != null ? typeMapper.mapToCallableMethod(context.accessibleDescriptor(setMethod, null), false) : null; 2431 return StackValue.property(propertyDescriptor, null, type, false, null, callableGetter, callableSetter, state, receiver); 2432 } 2433 2434 @Override 2435 public StackValue visitCallExpression(@NotNull KtCallExpression expression, StackValue receiver) { 2436 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); 2437 FunctionDescriptor descriptor = accessibleFunctionDescriptor(resolvedCall); 2438 2439 if (descriptor instanceof ConstructorDescriptor) { 2440 return generateNewCall(expression, resolvedCall); 2441 } 2442 2443 if (descriptor.getOriginal() instanceof SamConstructorDescriptor) { 2444 KtExpression argumentExpression = bindingContext.get(SAM_CONSTRUCTOR_TO_ARGUMENT, expression); 2445 assert argumentExpression != null : "Argument expression is not saved for a SAM constructor: " + descriptor; 2446 return genSamInterfaceValue(argumentExpression, this); 2447 } 2448 2449 return invokeFunction(resolvedCall, receiver); 2450 } 2451 2452 @Nullable 2453 private StackValue genSamInterfaceValue( 2454 @NotNull KtExpression probablyParenthesizedExpression, 2455 @NotNull final KtVisitor<StackValue, StackValue> visitor 2456 ) { 2457 final KtExpression expression = KtPsiUtil.deparenthesize(probablyParenthesizedExpression); 2458 final SamType samType = bindingContext.get(SAM_VALUE, probablyParenthesizedExpression); 2459 if (samType == null || expression == null) return null; 2460 2461 if (expression instanceof KtLambdaExpression) { 2462 return genClosure(((KtLambdaExpression) expression).getFunctionLiteral(), samType); 2463 } 2464 2465 if (expression instanceof KtNamedFunction) { 2466 return genClosure((KtNamedFunction) expression, samType); 2467 } 2468 2469 final Type asmType = 2470 state.getSamWrapperClasses().getSamWrapperClass(samType, expression.getContainingKtFile(), this); 2471 2472 return StackValue.operation(asmType, new Function1<InstructionAdapter, Unit>() { 2473 @Override 2474 public Unit invoke(InstructionAdapter v) { 2475 v.anew(asmType); 2476 v.dup(); 2477 2478 Type functionType = typeMapper.mapType(samType.getKotlinFunctionType()); 2479 expression.accept(visitor, StackValue.none()).put(functionType, v); 2480 2481 Label ifNonNull = new Label(); 2482 Label afterAll = new Label(); 2483 2484 v.dup(); 2485 v.ifnonnull(ifNonNull); 2486 2487 // if null: pop function value and wrapper objects, put null 2488 v.pop(); 2489 v.pop2(); 2490 v.aconst(null); 2491 v.goTo(afterAll); 2492 2493 v.mark(ifNonNull); 2494 v.invokespecial(asmType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType), false); 2495 2496 v.mark(afterAll); 2497 return null; 2498 } 2499 }); 2500 } 2501 2502 @NotNull 2503 protected FunctionDescriptor accessibleFunctionDescriptor(@NotNull ResolvedCall<?> resolvedCall) { 2504 FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2505 FunctionDescriptor originalIfSamAdapter = SamCodegenUtil.getOriginalIfSamAdapter(descriptor); 2506 if (originalIfSamAdapter != null) { 2507 descriptor = originalIfSamAdapter; 2508 } 2509 // $default method is not private, so you need no accessor to call it 2510 return CallUtilKt.usesDefaultArguments(resolvedCall) 2511 ? descriptor 2512 : context.accessibleDescriptor(descriptor, getSuperCallTarget(resolvedCall.getCall())); 2513 } 2514 2515 @NotNull 2516 public StackValue invokeFunction(@NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) { 2517 return invokeFunction(resolvedCall.getCall(), resolvedCall, receiver); 2518 } 2519 2520 @NotNull 2521 public StackValue invokeFunction(@NotNull Call call, @NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) { 2522 FunctionDescriptor fd = accessibleFunctionDescriptor(resolvedCall); 2523 ClassDescriptor superCallTarget = getSuperCallTarget(call); 2524 2525 fd = context.getAccessorForSuperCallIfNeeded(fd, superCallTarget); 2526 2527 Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject()); 2528 if (!codegenExtensions.isEmpty()) { 2529 ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v); 2530 for (ExpressionCodegenExtension extension : codegenExtensions) { 2531 StackValue stackValue = extension.applyFunction(receiver, resolvedCall, context); 2532 if (stackValue != null) return stackValue; 2533 } 2534 } 2535 2536 Callable callable = resolveToCallable(fd, superCallTarget != null, resolvedCall); 2537 2538 return callable.invokeMethodWithArguments(resolvedCall, receiver, this); 2539 } 2540 2541 @Nullable 2542 // Find the first parent of the current context which corresponds to a subclass of a given class 2543 public static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) { 2544 CodegenContext c = context; 2545 while (c != null) { 2546 if (c instanceof ClassContext && DescriptorUtils.isSubclass(c.getThisDescriptor(), descriptor)) { 2547 return c; 2548 } 2549 c = c.getParentContext(); 2550 } 2551 return null; 2552 } 2553 2554 @NotNull 2555 Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull ResolvedCall resolvedCall) { 2556 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(fd); 2557 if (intrinsic != null) { 2558 return intrinsic.toCallable(fd, superCall, resolvedCall, this); 2559 } 2560 2561 return resolveToCallableMethod(fd, superCall); 2562 } 2563 2564 @NotNull 2565 private CallableMethod resolveToCallableMethod(@NotNull FunctionDescriptor fd, boolean superCall) { 2566 return typeMapper.mapToCallableMethod(SamCodegenUtil.resolveSamAdapter(fd), superCall); 2567 } 2568 2569 public void invokeMethodWithArguments( 2570 @NotNull Callable callableMethod, 2571 @NotNull ResolvedCall<?> resolvedCall, 2572 @NotNull StackValue receiver 2573 ) { 2574 CallGenerator callGenerator = getOrCreateCallGenerator(resolvedCall); 2575 CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); 2576 2577 assert callGenerator == defaultCallGenerator || !tailRecursionCodegen.isTailRecursion(resolvedCall) : 2578 "Tail recursive method can't be inlined: " + descriptor; 2579 2580 ArgumentGenerator argumentGenerator = new CallBasedArgumentGenerator(this, callGenerator, descriptor.getValueParameters(), 2581 callableMethod.getValueParameterTypes()); 2582 2583 invokeMethodWithArguments(callableMethod, resolvedCall, receiver, callGenerator, argumentGenerator); 2584 } 2585 2586 public void invokeMethodWithArguments( 2587 @NotNull Callable callableMethod, 2588 @NotNull ResolvedCall<?> resolvedCall, 2589 @NotNull StackValue receiver, 2590 @NotNull CallGenerator callGenerator, 2591 @NotNull ArgumentGenerator argumentGenerator 2592 ) { 2593 boolean isConstructor = resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor; 2594 if (!isConstructor) { // otherwise already 2595 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); 2596 receiver.put(receiver.type, v); 2597 callableMethod.afterReceiverGeneration(v); 2598 } 2599 2600 callGenerator.putHiddenParams(); 2601 2602 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); 2603 assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor(); 2604 2605 DefaultCallArgs defaultArgs = 2606 argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values())); 2607 2608 if (tailRecursionCodegen.isTailRecursion(resolvedCall)) { 2609 tailRecursionCodegen.generateTailRecursion(resolvedCall); 2610 return; 2611 } 2612 2613 boolean defaultMaskWasGenerated = defaultArgs.generateOnStackIfNeeded(callGenerator, isConstructor); 2614 2615 // Extra constructor marker argument 2616 if (callableMethod instanceof CallableMethod) { 2617 List<JvmMethodParameterSignature> callableParameters = ((CallableMethod) callableMethod).getValueParameters(); 2618 for (JvmMethodParameterSignature parameter: callableParameters) { 2619 if (parameter.getKind() == JvmMethodParameterKind.CONSTRUCTOR_MARKER) { 2620 callGenerator.putValueIfNeeded(parameter.getAsmType(), StackValue.constant(null, parameter.getAsmType())); 2621 } 2622 } 2623 } 2624 2625 callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this); 2626 2627 KotlinType returnType = resolvedCall.getResultingDescriptor().getReturnType(); 2628 if (returnType != null && KotlinBuiltIns.isNothing(returnType)) { 2629 v.aconst(null); 2630 v.athrow(); 2631 } 2632 } 2633 2634 @NotNull 2635 private CallGenerator getOrCreateCallGenerator( 2636 @NotNull CallableDescriptor descriptor, 2637 @Nullable KtElement callElement, 2638 @Nullable TypeParameterMappings typeParameterMappings, 2639 boolean isDefaultCompilation 2640 ) { 2641 if (callElement == null) return defaultCallGenerator; 2642 2643 // We should inline callable containing reified type parameters even if inline is disabled 2644 // because they may contain something to reify and straight call will probably fail at runtime 2645 boolean isInline = (state.isInlineEnabled() || InlineUtil.containsReifiedTypeParameters(descriptor)) && 2646 (InlineUtil.isInline(descriptor) || InlineUtil.isArrayConstructorWithLambda(descriptor)); 2647 2648 if (!isInline) return defaultCallGenerator; 2649 2650 FunctionDescriptor original = DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal()); 2651 if (isDefaultCompilation) { 2652 return new InlineCodegenForDefaultBody(original, this, state); 2653 } 2654 else { 2655 return new InlineCodegen(this, state, original, callElement, typeParameterMappings); 2656 } 2657 } 2658 2659 @NotNull 2660 protected CallGenerator getOrCreateCallGeneratorForDefaultImplBody(@NotNull FunctionDescriptor descriptor, @Nullable KtNamedFunction function) { 2661 return getOrCreateCallGenerator(descriptor, function, null, true); 2662 } 2663 2664 @NotNull 2665 CallGenerator getOrCreateCallGenerator(@NotNull ResolvedCall<?> resolvedCall) { 2666 Map<TypeParameterDescriptor, KotlinType> typeArguments = resolvedCall.getTypeArguments(); 2667 TypeParameterMappings mappings = new TypeParameterMappings(); 2668 for (Map.Entry<TypeParameterDescriptor, KotlinType> entry : typeArguments.entrySet()) { 2669 TypeParameterDescriptor key = entry.getKey(); 2670 KotlinType type = entry.getValue(); 2671 2672 boolean isReified = key.isReified() || InlineUtil.isArrayConstructorWithLambda(resolvedCall.getResultingDescriptor()); 2673 2674 Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type); 2675 if (typeParameterAndReificationArgument == null) { 2676 KotlinType approximatedType = CapturedTypeApproximationKt.approximateCapturedTypes(entry.getValue()).getUpper(); 2677 // type is not generic 2678 JvmSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE); 2679 Type asmType = typeMapper.mapTypeParameter(approximatedType, signatureWriter); 2680 2681 mappings.addParameterMappingToType( 2682 key.getName().getIdentifier(), approximatedType, asmType, signatureWriter.toString(), isReified 2683 ); 2684 } 2685 else { 2686 mappings.addParameterMappingForFurtherReification( 2687 key.getName().getIdentifier(), type, typeParameterAndReificationArgument.getSecond(), isReified 2688 ); 2689 } 2690 } 2691 return getOrCreateCallGenerator( 2692 resolvedCall.getResultingDescriptor(), resolvedCall.getCall().getCallElement(), mappings, false); 2693 } 2694 2695 2696 @Nullable 2697 private static Pair<TypeParameterDescriptor, ReificationArgument> extractReificationArgument(@NotNull KotlinType type) { 2698 int arrayDepth = 0; 2699 boolean isNullable = type.isMarkedNullable(); 2700 while (KotlinBuiltIns.isArray(type)) { 2701 arrayDepth++; 2702 type = type.getArguments().get(0).getType(); 2703 } 2704 2705 TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type); 2706 if (parameterDescriptor == null) return null; 2707 2708 return new Pair<TypeParameterDescriptor, ReificationArgument>( 2709 parameterDescriptor, 2710 new ReificationArgument(parameterDescriptor.getName().asString(), isNullable, arrayDepth)); 2711 } 2712 2713 @NotNull 2714 public StackValue generateReceiverValue(@Nullable ReceiverValue receiverValue, boolean isSuper) { 2715 if (receiverValue instanceof ImplicitClassReceiver) { 2716 ClassDescriptor receiverDescriptor = ((ImplicitClassReceiver) receiverValue).getDeclarationDescriptor(); 2717 if (DescriptorUtils.isCompanionObject(receiverDescriptor)) { 2718 CallableMemberDescriptor contextDescriptor = context.getContextDescriptor(); 2719 if (contextDescriptor instanceof FunctionDescriptor && receiverDescriptor == contextDescriptor.getContainingDeclaration()) { 2720 return StackValue.LOCAL_0; 2721 } 2722 else { 2723 return StackValue.singleton(receiverDescriptor, typeMapper); 2724 } 2725 } 2726 else if (receiverDescriptor instanceof ScriptDescriptor) { 2727 return generateScriptReceiver 2728 ((ScriptDescriptor) receiverDescriptor); 2729 } 2730 else { 2731 return StackValue.thisOrOuter(this, receiverDescriptor, isSuper, 2732 receiverValue instanceof CastImplicitClassReceiver || isEnumEntry(receiverDescriptor)); 2733 } 2734 } 2735 else if (receiverValue instanceof ExtensionReceiver) { 2736 return generateReceiver(((ExtensionReceiver) receiverValue).getDeclarationDescriptor()); 2737 } 2738 else if (receiverValue instanceof ExpressionReceiver) { 2739 return gen(((ExpressionReceiver) receiverValue).getExpression()); 2740 } 2741 else { 2742 throw new UnsupportedOperationException("Unsupported receiver value: " + receiverValue); 2743 } 2744 } 2745 2746 @NotNull 2747 private StackValue generateReceiver(@NotNull CallableDescriptor descriptor) { 2748 return context.generateReceiver(descriptor, state, false); 2749 } 2750 2751 @NotNull 2752 private StackValue generateScriptReceiver(@NotNull ScriptDescriptor receiver) { 2753 CodegenContext cur = context; 2754 StackValue result = StackValue.LOCAL_0; 2755 boolean inStartConstructorContext = cur instanceof ConstructorContext; 2756 while (cur != null) { 2757 if (!inStartConstructorContext) { 2758 cur = getNotNullParentContextForMethod(cur); 2759 } 2760 2761 if (cur instanceof ScriptContext) { 2762 ScriptContext scriptContext = (ScriptContext) cur; 2763 2764 if (scriptContext.getScriptDescriptor() == receiver) { 2765 //TODO lazy 2766 return result; 2767 } 2768 Type currentScriptType = typeMapper.mapType(scriptContext.getScriptDescriptor()); 2769 Type classType = typeMapper.mapType(receiver); 2770 String fieldName = scriptContext.getScriptFieldName(receiver); 2771 return StackValue.field(classType, currentScriptType, fieldName, false, result, receiver); 2772 } 2773 2774 result = cur.getOuterExpression(result, false); 2775 2776 if (inStartConstructorContext) { 2777 cur = getNotNullParentContextForMethod(cur); 2778 inStartConstructorContext = false; 2779 } 2780 2781 cur = cur.getParentContext(); 2782 } 2783 2784 throw new UnsupportedOperationException(); 2785 } 2786 2787 @NotNull 2788 public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) { 2789 return generateThisOrOuter(calleeContainingClass, isSuper, false); 2790 } 2791 2792 @NotNull 2793 public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper, boolean forceOuter) { 2794 boolean isSingleton = calleeContainingClass.getKind().isSingleton(); 2795 if (isSingleton) { 2796 if (calleeContainingClass.equals(context.getThisDescriptor()) && 2797 !AnnotationUtilKt.isPlatformStaticInObjectOrClass(context.getContextDescriptor())) { 2798 return StackValue.local(0, typeMapper.mapType(calleeContainingClass)); 2799 } 2800 else if (isEnumEntry(calleeContainingClass)) { 2801 return StackValue.enumEntry(calleeContainingClass, typeMapper); 2802 } 2803 else { 2804 return StackValue.singleton(calleeContainingClass, typeMapper); 2805 } 2806 } 2807 2808 CodegenContext cur = context; 2809 Type type = asmType(calleeContainingClass.getDefaultType()); 2810 StackValue result = StackValue.local(0, type); 2811 boolean inStartConstructorContext = cur instanceof ConstructorContext; 2812 while (cur != null) { 2813 ClassDescriptor thisDescriptor = cur.getThisDescriptor(); 2814 2815 if (!isSuper && thisDescriptor == calleeContainingClass) { 2816 return result; 2817 } 2818 2819 if (!forceOuter && isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) { 2820 return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass); 2821 } 2822 2823 forceOuter = false; 2824 2825 //for constructor super call we should access to outer instance through parameter in locals, in other cases through field for captured outer 2826 if (inStartConstructorContext) { 2827 result = cur.getOuterExpression(result, false); 2828 cur = getNotNullParentContextForMethod(cur); 2829 inStartConstructorContext = false; 2830 } 2831 else { 2832 cur = getNotNullParentContextForMethod(cur); 2833 result = cur.getOuterExpression(result, false); 2834 } 2835 2836 cur = cur.getParentContext(); 2837 } 2838 2839 throw new UnsupportedOperationException(); 2840 } 2841 2842 @NotNull 2843 private static CodegenContext getNotNullParentContextForMethod(CodegenContext cur) { 2844 if (cur instanceof MethodContext) { 2845 cur = cur.getParentContext(); 2846 } 2847 assert cur != null; 2848 return cur; 2849 } 2850 2851 2852 public void genVarargs(@NotNull VarargValueArgument valueArgument, @NotNull KotlinType outType) { 2853 Type type = asmType(outType); 2854 assert type.getSort() == Type.ARRAY; 2855 Type elementType = correctElementType(type); 2856 List<ValueArgument> arguments = valueArgument.getArguments(); 2857 int size = arguments.size(); 2858 2859 boolean hasSpread = false; 2860 for (int i = 0; i != size; ++i) { 2861 if (arguments.get(i).getSpreadElement() != null) { 2862 hasSpread = true; 2863 break; 2864 } 2865 } 2866 2867 if (hasSpread) { 2868 boolean arrayOfReferences = KotlinBuiltIns.isArray(outType); 2869 if (size == 1) { 2870 // Arrays.copyOf(receiverValue, newLength) 2871 ValueArgument argument = arguments.get(0); 2872 Type arrayType = arrayOfReferences ? Type.getType("[Ljava/lang/Object;") 2873 : Type.getType("[" + elementType.getDescriptor()); 2874 gen(argument.getArgumentExpression(), type); 2875 v.dup(); 2876 v.arraylength(); 2877 v.invokestatic("java/util/Arrays", "copyOf", Type.getMethodDescriptor(arrayType, arrayType, Type.INT_TYPE), false); 2878 if (arrayOfReferences) { 2879 v.checkcast(type); 2880 } 2881 } 2882 else { 2883 String owner; 2884 String addDescriptor; 2885 String toArrayDescriptor; 2886 if (arrayOfReferences) { 2887 owner = "kotlin/jvm/internal/SpreadBuilder"; 2888 addDescriptor = "(Ljava/lang/Object;)V"; 2889 toArrayDescriptor = "([Ljava/lang/Object;)[Ljava/lang/Object;"; 2890 } 2891 else { 2892 String spreadBuilderClassName = AsmUtil.asmPrimitiveTypeToLangPrimitiveType(elementType).getTypeName().getIdentifier() + "SpreadBuilder"; 2893 owner = "kotlin/jvm/internal/" + spreadBuilderClassName; 2894 addDescriptor = "(" + elementType.getDescriptor() + ")V"; 2895 toArrayDescriptor = "()" + type.getDescriptor(); 2896 } 2897 v.anew(Type.getObjectType(owner)); 2898 v.dup(); 2899 v.iconst(size); 2900 v.invokespecial(owner, "<init>", "(I)V", false); 2901 for (int i = 0; i != size; ++i) { 2902 v.dup(); 2903 ValueArgument argument = arguments.get(i); 2904 if (argument.getSpreadElement() != null) { 2905 gen(argument.getArgumentExpression(), OBJECT_TYPE); 2906 v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V", false); 2907 } 2908 else { 2909 gen(argument.getArgumentExpression(), elementType); 2910 v.invokevirtual(owner, "add", addDescriptor, false); 2911 } 2912 } 2913 if (arrayOfReferences) { 2914 v.dup(); 2915 v.invokevirtual(owner, "size", "()I", false); 2916 newArrayInstruction(outType); 2917 v.invokevirtual(owner, "toArray", toArrayDescriptor, false); 2918 v.checkcast(type); 2919 } 2920 else { 2921 v.invokevirtual(owner, "toArray", toArrayDescriptor, false); 2922 } 2923 } 2924 } 2925 else { 2926 v.iconst(arguments.size()); 2927 newArrayInstruction(outType); 2928 for (int i = 0; i != size; ++i) { 2929 v.dup(); 2930 StackValue rightSide = gen(arguments.get(i).getArgumentExpression()); 2931 StackValue.arrayElement(elementType, StackValue.onStack(type), StackValue.constant(i, Type.INT_TYPE)).store(rightSide, v); 2932 } 2933 } 2934 } 2935 2936 public int indexOfLocal(KtReferenceExpression lhs) { 2937 DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, lhs); 2938 if (isVarCapturedInClosure(bindingContext, declarationDescriptor)) { 2939 return -1; 2940 } 2941 return lookupLocalIndex(declarationDescriptor); 2942 } 2943 2944 @Override 2945 public StackValue visitClassLiteralExpression(@NotNull KtClassLiteralExpression expression, StackValue data) { 2946 KotlinType type = bindingContext.getType(expression); 2947 assert type != null; 2948 2949 assert state.getReflectionTypes().getKClass().getTypeConstructor().equals(type.getConstructor()) 2950 : "::class expression should be type checked to a KClass: " + type; 2951 2952 return generateClassLiteralReference(typeMapper, CollectionsKt.single(type.getArguments()).getType(), this); 2953 } 2954 2955 @Override 2956 public StackValue visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression, StackValue data) { 2957 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression.getCallableReference(), bindingContext); 2958 FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression); 2959 if (functionDescriptor != null) { 2960 FunctionReferenceGenerationStrategy strategy = new FunctionReferenceGenerationStrategy(state, functionDescriptor, resolvedCall); 2961 return genClosure(expression, functionDescriptor, strategy, null, (FunctionDescriptor) resolvedCall.getResultingDescriptor()); 2962 } 2963 2964 VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression); 2965 if (variableDescriptor != null) { 2966 return generatePropertyReference(expression, variableDescriptor, resolvedCall); 2967 } 2968 2969 throw new UnsupportedOperationException("Unsupported callable reference expression: " + expression.getText()); 2970 } 2971 2972 @NotNull 2973 private StackValue generatePropertyReference( 2974 @NotNull KtElement element, 2975 @NotNull VariableDescriptor variableDescriptor, 2976 @NotNull ResolvedCall<?> resolvedCall 2977 ) { 2978 ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor); 2979 2980 ClassBuilder classBuilder = state.getFactory().newVisitor( 2981 JvmDeclarationOriginKt.OtherOrigin(element), 2982 typeMapper.mapClass(classDescriptor), 2983 element.getContainingFile() 2984 ); 2985 2986 PropertyReferenceCodegen codegen = new PropertyReferenceCodegen( 2987 state, parentCodegen, context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION), 2988 element, classBuilder, variableDescriptor, resolvedCall 2989 ); 2990 codegen.generate(); 2991 2992 return codegen.putInstanceOnStack(); 2993 } 2994 2995 @NotNull 2996 public static StackValue generateClassLiteralReference(@NotNull KotlinTypeMapper typeMapper, @NotNull KotlinType type) { 2997 return generateClassLiteralReference(typeMapper, type, null); 2998 } 2999 3000 @NotNull 3001 private static StackValue generateClassLiteralReference(@NotNull final KotlinTypeMapper typeMapper, @NotNull final KotlinType type, @Nullable final ExpressionCodegen codegen) { 3002 return StackValue.operation(K_CLASS_TYPE, new Function1<InstructionAdapter, Unit>() { 3003 @Override 3004 public Unit invoke(InstructionAdapter v) { 3005 Type classAsmType = typeMapper.mapType(type); 3006 ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); 3007 if (descriptor instanceof TypeParameterDescriptor) { 3008 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor; 3009 assert typeParameterDescriptor.isReified() : 3010 "Non-reified type parameter under ::class should be rejected by type checker: " + typeParameterDescriptor; 3011 assert codegen != null : 3012 "Reference to member of reified type should be rejected by type checker " + typeParameterDescriptor; 3013 codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS); 3014 } 3015 3016 putJavaLangClassInstance(v, classAsmType); 3017 wrapJavaClassIntoKClass(v); 3018 3019 return Unit.INSTANCE; 3020 } 3021 }); 3022 } 3023 3024 @Override 3025 public StackValue visitDotQualifiedExpression(@NotNull KtDotQualifiedExpression expression, StackValue receiver) { 3026 StackValue receiverValue = StackValue.none(); //gen(expression.getReceiverExpression()) 3027 return genQualified(receiverValue, expression.getSelectorExpression()); 3028 } 3029 3030 private StackValue generateExpressionWithNullFallback(@NotNull KtExpression expression, @NotNull Label ifnull) { 3031 KtExpression deparenthesized = KtPsiUtil.deparenthesize(expression); 3032 assert deparenthesized != null : "Unexpected empty expression"; 3033 3034 expression = deparenthesized; 3035 Type type = expressionType(expression); 3036 3037 if (expression instanceof KtSafeQualifiedExpression && !isPrimitive(type)) { 3038 return StackValue.coercion(generateSafeQualifiedExpression((KtSafeQualifiedExpression) expression, ifnull), type); 3039 } 3040 else { 3041 return genLazy(expression, type); 3042 } 3043 } 3044 3045 private StackValue generateSafeQualifiedExpression(@NotNull KtSafeQualifiedExpression expression, @NotNull Label ifNull) { 3046 KtExpression receiver = expression.getReceiverExpression(); 3047 KtExpression selector = expression.getSelectorExpression(); 3048 3049 Type receiverType = expressionType(receiver); 3050 StackValue receiverValue = generateExpressionWithNullFallback(receiver, ifNull); 3051 3052 //Do not optimize for primitives cause in case of safe call extension receiver should be generated before dispatch one 3053 StackValue newReceiver = new StackValue.SafeCall(receiverType, receiverValue, isPrimitive(receiverType) ? null : ifNull); 3054 return genQualified(newReceiver, selector); 3055 } 3056 3057 @Override 3058 public StackValue visitSafeQualifiedExpression(@NotNull KtSafeQualifiedExpression expression, StackValue unused) { 3059 Label ifnull = new Label(); 3060 Type type = boxType(expressionType(expression)); 3061 3062 StackValue value = generateSafeQualifiedExpression(expression, ifnull); 3063 StackValue newReceiver = StackValue.coercion(value, type); 3064 StackValue result; 3065 3066 if (!isPrimitive(expressionType(expression.getReceiverExpression()))) { 3067 result = new StackValue.SafeFallback(type, ifnull, newReceiver); 3068 } else { 3069 result = newReceiver; 3070 } 3071 3072 return result; 3073 } 3074 3075 @Override 3076 public StackValue visitBinaryExpression(@NotNull KtBinaryExpression expression, @NotNull StackValue receiver) { 3077 KtSimpleNameExpression reference = expression.getOperationReference(); 3078 IElementType opToken = reference.getReferencedNameElementType(); 3079 if (opToken == KtTokens.EQ) { 3080 return generateAssignmentExpression(expression); 3081 } 3082 else if (KtTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) { 3083 return generateAugmentedAssignment(expression); 3084 } 3085 else if (opToken == KtTokens.ANDAND) { 3086 return generateBooleanAnd(expression); 3087 } 3088 else if (opToken == KtTokens.OROR) { 3089 return generateBooleanOr(expression); 3090 } 3091 else if (opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ || 3092 opToken == KtTokens.EQEQEQ || opToken == KtTokens.EXCLEQEQEQ) { 3093 return generateEquals(expression.getLeft(), expression.getRight(), opToken); 3094 } 3095 else if (opToken == KtTokens.LT || opToken == KtTokens.LTEQ || 3096 opToken == KtTokens.GT || opToken == KtTokens.GTEQ) { 3097 return generateComparison(expression, receiver); 3098 } 3099 else if (opToken == KtTokens.ELVIS) { 3100 return generateElvis(expression); 3101 } 3102 else if (opToken == KtTokens.IN_KEYWORD || opToken == KtTokens.NOT_IN) { 3103 return generateIn(StackValue.expression(expressionType(expression.getLeft()), expression.getLeft(), this), 3104 expression.getRight(), reference); 3105 } 3106 else { 3107 ConstantValue<?> compileTimeConstant = getPrimitiveOrStringCompileTimeConstant(expression, bindingContext); 3108 if (compileTimeConstant != null) { 3109 return StackValue.constant(compileTimeConstant.getValue(), expressionType(expression)); 3110 } 3111 3112 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); 3113 FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 3114 3115 if (descriptor instanceof ConstructorDescriptor) { 3116 return generateConstructorCall(resolvedCall, expressionType(expression)); 3117 } 3118 3119 return invokeFunction(resolvedCall, receiver); 3120 } 3121 } 3122 3123 private StackValue generateIn(final StackValue leftValue, KtExpression rangeExpression, final KtSimpleNameExpression operationReference) { 3124 final KtExpression deparenthesized = KtPsiUtil.deparenthesize(rangeExpression); 3125 3126 assert deparenthesized != null : "For with empty range expression"; 3127 3128 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 3129 @Override 3130 public Unit invoke(InstructionAdapter v) { 3131 if (isIntRangeExpr(deparenthesized) && AsmUtil.isIntPrimitive(leftValue.type)) { 3132 genInIntRange(leftValue, (KtBinaryExpression) deparenthesized); 3133 } 3134 else { 3135 ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt 3136 .getResolvedCallWithAssert(operationReference, bindingContext); 3137 StackValue result = invokeFunction(resolvedCall.getCall(), resolvedCall, StackValue.none()); 3138 result.put(result.type, v); 3139 } 3140 if (operationReference.getReferencedNameElementType() == KtTokens.NOT_IN) { 3141 genInvertBoolean(v); 3142 } 3143 return null; 3144 } 3145 }); 3146 } 3147 3148 private void genInIntRange(StackValue leftValue, KtBinaryExpression rangeExpression) { 3149 v.iconst(1); 3150 // 1 3151 leftValue.put(Type.INT_TYPE, v); 3152 // 1 l 3153 v.dup2(); 3154 // 1 l 1 l 3155 3156 //noinspection ConstantConditions 3157 gen(rangeExpression.getLeft(), Type.INT_TYPE); 3158 // 1 l 1 l r 3159 Label lok = new Label(); 3160 v.ificmpge(lok); 3161 // 1 l 1 3162 v.pop(); 3163 v.iconst(0); 3164 v.mark(lok); 3165 // 1 l c 3166 v.dupX2(); 3167 // c 1 l c 3168 v.pop(); 3169 // c 1 l 3170 3171 gen(rangeExpression.getRight(), Type.INT_TYPE); 3172 // c 1 l r 3173 Label rok = new Label(); 3174 v.ificmple(rok); 3175 // c 1 3176 v.pop(); 3177 v.iconst(0); 3178 v.mark(rok); 3179 // c c 3180 3181 v.and(Type.INT_TYPE); 3182 } 3183 3184 private StackValue generateBooleanAnd(KtBinaryExpression expression) { 3185 return StackValue.and(gen(expression.getLeft()), gen(expression.getRight())); 3186 } 3187 3188 private StackValue generateBooleanOr(KtBinaryExpression expression) { 3189 return StackValue.or(gen(expression.getLeft()), gen(expression.getRight())); 3190 } 3191 3192 private StackValue generateEquals(KtExpression left, KtExpression right, IElementType opToken) { 3193 Type leftType = expressionType(left); 3194 Type rightType = expressionType(right); 3195 3196 if (KtPsiUtil.isNullConstant(left)) { 3197 return genCmpWithNull(right, opToken); 3198 } 3199 3200 if (KtPsiUtil.isNullConstant(right)) { 3201 return genCmpWithNull(left, opToken); 3202 } 3203 3204 if (isIntZero(left, leftType) && isIntPrimitive(rightType)) { 3205 return genCmpWithZero(right, opToken); 3206 } 3207 3208 if (isIntZero(right, rightType) && isIntPrimitive(leftType)) { 3209 return genCmpWithZero(left, opToken); 3210 } 3211 3212 if (isPrimitive(leftType) != isPrimitive(rightType)) { 3213 leftType = boxType(leftType); 3214 rightType = boxType(rightType); 3215 } 3216 3217 StackValue leftValue = genLazy(left, leftType); 3218 StackValue rightValue = genLazy(right, rightType); 3219 3220 if (opToken == KtTokens.EQEQEQ || opToken == KtTokens.EXCLEQEQEQ) { 3221 // TODO: always casting to the type of the left operand in case of primitives looks wrong 3222 Type operandType = isPrimitive(leftType) ? leftType : OBJECT_TYPE; 3223 return StackValue.cmp(opToken, operandType, leftValue, rightValue); 3224 } 3225 3226 return genEqualsForExpressionsOnStack(opToken, leftValue, rightValue); 3227 } 3228 3229 private boolean isIntZero(KtExpression expr, Type exprType) { 3230 ConstantValue<?> exprValue = getPrimitiveOrStringCompileTimeConstant(expr, bindingContext); 3231 return isIntPrimitive(exprType) && exprValue != null && Integer.valueOf(0).equals(exprValue.getValue()); 3232 } 3233 3234 private StackValue genCmpWithZero(KtExpression exp, IElementType opToken) { 3235 return StackValue.compareIntWithZero(gen(exp), (KtTokens.EQEQ == opToken || KtTokens.EQEQEQ == opToken) ? IFNE : IFEQ); 3236 } 3237 3238 private StackValue genCmpWithNull(KtExpression exp, IElementType opToken) { 3239 return StackValue.compareWithNull(gen(exp), (KtTokens.EQEQ == opToken || KtTokens.EQEQEQ == opToken) ? IFNONNULL : IFNULL); 3240 } 3241 3242 private StackValue generateElvis(@NotNull final KtBinaryExpression expression) { 3243 KtExpression left = expression.getLeft(); 3244 3245 final Type exprType = expressionType(expression); 3246 final Type leftType = expressionType(left); 3247 3248 final Label ifNull = new Label(); 3249 3250 3251 assert left != null : "left expression in elvis should be not null: " + expression.getText(); 3252 final StackValue value = generateExpressionWithNullFallback(left, ifNull); 3253 3254 if (isPrimitive(leftType)) { 3255 return value; 3256 } 3257 3258 return StackValue.operation(exprType, new Function1<InstructionAdapter, Unit>() { 3259 @Override 3260 public Unit invoke(InstructionAdapter v) { 3261 value.put(value.type, v); 3262 v.dup(); 3263 3264 v.ifnull(ifNull); 3265 StackValue.onStack(leftType).put(exprType, v); 3266 3267 Label end = new Label(); 3268 v.goTo(end); 3269 3270 v.mark(ifNull); 3271 v.pop(); 3272 gen(expression.getRight(), exprType); 3273 v.mark(end); 3274 return null; 3275 } 3276 }); 3277 } 3278 3279 private StackValue generateComparison(KtBinaryExpression expression, StackValue receiver) { 3280 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); 3281 3282 KtExpression left = expression.getLeft(); 3283 KtExpression right = expression.getRight(); 3284 3285 Type type; 3286 StackValue leftValue; 3287 StackValue rightValue; 3288 Type leftType = expressionType(left); 3289 Type rightType = expressionType(right); 3290 Callable callable = resolveToCallable((FunctionDescriptor) resolvedCall.getResultingDescriptor(), false, resolvedCall); 3291 if (isPrimitive(leftType) && isPrimitive(rightType) && callable instanceof IntrinsicCallable) { 3292 type = comparisonOperandType(leftType, rightType); 3293 leftValue = gen(left); 3294 rightValue = gen(right); 3295 } 3296 else { 3297 type = Type.INT_TYPE; 3298 leftValue = invokeFunction(resolvedCall, receiver); 3299 rightValue = StackValue.constant(0, type); 3300 } 3301 return StackValue.cmp(expression.getOperationToken(), type, leftValue, rightValue); 3302 } 3303 3304 private StackValue generateAssignmentExpression(KtBinaryExpression expression) { 3305 StackValue stackValue = gen(expression.getLeft()); 3306 KtExpression right = expression.getRight(); 3307 assert right != null : expression.getText(); 3308 stackValue.store(gen(right), v); 3309 return StackValue.none(); 3310 } 3311 3312 private StackValue generateAugmentedAssignment(KtBinaryExpression expression) { 3313 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); 3314 FunctionDescriptor descriptor = accessibleFunctionDescriptor(resolvedCall); 3315 Callable callable = resolveToCallable(descriptor, false, resolvedCall); 3316 KtExpression lhs = expression.getLeft(); 3317 Type lhsType = expressionType(lhs); 3318 3319 boolean keepReturnValue = Boolean.TRUE.equals(bindingContext.get(VARIABLE_REASSIGNMENT, expression)) 3320 || !KotlinBuiltIns.isUnit(descriptor.getReturnType()); 3321 3322 callAugAssignMethod(expression, resolvedCall, callable, lhsType, keepReturnValue); 3323 3324 return StackValue.none(); 3325 } 3326 3327 private void callAugAssignMethod( 3328 @NotNull KtBinaryExpression expression, 3329 @NotNull ResolvedCall<?> resolvedCall, 3330 @NotNull Callable callable, 3331 @NotNull Type lhsType, 3332 boolean keepReturnValue 3333 ) { 3334 StackValue value = gen(expression.getLeft()); 3335 if (keepReturnValue) { 3336 value = StackValue.complexWriteReadReceiver(value); 3337 } 3338 value.put(lhsType, v); 3339 StackValue receiver = StackValue.onStack(lhsType); 3340 3341 callable.invokeMethodWithArguments(resolvedCall, receiver, this).put(callable.getReturnType(), v); 3342 3343 if (keepReturnValue) { 3344 value.store(StackValue.onStack(callable.getReturnType()), v, true); 3345 } 3346 } 3347 3348 public void invokeAppend(KtExpression expr) { 3349 ConstantValue<?> compileTimeConstant = getPrimitiveOrStringCompileTimeConstant(expr, bindingContext); 3350 3351 if (compileTimeConstant == null && expr instanceof KtBinaryExpression) { 3352 KtBinaryExpression binaryExpression = (KtBinaryExpression) expr; 3353 if (binaryExpression.getOperationToken() == KtTokens.PLUS) { 3354 KtExpression left = binaryExpression.getLeft(); 3355 KtExpression right = binaryExpression.getRight(); 3356 Type leftType = expressionType(left); 3357 3358 if (leftType.equals(JAVA_STRING_TYPE)) { 3359 invokeAppend(left); 3360 invokeAppend(right); 3361 return; 3362 } 3363 } 3364 } 3365 3366 Type exprType = expressionType(expr); 3367 if (compileTimeConstant != null) { 3368 StackValue.constant(compileTimeConstant.getValue(), exprType).put(exprType, v); 3369 } else { 3370 gen(expr, exprType); 3371 } 3372 genInvokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType); 3373 } 3374 3375 @Nullable 3376 private static KtSimpleNameExpression targetLabel(KtExpression expression) { 3377 if (expression.getParent() instanceof KtLabeledExpression) { 3378 return ((KtLabeledExpression) expression.getParent()).getTargetLabel(); 3379 } 3380 return null; 3381 } 3382 3383 @Override 3384 public StackValue visitLabeledExpression( 3385 @NotNull KtLabeledExpression expression, StackValue receiver 3386 ) { 3387 return genQualified(receiver, expression.getBaseExpression()); 3388 } 3389 3390 @Override 3391 public StackValue visitPrefixExpression(@NotNull KtPrefixExpression expression, @NotNull StackValue receiver) { 3392 ConstantValue<?> compileTimeConstant = getPrimitiveOrStringCompileTimeConstant(expression, bindingContext); 3393 if (compileTimeConstant != null) { 3394 return StackValue.constant(compileTimeConstant.getValue(), expressionType(expression)); 3395 } 3396 3397 DeclarationDescriptor originalOperation = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference()); 3398 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); 3399 CallableDescriptor op = resolvedCall.getResultingDescriptor(); 3400 3401 assert op instanceof FunctionDescriptor || originalOperation == null : String.valueOf(op); 3402 String operationName = originalOperation == null ? "" : originalOperation.getName().asString(); 3403 if (!(operationName.equals("inc") || operationName.equals("dec"))) { 3404 return invokeFunction(resolvedCall, receiver); 3405 } 3406 3407 int increment = operationName.equals("inc") ? 1 : -1; 3408 Type type = expressionType(expression.getBaseExpression()); 3409 StackValue value = gen(expression.getBaseExpression()); 3410 return StackValue.preIncrement(type, value, increment, resolvedCall, this); 3411 } 3412 3413 @Override 3414 public StackValue visitPostfixExpression(@NotNull final KtPostfixExpression expression, StackValue receiver) { 3415 if (expression.getOperationReference().getReferencedNameElementType() == KtTokens.EXCLEXCL) { 3416 final StackValue base = genQualified(receiver, expression.getBaseExpression()); 3417 if (isPrimitive(base.type)) { 3418 return base; 3419 } else { 3420 return StackValue.operation(base.type, new Function1<InstructionAdapter, Unit>() { 3421 @Override 3422 public Unit invoke(InstructionAdapter v) { 3423 base.put(base.type, v); 3424 v.dup(); 3425 Label ok = new Label(); 3426 v.ifnonnull(ok); 3427 v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "throwNpe", "()V", false); 3428 v.mark(ok); 3429 return null; 3430 } 3431 }); 3432 } 3433 } 3434 3435 DeclarationDescriptor originalOperation = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference()); 3436 String originalOperationName = originalOperation != null ? originalOperation.getName().asString() : null; 3437 final ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); 3438 DeclarationDescriptor op = resolvedCall.getResultingDescriptor(); 3439 if (!(op instanceof FunctionDescriptor) || originalOperation == null) { 3440 throw new UnsupportedOperationException("Don't know how to generate this postfix expression: " + originalOperationName + " " + op); 3441 } 3442 3443 3444 final Type asmResultType = expressionType(expression); 3445 final Type asmBaseType = expressionType(expression.getBaseExpression()); 3446 3447 DeclarationDescriptor cls = op.getContainingDeclaration(); 3448 3449 final int increment; 3450 if (originalOperationName.equals("inc")) { 3451 increment = 1; 3452 } 3453 else if (originalOperationName.equals("dec")) { 3454 increment = -1; 3455 } 3456 else { 3457 throw new UnsupportedOperationException("Unsupported postfix operation: " + originalOperationName + " " + op); 3458 } 3459 3460 final boolean isPrimitiveNumberClassDescriptor = isPrimitiveNumberClassDescriptor(cls); 3461 if (isPrimitiveNumberClassDescriptor && AsmUtil.isPrimitive(asmBaseType)) { 3462 KtExpression operand = expression.getBaseExpression(); 3463 // Optimization for j = i++, when j and i are Int without any smart cast: we just work with primitive int 3464 if (operand instanceof KtReferenceExpression && asmResultType == Type.INT_TYPE && 3465 bindingContext.get(BindingContext.SMARTCAST, operand) == null) { 3466 int index = indexOfLocal((KtReferenceExpression) operand); 3467 if (index >= 0) { 3468 return StackValue.postIncrement(index, increment); 3469 } 3470 } 3471 } 3472 3473 return StackValue.operation(asmBaseType, new Function1<InstructionAdapter, Unit>() { 3474 @Override 3475 public Unit invoke(InstructionAdapter v) { 3476 StackValue value = StackValue.complexWriteReadReceiver(gen(expression.getBaseExpression())); 3477 3478 value.put(asmBaseType, v); 3479 AsmUtil.dup(v, asmBaseType); 3480 3481 StackValue previousValue = StackValue.local(myFrameMap.enterTemp(asmBaseType), asmBaseType); 3482 previousValue.store(StackValue.onStack(asmBaseType), v); 3483 3484 Type storeType; 3485 if (isPrimitiveNumberClassDescriptor && AsmUtil.isPrimitive(asmBaseType)) { 3486 genIncrement(asmBaseType, increment, v); 3487 storeType = asmBaseType; 3488 } 3489 else { 3490 StackValue result = invokeFunction(resolvedCall, StackValue.onStack(asmBaseType)); 3491 result.put(result.type, v); 3492 storeType = result.type; 3493 } 3494 3495 value.store(StackValue.onStack(storeType), v, true); 3496 3497 previousValue.put(asmBaseType, v); 3498 3499 myFrameMap.leaveTemp(asmBaseType); 3500 3501 return Unit.INSTANCE; 3502 } 3503 }); 3504 } 3505 3506 @Override 3507 public StackValue visitProperty(@NotNull KtProperty property, StackValue receiver) { 3508 KtExpression initializer = property.getInitializer(); 3509 if (initializer == null) { 3510 return StackValue.none(); 3511 } 3512 initializeLocalVariable(property, gen(initializer)); 3513 return StackValue.none(); 3514 } 3515 3516 @Override 3517 public StackValue visitDestructuringDeclaration(@NotNull KtDestructuringDeclaration multiDeclaration, StackValue receiver) { 3518 KtExpression initializer = multiDeclaration.getInitializer(); 3519 if (initializer == null) return StackValue.none(); 3520 3521 KotlinType initializerType = bindingContext.getType(initializer); 3522 assert initializerType != null; 3523 3524 Type initializerAsmType = asmType(initializerType); 3525 3526 TransientReceiver initializerAsReceiver = new TransientReceiver(initializerType); 3527 3528 int tempVarIndex = myFrameMap.enterTemp(initializerAsmType); 3529 3530 gen(initializer, initializerAsmType); 3531 v.store(tempVarIndex, initializerAsmType); 3532 StackValue.Local local = StackValue.local(tempVarIndex, initializerAsmType); 3533 3534 for (KtDestructuringDeclarationEntry variableDeclaration : multiDeclaration.getEntries()) { 3535 ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(COMPONENT_RESOLVED_CALL, variableDeclaration); 3536 assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText(); 3537 Call call = makeFakeCall(initializerAsReceiver); 3538 initializeLocalVariable(variableDeclaration, invokeFunction(call, resolvedCall, local)); 3539 } 3540 3541 if (initializerAsmType.getSort() == Type.OBJECT || initializerAsmType.getSort() == Type.ARRAY) { 3542 v.aconst(null); 3543 v.store(tempVarIndex, initializerAsmType); 3544 } 3545 myFrameMap.leaveTemp(initializerAsmType); 3546 3547 return StackValue.none(); 3548 } 3549 3550 private void initializeLocalVariable( 3551 @NotNull KtVariableDeclaration variableDeclaration, 3552 @NotNull StackValue initializer 3553 ) { 3554 VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, variableDeclaration); 3555 3556 if (KtPsiUtil.isScriptDeclaration(variableDeclaration)) { 3557 return; 3558 } 3559 int index = lookupLocalIndex(variableDescriptor); 3560 3561 if (index < 0) { 3562 throw new IllegalStateException("Local variable not found for " + variableDescriptor); 3563 } 3564 3565 Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 3566 assert variableDescriptor != null; 3567 3568 Type varType = asmType(variableDescriptor.getType()); 3569 3570 StackValue storeTo = sharedVarType == null ? StackValue.local(index, varType) : StackValue.shared(index, varType); 3571 3572 storeTo.putReceiver(v, false); 3573 initializer.put(initializer.type, v); 3574 3575 markLineNumber(variableDeclaration, false); 3576 3577 storeTo.storeSelector(initializer.type, v); 3578 } 3579 3580 @NotNull 3581 private StackValue generateNewCall(@NotNull KtCallExpression expression, @NotNull ResolvedCall<?> resolvedCall) { 3582 Type type = expressionType(expression); 3583 if (type.getSort() == Type.ARRAY) { 3584 //noinspection ConstantConditions 3585 return generateNewArray(expression, bindingContext.getType(expression), resolvedCall); 3586 } 3587 3588 return generateConstructorCall(resolvedCall, type); 3589 } 3590 3591 @NotNull 3592 public ConstructorDescriptor getConstructorDescriptor(@NotNull ResolvedCall<?> resolvedCall) { 3593 FunctionDescriptor accessibleDescriptor = accessibleFunctionDescriptor(resolvedCall); 3594 assert accessibleDescriptor instanceof ConstructorDescriptor : 3595 "getConstructorDescriptor must be called only for constructors: " + accessibleDescriptor; 3596 return (ConstructorDescriptor) accessibleDescriptor; 3597 } 3598 3599 @NotNull 3600 public StackValue generateConstructorCall(@NotNull final ResolvedCall<?> resolvedCall, @NotNull final Type objectType) { 3601 return StackValue.functionCall(objectType, new Function1<InstructionAdapter, Unit>() { 3602 @Override 3603 public Unit invoke(InstructionAdapter v) { 3604 v.anew(objectType); 3605 v.dup(); 3606 3607 ConstructorDescriptor constructor = getConstructorDescriptor(resolvedCall); 3608 3609 ReceiverParameterDescriptor dispatchReceiver = constructor.getDispatchReceiverParameter(); 3610 ClassDescriptor containingDeclaration = constructor.getContainingDeclaration(); 3611 if (dispatchReceiver != null) { 3612 Type receiverType = typeMapper.mapType(dispatchReceiver.getType()); 3613 ReceiverValue receiver = resolvedCall.getDispatchReceiver(); 3614 boolean callSuper = containingDeclaration.isInner() && receiver instanceof ImplicitClassReceiver; 3615 generateReceiverValue(receiver, callSuper).put(receiverType, v); 3616 } 3617 3618 // Resolved call to local class constructor doesn't have dispatchReceiver, so we need to generate closure on stack 3619 // See StackValue.receiver for more info 3620 pushClosureOnStack(containingDeclaration, dispatchReceiver == null, defaultCallGenerator); 3621 3622 constructor = SamCodegenUtil.resolveSamAdapter(constructor); 3623 CallableMethod method = typeMapper.mapToCallableMethod(constructor, false); 3624 invokeMethodWithArguments(method, resolvedCall, StackValue.none()); 3625 3626 return Unit.INSTANCE; 3627 } 3628 }); 3629 } 3630 3631 public StackValue generateNewArray( 3632 @NotNull KtCallExpression expression, @NotNull final KotlinType arrayType, @NotNull ResolvedCall<?> resolvedCall 3633 ) { 3634 List<KtValueArgument> args = expression.getValueArguments(); 3635 assert args.size() == 1 || args.size() == 2 : "Unknown constructor called: " + args.size() + " arguments"; 3636 3637 if (args.size() == 1) { 3638 final KtExpression sizeExpression = args.get(0).getArgumentExpression(); 3639 return StackValue.operation(typeMapper.mapType(arrayType), new Function1<InstructionAdapter, Unit>() { 3640 @Override 3641 public Unit invoke(InstructionAdapter v) { 3642 gen(sizeExpression, Type.INT_TYPE); 3643 newArrayInstruction(arrayType); 3644 return Unit.INSTANCE; 3645 } 3646 }); 3647 } 3648 3649 return invokeFunction(resolvedCall, StackValue.none()); 3650 } 3651 3652 public void newArrayInstruction(@NotNull KotlinType arrayType) { 3653 if (KotlinBuiltIns.isArray(arrayType)) { 3654 KotlinType elementJetType = arrayType.getArguments().get(0).getType(); 3655 putReifiedOperationMarkerIfTypeIsReifiedParameter( 3656 elementJetType, 3657 ReifiedTypeInliner.OperationKind.NEW_ARRAY 3658 ); 3659 v.newarray(boxType(asmType(elementJetType))); 3660 } 3661 else { 3662 Type type = typeMapper.mapType(arrayType); 3663 v.newarray(correctElementType(type)); 3664 } 3665 } 3666 3667 @Override 3668 public StackValue visitArrayAccessExpression(@NotNull KtArrayAccessExpression expression, StackValue receiver) { 3669 KtExpression array = expression.getArrayExpression(); 3670 KotlinType type = array != null ? bindingContext.getType(array) : null; 3671 Type arrayType = expressionType(array); 3672 List<KtExpression> indices = expression.getIndexExpressions(); 3673 FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(REFERENCE_TARGET, expression); 3674 assert operationDescriptor != null; 3675 if (arrayType.getSort() == Type.ARRAY && 3676 indices.size() == 1 && 3677 isInt(operationDescriptor.getValueParameters().get(0).getType())) { 3678 assert type != null; 3679 Type elementType; 3680 if (KotlinBuiltIns.isArray(type)) { 3681 KotlinType jetElementType = type.getArguments().get(0).getType(); 3682 elementType = boxType(asmType(jetElementType)); 3683 } 3684 else { 3685 elementType = correctElementType(arrayType); 3686 } 3687 StackValue arrayValue = genLazy(array, arrayType); 3688 StackValue index = genLazy(indices.get(0), Type.INT_TYPE); 3689 3690 return StackValue.arrayElement(elementType, arrayValue, index); 3691 } 3692 else { 3693 ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(INDEXED_LVALUE_SET, expression); 3694 ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(INDEXED_LVALUE_GET, expression); 3695 3696 boolean isGetter = "get".equals(operationDescriptor.getName().asString()); 3697 3698 Callable callable = resolveToCallable(operationDescriptor, false, isGetter ? resolvedGetCall : resolvedSetCall); 3699 Callable callableMethod = resolveToCallableMethod(operationDescriptor, false); 3700 Type[] argumentTypes = callableMethod.getParameterTypes(); 3701 3702 StackValue.CollectionElementReceiver collectionElementReceiver = createCollectionElementReceiver( 3703 expression, receiver, operationDescriptor, isGetter, resolvedGetCall, resolvedSetCall, callable 3704 ); 3705 3706 Type elementType = isGetter ? callableMethod.getReturnType() : ArrayUtil.getLastElement(argumentTypes); 3707 return StackValue.collectionElement(collectionElementReceiver, elementType, resolvedGetCall, resolvedSetCall, this); 3708 } 3709 } 3710 3711 @NotNull 3712 private StackValue.CollectionElementReceiver createCollectionElementReceiver( 3713 @NotNull KtArrayAccessExpression expression, 3714 @NotNull StackValue receiver, 3715 @NotNull FunctionDescriptor operationDescriptor, 3716 boolean isGetter, 3717 ResolvedCall<FunctionDescriptor> resolvedGetCall, 3718 ResolvedCall<FunctionDescriptor> resolvedSetCall, 3719 @NotNull Callable callable 3720 ) { 3721 ResolvedCall<FunctionDescriptor> resolvedCall = isGetter ? resolvedGetCall : resolvedSetCall; 3722 assert resolvedCall != null : "couldn't find resolved call: " + expression.getText(); 3723 3724 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); 3725 assert valueArguments != null : "Failed to arrange value arguments by index: " + operationDescriptor; 3726 3727 if (!isGetter) { 3728 assert valueArguments.size() >= 2 : "Setter call should have at least 2 arguments: " + operationDescriptor; 3729 // Skip generation of the right hand side of an indexed assignment, which is the last value argument 3730 valueArguments.remove(valueArguments.size() - 1); 3731 } 3732 3733 return new StackValue.CollectionElementReceiver( 3734 callable, receiver, resolvedGetCall, resolvedSetCall, isGetter, this, valueArguments 3735 ); 3736 } 3737 3738 @Override 3739 public StackValue visitThrowExpression(@NotNull final KtThrowExpression expression, StackValue receiver) { 3740 return StackValue.operation(Type.VOID_TYPE, new Function1<InstructionAdapter, Unit>() { 3741 @Override 3742 public Unit invoke(InstructionAdapter adapter) { 3743 gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE); 3744 v.athrow(); 3745 return Unit.INSTANCE; 3746 } 3747 }); 3748 } 3749 3750 @Override 3751 public StackValue visitThisExpression(@NotNull KtThisExpression expression, StackValue receiver) { 3752 DeclarationDescriptor descriptor = bindingContext.get(REFERENCE_TARGET, expression.getInstanceReference()); 3753 if (descriptor instanceof ClassDescriptor) { 3754 //TODO rewrite with context.lookupInContext() 3755 return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false, true); 3756 } 3757 if (descriptor instanceof CallableDescriptor) { 3758 return generateReceiver((CallableDescriptor) descriptor); 3759 } 3760 throw new UnsupportedOperationException("Neither this nor receiver: " + descriptor); 3761 } 3762 3763 @Override 3764 public StackValue visitTryExpression(@NotNull KtTryExpression expression, StackValue receiver) { 3765 return generateTryExpression(expression, false); 3766 } 3767 3768 public StackValue generateTryExpression(final KtTryExpression expression, final boolean isStatement) { 3769 /* 3770 The "returned" value of try expression with no finally is either the last expression in the try block or the last expression in the catch block 3771 (or blocks). 3772 */ 3773 3774 KotlinType jetType = bindingContext.getType(expression); 3775 assert jetType != null; 3776 final Type expectedAsmType = isStatement ? Type.VOID_TYPE : asmType(jetType); 3777 3778 return StackValue.operation(expectedAsmType, new Function1<InstructionAdapter, Unit>() { 3779 @Override 3780 public Unit invoke(InstructionAdapter v) { 3781 KtFinallySection finallyBlock = expression.getFinallyBlock(); 3782 FinallyBlockStackElement finallyBlockStackElement = null; 3783 if (finallyBlock != null) { 3784 finallyBlockStackElement = new FinallyBlockStackElement(expression); 3785 blockStackElements.push(finallyBlockStackElement); 3786 } 3787 3788 //PseudoInsnsPackage.saveStackBeforeTryExpr(v); 3789 3790 Label tryStart = new Label(); 3791 v.mark(tryStart); 3792 v.nop(); // prevent verify error on empty try 3793 3794 gen(expression.getTryBlock(), expectedAsmType); 3795 3796 int savedValue = -1; 3797 if (!isStatement) { 3798 savedValue = myFrameMap.enterTemp(expectedAsmType); 3799 v.store(savedValue, expectedAsmType); 3800 } 3801 3802 Label tryEnd = new Label(); 3803 v.mark(tryEnd); 3804 3805 //do it before finally block generation 3806 List<Label> tryBlockRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, tryEnd); 3807 3808 Label end = new Label(); 3809 3810 genFinallyBlockOrGoto(finallyBlockStackElement, end, null); 3811 3812 List<KtCatchClause> clauses = expression.getCatchClauses(); 3813 for (int i = 0, size = clauses.size(); i < size; i++) { 3814 KtCatchClause clause = clauses.get(i); 3815 3816 Label clauseStart = new Label(); 3817 v.mark(clauseStart); 3818 3819 KtExpression catchBody = clause.getCatchBody(); 3820 if (catchBody != null) { 3821 markLineNumber(catchBody, false); 3822 } 3823 3824 VariableDescriptor descriptor = bindingContext.get(VALUE_PARAMETER, clause.getCatchParameter()); 3825 assert descriptor != null; 3826 Type descriptorType = asmType(descriptor.getType()); 3827 myFrameMap.enter(descriptor, descriptorType); 3828 int index = lookupLocalIndex(descriptor); 3829 v.store(index, descriptorType); 3830 3831 gen(catchBody, expectedAsmType); 3832 3833 if (!isStatement) { 3834 v.store(savedValue, expectedAsmType); 3835 } 3836 3837 myFrameMap.leave(descriptor); 3838 3839 Label clauseEnd = new Label(); 3840 v.mark(clauseEnd); 3841 3842 v.visitLocalVariable(descriptor.getName().asString(), descriptorType.getDescriptor(), null, clauseStart, clauseEnd, 3843 index); 3844 3845 genFinallyBlockOrGoto(finallyBlockStackElement, i != size - 1 || finallyBlock != null ? end : null, null); 3846 3847 generateExceptionTable(clauseStart, tryBlockRegions, descriptorType.getInternalName()); 3848 } 3849 3850 3851 //for default catch clause 3852 if (finallyBlock != null) { 3853 Label defaultCatchStart = new Label(); 3854 v.mark(defaultCatchStart); 3855 int savedException = myFrameMap.enterTemp(JAVA_THROWABLE_TYPE); 3856 v.store(savedException, JAVA_THROWABLE_TYPE); 3857 3858 Label defaultCatchEnd = new Label(); 3859 v.mark(defaultCatchEnd); 3860 3861 //do it before finally block generation 3862 //javac also generates entry in exception table for default catch clause too!!!! so defaultCatchEnd as end parameter 3863 List<Label> defaultCatchRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, defaultCatchEnd); 3864 3865 3866 genFinallyBlockOrGoto(finallyBlockStackElement, null, null); 3867 3868 v.load(savedException, JAVA_THROWABLE_TYPE); 3869 myFrameMap.leaveTemp(JAVA_THROWABLE_TYPE); 3870 3871 v.athrow(); 3872 3873 generateExceptionTable(defaultCatchStart, defaultCatchRegions, null); 3874 } 3875 3876 markLineNumber(expression, isStatement); 3877 v.mark(end); 3878 3879 if (!isStatement) { 3880 v.load(savedValue, expectedAsmType); 3881 myFrameMap.leaveTemp(expectedAsmType); 3882 } 3883 3884 if (finallyBlock != null) { 3885 blockStackElements.pop(); 3886 } 3887 return Unit.INSTANCE; 3888 } 3889 }); 3890 } 3891 3892 private void generateExceptionTable(@NotNull Label catchStart, @NotNull List<Label> catchedRegions, @Nullable String exception) { 3893 for (int i = 0; i < catchedRegions.size(); i += 2) { 3894 Label startRegion = catchedRegions.get(i); 3895 Label endRegion = catchedRegions.get(i+1); 3896 v.visitTryCatchBlock(startRegion, endRegion, catchStart, exception); 3897 } 3898 } 3899 3900 @NotNull 3901 private static List<Label> getCurrentCatchIntervals( 3902 @Nullable FinallyBlockStackElement finallyBlockStackElement, 3903 @NotNull Label blockStart, 3904 @NotNull Label blockEnd 3905 ) { 3906 List<Label> gapsInBlock = 3907 finallyBlockStackElement != null ? new ArrayList<Label>(finallyBlockStackElement.gaps) : Collections.<Label>emptyList(); 3908 assert gapsInBlock.size() % 2 == 0; 3909 List<Label> blockRegions = new ArrayList<Label>(gapsInBlock.size() + 2); 3910 blockRegions.add(blockStart); 3911 blockRegions.addAll(gapsInBlock); 3912 blockRegions.add(blockEnd); 3913 return blockRegions; 3914 } 3915 3916 @Override 3917 public StackValue visitBinaryWithTypeRHSExpression(@NotNull KtBinaryExpressionWithTypeRHS expression, StackValue receiver) { 3918 KtExpression left = expression.getLeft(); 3919 final IElementType opToken = expression.getOperationReference().getReferencedNameElementType(); 3920 3921 final KotlinType rightType = bindingContext.get(TYPE, expression.getRight()); 3922 assert rightType != null; 3923 3924 final StackValue value = genQualified(receiver, left); 3925 3926 return StackValue.operation(boxType(asmType(rightType)), new Function1<InstructionAdapter, Unit>() { 3927 @Override 3928 public Unit invoke(InstructionAdapter v) { 3929 value.put(boxType(value.type), v); 3930 3931 if (value.type == Type.VOID_TYPE) { 3932 StackValue.putUnitInstance(v); 3933 } 3934 3935 boolean safeAs = opToken == KtTokens.AS_SAFE; 3936 Type type = boxType(asmType(rightType)); 3937 if (TypeUtils.isReifiedTypeParameter(rightType)) { 3938 putReifiedOperationMarkerIfTypeIsReifiedParameter(rightType, 3939 safeAs ? ReifiedTypeInliner.OperationKind.SAFE_AS 3940 : ReifiedTypeInliner.OperationKind.AS); 3941 v.checkcast(type); 3942 return Unit.INSTANCE; 3943 } 3944 3945 CodegenUtilKt.generateAsCast(v, rightType, type, safeAs); 3946 3947 return Unit.INSTANCE; 3948 } 3949 }); 3950 } 3951 3952 @Override 3953 public StackValue visitIsExpression(@NotNull KtIsExpression expression, StackValue receiver) { 3954 StackValue match = StackValue.expression(OBJECT_TYPE, expression.getLeftHandSide(), this); 3955 return generateIsCheck(match, expression.getTypeReference(), expression.isNegated()); 3956 } 3957 3958 private StackValue generateExpressionMatch(StackValue expressionToMatch, KtExpression patternExpression) { 3959 if (expressionToMatch != null) { 3960 Type subjectType = expressionToMatch.type; 3961 markStartLineNumber(patternExpression); 3962 KotlinType condJetType = bindingContext.getType(patternExpression); 3963 Type condType; 3964 if (isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) { 3965 assert condJetType != null; 3966 condType = asmType(condJetType); 3967 if (!(isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) { 3968 subjectType = boxType(subjectType); 3969 } 3970 } 3971 else { 3972 condType = OBJECT_TYPE; 3973 } 3974 StackValue condition = genLazy(patternExpression, condType); 3975 return genEqualsForExpressionsOnStack(KtTokens.EQEQ, StackValue.coercion(expressionToMatch, subjectType), condition); 3976 } 3977 else { 3978 return gen(patternExpression); 3979 } 3980 } 3981 3982 private StackValue generateIsCheck(StackValue expressionToMatch, KtTypeReference typeReference, boolean negated) { 3983 KotlinType jetType = bindingContext.get(TYPE, typeReference); 3984 markStartLineNumber(typeReference); 3985 StackValue value = generateIsCheck(expressionToMatch, jetType, false); 3986 return negated ? StackValue.not(value) : value; 3987 } 3988 3989 private StackValue generateIsCheck(final StackValue expressionToGen, final KotlinType kotlinType, final boolean leaveExpressionOnStack) { 3990 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 3991 @Override 3992 public Unit invoke(InstructionAdapter v) { 3993 expressionToGen.put(OBJECT_TYPE, v); 3994 if (leaveExpressionOnStack) { 3995 v.dup(); 3996 } 3997 3998 Type type = boxType(asmType(kotlinType)); 3999 if (TypeUtils.isReifiedTypeParameter(kotlinType)) { 4000 putReifiedOperationMarkerIfTypeIsReifiedParameter(kotlinType, ReifiedTypeInliner.OperationKind.IS); 4001 v.instanceOf(type); 4002 return null; 4003 } 4004 4005 CodegenUtilKt.generateIsCheck(v, kotlinType, type); 4006 return null; 4007 } 4008 }); 4009 } 4010 4011 public void putReifiedOperationMarkerIfTypeIsReifiedParameter( 4012 @NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind 4013 ) { 4014 Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type); 4015 if (typeParameterAndReificationArgument != null && typeParameterAndReificationArgument.getFirst().isReified()) { 4016 TypeParameterDescriptor typeParameterDescriptor = typeParameterAndReificationArgument.getFirst(); 4017 if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) { 4018 parentCodegen.getReifiedTypeParametersUsages(). 4019 addUsedReifiedParameter(typeParameterDescriptor.getName().asString()); 4020 } 4021 v.iconst(operationKind.getId()); 4022 v.visitLdcInsn(typeParameterAndReificationArgument.getSecond().asString()); 4023 v.invokestatic( 4024 IntrinsicMethods.INTRINSICS_CLASS_NAME, ReifiedTypeInliner.REIFIED_OPERATION_MARKER_METHOD_NAME, 4025 Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE, Type.getType(String.class)), false 4026 ); 4027 } 4028 } 4029 4030 public void propagateChildReifiedTypeParametersUsages(@NotNull ReifiedTypeParametersUsages usages) { 4031 parentCodegen.getReifiedTypeParametersUsages().propagateChildUsagesWithinContext(usages, context); 4032 } 4033 4034 @Override 4035 public StackValue visitWhenExpression(@NotNull KtWhenExpression expression, StackValue receiver) { 4036 return generateWhenExpression(expression, false); 4037 } 4038 4039 public StackValue generateWhenExpression(final KtWhenExpression expression, final boolean isStatement) { 4040 final KtExpression expr = expression.getSubjectExpression(); 4041 final Type subjectType = expressionType(expr); 4042 4043 final Type resultType = isStatement ? Type.VOID_TYPE : expressionType(expression); 4044 4045 return StackValue.operation(resultType, new Function1<InstructionAdapter, Unit>() { 4046 @Override 4047 public Unit invoke(InstructionAdapter v) { 4048 SwitchCodegen switchCodegen = SwitchCodegenUtil.buildAppropriateSwitchCodegenIfPossible( 4049 expression, isStatement, isExhaustive(expression, isStatement), ExpressionCodegen.this 4050 ); 4051 if (switchCodegen != null) { 4052 switchCodegen.generate(); 4053 return Unit.INSTANCE; 4054 } 4055 4056 int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1; 4057 if (subjectLocal != -1) { 4058 gen(expr, subjectType); 4059 tempVariables.put(expr, StackValue.local(subjectLocal, subjectType)); 4060 v.store(subjectLocal, subjectType); 4061 } 4062 4063 Label end = new Label(); 4064 boolean hasElse = KtPsiUtil.checkWhenExpressionHasSingleElse(expression); 4065 4066 Label nextCondition = null; 4067 for (KtWhenEntry whenEntry : expression.getEntries()) { 4068 if (nextCondition != null) { 4069 v.mark(nextCondition); 4070 } 4071 nextCondition = new Label(); 4072 FrameMap.Mark mark = myFrameMap.mark(); 4073 Label thisEntry = new Label(); 4074 if (!whenEntry.isElse()) { 4075 KtWhenCondition[] conditions = whenEntry.getConditions(); 4076 for (int i = 0; i < conditions.length; i++) { 4077 StackValue conditionValue = generateWhenCondition(subjectType, subjectLocal, conditions[i]); 4078 BranchedValue.Companion.condJump(conditionValue, nextCondition, true, v); 4079 if (i < conditions.length - 1) { 4080 v.goTo(thisEntry); 4081 v.mark(nextCondition); 4082 nextCondition = new Label(); 4083 } 4084 } 4085 } 4086 4087 v.visitLabel(thisEntry); 4088 gen(whenEntry.getExpression(), resultType); 4089 mark.dropTo(); 4090 if (!whenEntry.isElse()) { 4091 v.goTo(end); 4092 } 4093 } 4094 if (!hasElse && nextCondition != null) { 4095 v.mark(nextCondition); 4096 putUnitInstanceOntoStackForNonExhaustiveWhen(expression, isStatement); 4097 } 4098 4099 markLineNumber(expression, isStatement); 4100 v.mark(end); 4101 4102 myFrameMap.leaveTemp(subjectType); 4103 tempVariables.remove(expr); 4104 return null; 4105 } 4106 }); 4107 } 4108 4109 private boolean isExhaustive(@NotNull KtWhenExpression whenExpression, boolean isStatement) { 4110 if (isStatement && !BindingContextUtilsKt.isUsedAsExpression(whenExpression, bindingContext)) { 4111 return Boolean.TRUE.equals(bindingContext.get(BindingContext.IMPLICIT_EXHAUSTIVE_WHEN, whenExpression)); 4112 } 4113 else { 4114 return Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, whenExpression)); 4115 } 4116 } 4117 4118 public void putUnitInstanceOntoStackForNonExhaustiveWhen( 4119 @NotNull KtWhenExpression whenExpression, 4120 boolean isStatement 4121 ) { 4122 if (isExhaustive(whenExpression, isStatement)) { 4123 // when() is supposed to be exhaustive 4124 genThrow(v, "kotlin/NoWhenBranchMatchedException", null); 4125 } 4126 else if (!isStatement) { 4127 // non-exhaustive when() with no else -> Unit must be expected 4128 StackValue.putUnitInstance(v); 4129 } 4130 } 4131 4132 private StackValue generateWhenCondition(Type subjectType, int subjectLocal, KtWhenCondition condition) { 4133 if (condition instanceof KtWhenConditionInRange) { 4134 KtWhenConditionInRange conditionInRange = (KtWhenConditionInRange) condition; 4135 return generateIn(StackValue.local(subjectLocal, subjectType), 4136 conditionInRange.getRangeExpression(), 4137 conditionInRange.getOperationReference()); 4138 } 4139 StackValue.Local match = subjectLocal == -1 ? null : StackValue.local(subjectLocal, subjectType); 4140 if (condition instanceof KtWhenConditionIsPattern) { 4141 KtWhenConditionIsPattern patternCondition = (KtWhenConditionIsPattern) condition; 4142 return generateIsCheck(match, patternCondition.getTypeReference(), patternCondition.isNegated()); 4143 } 4144 else if (condition instanceof KtWhenConditionWithExpression) { 4145 KtExpression patternExpression = ((KtWhenConditionWithExpression) condition).getExpression(); 4146 return generateExpressionMatch(match, patternExpression); 4147 } 4148 else { 4149 throw new UnsupportedOperationException("unsupported kind of when condition"); 4150 } 4151 } 4152 4153 private boolean isIntRangeExpr(KtExpression rangeExpression) { 4154 if (rangeExpression instanceof KtBinaryExpression) { 4155 KtBinaryExpression binaryExpression = (KtBinaryExpression) rangeExpression; 4156 if (binaryExpression.getOperationReference().getReferencedNameElementType() == KtTokens.RANGE) { 4157 KotlinType jetType = bindingContext.getType(rangeExpression); 4158 assert jetType != null; 4159 DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); 4160 return DescriptorUtilsKt.getBuiltIns(descriptor).getIntegralRanges().contains(descriptor); 4161 } 4162 } 4163 return false; 4164 } 4165 4166 private Call makeFakeCall(ReceiverValue initializerAsReceiver) { 4167 KtSimpleNameExpression fake = KtPsiFactoryKt.KtPsiFactory(state.getProject()).createSimpleName("fake"); 4168 return CallMaker.makeCall(fake, initializerAsReceiver); 4169 } 4170 4171 @Override 4172 public String toString() { 4173 return context.getContextDescriptor().toString(); 4174 } 4175 4176 @NotNull 4177 public FrameMap getFrameMap() { 4178 return myFrameMap; 4179 } 4180 4181 @NotNull 4182 public MethodContext getContext() { 4183 return context; 4184 } 4185 4186 @NotNull 4187 public NameGenerator getInlineNameGenerator() { 4188 NameGenerator nameGenerator = getParentCodegen().getInlineNameGenerator(); 4189 Name name = context.getContextDescriptor().getName(); 4190 return nameGenerator.subGenerator((name.isSpecial() ? "$special" : name.asString()) + "$$inlined" ); 4191 } 4192 4193 public Type getReturnType() { 4194 return returnType; 4195 } 4196 4197 public Stack<BlockStackElement> getBlockStackElements() { 4198 return new Stack<BlockStackElement>(blockStackElements); 4199 } 4200 4201 public void addBlockStackElementsForNonLocalReturns(@NotNull Stack<BlockStackElement> elements, int finallyDepth) { 4202 blockStackElements.addAll(elements); 4203 this.finallyDepth = finallyDepth; 4204 } 4205 4206 private static class NonLocalReturnInfo { 4207 4208 final Type returnType; 4209 4210 final String labelName; 4211 4212 private NonLocalReturnInfo(Type type, String name) { 4213 returnType = type; 4214 labelName = name; 4215 } 4216 } 4217 }