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