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