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