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