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