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