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