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