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