रूप @rickster का सुझाव दिया, मैं इस फ़ाइल (simple.swift) के उत्पन्न 86 विधानसभा पर एक नज़र था:
func thingWithClosure(a: Int, b: (() -> Void)?) {
println(a)
b?()
}
thingWithClosure(3) {
println("i'm a closure")
}
thingWithClosure(5, nil)
thingWithClosure(2) {}
मेरे विधानसभा सुंदर जंग लगी है, लेकिन मैं थोड़े थोड़ा इसे भेंगापन कर सकते हैं। ..
unoptimized उत्पन्न x86 विधानसभा के मुख्य अनुभाग, या यह कम से कम हिस्सा है, इस तरह दिखता है:
callq _swift_once
movq __TZvO[email protected]GOTPCREL(%rip), %rax
movq -64(%rbp), %rcx
movq %rcx, (%rax)
leaq l_metadata+16(%rip), %rdi
movl $32, %r9d
movl %r9d, %eax
movl $7, %r9d
movl %r9d, %edx
movq %rax, %rsi
movq %rdx, -80(%rbp)
movq %rax, -88(%rbp)
callq _swift_allocObject
leaq __TF6simpleU_FT_T_(%rip), %rcx
movq %rcx, 16(%rax)
movq $0, 24(%rax)
leaq __TPA__TTRXFo__dT__XFo_iT__iT__(%rip), %rcx
movq %rcx, -16(%rbp)
movq %rax, -8(%rbp)
movq -16(%rbp), %rsi
movl $3, %r9d
movl %r9d, %edi
movq %rax, %rdx
--> callq __TF6simple16thingWithClosureFTSiGSqFT_T___T_
movq $0, -24(%rbp)
movq $0, -32(%rbp)
movl $5, %r9d
movl %r9d, %edi
movq -72(%rbp), %rsi
movq -72(%rbp), %rdx
--> callq __TF6simple16thingWithClosureFTSiGSqFT_T___T_
leaq l_metadata2+16(%rip), %rdi
movq -88(%rbp), %rsi
movq -80(%rbp), %rdx
callq _swift_allocObject
leaq __TF6simpleU0_FT_T_(%rip), %rcx
movq %rcx, 16(%rax)
movq $0, 24(%rax)
leaq __TPA__TTRXFo__dT__XFo_iT__iT__3(%rip), %rcx
movq %rcx, -48(%rbp)
movq %rax, -40(%rbp)
movq -48(%rbp), %rsi
movl $2, %r9d
movl %r9d, %edi
movq %rax, %rdx
--> callq __TF6simple16thingWithClosureFTSiGSqFT_T___T_
xorl %eax, %eax
addq $96, %rsp
popq %rbp
retq
.cfi_endproc
मैं ने बताया गया है जहां समारोह 012,391,031 के साथ कहा जाता है। प्रत्येक callq
निर्देश से कुछ निर्देश देख रहे हैं, आप देख सकते हैं कि a
तर्क r9d
रजिस्टर में स्थानांतरित हो गया है।
इसी तरह, अनुकूलित उत्पादन:
callq _swift_once
movq __TZvO[email protected]GOTPCREL(%rip), %rax
movq %r14, (%rax)
movq $3, -24(%rbp)
movq [email protected](%rip), %rbx
addq $8, %rbx
leaq -24(%rbp), %rdi
movq %rbx, %rsi
callq __TFSs7printlnU__FQ_T_
leaq L___unnamed_1(%rip), %rax
movq %rax, -48(%rbp)
movq $13, -40(%rbp)
movq $0, -32(%rbp)
movq [email protected](%rip), %rsi
addq $8, %rsi
leaq -48(%rbp), %rdi
--> callq __TFSs7printlnU__FQ_T_
movq $5, -56(%rbp)
leaq -56(%rbp), %rdi
movq %rbx, %rsi
--> callq __TFSs7printlnU__FQ_T_
movq $2, -64(%rbp)
leaq -64(%rbp), %rdi
movq %rbx, %rsi
--> callq __TFSs7printlnU__FQ_T_
xorl %eax, %eax
addq $48, %rsp
popq %rbx
popq %r14
popq %rbp
retq
.cfi_endproc
यहाँ, संकलक समारोह inlined है, तो मैं -->
बजाय साथ println
कॉल ने बताया है।
मैंने एक अनुरूपित 16-बिट सीपीयू साल पहले x86 असेंबली का परिचय लिया था, इसलिए मैं नाटक करने वाला नहीं हूं कि मुझे पता है कि वास्तव में क्या हो रहा है, लेकिन ऐसा लगता है कि -O
के साथ संकलित होने पर, कंपाइलर लगभग बराबर समकक्ष कोड उत्सर्जित करता है (निर्देश गणना के संदर्भ में, लेकिन शायद स्मृति लुकअप के मामले में नहीं, आदि)। ऐसा लगता है कि println
पर कॉल leaq
(लोड प्रभावी पता) निर्देशों के साथ छेड़छाड़ की गई हैं, इसलिए हम सभी जगहों पर कूद सकते हैं, लेकिन मुझे यकीन नहीं है कि (कहां अधिक निर्देश हो सकते हैं? स्थिर डेटा लोड हो सकता है?), या अगर यह मायने रखता है।
अप्रत्याशित संस्करण nil
पैरामीटर केस के लिए अधिक से अधिक निर्देश उत्सर्जित करता है, इसलिए प्रमुख अंतर डीबग प्रदर्शन हो सकता है।
बेशक, यह x86 है, इसलिए यह एआरएम पर पूरी तरह से अलग हो सकता है .... शायद एआरएम असेंबली, एलएलवीएम आईआर, या स्विफ्ट आईआर आउटपुट अधिक प्रकाश डालेगा?
यदि कोई बेहतर समझ वाला कोई भी व्यक्ति स्पष्ट कर सकता है, तो मैं खुशी से इस उत्तर को अपडेट कर दूंगा।
डुनो स्वयं निश्चित रूप से, लेकिन आप एक्सकोड में जेनरेट की गई असेंबली को देखकर पता लगा सकते हैं। – rickster
मुझे यकीन नहीं है कि वैध अनुकूलन होगा। 1 एक बंद है जो कुछ भी नहीं करता है, wheres 2 बिल्कुल बंद नहीं करता है। कोई बंद करने का मतलब "डिफ़ॉल्ट व्यवहार का उपयोग नहीं करना" हो सकता है, लेकिन एक खाली बंद करने का अर्थ है "कुछ भी नहीं" जो आवश्यक नहीं है। – Ferruccio