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