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