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