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