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