001 /*
002 * Copyright 2010-2015 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.kotlin.codegen;
018
019 import com.intellij.openapi.progress.ProcessCanceledException;
020 import com.intellij.psi.PsiElement;
021 import kotlin.Unit;
022 import kotlin.jvm.functions.Function0;
023 import kotlin.jvm.functions.Function1;
024 import org.jetbrains.annotations.NotNull;
025 import org.jetbrains.annotations.Nullable;
026 import org.jetbrains.kotlin.backend.common.CodegenUtil;
027 import org.jetbrains.kotlin.codegen.context.*;
028 import org.jetbrains.kotlin.codegen.inline.*;
029 import org.jetbrains.kotlin.codegen.state.GenerationState;
030 import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
031 import org.jetbrains.kotlin.descriptors.*;
032 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
033 import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
034 import org.jetbrains.kotlin.fileClasses.FileClasses;
035 import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
036 import org.jetbrains.kotlin.load.java.JvmAbi;
037 import org.jetbrains.kotlin.name.Name;
038 import org.jetbrains.kotlin.name.SpecialNames;
039 import org.jetbrains.kotlin.psi.*;
040 import org.jetbrains.kotlin.resolve.*;
041 import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
042 import org.jetbrains.kotlin.resolve.constants.ConstantValue;
043 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
044 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
045 import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
046 import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
047 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
048 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
049 import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
050 import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
051 import org.jetbrains.kotlin.storage.LockBasedStorageManager;
052 import org.jetbrains.kotlin.storage.NotNullLazyValue;
053 import org.jetbrains.kotlin.types.ErrorUtils;
054 import org.jetbrains.kotlin.types.KotlinType;
055 import org.jetbrains.org.objectweb.asm.Label;
056 import org.jetbrains.org.objectweb.asm.MethodVisitor;
057 import org.jetbrains.org.objectweb.asm.Type;
058 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
059 import org.jetbrains.org.objectweb.asm.commons.Method;
060
061 import java.util.*;
062
063 import static org.jetbrains.kotlin.codegen.AsmUtil.calculateInnerClassAccessFlags;
064 import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
065 import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
066 import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE;
067 import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
068 import static org.jetbrains.kotlin.resolve.DescriptorUtils.isTopLevelDeclaration;
069 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
070 import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
071 import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt.Synthetic;
072 import static org.jetbrains.org.objectweb.asm.Opcodes.*;
073
074 public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclarationContainer*/> {
075 protected final GenerationState state;
076 protected final T element;
077 protected final FieldOwnerContext context;
078 protected final ClassBuilder v;
079 protected final FunctionCodegen functionCodegen;
080 protected final PropertyCodegen propertyCodegen;
081 protected final JetTypeMapper typeMapper;
082 protected final BindingContext bindingContext;
083 protected final JvmFileClassesProvider fileClassesProvider;
084 private final MemberCodegen<?> parentCodegen;
085 private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages();
086 protected final Collection<ClassDescriptor> innerClasses = new LinkedHashSet<ClassDescriptor>();
087
088 protected ExpressionCodegen clInit;
089 private NameGenerator inlineNameGenerator;
090
091 private SourceMapper sourceMapper;
092 private final ConstantExpressionEvaluator constantExpressionEvaluator;
093
094 public MemberCodegen(
095 @NotNull GenerationState state,
096 @Nullable MemberCodegen<?> parentCodegen,
097 @NotNull FieldOwnerContext context,
098 T element,
099 @NotNull ClassBuilder builder
100 ) {
101 this.state = state;
102 this.typeMapper = state.getTypeMapper();
103 this.bindingContext = state.getBindingContext();
104 this.fileClassesProvider = state.getFileClassesProvider();
105 this.element = element;
106 this.context = context;
107 this.v = builder;
108 this.functionCodegen = new FunctionCodegen(context, v, state, this);
109 this.propertyCodegen = new PropertyCodegen(context, v, functionCodegen, this);
110 this.parentCodegen = parentCodegen;
111 this.constantExpressionEvaluator = new ConstantExpressionEvaluator(state.getModule().getBuiltIns());
112 }
113
114 protected MemberCodegen(@NotNull MemberCodegen<T> wrapped, T declaration, FieldOwnerContext codegenContext) {
115 this(wrapped.state, wrapped.getParentCodegen(), codegenContext, declaration, wrapped.v);
116 }
117
118 public void generate() {
119 generateDeclaration();
120
121 generateBody();
122
123 generateSyntheticParts();
124
125 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
126 generateKotlinAnnotation();
127 }
128
129 done();
130 }
131
132 protected abstract void generateDeclaration();
133
134 protected abstract void generateBody();
135
136 protected void generateSyntheticParts() {
137 }
138
139 protected abstract void generateKotlinAnnotation();
140
141 @Nullable
142 protected ClassDescriptor classForInnerClassRecord() {
143 return null;
144 }
145
146 public static void markLineNumberForSyntheticFunction(@Nullable ClassDescriptor declarationDescriptor, @NotNull InstructionAdapter v) {
147 if (declarationDescriptor == null) {
148 return;
149 }
150
151 PsiElement classElement = DescriptorToSourceUtils.getSourceFromDescriptor(declarationDescriptor);
152 if (classElement != null) {
153 markLineNumberForSyntheticFunction(classElement, v);
154 }
155 }
156
157 public static void markLineNumberForSyntheticFunction(@NotNull PsiElement element, @NotNull InstructionAdapter v) {
158 Integer lineNumber = CodegenUtil.getLineNumberForElement(element, false);
159 if (lineNumber != null) {
160 Label label = new Label();
161 v.visitLabel(label);
162 v.visitLineNumber(lineNumber, label);
163 }
164 }
165
166 protected void done() {
167 if (clInit != null) {
168 clInit.v.visitInsn(RETURN);
169 FunctionCodegen.endVisit(clInit.v, "static initializer", element);
170 }
171
172 writeInnerClasses();
173
174 if (sourceMapper != null) {
175 SourceMapper.Companion.flushToClassBuilder(sourceMapper, v);
176 }
177
178 v.done();
179 }
180
181 public void genFunctionOrProperty(@NotNull KtDeclaration functionOrProperty) {
182 if (functionOrProperty instanceof KtNamedFunction) {
183 try {
184 functionCodegen.gen((KtNamedFunction) functionOrProperty);
185 }
186 catch (ProcessCanceledException e) {
187 throw e;
188 }
189 catch (CompilationException e) {
190 throw e;
191 }
192 catch (Exception e) {
193 throw new CompilationException("Failed to generate function " + functionOrProperty.getName(), e, functionOrProperty);
194 }
195 }
196 else if (functionOrProperty instanceof KtProperty) {
197 try {
198 propertyCodegen.gen((KtProperty) functionOrProperty);
199 }
200 catch (ProcessCanceledException e) {
201 throw e;
202 }
203 catch (CompilationException e) {
204 throw e;
205 }
206 catch (Exception e) {
207 throw new CompilationException("Failed to generate property " + functionOrProperty.getName(), e, functionOrProperty);
208 }
209 }
210 else {
211 throw new IllegalArgumentException("Unknown parameter: " + functionOrProperty);
212 }
213 }
214
215 public static void genClassOrObject(
216 @NotNull CodegenContext parentContext,
217 @NotNull KtClassOrObject aClass,
218 @NotNull GenerationState state,
219 @Nullable MemberCodegen<?> parentCodegen
220 ) {
221 ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
222
223 if (descriptor == null || ErrorUtils.isError(descriptor)) {
224 badDescriptor(descriptor, state.getClassBuilderMode());
225 return;
226 }
227
228 if (descriptor.getName().equals(SpecialNames.NO_NAME_PROVIDED)) {
229 badDescriptor(descriptor, state.getClassBuilderMode());
230 }
231
232 Type classType = state.getTypeMapper().mapClass(descriptor);
233 ClassBuilder classBuilder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(aClass, descriptor), classType, aClass.getContainingFile());
234 ClassContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
235 new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, parentCodegen, false).generate();
236 }
237
238 private static void badDescriptor(ClassDescriptor descriptor, ClassBuilderMode mode) {
239 if (mode != ClassBuilderMode.LIGHT_CLASSES) {
240 throw new IllegalStateException("Generating bad descriptor in ClassBuilderMode = " + mode + ": " + descriptor);
241 }
242 }
243
244 public void genClassOrObject(KtClassOrObject aClass) {
245 genClassOrObject(context, aClass, state, this);
246 }
247
248 private void writeInnerClasses() {
249 // JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information
250 // for each enclosing class and for each immediate member
251 ClassDescriptor classDescriptor = classForInnerClassRecord();
252 if (classDescriptor != null) {
253 if (parentCodegen != null) {
254 parentCodegen.innerClasses.add(classDescriptor);
255 }
256
257 for (MemberCodegen<?> codegen = this; codegen != null; codegen = codegen.getParentCodegen()) {
258 ClassDescriptor outerClass = codegen.classForInnerClassRecord();
259 if (outerClass != null) {
260 innerClasses.add(outerClass);
261 }
262 }
263 }
264
265 for (ClassDescriptor innerClass : innerClasses) {
266 writeInnerClass(innerClass);
267 }
268 }
269
270 private void writeInnerClass(@NotNull ClassDescriptor innerClass) {
271 DeclarationDescriptor containing = innerClass.getContainingDeclaration();
272 String outerClassInternalName = null;
273 if (containing instanceof ClassDescriptor) {
274 outerClassInternalName = typeMapper.mapClass((ClassDescriptor) containing).getInternalName();
275 } /* disabled cause of KT-7775
276 else if (containing instanceof ScriptDescriptor) {
277 outerClassInternalName = asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) containing).getInternalName();
278 }*/
279
280 String innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString();
281
282 String innerClassInternalName = typeMapper.mapClass(innerClass).getInternalName();
283 v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, calculateInnerClassAccessFlags(innerClass));
284 }
285
286 protected void writeOuterClassAndEnclosingMethod() {
287 CodegenContext context = this.context.getParentContext();
288 while (context instanceof MethodContext && ((MethodContext) context).isInliningLambda()) {
289 // If this is a lambda which will be inlined, skip its MethodContext and enclosing ClosureContext
290 //noinspection ConstantConditions
291 context = context.getParentContext().getParentContext();
292 }
293 assert context != null : "Outermost context can't be null: " + this.context;
294
295 Type enclosingAsmType = computeOuterClass(context);
296 if (enclosingAsmType != null) {
297 Method method = computeEnclosingMethod(context);
298
299 v.visitOuterClass(
300 enclosingAsmType.getInternalName(),
301 method == null ? null : method.getName(),
302 method == null ? null : method.getDescriptor()
303 );
304 }
305 }
306
307 @Nullable
308 private Type computeOuterClass(@NotNull CodegenContext<?> context) {
309 CodegenContext<? extends ClassOrPackageFragmentDescriptor> outermost = context.getClassOrPackageParentContext();
310 if (outermost instanceof ClassContext) {
311 return typeMapper.mapType(((ClassContext) outermost).getContextDescriptor());
312 }
313 else if (outermost instanceof DelegatingFacadeContext || outermost instanceof DelegatingToPartContext) {
314 Type implementationOwnerType = CodegenContextUtil.getImplementationOwnerClassType(outermost);
315 if (implementationOwnerType != null) {
316 return implementationOwnerType;
317 }
318 else {
319 return FileClasses.getFileClassType(fileClassesProvider, element.getContainingJetFile());
320 }
321 }
322 /*disabled cause of KT-7775
323 else if (outermost instanceof ScriptContext) {
324 return asmTypeForScriptDescriptor(bindingContext, ((ScriptContext) outermost).getScriptDescriptor());
325 }*/
326 return null;
327 }
328
329 @Nullable
330 private Method computeEnclosingMethod(@NotNull CodegenContext context) {
331 if (context instanceof MethodContext) {
332 Method method = typeMapper.mapSignature(((MethodContext) context).getFunctionDescriptor()).getAsmMethod();
333 if (!method.getName().equals("<clinit>")) {
334 return method;
335 }
336 }
337 return null;
338 }
339
340 @NotNull
341 public NameGenerator getInlineNameGenerator() {
342 if (inlineNameGenerator == null) {
343 String prefix = InlineCodegenUtil.getInlineName(context, typeMapper, fileClassesProvider);
344 inlineNameGenerator = new NameGenerator(prefix);
345 }
346 return inlineNameGenerator;
347 }
348
349 @NotNull
350 protected ExpressionCodegen createOrGetClInitCodegen() {
351 DeclarationDescriptor descriptor = context.getContextDescriptor();
352 if (clInit == null) {
353 MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(descriptor), ACC_STATIC, "<clinit>", "()V", null, null);
354 SimpleFunctionDescriptorImpl clInit =
355 SimpleFunctionDescriptorImpl.create(descriptor, Annotations.Companion.getEMPTY(), Name.special("<clinit>"), SYNTHESIZED,
356 KotlinSourceElementKt.toSourceElement(element));
357 clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
358 Collections.<ValueParameterDescriptor>emptyList(),
359 DescriptorUtilsKt.getModule(descriptor).getBuiltIns().getUnitType(),
360 null, Visibilities.PRIVATE);
361
362 this.clInit = new ExpressionCodegen(mv, new FrameMap(), Type.VOID_TYPE, context.intoFunction(clInit), state, this);
363 }
364 return clInit;
365 }
366
367 protected void generateInitializers(@NotNull Function0<ExpressionCodegen> createCodegen) {
368 NotNullLazyValue<ExpressionCodegen> codegen = LockBasedStorageManager.NO_LOCKS.createLazyValue(createCodegen);
369 for (KtDeclaration declaration : ((KtDeclarationContainer) element).getDeclarations()) {
370 if (declaration instanceof KtProperty) {
371 if (shouldInitializeProperty((KtProperty) declaration)) {
372 initializeProperty(codegen.invoke(), (KtProperty) declaration);
373 }
374 }
375 else if (declaration instanceof KtClassInitializer) {
376 KtExpression body = ((KtClassInitializer) declaration).getBody();
377 if (body != null) {
378 codegen.invoke().gen(body, Type.VOID_TYPE);
379 }
380 }
381 }
382 }
383
384 private void initializeProperty(@NotNull ExpressionCodegen codegen, @NotNull KtProperty property) {
385 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property);
386 assert propertyDescriptor != null;
387
388 KtExpression initializer = property.getDelegateExpressionOrInitializer();
389 assert initializer != null : "shouldInitializeProperty must return false if initializer is null";
390
391 StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null, true, StackValue.LOCAL_0);
392
393 propValue.store(codegen.gen(initializer), codegen.v);
394 }
395
396 private boolean shouldInitializeProperty(@NotNull KtProperty property) {
397 if (!property.hasDelegateExpressionOrInitializer()) return false;
398
399 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property);
400 assert propertyDescriptor != null;
401
402 if (propertyDescriptor.isConst()) {
403 //const initializer always inlined
404 return false;
405 }
406
407 KtExpression initializer = property.getInitializer();
408
409 ConstantValue<?> initializerValue = computeInitializerValue(property, propertyDescriptor, initializer);
410 // we must write constant values for fields in light classes,
411 // because Java's completion for annotation arguments uses this information
412 if (initializerValue == null) return state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES;
413
414 //TODO: OPTIMIZATION: don't initialize static final fields
415 KotlinType jetType = getPropertyOrDelegateType(property, propertyDescriptor);
416 Type type = typeMapper.mapType(jetType);
417 return !skipDefaultValue(propertyDescriptor, initializerValue.getValue(), type);
418 }
419
420 @Nullable
421 private ConstantValue<?> computeInitializerValue(
422 @NotNull KtProperty property,
423 @NotNull PropertyDescriptor propertyDescriptor,
424 @Nullable KtExpression initializer
425 ) {
426 if (property.isVar() && initializer != null) {
427 BindingTrace tempTrace = TemporaryBindingTrace.create(state.getBindingTrace(), "property initializer");
428 return constantExpressionEvaluator.evaluateToConstantValue(initializer, tempTrace, propertyDescriptor.getType());
429 }
430 return propertyDescriptor.getCompileTimeInitializer();
431 }
432
433 @NotNull
434 private KotlinType getPropertyOrDelegateType(@NotNull KtProperty property, @NotNull PropertyDescriptor descriptor) {
435 KtExpression delegateExpression = property.getDelegateExpression();
436 if (delegateExpression != null) {
437 KotlinType delegateType = bindingContext.getType(delegateExpression);
438 assert delegateType != null : "Type of delegate expression should be recorded";
439 return delegateType;
440 }
441 return descriptor.getType();
442 }
443
444 private static boolean skipDefaultValue(@NotNull PropertyDescriptor propertyDescriptor, Object value, @NotNull Type type) {
445 if (isPrimitive(type)) {
446 if (!propertyDescriptor.getType().isMarkedNullable() && value instanceof Number) {
447 if (type == Type.INT_TYPE && ((Number) value).intValue() == 0) {
448 return true;
449 }
450 if (type == Type.BYTE_TYPE && ((Number) value).byteValue() == 0) {
451 return true;
452 }
453 if (type == Type.LONG_TYPE && ((Number) value).longValue() == 0L) {
454 return true;
455 }
456 if (type == Type.SHORT_TYPE && ((Number) value).shortValue() == 0) {
457 return true;
458 }
459 if (type == Type.DOUBLE_TYPE && ((Number) value).doubleValue() == 0d) {
460 return true;
461 }
462 if (type == Type.FLOAT_TYPE && ((Number) value).floatValue() == 0f) {
463 return true;
464 }
465 }
466 if (type == Type.BOOLEAN_TYPE && value instanceof Boolean && !((Boolean) value)) {
467 return true;
468 }
469 if (type == Type.CHAR_TYPE && value instanceof Character && ((Character) value) == 0) {
470 return true;
471 }
472 }
473 else {
474 if (value == null) {
475 return true;
476 }
477 }
478 return false;
479 }
480
481 public static void generateModuleNameField(
482 @NotNull GenerationState state,
483 @NotNull ClassBuilder classBuilder
484 ) {
485 classBuilder.newField(NO_ORIGIN, ACC_PUBLIC | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.MODULE_NAME_FIELD,
486 AsmTypes.JAVA_STRING_TYPE.getDescriptor(), null, state.getModuleName());
487 }
488
489 protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) {
490 List<KtProperty> delegatedProperties = new ArrayList<KtProperty>();
491 for (KtDeclaration declaration : ((KtDeclarationContainer) element).getDeclarations()) {
492 if (declaration instanceof KtProperty) {
493 KtProperty property = (KtProperty) declaration;
494 if (property.hasDelegate()) {
495 delegatedProperties.add(property);
496 }
497 }
498 }
499 if (delegatedProperties.isEmpty()) return;
500
501 v.newField(NO_ORIGIN, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME,
502 "[" + PROPERTY_METADATA_TYPE, null, null);
503
504 if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return;
505
506 InstructionAdapter iv = createOrGetClInitCodegen().v;
507 iv.iconst(delegatedProperties.size());
508 iv.newarray(PROPERTY_METADATA_TYPE);
509
510 for (int i = 0, size = delegatedProperties.size(); i < size; i++) {
511 PropertyDescriptor property =
512 (PropertyDescriptor) BindingContextUtils.getNotNull(bindingContext, VARIABLE, delegatedProperties.get(i));
513
514 iv.dup();
515 iv.iconst(i);
516
517 StackValue value;
518 // TODO: remove this option and always generate PropertyReferenceNImpl creation
519 if ("true".equalsIgnoreCase(System.getProperty("kotlin.jvm.optimize.delegated.properties"))) {
520 int receiverCount = (property.getDispatchReceiverParameter() != null ? 1 : 0) +
521 (property.getExtensionReceiverParameter() != null ? 1 : 0);
522 Type implType = property.isVar() ? MUTABLE_PROPERTY_REFERENCE_IMPL[receiverCount] : PROPERTY_REFERENCE_IMPL[receiverCount];
523 iv.anew(implType);
524 iv.dup();
525 // TODO: generate the container once and save to a local field instead
526 ClosureCodegen.generateCallableReferenceDeclarationContainer(iv, property, state);
527 iv.aconst(property.getName().asString());
528 iv.aconst(PropertyReferenceCodegen.getPropertyReferenceSignature(property, state));
529 iv.invokespecial(
530 implType.getInternalName(), "<init>",
531 Type.getMethodDescriptor(Type.VOID_TYPE, K_DECLARATION_CONTAINER_TYPE, JAVA_STRING_TYPE, JAVA_STRING_TYPE), false
532 );
533 value = StackValue.onStack(implType);
534 Method wrapper = PropertyReferenceCodegen.getWrapperMethodForPropertyReference(property, receiverCount);
535 iv.invokestatic(REFLECTION, wrapper.getName(), wrapper.getDescriptor(), false);
536 }
537 else {
538 ReceiverParameterDescriptor dispatchReceiver = property.getDispatchReceiverParameter();
539
540 //noinspection ConstantConditions
541 value = createOrGetClInitCodegen().generatePropertyReference(
542 delegatedProperties.get(i).getDelegate(), property, property,
543 dispatchReceiver != null ? new TransientReceiver(dispatchReceiver.getType()) : ReceiverValue.NO_RECEIVER
544 );
545 }
546
547 value.put(PROPERTY_METADATA_TYPE, iv);
548
549 iv.astore(PROPERTY_METADATA_TYPE);
550 }
551
552 iv.putstatic(thisAsmType.getInternalName(), JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, "[" + PROPERTY_METADATA_TYPE);
553 }
554
555 public String getClassName() {
556 return v.getThisName();
557 }
558
559 @NotNull
560 public FieldOwnerContext<?> getContext() {
561 return context;
562 }
563
564 @NotNull
565 public ReifiedTypeParametersUsages getReifiedTypeParametersUsages() {
566 return reifiedTypeParametersUsages;
567 }
568
569 public MemberCodegen<?> getParentCodegen() {
570 return parentCodegen;
571 }
572
573 @Override
574 public String toString() {
575 return context.toString();
576 }
577
578 @NotNull
579 public SourceMapper getOrCreateSourceMapper() {
580 if (sourceMapper == null) {
581 sourceMapper = new DefaultSourceMapper(SourceInfo.Companion.createInfo(element, getClassName()), null);
582 }
583 return sourceMapper;
584 }
585
586 protected void generateConstInstance(
587 @NotNull Type thisAsmType,
588 @NotNull Type fieldAsmType,
589 @NotNull Function1<InstructionAdapter, Unit> initialization
590 ) {
591 v.newField(JvmDeclarationOriginKt.OtherOrigin(element), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD, fieldAsmType.getDescriptor(),
592 null, null);
593
594 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
595 InstructionAdapter iv = createOrGetClInitCodegen().v;
596 iv.anew(thisAsmType);
597 iv.dup();
598 iv.invokespecial(thisAsmType.getInternalName(), "<init>", "()V", false);
599 initialization.invoke(iv);
600 iv.putstatic(thisAsmType.getInternalName(), JvmAbi.INSTANCE_FIELD, fieldAsmType.getDescriptor());
601 }
602 }
603
604 protected void generateSyntheticAccessors() {
605 for (AccessorForCallableDescriptor<?> accessor : ((CodegenContext<?>) context).getAccessors()) {
606 generateSyntheticAccessor(accessor);
607 }
608 }
609
610 private void generateSyntheticAccessor(@NotNull AccessorForCallableDescriptor<?> accessorForCallableDescriptor) {
611 if (accessorForCallableDescriptor instanceof FunctionDescriptor) {
612 final FunctionDescriptor accessor = (FunctionDescriptor) accessorForCallableDescriptor;
613 final FunctionDescriptor original = (FunctionDescriptor) accessorForCallableDescriptor.getCalleeDescriptor();
614 functionCodegen.generateMethod(
615 Synthetic(null, original), accessor,
616 new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, accessor) {
617 @Override
618 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
619 markLineNumberForSyntheticFunction(element, codegen.v);
620
621 generateMethodCallTo(original, accessor, codegen.v);
622 codegen.v.areturn(signature.getReturnType());
623 }
624 }
625 );
626 }
627 else if (accessorForCallableDescriptor instanceof AccessorForPropertyDescriptor) {
628 final AccessorForPropertyDescriptor accessor = (AccessorForPropertyDescriptor) accessorForCallableDescriptor;
629 final PropertyDescriptor original = accessor.getCalleeDescriptor();
630
631 class PropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> {
632 public PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) {
633 super(MemberCodegen.this.state, callableDescriptor);
634 }
635
636 @Override
637 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
638 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) &&
639 !isCompanionObject(accessor.getContainingDeclaration());
640 StackValue property = codegen.intermediateValueForProperty(
641 original, forceField, accessor.getSuperCallExpression(), true, StackValue.none()
642 );
643
644 InstructionAdapter iv = codegen.v;
645
646 markLineNumberForSyntheticFunction(element, iv);
647
648 Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
649 for (int i = 0, reg = 0; i < argTypes.length; i++) {
650 Type argType = argTypes[i];
651 iv.load(reg, argType);
652 //noinspection AssignmentToForLoopParameter
653 reg += argType.getSize();
654 }
655
656 if (callableDescriptor instanceof PropertyGetterDescriptor) {
657 property.put(property.type, iv);
658 }
659 else {
660 property.store(StackValue.onStack(property.type), iv, true);
661 }
662
663 iv.areturn(signature.getReturnType());
664 }
665 }
666
667 PropertyGetterDescriptor getter = accessor.getGetter();
668 assert getter != null;
669 functionCodegen.generateMethod(Synthetic(null, original.getGetter() != null ? original.getGetter() : original),
670 getter, new PropertyAccessorStrategy(getter));
671
672
673 if (accessor.isVar()) {
674 PropertySetterDescriptor setter = accessor.getSetter();
675 assert setter != null;
676
677 functionCodegen.generateMethod(Synthetic(null, original.getSetter() != null ? original.getSetter() : original),
678 setter, new PropertyAccessorStrategy(setter));
679 }
680 }
681 else {
682 throw new UnsupportedOperationException();
683 }
684 }
685
686 private void generateMethodCallTo(
687 @NotNull FunctionDescriptor functionDescriptor,
688 @Nullable FunctionDescriptor accessorDescriptor,
689 @NotNull InstructionAdapter iv
690 ) {
691 CallableMethod callableMethod = typeMapper.mapToCallableMethod(
692 functionDescriptor,
693 accessorDescriptor instanceof AccessorForCallableDescriptor &&
694 ((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallExpression() != null
695 );
696
697 boolean isTopLevelDeclaration = isTopLevelDeclaration(functionDescriptor);
698 int reg = isTopLevelDeclaration ? 0 : 1;
699 boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor;
700 if (!accessorIsConstructor && functionDescriptor instanceof ConstructorDescriptor) {
701 iv.anew(callableMethod.getOwner());
702 iv.dup();
703 reg = 0;
704 }
705 else if (accessorIsConstructor || (accessorDescriptor != null && JetTypeMapper.isAccessor(accessorDescriptor) && !isTopLevelDeclaration)) {
706 if (!AnnotationUtilKt.isPlatformStaticInObjectOrClass(functionDescriptor)) {
707 iv.load(0, OBJECT_TYPE);
708 }
709 }
710
711 for (Type argType : callableMethod.getParameterTypes()) {
712 if (AsmTypes.DEFAULT_CONSTRUCTOR_MARKER.equals(argType)) {
713 iv.aconst(null);
714 }
715 else {
716 iv.load(reg, argType);
717 reg += argType.getSize();
718 }
719 }
720
721 callableMethod.genInvokeInstruction(iv);
722 }
723 }