Fix Interop/PInvoke/Miscellaneous/HandleRef tests under GCStress (#21131)
[platform/upstream/coreclr.git] / src / vm / ilmarshalers.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 // 
5 // File: ILMarshalers.cpp
6 // 
7
8 // 
9
10
11 #include "common.h"
12 #include "dllimport.h"
13 #include "mlinfo.h"
14 #include "ilmarshalers.h"
15 #include "olevariant.h"
16 #include "comdatetime.h"
17 #include "fieldmarshaler.h"
18
19 LocalDesc ILReflectionObjectMarshaler::GetManagedType()
20 {
21     STANDARD_VM_CONTRACT;
22     
23     return LocalDesc(MscorlibBinder::GetClass(GetManagedTypeBinderID()));
24 }
25
26 LocalDesc ILReflectionObjectMarshaler::GetNativeType()
27 {
28     LIMITED_METHOD_CONTRACT;
29     
30     return LocalDesc(ELEMENT_TYPE_I);
31 }
32
33 void ILReflectionObjectMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
34 {
35     STANDARD_VM_CONTRACT;
36     
37     int tokObject__m_handle = pslILEmit->GetToken(MscorlibBinder::GetField(GetObjectFieldID()));
38     int tokStruct__m_object = 0;
39     BinderFieldID structField = GetStructureFieldID();
40
41     // This marshaler can generate code for marshaling an object containing a handle, and for 
42     // marshaling a struct referring to an object containing a handle.
43     if (structField != 0)
44     {
45         tokStruct__m_object = pslILEmit->GetToken(MscorlibBinder::GetField(structField));
46     }
47     
48     ILCodeLabel* pNullLabel = pslILEmit->NewCodeLabel();
49
50     pslILEmit->EmitLoadNullPtr();
51     EmitStoreNativeValue(pslILEmit);
52
53     if (tokStruct__m_object != 0)
54     {
55         EmitLoadManagedHomeAddr(pslILEmit);
56         pslILEmit->EmitLDFLD(tokStruct__m_object);
57     }
58     else
59     {
60         EmitLoadManagedValue(pslILEmit);
61     }
62     pslILEmit->EmitBRFALSE(pNullLabel);
63     
64     if (tokStruct__m_object != 0)
65     {
66         EmitLoadManagedHomeAddr(pslILEmit);
67         pslILEmit->EmitLDFLD(tokStruct__m_object);
68     }
69     else
70     {
71         EmitLoadManagedValue(pslILEmit);
72     }
73
74     pslILEmit->EmitLDFLD(tokObject__m_handle);
75     EmitStoreNativeValue(pslILEmit);
76     
77     pslILEmit->EmitLabel(pNullLabel);
78
79     if (IsCLRToNative(m_dwMarshalFlags))
80     {
81         // keep the object alive across the call-out to native
82         if (tokStruct__m_object != 0)
83         {
84             EmitLoadManagedHomeAddr(m_pcsUnmarshal);
85             m_pcsUnmarshal->EmitLDFLD(tokStruct__m_object);
86         }
87         else
88         {
89             EmitLoadManagedValue(m_pcsUnmarshal);
90         }
91         m_pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
92     }
93 }
94
95 void ILReflectionObjectMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
96 {
97     STANDARD_VM_CONTRACT;
98     
99     COMPlusThrow(kTypeLoadException, IDS_EE_COM_UNSUPPORTED_SIG);
100 }
101
102 LocalDesc ILDelegateMarshaler::GetNativeType()
103 {
104     LIMITED_METHOD_CONTRACT;
105     
106     return LocalDesc(ELEMENT_TYPE_I);
107 }
108
109 LocalDesc ILDelegateMarshaler::GetManagedType()
110 {
111     LIMITED_METHOD_CONTRACT;
112     
113     return LocalDesc(m_pargs->m_pMT);
114 }
115
116 void ILDelegateMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
117 {
118     STANDARD_VM_CONTRACT;
119            
120     ILCodeLabel* pNullLabel = pslILEmit->NewCodeLabel();
121
122     pslILEmit->EmitLoadNullPtr();
123     EmitStoreNativeValue(pslILEmit);
124
125     EmitLoadManagedValue(pslILEmit);
126     pslILEmit->EmitBRFALSE(pNullLabel);
127     
128     EmitLoadManagedValue(pslILEmit);
129     pslILEmit->EmitCALL(METHOD__MARSHAL__GET_FUNCTION_POINTER_FOR_DELEGATE, 1, 1);
130     EmitStoreNativeValue(pslILEmit);
131     
132     pslILEmit->EmitLabel(pNullLabel);
133
134     //
135     // @TODO: is there a better way to do this?
136     //
137     if (IsCLRToNative(m_dwMarshalFlags))
138     {
139         // keep the delegate ref alive across the call-out to native
140         EmitLoadManagedValue(m_pcsUnmarshal);
141         m_pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
142     }
143 }
144
145 void ILDelegateMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
146 {
147     STANDARD_VM_CONTRACT;
148     
149     ILCodeLabel* pNullLabel = pslILEmit->NewCodeLabel();
150
151     EmitLoadNativeValue(pslILEmit);
152     pslILEmit->EmitBRFALSE(pNullLabel);
153
154     EmitLoadNativeValue(pslILEmit);
155     pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->m_pMT));
156     pslILEmit->EmitCALL(METHOD__TYPE__GET_TYPE_FROM_HANDLE, 1, 1); // Type System.Type.GetTypeFromHandle(RuntimeTypeHandle handle)
157     pslILEmit->EmitCALL(METHOD__MARSHAL__GET_DELEGATE_FOR_FUNCTION_POINTER, 2, 1); // Delegate System.Marshal.GetDelegateForFunctionPointer(IntPtr p, Type t)
158     EmitStoreManagedValue(pslILEmit);
159
160     pslILEmit->EmitLabel(pNullLabel);
161 }
162
163
164 LocalDesc ILBoolMarshaler::GetNativeType()
165 {
166     LIMITED_METHOD_CONTRACT;
167     
168     return LocalDesc(GetNativeBoolElementType());
169 }
170
171 LocalDesc ILBoolMarshaler::GetManagedType()
172 {
173     LIMITED_METHOD_CONTRACT;
174     
175     return LocalDesc(ELEMENT_TYPE_BOOLEAN);
176 }
177
178 void ILBoolMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
179 {
180     STANDARD_VM_CONTRACT;
181
182     ILCodeLabel* pLoadFalseLabel = pslILEmit->NewCodeLabel();
183     ILCodeLabel* pDoneLabel = pslILEmit->NewCodeLabel();
184
185
186     int trueValue = GetNativeTrueValue();
187     int falseValue = GetNativeFalseValue();
188
189     EmitLoadManagedValue(pslILEmit);
190
191     if (falseValue == 0 && trueValue == 1)
192     {
193         // this can be done without jumps
194         pslILEmit->EmitLDC(0);
195         pslILEmit->EmitCEQ();
196         pslILEmit->EmitLDC(0);
197         pslILEmit->EmitCEQ();
198     }
199     else
200     {
201         pslILEmit->EmitBRFALSE(pLoadFalseLabel);
202         pslILEmit->EmitLDC(trueValue);
203         pslILEmit->EmitBR(pDoneLabel);
204 #ifdef _DEBUG
205         pslILEmit->EmitPOP();   // keep the simple stack level calculator happy 
206 #endif // _DEBUG
207         pslILEmit->EmitLabel(pLoadFalseLabel);
208         pslILEmit->EmitLDC(falseValue);
209         pslILEmit->EmitLabel(pDoneLabel);
210     }
211
212     EmitStoreNativeValue(pslILEmit);
213 }
214
215 void ILBoolMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
216 {
217     STANDARD_VM_CONTRACT;
218     
219     int falseValue = GetNativeFalseValue();
220
221     EmitLoadNativeValue(pslILEmit);
222
223     pslILEmit->EmitLDC(falseValue);
224     pslILEmit->EmitCEQ();
225     pslILEmit->EmitLDC(0);
226     pslILEmit->EmitCEQ();
227
228     EmitStoreManagedValue(pslILEmit);
229 }    
230
231
232 LocalDesc ILWSTRMarshaler::GetNativeType()
233 {
234     LIMITED_METHOD_CONTRACT;
235
236     //
237     // pointer to value class
238     //
239     return LocalDesc(ELEMENT_TYPE_I);
240 }
241
242 LocalDesc ILWSTRMarshaler::GetManagedType()
243 {
244     LIMITED_METHOD_CONTRACT;
245
246     //
247     // value class
248     //
249     return LocalDesc(ELEMENT_TYPE_STRING);
250 }
251
252 void ILWSTRMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
253 {
254     LIMITED_METHOD_CONTRACT;
255     UNREACHABLE_MSG("Should be in-only and all other paths are covered by the EmitConvertSpaceAndContents* paths");
256 }
257
258 void ILWSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
259 {
260     LIMITED_METHOD_CONTRACT;
261     UNREACHABLE_MSG("Should be in-only and all other paths are covered by the EmitConvertSpaceAndContents* paths");
262 }
263
264 void ILWSTRMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
265 {
266     LIMITED_METHOD_CONTRACT;
267     UNREACHABLE_MSG("Should be in-only and all other paths are covered by the EmitConvertSpaceAndContents* paths");
268 }    
269
270 void ILWSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
271 {
272     LIMITED_METHOD_CONTRACT;
273     UNREACHABLE_MSG("Should be in-only and all other paths are covered by the EmitConvertSpaceAndContents* paths");
274 }    
275
276 bool ILWSTRMarshaler::NeedsClearNative()
277 {
278     LIMITED_METHOD_CONTRACT;
279
280     // will evaluate to true iff there is something CoTaskMemAlloc'ed that we need to free
281     bool needsClear = (IsByref(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags)) || IsRetval(m_dwMarshalFlags);
282     
283     // m_fCoMemoryAllocated => needsClear
284     // (if we allocated the memory, we will free it; for byref [out] and retval we free memory allocated by the callee)
285     _ASSERTE(!m_fCoMemoryAllocated || needsClear);
286
287     return needsClear;
288 }
289
290 void ILWSTRMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
291 {
292     STANDARD_VM_CONTRACT;
293
294     EmitLoadNativeValue(pslILEmit);
295     // static void CoTaskMemFree(IntPtr ptr)
296     pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
297 }
298
299 void ILWSTRMarshaler::EmitClearNativeTemp(ILCodeStream* pslILEmit)
300 {
301     LIMITED_METHOD_CONTRACT;
302     UNREACHABLE_MSG("The string is either pinned or a copy is stack-allocated, NeedsClearNative should have returned false");
303 }
304
305 bool ILWSTRMarshaler::CanUsePinnedManagedString(DWORD dwMarshalFlags)
306 {
307     LIMITED_METHOD_CONTRACT;
308     return IsCLRToNative(dwMarshalFlags) && !IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && !IsOut(dwMarshalFlags);
309 }
310
311 //
312 // input stack:  0: managed string
313 // output stack: 0: (string_length+1) * sizeof(WCHAR)
314 //
315 void ILWSTRMarshaler::EmitCheckManagedStringLength(ILCodeStream* pslILEmit)
316 {
317     STANDARD_VM_CONTRACT;
318
319     pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
320     pslILEmit->EmitLDC(1);
321     pslILEmit->EmitADD();
322     pslILEmit->EmitDUP();
323     pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
324     pslILEmit->EmitDUP();
325     pslILEmit->EmitADD();           // (length+1) * sizeof(WCHAR)
326 }
327
328 void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit)
329 {
330     STANDARD_VM_CONTRACT;
331
332     INDEBUG(m_fCoMemoryAllocated = true);
333
334     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
335     DWORD dwLengthLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
336     
337     pslILEmit->EmitLoadNullPtr();
338     EmitStoreNativeValue(pslILEmit);
339     
340     EmitLoadManagedValue(pslILEmit);
341     pslILEmit->EmitBRFALSE(pNullRefLabel);
342     
343     EmitLoadManagedValue(pslILEmit);
344     EmitCheckManagedStringLength(pslILEmit);
345
346     // cb
347
348     pslILEmit->EmitDUP();
349     pslILEmit->EmitSTLOC(dwLengthLocalNum);
350
351     // cb
352
353     // static IntPtr AllocCoTaskMem(int cb)
354     pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
355     EmitStoreNativeValue(pslILEmit);
356
357     EmitLoadManagedValue(pslILEmit);
358     EmitLoadNativeValue(pslILEmit);
359
360     // src, dst
361
362     pslILEmit->EmitLDLOC(dwLengthLocalNum); // length
363     
364     // static void System.String.InternalCopy(String src, IntPtr dest,int len)
365     pslILEmit->EmitCALL(METHOD__STRING__INTERNAL_COPY, 3, 0);
366     pslILEmit->EmitLabel(pNullRefLabel);
367 }
368
369 void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
370 {
371     STANDARD_VM_CONTRACT;
372
373     if (CanUsePinnedManagedString(m_dwMarshalFlags))
374     {
375         LocalDesc locDesc = GetManagedType();
376         locDesc.MakePinned();
377         DWORD dwPinnedLocal = pslILEmit->NewLocal(locDesc);
378         int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__STRING__M_FIRST_CHAR));
379         ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
380         
381         pslILEmit->EmitLoadNullPtr();
382         EmitStoreNativeValue(pslILEmit);
383
384         EmitLoadManagedValue(pslILEmit);
385         pslILEmit->EmitBRFALSE(pNullRefLabel);
386
387         EmitLoadManagedValue(pslILEmit);
388         pslILEmit->EmitSTLOC(dwPinnedLocal);
389         pslILEmit->EmitLDLOC(dwPinnedLocal);
390         pslILEmit->EmitLDFLDA(fieldDef);
391         EmitStoreNativeValue(pslILEmit);
392
393         if (g_pConfig->InteropLogArguments())
394         {
395             m_pslNDirect->EmitLogNativeArgument(pslILEmit, dwPinnedLocal);
396         }
397
398         pslILEmit->EmitLabel(pNullRefLabel);
399
400     }
401     else
402     {
403         ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
404         DWORD dwLengthLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
405         
406         pslILEmit->EmitLoadNullPtr();
407         EmitStoreNativeValue(pslILEmit);
408         
409         EmitLoadManagedValue(pslILEmit);
410         pslILEmit->EmitBRFALSE(pNullRefLabel);
411         
412         EmitLoadManagedValue(pslILEmit);
413         EmitCheckManagedStringLength(pslILEmit);
414
415         // cb
416
417         pslILEmit->EmitDUP();
418         pslILEmit->EmitSTLOC(dwLengthLocalNum);
419
420         // cb
421
422         pslILEmit->EmitLOCALLOC();              // @TODO: add a non-localloc path for large strings
423         EmitStoreNativeValue(pslILEmit);
424
425         EmitLoadManagedValue(pslILEmit);
426         EmitLoadNativeValue(pslILEmit);
427
428         // src, dst
429
430         pslILEmit->EmitLDLOC(dwLengthLocalNum); // length
431         
432         // static void System.String.InternalCopy(String src, IntPtr dest,int len)
433         pslILEmit->EmitCALL(METHOD__STRING__INTERNAL_COPY, 3, 0);
434         pslILEmit->EmitLabel(pNullRefLabel);
435     }
436 }
437
438 //
439 // input stack:  0: native string
440 // output stack: 0: num chars, no null
441 //
442 void ILWSTRMarshaler::EmitCheckNativeStringLength(ILCodeStream* pslILEmit)
443 {
444     STANDARD_VM_CONTRACT;
445
446     pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
447     pslILEmit->EmitDUP();
448     pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
449 }
450
451 void ILWSTRMarshaler::EmitConvertSpaceAndContentsNativeToCLR(ILCodeStream* pslILEmit)
452 {
453     STANDARD_VM_CONTRACT;
454
455     ILCodeLabel* pIsNullLabelByref = pslILEmit->NewCodeLabel();
456         
457     EmitLoadNativeValue(pslILEmit);
458     pslILEmit->EmitBRFALSE(pIsNullLabelByref);
459
460     EmitLoadNativeValue(pslILEmit);
461     pslILEmit->EmitDUP();
462     EmitCheckNativeStringLength(pslILEmit);
463     pslILEmit->EmitPOP();       // pop num chars
464     
465     pslILEmit->EmitNEWOBJ(METHOD__STRING__CTOR_CHARPTR, 1);
466     EmitStoreManagedValue(pslILEmit);
467     
468     pslILEmit->EmitLabel(pIsNullLabelByref);
469 }
470
471
472 LocalDesc ILOptimizedAllocMarshaler::GetNativeType()
473 {
474     LIMITED_METHOD_CONTRACT;
475     return LocalDesc(ELEMENT_TYPE_I);
476 }
477
478 bool ILOptimizedAllocMarshaler::NeedsClearNative()
479 {
480     LIMITED_METHOD_CONTRACT;
481     return true;
482 }
483
484 void ILOptimizedAllocMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
485 {
486     STANDARD_VM_CONTRACT;
487
488     ILCodeLabel *pOptimize = NULL;
489
490     if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
491     {
492         pOptimize = pslILEmit->NewCodeLabel();
493         
494         // if (m_dwLocalBuffer) goto Optimize
495         pslILEmit->EmitLDLOC(m_dwLocalBuffer);
496         pslILEmit->EmitBRTRUE(pOptimize);
497     }
498
499     EmitLoadNativeValue(pslILEmit);
500     // static void m_idClearNative(IntPtr ptr)
501     pslILEmit->EmitCALL(m_idClearNative, 1, 0);
502
503     // Optimize:
504     if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
505     {        
506         pslILEmit->EmitLabel(pOptimize);
507     }
508 }
509
510 LocalDesc ILUTF8BufferMarshaler::GetManagedType()
511 {
512     STANDARD_VM_CONTRACT;
513     return LocalDesc(MscorlibBinder::GetClass(CLASS__STRING_BUILDER));
514 }
515
516 void ILUTF8BufferMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
517 {
518     STANDARD_VM_CONTRACT;
519
520     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
521
522     pslILEmit->EmitLoadNullPtr();
523     EmitStoreNativeValue(pslILEmit);
524
525     EmitLoadManagedValue(pslILEmit);
526     pslILEmit->EmitBRFALSE(pNullRefLabel);
527
528     EmitLoadManagedValue(pslILEmit);
529     // int System.Text.StringBuilder.get_Capacity()
530     pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_CAPACITY, 1, 1);
531     pslILEmit->EmitDUP();
532
533     // static void StubHelpers.CheckStringLength(int length)
534     pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
535
536     // Max number of bytes for UTF8 string in BMP plane is ( StringBuilder.Capacity + 1 ) * 3 + 1
537     // first +1 if the high surrogate is '?' and second +1 for null byte.
538
539     // stack: capacity_in_bytes
540     pslILEmit->EmitLDC(1);
541     pslILEmit->EmitADD();
542
543     // stack: capacity
544     pslILEmit->EmitLDC(3);
545     pslILEmit->EmitMUL();
546
547     // stack: offset_of_null
548     DWORD dwTmpOffsetOfSecretNull = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
549     pslILEmit->EmitDUP();
550     pslILEmit->EmitSTLOC(dwTmpOffsetOfSecretNull); // make sure the stack is empty for localloc
551
552     // make space for '\0'
553     pslILEmit->EmitLDC(1);
554     pslILEmit->EmitADD();
555
556     // stack: alloc_size_in_bytes
557     ILCodeLabel *pAllocRejoin = pslILEmit->NewCodeLabel();
558     if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
559     {
560         ILCodeLabel *pNoOptimize = pslILEmit->NewCodeLabel();
561         m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
562
563         // LocalBuffer = 0
564         pslILEmit->EmitLoadNullPtr();
565         pslILEmit->EmitSTLOC(m_dwLocalBuffer);
566
567         // if (alloc_size_in_bytes > MAX_LOCAL_BUFFER_LENGTH) goto NoOptimize
568         pslILEmit->EmitDUP();
569         pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
570         pslILEmit->EmitCGT_UN();
571         pslILEmit->EmitBRTRUE(pNoOptimize);
572
573         pslILEmit->EmitLOCALLOC();
574         pslILEmit->EmitDUP();
575         pslILEmit->EmitSTLOC(m_dwLocalBuffer);
576         pslILEmit->EmitBR(pAllocRejoin);
577
578         pslILEmit->EmitLabel(pNoOptimize);
579     }
580
581     // static IntPtr AllocCoTaskMem(int cb)
582     pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
583
584     pslILEmit->EmitLabel(pAllocRejoin);
585
586     // stack: native_addr
587
588     pslILEmit->EmitDUP();
589     EmitStoreNativeValue(pslILEmit);
590
591     pslILEmit->EmitLDLOC(dwTmpOffsetOfSecretNull);
592
593     // stack: native_addr offset_of_null
594     pslILEmit->EmitADD();
595
596     // stack: addr_of_null0    
597     pslILEmit->EmitLDC(0);
598     pslILEmit->EmitSTIND_I1();
599
600     pslILEmit->EmitLabel(pNullRefLabel);
601 }
602
603 void ILUTF8BufferMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
604 {
605     STANDARD_VM_CONTRACT;
606     DWORD dwUtf8MarshalFlags =
607         (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
608         (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
609
610     // setup to call UTF8BufferMarshaler.ConvertToNative
611     EmitLoadManagedValue(pslILEmit);
612     EmitLoadNativeValue(pslILEmit);
613     pslILEmit->EmitLDC(dwUtf8MarshalFlags);
614
615     //ConvertToNative(StringBuilder sb,IntPtr pNativeBuffer, int flags) 
616     pslILEmit->EmitCALL(METHOD__UTF8BUFFERMARSHALER__CONVERT_TO_NATIVE, 3, 1);
617     EmitStoreNativeValue(pslILEmit);
618 }
619
620 void ILUTF8BufferMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
621 {
622     STANDARD_VM_CONTRACT;
623
624     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
625
626     EmitLoadNativeValue(pslILEmit);
627     pslILEmit->EmitBRFALSE(pNullRefLabel);
628
629     if (IsIn(m_dwMarshalFlags) || IsCLRToNative(m_dwMarshalFlags))
630     {
631         EmitLoadNativeValue(pslILEmit);
632         // static int System.StubHelpers.StubHelpers.strlen(sbyte* ptr)
633         pslILEmit->EmitCALL(METHOD__STUBHELPERS__STRLEN, 1, 1);
634     }
635     else
636     {
637         // don't touch the native buffer in the native->CLR out-only case
638         pslILEmit->EmitLDC(0);
639     }
640     // Convert to UTF8 and then call 
641     // System.Text.StringBuilder..ctor(int capacity)
642     pslILEmit->EmitNEWOBJ(METHOD__STRING_BUILDER__CTOR_INT, 1);
643     EmitStoreManagedValue(pslILEmit);
644     pslILEmit->EmitLabel(pNullRefLabel);
645 }
646
647 void ILUTF8BufferMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
648 {
649     STANDARD_VM_CONTRACT;
650
651     EmitLoadManagedValue(pslILEmit);
652     EmitLoadNativeValue(pslILEmit);
653
654     //void UTF8BufferMarshaler.ConvertToManaged(StringBuilder sb, IntPtr pNative)
655     pslILEmit->EmitCALL(METHOD__UTF8BUFFERMARSHALER__CONVERT_TO_MANAGED, 2, 0);
656 }
657
658
659 LocalDesc ILWSTRBufferMarshaler::GetManagedType()
660 {
661     STANDARD_VM_CONTRACT;
662     
663     return LocalDesc(MscorlibBinder::GetClass(CLASS__STRING_BUILDER));
664 }
665
666 void ILWSTRBufferMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
667 {
668     STANDARD_VM_CONTRACT;
669
670     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
671
672     pslILEmit->EmitLoadNullPtr();
673     EmitStoreNativeValue(pslILEmit);
674
675     EmitLoadManagedValue(pslILEmit);
676     pslILEmit->EmitBRFALSE(pNullRefLabel);
677
678     EmitLoadManagedValue(pslILEmit);
679     // int System.Text.StringBuilder.get_Capacity()
680     pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_CAPACITY, 1, 1);
681     pslILEmit->EmitDUP();
682
683     // static void StubHelpers.CheckStringLength(int length)
684     pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
685
686     // stack: capacity
687
688     pslILEmit->EmitLDC(2);
689     pslILEmit->EmitMUL();
690
691     // stack: capacity_in_bytes
692
693     pslILEmit->EmitLDC(2);
694     pslILEmit->EmitADD();
695
696     // stack: offset_of_secret_null
697
698     DWORD dwTmpOffsetOfSecretNull = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
699     pslILEmit->EmitDUP();
700     pslILEmit->EmitSTLOC(dwTmpOffsetOfSecretNull); // make sure the stack is empty for localloc
701
702     pslILEmit->EmitLDC(2);
703     pslILEmit->EmitADD();
704
705     // stack: alloc_size_in_bytes
706     ILCodeLabel *pAllocRejoin = pslILEmit->NewCodeLabel(); 
707     if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
708     {
709         ILCodeLabel *pNoOptimize = pslILEmit->NewCodeLabel(); 
710         m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
711
712         // LocalBuffer = 0
713         pslILEmit->EmitLoadNullPtr();
714         pslILEmit->EmitSTLOC(m_dwLocalBuffer);
715
716         // if (alloc_size_in_bytes > MAX_LOCAL_BUFFER_LENGTH) goto NoOptimize
717         pslILEmit->EmitDUP();
718         pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
719         pslILEmit->EmitCGT_UN();
720         pslILEmit->EmitBRTRUE(pNoOptimize);
721
722         pslILEmit->EmitLOCALLOC();
723         pslILEmit->EmitDUP();
724         pslILEmit->EmitSTLOC(m_dwLocalBuffer);
725         pslILEmit->EmitBR(pAllocRejoin);
726
727         pslILEmit->EmitLabel(pNoOptimize);
728     }
729    
730     // static IntPtr AllocCoTaskMem(int cb)
731     pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
732
733     pslILEmit->EmitLabel(pAllocRejoin);
734
735     // stack: native_addr
736
737     pslILEmit->EmitDUP();
738     EmitStoreNativeValue(pslILEmit);
739
740     pslILEmit->EmitLDLOC(dwTmpOffsetOfSecretNull);
741
742     // stack: offset_of_secret_null  native_addr
743
744     pslILEmit->EmitADD();
745
746     // stack: addr_of_secret_null
747
748     pslILEmit->EmitLDC(0);
749
750     // stack: addr_of_secret_null  0
751
752     pslILEmit->EmitSTIND_I2();
753     pslILEmit->EmitLabel(pNullRefLabel);
754 }
755
756 void ILWSTRBufferMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
757 {
758     STANDARD_VM_CONTRACT;
759
760     DWORD dwTempNumBytesLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
761
762     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
763
764     EmitLoadNativeValue(pslILEmit);
765     pslILEmit->EmitBRFALSE(pNullRefLabel);
766
767     EmitLoadManagedValue(pslILEmit);
768     pslILEmit->EmitDUP();
769     
770     // stack: StringBuilder StringBuilder
771
772     // int System.Text.StringBuilder.get_Length()
773     pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_LENGTH, 1, 1);
774
775     // stack: StringBuilder length
776
777     // if (!fConvertSpaceJustCalled)
778     {
779         // we don't need to double-check the length because the length
780         // must be smaller than the capacity and the capacity was already
781         // checked by EmitConvertSpaceCLRToNative
782         
783         pslILEmit->EmitDUP();
784         // static void StubHelpers.CheckStringLength(int length)
785         pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
786     }
787
788     // stack: StringBuilder length 
789
790     pslILEmit->EmitDUP();
791     pslILEmit->EmitADD();
792
793     // stack: StringBuilder cb
794
795     pslILEmit->EmitSTLOC(dwTempNumBytesLocal);
796
797     // stack: StringBuilder
798
799     EmitLoadNativeValue(pslILEmit);
800     pslILEmit->EmitLDLOC(dwTempNumBytesLocal);
801
802     // stack: stringbuilder native_buffer cb
803
804     // void System.Text.StringBuilder.InternalCopy(IntPtr dest,int len)
805     pslILEmit->EmitCALL(METHOD__STRING_BUILDER__INTERNAL_COPY, 3, 0);
806
807     //
808     // null-terminate the native string
809     //
810     EmitLoadNativeValue(pslILEmit);
811     pslILEmit->EmitLDLOC(dwTempNumBytesLocal);
812     pslILEmit->EmitADD();
813     pslILEmit->EmitLDC(0);
814     pslILEmit->EmitSTIND_I2();
815
816     pslILEmit->EmitLabel(pNullRefLabel);
817 }
818
819 void ILWSTRBufferMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
820 {
821     STANDARD_VM_CONTRACT;
822
823     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
824
825     EmitLoadNativeValue(pslILEmit);
826     pslILEmit->EmitBRFALSE(pNullRefLabel);
827
828     if (IsIn(m_dwMarshalFlags) || IsCLRToNative(m_dwMarshalFlags))
829     {
830         EmitLoadNativeValue(pslILEmit);
831         // static int System.String.wcslen(char *ptr)
832         pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
833     }
834     else
835     {
836         // don't touch the native buffer in the native->CLR out-only case
837         pslILEmit->EmitLDC(0);
838     }
839
840     // System.Text.StringBuilder..ctor(int capacity)
841     pslILEmit->EmitNEWOBJ(METHOD__STRING_BUILDER__CTOR_INT, 1);
842     EmitStoreManagedValue(pslILEmit);
843
844     pslILEmit->EmitLabel(pNullRefLabel);
845 }
846
847 void ILWSTRBufferMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
848 {
849     STANDARD_VM_CONTRACT;
850
851     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
852
853     EmitLoadNativeValue(pslILEmit);
854     pslILEmit->EmitBRFALSE(pNullRefLabel);
855
856     EmitLoadManagedValue(pslILEmit);
857     EmitLoadNativeValue(pslILEmit);
858
859     pslILEmit->EmitDUP();
860     // static int System.String.wcslen(char *ptr)
861     pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
862     
863     // void System.Text.StringBuilder.ReplaceBuffer(char* newBuffer, int newLength);
864     pslILEmit->EmitCALL(METHOD__STRING_BUILDER__REPLACE_BUFFER_INTERNAL, 3, 0);
865     pslILEmit->EmitLabel(pNullRefLabel);
866 }        
867
868 LocalDesc ILCSTRBufferMarshaler::GetManagedType()
869 {
870     STANDARD_VM_CONTRACT;
871     
872     return LocalDesc(MscorlibBinder::GetClass(CLASS__STRING_BUILDER));
873 }
874
875 void ILCSTRBufferMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
876 {
877     STANDARD_VM_CONTRACT;
878
879     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
880
881     pslILEmit->EmitLoadNullPtr();
882     EmitStoreNativeValue(pslILEmit);
883
884     EmitLoadManagedValue(pslILEmit);
885     pslILEmit->EmitBRFALSE(pNullRefLabel);
886
887     EmitLoadManagedValue(pslILEmit);
888     // int System.Text.StringBuilder.get_Capacity()
889     pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_CAPACITY, 1, 1);
890     pslILEmit->EmitDUP();
891
892     // static void StubHelpers.CheckStringLength(int length)
893     pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
894
895     // stack: capacity
896
897     pslILEmit->EmitLDSFLD(pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__MARSHAL__SYSTEM_MAX_DBCS_CHAR_SIZE)));
898     pslILEmit->EmitMUL();
899
900     // stack: capacity_in_bytes
901
902     pslILEmit->EmitLDC(1);  
903     pslILEmit->EmitADD();
904
905     // stack: offset_of_secret_null
906
907     DWORD dwTmpOffsetOfSecretNull = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
908     pslILEmit->EmitDUP();
909     pslILEmit->EmitSTLOC(dwTmpOffsetOfSecretNull); // make sure the stack is empty for localloc
910
911     pslILEmit->EmitLDC(3);
912     pslILEmit->EmitADD();
913
914     // stack: alloc_size_in_bytes
915     ILCodeLabel *pAllocRejoin = pslILEmit->NewCodeLabel(); 
916     if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
917     {
918         ILCodeLabel *pNoOptimize = pslILEmit->NewCodeLabel(); 
919         m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
920
921         // LocalBuffer = 0
922         pslILEmit->EmitLoadNullPtr();
923         pslILEmit->EmitSTLOC(m_dwLocalBuffer);
924
925         // if (alloc_size_in_bytes > MAX_LOCAL_BUFFER_LENGTH) goto NoOptimize
926         pslILEmit->EmitDUP();
927         pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
928         pslILEmit->EmitCGT_UN();
929         pslILEmit->EmitBRTRUE(pNoOptimize);
930
931         pslILEmit->EmitLOCALLOC();
932         pslILEmit->EmitDUP();
933         pslILEmit->EmitSTLOC(m_dwLocalBuffer);
934         pslILEmit->EmitBR(pAllocRejoin);
935
936         pslILEmit->EmitLabel(pNoOptimize);
937     }
938
939     // static IntPtr AllocCoTaskMem(int cb)
940     pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
941
942     pslILEmit->EmitLabel(pAllocRejoin);
943
944     // stack: native_addr
945
946     pslILEmit->EmitDUP();
947     EmitStoreNativeValue(pslILEmit);
948
949     pslILEmit->EmitLDLOC(dwTmpOffsetOfSecretNull);
950
951     // stack: native_addr offset_of_secret_null
952
953     pslILEmit->EmitADD();
954
955     // stack: addr_of_secret_null0
956
957     pslILEmit->EmitDUP();
958     pslILEmit->EmitLDC(0);
959     pslILEmit->EmitSTIND_I1();
960
961     // stack: addr_of_secret_null0
962
963     pslILEmit->EmitDUP();
964     pslILEmit->EmitLDC(1);
965     pslILEmit->EmitADD();
966     pslILEmit->EmitLDC(0);
967     pslILEmit->EmitSTIND_I1();
968
969     // stack: addr_of_secret_null0
970
971     pslILEmit->EmitLDC(2);
972     pslILEmit->EmitADD();
973     pslILEmit->EmitLDC(0);
974     pslILEmit->EmitSTIND_I1();
975
976     pslILEmit->EmitLabel(pNullRefLabel);
977 }
978
979 void ILCSTRBufferMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
980 {
981     STANDARD_VM_CONTRACT;
982
983     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
984     DWORD dwNumBytesLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
985     DWORD dwSrcLocal = pslILEmit->NewLocal(ELEMENT_TYPE_OBJECT);
986
987     EmitLoadNativeValue(pslILEmit);
988     pslILEmit->EmitBRFALSE(pNullRefLabel);
989
990     EmitLoadManagedValue(pslILEmit);
991     // int System.Text.StringBuilder.get_Length()
992     pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_LENGTH, 1, 1);
993     // static void StubHelpers.CheckStringLength(int length)
994     pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
995
996     EmitLoadManagedValue(pslILEmit);
997     // String System.Text.StringBuilder.ToString()
998     pslILEmit->EmitCALL(METHOD__STRING_BUILDER__TO_STRING, 1, 1);
999     pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetBestFitMapping());
1000     pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar());
1001     pslILEmit->EmitLDLOCA(dwNumBytesLocalNum);
1002
1003     // static byte[] DoAnsiConversion(string str, bool fBestFit, bool fThrowOnUnmappableChar, out int cbLength)
1004     pslILEmit->EmitCALL(METHOD__ANSICHARMARSHALER__DO_ANSI_CONVERSION, 4, 1);
1005     pslILEmit->EmitSTLOC(dwSrcLocal);
1006     EmitLoadNativeValue(pslILEmit);             // pDest
1007     pslILEmit->EmitLDC(0);                      // destIndex
1008     pslILEmit->EmitLDLOC(dwSrcLocal);           // src[]
1009     pslILEmit->EmitLDC(0);                      // srcIndex
1010     pslILEmit->EmitLDLOC(dwNumBytesLocalNum);   // len
1011
1012     // static void Memcpy(byte* pDest, int destIndex, byte[] src, int srcIndex, int len)
1013     pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY_PTRBYTE_ARRBYTE, 5, 0);
1014
1015     // null terminate the string
1016     EmitLoadNativeValue(pslILEmit);
1017     pslILEmit->EmitLDLOC(dwNumBytesLocalNum);
1018     pslILEmit->EmitADD();
1019     pslILEmit->EmitLDC(0);
1020     pslILEmit->EmitSTIND_I1();
1021
1022     pslILEmit->EmitLabel(pNullRefLabel);
1023 }
1024
1025 void ILCSTRBufferMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
1026 {
1027     STANDARD_VM_CONTRACT;
1028
1029     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1030
1031     EmitLoadNativeValue(pslILEmit);
1032     pslILEmit->EmitBRFALSE(pNullRefLabel);
1033
1034     if (IsIn(m_dwMarshalFlags) || IsCLRToNative(m_dwMarshalFlags))
1035     {
1036         EmitLoadNativeValue(pslILEmit);
1037         // static int System.StubHelpers.StubHelpers.strlen(sbyte* ptr)
1038         pslILEmit->EmitCALL(METHOD__STUBHELPERS__STRLEN, 1, 1);
1039     }
1040     else
1041     {
1042         // don't touch the native buffer in the native->CLR out-only case
1043         pslILEmit->EmitLDC(0);
1044     }
1045
1046     // System.Text.StringBuilder..ctor(int capacity)
1047     pslILEmit->EmitNEWOBJ(METHOD__STRING_BUILDER__CTOR_INT, 1);
1048     EmitStoreManagedValue(pslILEmit);
1049
1050     pslILEmit->EmitLabel(pNullRefLabel);
1051 }
1052
1053 void ILCSTRBufferMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1054 {
1055     STANDARD_VM_CONTRACT;
1056     
1057     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1058
1059     EmitLoadNativeValue(pslILEmit);
1060     pslILEmit->EmitBRFALSE(pNullRefLabel);
1061
1062     EmitLoadManagedValue(pslILEmit);
1063     EmitLoadNativeValue(pslILEmit);
1064
1065     pslILEmit->EmitDUP();
1066     // static int System.StubHelpers.StubHelpers.strlen(sbyte* ptr)
1067     pslILEmit->EmitCALL(METHOD__STUBHELPERS__STRLEN, 1, 1);
1068     
1069     // void System.Text.StringBuilder.ReplaceBuffer(sbyte* newBuffer, int newLength);
1070     pslILEmit->EmitCALL(METHOD__STRING_BUILDER__REPLACE_BUFFER_ANSI_INTERNAL, 3, 0);
1071
1072     pslILEmit->EmitLabel(pNullRefLabel);
1073 }        
1074
1075
1076
1077 LocalDesc ILValueClassMarshaler::GetNativeType()
1078 {
1079     STANDARD_VM_CONTRACT;
1080
1081     return LocalDesc(TypeHandle(m_pargs->m_pMT).MakeNativeValueType());
1082 }
1083
1084 LocalDesc ILValueClassMarshaler::GetManagedType()
1085 {
1086     LIMITED_METHOD_CONTRACT;
1087     
1088     return LocalDesc(m_pargs->m_pMT);
1089 }
1090
1091 void ILValueClassMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1092 {
1093     STANDARD_VM_CONTRACT;
1094     
1095     EmitLoadNativeHomeAddr(pslILEmit);
1096     pslILEmit->EmitINITOBJ(pslILEmit->GetToken(TypeHandle(m_pargs->m_pMT).MakeNativeValueType()));
1097 }
1098
1099 bool ILValueClassMarshaler::NeedsClearNative()
1100 {
1101     return true;
1102 }
1103
1104 void ILValueClassMarshaler::EmitClearNative(ILCodeStream * pslILEmit)
1105 {
1106     STANDARD_VM_CONTRACT;
1107
1108     mdToken     managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
1109     
1110     EmitLoadNativeHomeAddr(pslILEmit);
1111     pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
1112     pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1113     pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CLEAR_NATIVE, 2, 0);
1114 }
1115
1116
1117 void ILValueClassMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1118 {
1119     STANDARD_VM_CONTRACT;
1120
1121     mdToken     managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
1122
1123     EmitLoadNativeHomeAddr(pslILEmit);      // dst
1124     EmitLoadManagedHomeAddr(pslILEmit);     // src
1125     pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
1126     pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1); // Convert RTH to IntPtr
1127
1128     m_pslNDirect->LoadCleanupWorkList(pslILEmit);
1129     pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CONVERT_TO_NATIVE, 4, 0);        // void ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, ref CleanupWorkListElement pCleanupWorkList)
1130 }
1131
1132 void ILValueClassMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1133 {
1134     STANDARD_VM_CONTRACT;
1135
1136     mdToken     managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
1137
1138     EmitLoadManagedHomeAddr(pslILEmit);     // dst
1139     EmitLoadNativeHomeAddr(pslILEmit);      // src
1140     pslILEmit->EmitLDTOKEN(managedVCToken);                                 // pMT
1141     pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1142     pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CONVERT_TO_MANAGED, 3, 0);   // void ConvertToManaged(IntPtr dst, IntPtr src, IntPtr pMT)
1143 }
1144
1145
1146 #ifdef FEATURE_COMINTEROP
1147 LocalDesc ILObjectMarshaler::GetNativeType()
1148 {
1149     STANDARD_VM_CONTRACT;
1150
1151     return LocalDesc(TypeHandle(MscorlibBinder::GetClass(CLASS__NATIVEVARIANT)));
1152 }
1153
1154 LocalDesc ILObjectMarshaler::GetManagedType()
1155 {
1156     LIMITED_METHOD_CONTRACT;
1157     
1158     return LocalDesc(ELEMENT_TYPE_OBJECT);
1159 }
1160
1161 void ILObjectMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1162 {
1163     STANDARD_VM_CONTRACT;
1164
1165     if (!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
1166     {
1167         // Keep the VARIANT as it is - the stubhelper will do a VT_BYREF check on it.
1168     }
1169     else
1170     {
1171         // V_VT(pDest) = VT_EMPTY
1172         EmitReInitNative(pslILEmit);
1173     }
1174
1175     EmitLoadManagedValue(pslILEmit);                        // load src
1176     EmitLoadNativeHomeAddr(pslILEmit);                      // load dst
1177     pslILEmit->EmitCALL(METHOD__OBJECTMARSHALER__CONVERT_TO_NATIVE, 2, 0); // void ConvertToNative(object objSrc, IntPtr pDstVariant)
1178 }
1179
1180 void ILObjectMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1181 {
1182     STANDARD_VM_CONTRACT;
1183
1184     EmitLoadNativeHomeAddr(pslILEmit);
1185     pslILEmit->EmitCALL(METHOD__OBJECTMARSHALER__CONVERT_TO_MANAGED, 1, 1);  // object ConvertToManaged(IntPtr pSrcVariant);
1186     EmitStoreManagedValue(pslILEmit);
1187 }    
1188
1189 bool ILObjectMarshaler::NeedsClearNative()
1190 {
1191     LIMITED_METHOD_CONTRACT;
1192     return true;
1193 }
1194
1195 void ILObjectMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1196 {
1197     STANDARD_VM_CONTRACT;
1198     
1199     if (!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
1200     {
1201         // We don't want to clear variants passed from native by-ref here as we
1202         // want to be able to detect the VT_BYREF case during backpropagation.
1203
1204         // @TODO: We shouldn't be skipping the call if pslILEmit is ILStubLinker::kExceptionCleanup
1205         // because we always want to do real cleanup in this stream.
1206     }
1207     else
1208     {
1209         EmitLoadNativeHomeAddr(pslILEmit);
1210         pslILEmit->EmitCALL(METHOD__OBJECTMARSHALER__CLEAR_NATIVE, 1, 0);
1211     }
1212 }
1213
1214 void ILObjectMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1215 {
1216     CONTRACTL
1217     {
1218         STANDARD_VM_CHECK;
1219         CONSISTENCY_CHECK(offsetof(VARIANT, vt) == 0);
1220     }
1221     CONTRACTL_END;
1222
1223     if (!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
1224     {
1225         // We don't want to clear variants passed from native by-ref here as we
1226         // want to be able to detect the VT_BYREF case during backpropagation.
1227     }
1228     else
1229     {
1230         EmitLoadNativeHomeAddr(pslILEmit);
1231         pslILEmit->EmitLDC(VT_EMPTY);
1232         pslILEmit->EmitSTIND_I2();
1233     }
1234 }
1235 #endif // FEATURE_COMINTEROP
1236
1237 LocalDesc ILDateMarshaler::GetNativeType()
1238 {
1239     LIMITED_METHOD_CONTRACT;
1240
1241     return LocalDesc(ELEMENT_TYPE_R8);
1242 }
1243
1244 LocalDesc ILDateMarshaler::GetManagedType()
1245 {
1246     STANDARD_VM_CONTRACT;
1247     
1248     return LocalDesc(MscorlibBinder::GetClass(CLASS__DATE_TIME));
1249 }
1250
1251 void ILDateMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1252 {
1253     STANDARD_VM_CONTRACT;
1254
1255     EmitLoadManagedValue(pslILEmit);
1256     // double ConvertToNative(INT64 managedDate)
1257     pslILEmit->EmitCALL(METHOD__DATEMARSHALER__CONVERT_TO_NATIVE, 1, 1); 
1258     EmitStoreNativeValue(pslILEmit);
1259 }
1260
1261 void ILDateMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1262 {
1263     STANDARD_VM_CONTRACT;
1264
1265     // will call DateTime constructor on managed home
1266     EmitLoadManagedHomeAddr(pslILEmit);
1267
1268     EmitLoadNativeValue(pslILEmit);
1269     // long ConvertToNative(double nativeData)
1270     pslILEmit->EmitCALL(METHOD__DATEMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1271     
1272     pslILEmit->EmitCALL(METHOD__DATE_TIME__LONG_CTOR, 2, 0);
1273 }
1274
1275 void ILDateMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1276 {
1277     STANDARD_VM_CONTRACT;
1278
1279     // ldc.i4.0, conv.r8 is shorter than ldc.r8 0.0
1280     pslILEmit->EmitLDC(0);
1281     pslILEmit->EmitCONV_R8();
1282     EmitStoreNativeValue(pslILEmit);
1283 }
1284
1285 LocalDesc ILCurrencyMarshaler::GetNativeType()
1286 {
1287     STANDARD_VM_CONTRACT;
1288
1289     return LocalDesc(TypeHandle(MscorlibBinder::GetClass(CLASS__CURRENCY)));
1290 }
1291
1292 LocalDesc ILCurrencyMarshaler::GetManagedType()
1293 {
1294     STANDARD_VM_CONTRACT;
1295     
1296     return LocalDesc(TypeHandle(MscorlibBinder::GetClass(CLASS__DECIMAL)));
1297 }
1298
1299
1300 void ILCurrencyMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1301 {
1302     STANDARD_VM_CONTRACT;
1303
1304     EmitLoadNativeHomeAddr(pslILEmit);
1305     pslILEmit->EmitINITOBJ(pslILEmit->GetToken(TypeHandle(MscorlibBinder::GetClass(CLASS__CURRENCY))));
1306 }
1307
1308 void ILCurrencyMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1309 {
1310     STANDARD_VM_CONTRACT;
1311
1312     EmitLoadNativeHomeAddr(pslILEmit);
1313     EmitLoadManagedValue(pslILEmit);
1314
1315     pslILEmit->EmitCALL(METHOD__CURRENCY__DECIMAL_CTOR, 2, 0);
1316 }
1317
1318 void ILCurrencyMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1319 {
1320     STANDARD_VM_CONTRACT;
1321
1322     EmitLoadManagedHomeAddr(pslILEmit);
1323     EmitLoadNativeValue(pslILEmit);
1324
1325     pslILEmit->EmitCALL(METHOD__DECIMAL__CURRENCY_CTOR, 2, 0);
1326 }    
1327
1328
1329 #ifdef FEATURE_COMINTEROP
1330 LocalDesc ILInterfaceMarshaler::GetNativeType()
1331 {
1332     LIMITED_METHOD_CONTRACT;
1333
1334     return LocalDesc(ELEMENT_TYPE_I);
1335 }
1336
1337 LocalDesc ILInterfaceMarshaler::GetManagedType()
1338 {
1339     LIMITED_METHOD_CONTRACT;
1340     
1341     return LocalDesc(ELEMENT_TYPE_OBJECT);
1342 }
1343
1344 void ILInterfaceMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1345 {
1346     STANDARD_VM_CONTRACT;
1347
1348     ItfMarshalInfo itfInfo;
1349     m_pargs->m_pMarshalInfo->GetItfMarshalInfo(&itfInfo);
1350
1351     EmitLoadManagedValue(pslILEmit);
1352     
1353     if (itfInfo.thNativeItf.GetMethodTable())
1354     {
1355         pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thNativeItf.GetMethodTable()));
1356         pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1357     }
1358     else
1359     {
1360         pslILEmit->EmitLoadNullPtr();
1361     }
1362     
1363     if (itfInfo.thClass.GetMethodTable())
1364     {
1365         pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thClass.GetMethodTable()));
1366         pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1367     }
1368     else
1369     {
1370         pslILEmit->EmitLoadNullPtr();
1371     }
1372     pslILEmit->EmitLDC(itfInfo.dwFlags);
1373
1374     // static IntPtr ConvertToNative(object objSrc, IntPtr itfMT, IntPtr classMT, int flags);
1375     pslILEmit->EmitCALL(METHOD__INTERFACEMARSHALER__CONVERT_TO_NATIVE, 4, 1);
1376
1377     EmitStoreNativeValue(pslILEmit);
1378
1379     if (IsCLRToNative(m_dwMarshalFlags) && 
1380         m_pargs->m_pMarshalInfo->IsWinRTScenario())
1381     {    
1382         // If we are calling from CLR into WinRT and we are passing an interface to WinRT, we need to
1383         // keep the object alive across unmanaged call because Jupiter might need to add this
1384         // RCW into their live tree and whatever CCWs referenced by this RCW could get collected
1385         // before the call to native, for example:
1386         //
1387         // Button btn = new Button();
1388         // btn.OnClick += ...
1389         // m_grid.Children.Add(btn)
1390         //
1391         // In this case, btn could be collected and takes the delegate CCW with it, before Children.add 
1392         // native method is called, and as a result Jupiter will add the neutered CCW into the tree
1393         //
1394         // The fix is to extend the lifetime of the argument across the call to native by doing a GC.KeepAlive
1395         // keep the delegate ref alive across the call-out to native
1396         EmitLoadManagedValue(m_pcsUnmarshal);
1397         m_pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
1398     }
1399 }
1400
1401 void ILInterfaceMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1402 {
1403     STANDARD_VM_CONTRACT;
1404
1405     ItfMarshalInfo itfInfo;
1406     m_pargs->m_pMarshalInfo->GetItfMarshalInfo(&itfInfo);
1407
1408     // the helper may assign NULL to the home (see below)
1409     EmitLoadNativeHomeAddr(pslILEmit);
1410     
1411     if (IsCLRToNative(m_dwMarshalFlags) && m_pargs->m_pMarshalInfo->IsWinRTScenario())
1412     {
1413         // We are converting an interface pointer to object in a CLR->native stub which means
1414         // that the interface pointer has been AddRef'ed for us by the callee. If we end up
1415         // wrapping it with a new RCW, we can omit another AddRef/Release pair. Note that if
1416         // a new RCW is created the native home will be zeroed out by the helper so the call
1417         // to InterfaceMarshaler__ClearNative will become a no-op.
1418
1419         // Note that we are only doing this for WinRT scenarios to reduce the risk of this change
1420         itfInfo.dwFlags |= ItfMarshalInfo::ITF_MARSHAL_SUPPRESS_ADDREF;
1421     }
1422
1423     if (itfInfo.thItf.GetMethodTable())
1424     {
1425         pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thItf.GetMethodTable()));
1426         pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1427     }
1428     else
1429     {
1430         pslILEmit->EmitLoadNullPtr();
1431     }
1432     
1433     if (itfInfo.thClass.GetMethodTable())
1434     {
1435         pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thClass.GetMethodTable()));
1436         pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1437     }
1438     else
1439     {
1440         pslILEmit->EmitLoadNullPtr();
1441     }
1442     pslILEmit->EmitLDC(itfInfo.dwFlags);
1443     
1444     // static object ConvertToManaged(IntPtr pUnk, IntPtr itfMT, IntPtr classMT, int flags);
1445     pslILEmit->EmitCALL(METHOD__INTERFACEMARSHALER__CONVERT_TO_MANAGED, 4, 1);
1446     
1447     EmitStoreManagedValue(pslILEmit);
1448 }    
1449
1450 bool ILInterfaceMarshaler::NeedsClearNative()
1451 {
1452     LIMITED_METHOD_CONTRACT;
1453     return true;
1454 }
1455
1456 void ILMarshaler::EmitInterfaceClearNative(ILCodeStream* pslILEmit)
1457 {
1458     STANDARD_VM_CONTRACT;
1459
1460     ILCodeLabel *pSkipClearNativeLabel = pslILEmit->NewCodeLabel();
1461     EmitLoadNativeValue(pslILEmit);
1462     pslILEmit->EmitBRFALSE(pSkipClearNativeLabel);
1463     EmitLoadNativeValue(pslILEmit);
1464     // static void ClearNative(IntPtr pUnk);
1465     pslILEmit->EmitCALL(METHOD__INTERFACEMARSHALER__CLEAR_NATIVE, 1, 0);
1466     pslILEmit->EmitLabel(pSkipClearNativeLabel);
1467 }
1468
1469 void ILInterfaceMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1470 {
1471     STANDARD_VM_CONTRACT;
1472     EmitInterfaceClearNative(pslILEmit);
1473 }
1474 #endif // FEATURE_COMINTEROP
1475
1476
1477 LocalDesc ILAnsiCharMarshaler::GetNativeType()
1478 {
1479     LIMITED_METHOD_CONTRACT;
1480
1481     return LocalDesc(ELEMENT_TYPE_U1);
1482 }
1483
1484 LocalDesc ILAnsiCharMarshaler::GetManagedType()
1485 {
1486     LIMITED_METHOD_CONTRACT;
1487     
1488     return LocalDesc(ELEMENT_TYPE_CHAR);
1489 }
1490
1491 void ILAnsiCharMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1492 {
1493     STANDARD_VM_CONTRACT;
1494
1495     EmitLoadManagedValue(pslILEmit);
1496     pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetBestFitMapping());
1497     pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar());
1498     pslILEmit->EmitCALL(METHOD__ANSICHARMARSHALER__CONVERT_TO_NATIVE, 3, 1);
1499     EmitStoreNativeValue(pslILEmit);
1500 }
1501
1502 void ILAnsiCharMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1503 {
1504     STANDARD_VM_CONTRACT;
1505
1506     EmitLoadNativeValue(pslILEmit);
1507     pslILEmit->EmitCALL(METHOD__ANSICHARMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1508     EmitStoreManagedValue(pslILEmit);
1509 }    
1510
1511 #ifdef FEATURE_COMINTEROP
1512 LocalDesc ILOleColorMarshaler::GetNativeType()
1513 {
1514     LIMITED_METHOD_CONTRACT;
1515
1516     return LocalDesc(ELEMENT_TYPE_I4);
1517 }
1518
1519 LocalDesc ILOleColorMarshaler::GetManagedType()
1520 {
1521     STANDARD_VM_CONTRACT;
1522
1523     BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
1524     TypeHandle  hndColorType = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetColorType();
1525
1526     //
1527     // value class
1528     //
1529     return LocalDesc(hndColorType); // System.Drawing.Color
1530 }
1531
1532 void ILOleColorMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1533 {
1534     STANDARD_VM_CONTRACT;
1535
1536     BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
1537     MethodDesc* pConvertMD = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetSystemColorToOleColorMD();
1538
1539     EmitLoadManagedValue(pslILEmit);
1540     // int System.Drawing.ColorTranslator.ToOle(System.Drawing.Color c)
1541     pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
1542     EmitStoreNativeValue(pslILEmit);
1543 }
1544
1545 void ILOleColorMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1546 {
1547     STANDARD_VM_CONTRACT;
1548
1549     BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
1550     MethodDesc* pConvertMD = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetOleColorToSystemColorMD();
1551
1552     EmitLoadNativeValue(pslILEmit);
1553     // System.Drawing.Color System.Drawing.ColorTranslator.FromOle(int oleColor)
1554     pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
1555     EmitStoreManagedValue(pslILEmit);
1556 }    
1557
1558 bool ILVBByValStrWMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1559 {
1560     LIMITED_METHOD_CONTRACT;
1561     if (IsCLRToNative(dwMarshalFlags) && IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && IsOut(dwMarshalFlags))
1562     {
1563         return true;
1564     }
1565     
1566     *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1567     return false;
1568 }
1569
1570 bool ILVBByValStrWMarshaler::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1571 {
1572     LIMITED_METHOD_CONTRACT;
1573     *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1574     return false;
1575 }
1576
1577 LocalDesc ILVBByValStrWMarshaler::GetNativeType()
1578 {
1579     LIMITED_METHOD_CONTRACT;
1580     
1581     return LocalDesc(ELEMENT_TYPE_I); // BSTR
1582 }
1583
1584 LocalDesc ILVBByValStrWMarshaler::GetManagedType()
1585 {
1586     LIMITED_METHOD_CONTRACT;
1587     
1588     return LocalDesc(ELEMENT_TYPE_STRING);
1589 }
1590
1591 bool ILVBByValStrWMarshaler::IsNativePassedByRef()
1592 {
1593     LIMITED_METHOD_CONTRACT;
1594     return false;
1595 }
1596
1597 void ILVBByValStrWMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1598 {
1599     STANDARD_VM_CONTRACT;
1600
1601     ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
1602     m_dwLocalBuffer = pcsSetup->NewLocal(ELEMENT_TYPE_I);
1603     pcsSetup->EmitLoadNullPtr();
1604     pcsSetup->EmitSTLOC(m_dwLocalBuffer);
1605
1606
1607     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1608     m_dwCCHLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1609     DWORD dwNumBytesLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1610
1611     pslILEmit->EmitLoadNullPtr();
1612     EmitStoreNativeValue(pslILEmit);
1613     
1614     EmitLoadManagedValue(pslILEmit);
1615     pslILEmit->EmitBRFALSE(pNullRefLabel);
1616
1617     EmitLoadManagedValue(pslILEmit);
1618     pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
1619     pslILEmit->EmitDUP();
1620     pslILEmit->EmitSTLOC(m_dwCCHLocal);
1621
1622     // cch
1623     
1624     pslILEmit->EmitLDC(1);
1625     pslILEmit->EmitADD();
1626     pslILEmit->EmitDUP();
1627     pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
1628     pslILEmit->EmitDUP();
1629     pslILEmit->EmitADD();           // (length+1) * sizeof(WCHAR)
1630     pslILEmit->EmitDUP();
1631     pslILEmit->EmitSTLOC(dwNumBytesLocal);      // len <- doesn't include size of the DWORD preceeding the string
1632     pslILEmit->EmitLDC(sizeof(DWORD));
1633     pslILEmit->EmitADD();           // (length+1) * sizeof(WCHAR) + sizeof(DWORD)
1634
1635     // cb
1636
1637     ILCodeLabel* pNoOptimizeLabel = pslILEmit->NewCodeLabel();
1638     ILCodeLabel* pAllocRejoinLabel = pslILEmit->NewCodeLabel();
1639     pslILEmit->EmitDUP();
1640     pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
1641     pslILEmit->EmitCGT_UN();
1642     pslILEmit->EmitBRTRUE(pNoOptimizeLabel);
1643
1644     pslILEmit->EmitLOCALLOC();
1645     pslILEmit->EmitBR(pAllocRejoinLabel);
1646
1647     pslILEmit->EmitLabel(pNoOptimizeLabel);
1648     pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
1649     pslILEmit->EmitDUP();
1650     pslILEmit->EmitSTLOC(m_dwLocalBuffer);
1651
1652     pslILEmit->EmitLabel(pAllocRejoinLabel);
1653     pslILEmit->EmitDUP();
1654     pslILEmit->EmitLDLOC(m_dwCCHLocal);
1655     pslILEmit->EmitSTIND_I4();
1656     pslILEmit->EmitLDC(sizeof(DWORD));
1657     pslILEmit->EmitADD();
1658     EmitStoreNativeValue(pslILEmit);
1659
1660     // <emtpy>
1661
1662     EmitLoadManagedValue(pslILEmit);        // src
1663     EmitLoadNativeValue(pslILEmit);         // dest
1664     pslILEmit->EmitLDLOC(dwNumBytesLocal);  // len
1665
1666     // static void System.String.InternalCopy(String src, IntPtr dest,int len)
1667     pslILEmit->EmitCALL(METHOD__STRING__INTERNAL_COPY, 3, 0);
1668
1669     pslILEmit->EmitLabel(pNullRefLabel);
1670 }
1671
1672 void ILVBByValStrWMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1673 {
1674     STANDARD_VM_CONTRACT;
1675
1676     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1677     EmitLoadNativeValue(pslILEmit);
1678     pslILEmit->EmitBRFALSE(pNullRefLabel);
1679
1680     pslILEmit->EmitLDNULL();            // this
1681     EmitLoadNativeValue(pslILEmit);     // ptr
1682     pslILEmit->EmitLDC(0);              // startIndex
1683     pslILEmit->EmitLDLOC(m_dwCCHLocal); // length
1684
1685     // String CtorCharPtrStartLength(char *ptr, int startIndex, int length)
1686     // TODO Phase5: Why do we call this weirdo?
1687     pslILEmit->EmitCALL(METHOD__STRING__CTORF_CHARPTR_START_LEN, 4, 1);
1688
1689     EmitStoreManagedValue(pslILEmit);
1690     pslILEmit->EmitLabel(pNullRefLabel);
1691 }
1692
1693
1694 bool ILVBByValStrWMarshaler::NeedsClearNative()
1695 {
1696     LIMITED_METHOD_CONTRACT;
1697     return true;
1698 }
1699
1700 void ILVBByValStrWMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1701 {                
1702     STANDARD_VM_CONTRACT;
1703
1704     ILCodeLabel* pExitLabel = pslILEmit->NewCodeLabel();
1705     pslILEmit->EmitLDLOC(m_dwLocalBuffer);
1706     pslILEmit->EmitBRFALSE(pExitLabel);
1707     pslILEmit->EmitLDLOC(m_dwLocalBuffer);
1708     pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
1709     pslILEmit->EmitLabel(pExitLabel);
1710 }
1711
1712
1713 bool ILVBByValStrMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1714 {
1715     if (IsCLRToNative(dwMarshalFlags) && IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && IsOut(dwMarshalFlags))
1716     {
1717         return true;
1718     }
1719     
1720     *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1721     return false;
1722 }
1723
1724 bool ILVBByValStrMarshaler::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1725 {
1726     *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1727     return false;
1728 }
1729
1730 LocalDesc ILVBByValStrMarshaler::GetNativeType()
1731 {
1732     LIMITED_METHOD_CONTRACT;
1733     
1734     return LocalDesc(ELEMENT_TYPE_I); // BSTR
1735 }
1736
1737 LocalDesc ILVBByValStrMarshaler::GetManagedType()
1738 {
1739     LIMITED_METHOD_CONTRACT;
1740     
1741     return LocalDesc(ELEMENT_TYPE_STRING);
1742 }
1743
1744 bool ILVBByValStrMarshaler::IsNativePassedByRef()
1745 {
1746     LIMITED_METHOD_CONTRACT;
1747     return false;
1748 }
1749
1750 void ILVBByValStrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1751 {
1752     STANDARD_VM_CONTRACT;
1753
1754     m_dwCCHLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1755
1756     EmitLoadManagedValue(pslILEmit);
1757     pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetBestFitMapping());
1758     pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar());
1759     pslILEmit->EmitLDLOCA(m_dwCCHLocal);
1760
1761     // static IntPtr ConvertToNative(string strManaged, bool fBestFit, bool fThrowOnUnmappableChar, ref int cch)
1762     pslILEmit->EmitCALL(METHOD__VBBYVALSTRMARSHALER__CONVERT_TO_NATIVE, 4, 1);
1763
1764     EmitStoreNativeValue(pslILEmit);
1765 }
1766
1767 void ILVBByValStrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1768 {
1769     STANDARD_VM_CONTRACT;
1770
1771     EmitLoadNativeValue(pslILEmit);     // pNative
1772     pslILEmit->EmitLDLOC(m_dwCCHLocal); // cch
1773
1774     // static string ConvertToManaged(IntPtr pNative, int cch)
1775     pslILEmit->EmitCALL(METHOD__VBBYVALSTRMARSHALER__CONVERT_TO_MANAGED, 2, 1);
1776
1777     EmitStoreManagedValue(pslILEmit);
1778 }
1779
1780 bool ILVBByValStrMarshaler::NeedsClearNative()
1781 {
1782     LIMITED_METHOD_CONTRACT;
1783     return true;
1784 }
1785
1786 void ILVBByValStrMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1787 {
1788     STANDARD_VM_CONTRACT;
1789
1790     EmitLoadNativeValue(pslILEmit);     // pNative
1791
1792     // static void ClearNative(IntPtr pNative);
1793     pslILEmit->EmitCALL(METHOD__VBBYVALSTRMARSHALER__CLEAR_NATIVE, 1, 0);
1794 }
1795 #endif // FEATURE_COMINTEROP
1796
1797 LocalDesc ILBSTRMarshaler::GetManagedType()
1798 {
1799     LIMITED_METHOD_CONTRACT;
1800     
1801     return LocalDesc(ELEMENT_TYPE_STRING);
1802 }
1803
1804 void ILBSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1805 {
1806     STANDARD_VM_CONTRACT;
1807     
1808     ILCodeLabel* pRejoinLabel = pslILEmit->NewCodeLabel();
1809
1810     EmitLoadManagedValue(pslILEmit);
1811     
1812     if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
1813     {
1814         ILCodeLabel *pNoOptimizeLabel = pslILEmit->NewCodeLabel(); 
1815         m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
1816
1817         // LocalBuffer = 0
1818         pslILEmit->EmitLoadNullPtr();
1819         pslILEmit->EmitSTLOC(m_dwLocalBuffer);
1820
1821         pslILEmit->EmitDUP();
1822         pslILEmit->EmitBRFALSE(pNoOptimizeLabel);
1823
1824         // String.Length
1825         pslILEmit->EmitDUP();
1826         pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
1827
1828         // if (length > (MAX_LOCAL_BUFFER_LENGTH - 6) / 2) goto NoOptimize
1829         pslILEmit->EmitLDC((MAX_LOCAL_BUFFER_LENGTH - 6) / 2); // number of Unicode characters - terminator - length dword
1830         pslILEmit->EmitCGT_UN();
1831         pslILEmit->EmitBRTRUE(pNoOptimizeLabel);
1832
1833         // LocalBuffer = localloc[(String.Length * 2) + 6]
1834         pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
1835         pslILEmit->EmitLDC(2);
1836         pslILEmit->EmitMUL();
1837         pslILEmit->EmitLDC(7); // + length (4B) + terminator (2B) + possible trailing byte (1B)
1838         pslILEmit->EmitADD();
1839
1840 #ifdef _DEBUG
1841         // Save the buffer length
1842         DWORD dwTmpAllocSize = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1843         pslILEmit->EmitDUP();
1844         pslILEmit->EmitSTLOC(dwTmpAllocSize);
1845 #endif // _DEBUG
1846
1847         pslILEmit->EmitLOCALLOC();
1848
1849 #ifdef _DEBUG
1850         // Pass buffer length in the first DWORD so the helper is able to assert that
1851         // the buffer is large enough.
1852         pslILEmit->EmitDUP();
1853         pslILEmit->EmitLDLOC(dwTmpAllocSize);
1854         pslILEmit->EmitSTIND_I4();
1855 #endif // _DEBUG
1856
1857         pslILEmit->EmitSTLOC(m_dwLocalBuffer);
1858
1859         // load string and LocalBuffer
1860         EmitLoadManagedValue(pslILEmit);
1861         pslILEmit->EmitLDLOC(m_dwLocalBuffer);
1862         pslILEmit->EmitBR(pRejoinLabel);
1863
1864         pslILEmit->EmitLabel(pNoOptimizeLabel);
1865     }
1866     pslILEmit->EmitLoadNullPtr();
1867
1868     pslILEmit->EmitLabel(pRejoinLabel);
1869     pslILEmit->EmitCALL(METHOD__BSTRMARSHALER__CONVERT_TO_NATIVE, 2, 1);
1870     EmitStoreNativeValue(pslILEmit);
1871 }
1872
1873 void ILBSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1874 {
1875     STANDARD_VM_CONTRACT;
1876     
1877     EmitLoadNativeValue(pslILEmit);
1878     pslILEmit->EmitCALL(METHOD__BSTRMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1879     EmitStoreManagedValue(pslILEmit);
1880 }
1881
1882 LocalDesc ILAnsiBSTRMarshaler::GetNativeType()
1883 {
1884     LIMITED_METHOD_CONTRACT;
1885     
1886     return LocalDesc(ELEMENT_TYPE_I); // BSTR
1887 }
1888
1889 LocalDesc ILAnsiBSTRMarshaler::GetManagedType()
1890 {
1891     LIMITED_METHOD_CONTRACT;
1892     
1893     return LocalDesc(ELEMENT_TYPE_STRING);
1894 }
1895
1896 void ILAnsiBSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1897 {
1898     STANDARD_VM_CONTRACT;
1899
1900     DWORD dwAnsiMarshalFlags = 
1901         (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) | 
1902         (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
1903     
1904     pslILEmit->EmitLDC(dwAnsiMarshalFlags);
1905     EmitLoadManagedValue(pslILEmit);
1906     pslILEmit->EmitCALL(METHOD__ANSIBSTRMARSHALER__CONVERT_TO_NATIVE, 2, 1);
1907     EmitStoreNativeValue(pslILEmit);
1908 }
1909
1910 void ILAnsiBSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1911 {
1912     STANDARD_VM_CONTRACT;
1913
1914     EmitLoadNativeValue(pslILEmit);
1915     pslILEmit->EmitCALL(METHOD__ANSIBSTRMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1916     EmitStoreManagedValue(pslILEmit);
1917 }
1918
1919 bool ILAnsiBSTRMarshaler::NeedsClearNative()
1920 {
1921     LIMITED_METHOD_CONTRACT;
1922     return true;
1923 }
1924
1925 void ILAnsiBSTRMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1926 {
1927     STANDARD_VM_CONTRACT;
1928     
1929     EmitLoadNativeValue(pslILEmit);
1930     pslILEmit->EmitCALL(METHOD__ANSIBSTRMARSHALER__CLEAR_NATIVE, 1, 0);
1931 }
1932
1933 #ifdef FEATURE_COMINTEROP
1934
1935 LocalDesc ILHSTRINGMarshaler::GetNativeType()
1936 {
1937     LIMITED_METHOD_CONTRACT;
1938     return LocalDesc(ELEMENT_TYPE_I);   // HSTRING
1939 }
1940
1941 LocalDesc ILHSTRINGMarshaler::GetManagedType()
1942 {
1943     LIMITED_METHOD_CONTRACT;
1944     return LocalDesc(ELEMENT_TYPE_STRING);
1945 }
1946
1947 bool ILHSTRINGMarshaler::NeedsClearNative()
1948 {
1949     LIMITED_METHOD_CONTRACT;
1950     return true;
1951 }
1952
1953 void ILHSTRINGMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1954 {
1955     CONTRACTL
1956     {
1957         STANDARD_VM_CHECK;
1958         PRECONDITION(CheckPointer(pslILEmit));
1959     }
1960     CONTRACTL_END;
1961
1962     // If we're only going into native code, then we can optimize and create a HSTRING reference over
1963     // the pinned System.String.  However, if the parameter will remain in native code as an out
1964     // value, then we need to create a real HSTRING.
1965     if (!IsOut(m_dwMarshalFlags) && !IsRetval(m_dwMarshalFlags))
1966     {
1967         EmitConvertCLRToHSTRINGReference(pslILEmit);
1968     }
1969     else
1970     {
1971         EmitConvertCLRToHSTRING(pslILEmit);
1972     }
1973 }
1974
1975 void ILHSTRINGMarshaler::EmitConvertCLRToHSTRINGReference(ILCodeStream* pslILEmit)
1976 {
1977     CONTRACTL
1978     {
1979         STANDARD_VM_CHECK;
1980         PRECONDITION(CheckPointer(pslILEmit));
1981         PRECONDITION(!IsOut(m_dwMarshalFlags));
1982         PRECONDITION(!IsRetval(m_dwMarshalFlags));
1983     }
1984     CONTRACTL_END;
1985
1986     //
1987     // The general strategy for fast path marshaling a short lived System.String -> HSTRING is:
1988     //      1. Pin the System.String
1989     //      2. Create an HSTRING Reference over the pinned string
1990     //      3. Pass that reference to native code
1991     //
1992
1993     // Local to hold the HSTRING_HEADER of the HSTRING reference
1994     MethodTable *pHStringHeaderMT = MscorlibBinder::GetClass(CLASS__HSTRING_HEADER_MANAGED);
1995     DWORD dwHStringHeaderLocal = pslILEmit->NewLocal(pHStringHeaderMT);
1996
1997     // Local to hold the pinned input string
1998     LocalDesc pinnedStringDesc = GetManagedType();
1999     pinnedStringDesc.MakePinned();
2000     DWORD dwPinnedStringLocal = pslILEmit->NewLocal(pinnedStringDesc);
2001
2002     // pinnedString = managed
2003     EmitLoadManagedValue(pslILEmit);
2004     pslILEmit->EmitSTLOC(dwPinnedStringLocal);
2005
2006     // hstring = HSTRINGMarshaler.ConvertManagedToNativeReference(pinnedString, out HStringHeader)
2007     pslILEmit->EmitLDLOC(dwPinnedStringLocal);
2008     pslILEmit->EmitLDLOCA(dwHStringHeaderLocal);
2009     pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_NATIVE_REFERENCE, 2, 1);
2010
2011     if (g_pConfig->InteropLogArguments())
2012     {
2013         m_pslNDirect->EmitLogNativeArgument(pslILEmit, dwPinnedStringLocal);
2014     }
2015
2016     EmitStoreNativeValue(pslILEmit);
2017 }
2018
2019 void ILHSTRINGMarshaler::EmitConvertCLRToHSTRING(ILCodeStream* pslILEmit)
2020 {
2021     CONTRACTL
2022     {
2023         STANDARD_VM_CHECK;
2024         PRECONDITION(CheckPointer(pslILEmit));
2025     }
2026     CONTRACTL_END;
2027
2028     // hstring = HSTRINGMarshaler.ConvertManagedToNative(managed);
2029     EmitLoadManagedValue(pslILEmit);
2030     pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_NATIVE, 1, 1);
2031     EmitStoreNativeValue(pslILEmit);
2032 }
2033
2034 void ILHSTRINGMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2035 {
2036     STANDARD_VM_CONTRACT;
2037
2038     //
2039     // To convert an HSTRING to a CLR String:
2040     //      1. WindowsGetStringRawBuffer() to get the raw string data
2041     //      2. WindowsGetStringLen() to get the string length
2042     //      3. Construct a System.String from these parameters
2043     //      4. Release the HSTRING
2044     //
2045
2046     // string = HSTRINGMarshaler.ConvertNativeToManaged(native);
2047     EmitLoadNativeValue(pslILEmit);
2048     pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_MANAGED, 1, 1);
2049     EmitStoreManagedValue(pslILEmit);
2050 }
2051
2052
2053 void ILHSTRINGMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
2054 {
2055     STANDARD_VM_CONTRACT;
2056
2057     // HStringMarshaler.ClearNative(hstring)
2058     EmitLoadNativeValue(pslILEmit);
2059     pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CLEAR_NATIVE, 1, 0);
2060 }
2061
2062 #endif // FEATURE_COMINTEROP
2063
2064 LocalDesc ILCUTF8Marshaler::GetManagedType()
2065 {
2066         LIMITED_METHOD_CONTRACT;
2067
2068         return LocalDesc(ELEMENT_TYPE_STRING);
2069 }
2070
2071 void ILCUTF8Marshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2072 {
2073         STANDARD_VM_CONTRACT;
2074
2075         DWORD dwUtf8MarshalFlags =
2076                 (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
2077                 (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
2078
2079         bool bPassByValueInOnly = IsIn(m_dwMarshalFlags) && !IsOut(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags);
2080         if (bPassByValueInOnly)
2081         {
2082                 DWORD dwBufSize = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
2083                 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
2084
2085                 // LocalBuffer = 0
2086                 pslILEmit->EmitLoadNullPtr();
2087                 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2088
2089                 ILCodeLabel* pNoOptimize = pslILEmit->NewCodeLabel();
2090
2091                 // if == NULL, goto NoOptimize
2092                 EmitLoadManagedValue(pslILEmit);
2093                 pslILEmit->EmitBRFALSE(pNoOptimize);
2094                                                 
2095                 // (String.Length + 1)
2096                 // Characters would be # of characters + 1 in case left over high surrogate is ?
2097                 EmitLoadManagedValue(pslILEmit);
2098                 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
2099                 pslILEmit->EmitLDC(1);
2100                 pslILEmit->EmitADD();
2101
2102                 // Max 3 bytes per char.
2103                 // (String.Length + 1) * 3              
2104                 pslILEmit->EmitLDC(3);
2105                 pslILEmit->EmitMUL();
2106
2107                 // +1 for the 0x0 that we put in.
2108                 // ((String.Length + 1) * 3) + 1
2109                 pslILEmit->EmitLDC(1);
2110                 pslILEmit->EmitADD();
2111                                 
2112                 // BufSize = ( (String.Length+1) * 3) + 1
2113                 pslILEmit->EmitSTLOC(dwBufSize);
2114
2115                 // if (MAX_LOCAL_BUFFER_LENGTH < BufSize ) goto NoOptimize
2116                 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
2117                 pslILEmit->EmitLDLOC(dwBufSize);
2118                 pslILEmit->EmitCLT();
2119                 pslILEmit->EmitBRTRUE(pNoOptimize);
2120
2121                 // LocalBuffer = localloc(BufSize);
2122                 pslILEmit->EmitLDLOC(dwBufSize);
2123                 pslILEmit->EmitLOCALLOC();
2124                 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2125
2126                 // NoOptimize:
2127                 pslILEmit->EmitLabel(pNoOptimize);
2128         }
2129
2130         // UTF8Marshaler.ConvertToNative(dwUtf8MarshalFlags,pManaged, pLocalBuffer)
2131         pslILEmit->EmitLDC(dwUtf8MarshalFlags);
2132         EmitLoadManagedValue(pslILEmit);
2133
2134         if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
2135         {
2136                 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
2137         }
2138         else
2139         {
2140                 pslILEmit->EmitLoadNullPtr();
2141         }
2142
2143         pslILEmit->EmitCALL(METHOD__CUTF8MARSHALER__CONVERT_TO_NATIVE, 3, 1);
2144
2145         EmitStoreNativeValue(pslILEmit);
2146 }
2147
2148 void ILCUTF8Marshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2149 {
2150         STANDARD_VM_CONTRACT;
2151
2152         EmitLoadNativeValue(pslILEmit);
2153         pslILEmit->EmitCALL(METHOD__CUTF8MARSHALER__CONVERT_TO_MANAGED, 1, 1);
2154         EmitStoreManagedValue(pslILEmit);
2155 }
2156
2157
2158 LocalDesc ILCSTRMarshaler::GetManagedType()
2159 {
2160     LIMITED_METHOD_CONTRACT;
2161     
2162     return LocalDesc(ELEMENT_TYPE_STRING);
2163 }
2164
2165 void ILCSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2166 {
2167     STANDARD_VM_CONTRACT;
2168
2169     DWORD dwAnsiMarshalFlags = 
2170         (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) | 
2171         (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
2172
2173     bool bPassByValueInOnly = IsIn(m_dwMarshalFlags) && !IsOut(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags);
2174     if (bPassByValueInOnly)
2175     {
2176         DWORD dwBufSize = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
2177         m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
2178
2179         // LocalBuffer = 0
2180         pslILEmit->EmitLoadNullPtr();
2181         pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2182
2183         ILCodeLabel* pNoOptimize = pslILEmit->NewCodeLabel(); 
2184
2185         // if == NULL, goto NoOptimize
2186         EmitLoadManagedValue(pslILEmit);
2187         pslILEmit->EmitBRFALSE(pNoOptimize);
2188
2189         // String.Length + 2
2190         EmitLoadManagedValue(pslILEmit);
2191         pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
2192         pslILEmit->EmitLDC(2);
2193         pslILEmit->EmitADD();
2194
2195         // (String.Length + 2) * GetMaxDBCSCharByteSize()
2196         pslILEmit->EmitLDSFLD(pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__MARSHAL__SYSTEM_MAX_DBCS_CHAR_SIZE)));
2197         pslILEmit->EmitMUL();
2198
2199         // BufSize = (String.Length + 2) * GetMaxDBCSCharByteSize()
2200         pslILEmit->EmitSTLOC(dwBufSize);
2201
2202         // if (MAX_LOCAL_BUFFER_LENGTH < BufSize ) goto NoOptimize
2203         pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
2204         pslILEmit->EmitLDLOC(dwBufSize);
2205         pslILEmit->EmitCLT();
2206         pslILEmit->EmitBRTRUE(pNoOptimize);
2207
2208         // LocalBuffer = localloc(BufSize);
2209         pslILEmit->EmitLDLOC(dwBufSize);
2210         pslILEmit->EmitLOCALLOC();
2211         pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2212
2213         // NoOptimize:
2214         pslILEmit->EmitLabel(pNoOptimize);
2215     }
2216
2217     // CSTRMarshaler.ConvertToNative pManaged, dwAnsiMarshalFlags, pLocalBuffer
2218     pslILEmit->EmitLDC(dwAnsiMarshalFlags);
2219     EmitLoadManagedValue(pslILEmit);
2220
2221     if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
2222     {
2223         pslILEmit->EmitLDLOC(m_dwLocalBuffer);
2224     }
2225     else
2226     {
2227         pslILEmit->EmitLoadNullPtr();
2228     }
2229
2230     pslILEmit->EmitCALL(METHOD__CSTRMARSHALER__CONVERT_TO_NATIVE, 3, 1);
2231     
2232     EmitStoreNativeValue(pslILEmit);
2233 }
2234
2235 void ILCSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2236 {
2237     STANDARD_VM_CONTRACT;
2238
2239     EmitLoadNativeValue(pslILEmit);
2240     pslILEmit->EmitCALL(METHOD__CSTRMARSHALER__CONVERT_TO_MANAGED, 1, 1);
2241     EmitStoreManagedValue(pslILEmit);
2242 }
2243
2244 LocalDesc ILLayoutClassPtrMarshalerBase::GetNativeType()
2245 {
2246     LIMITED_METHOD_CONTRACT;
2247     
2248     return LocalDesc(ELEMENT_TYPE_I); // ptr to struct
2249 }
2250
2251 LocalDesc ILLayoutClassPtrMarshalerBase::GetManagedType()
2252 {
2253     LIMITED_METHOD_CONTRACT;
2254     
2255     return LocalDesc(m_pargs->m_pMT);
2256 }
2257
2258 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2259 {
2260     STANDARD_VM_CONTRACT;
2261     
2262     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2263     UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2264
2265     pslILEmit->EmitLoadNullPtr();
2266     EmitStoreNativeValue(pslILEmit);
2267     
2268     EmitLoadManagedValue(pslILEmit);
2269     pslILEmit->EmitBRFALSE(pNullRefLabel);
2270     pslILEmit->EmitLDC(uNativeSize);
2271     pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
2272     pslILEmit->EmitDUP();           // for INITBLK
2273     EmitStoreNativeValue(pslILEmit);
2274
2275     // initialize local block we just allocated
2276     pslILEmit->EmitLDC(0);
2277     pslILEmit->EmitLDC(uNativeSize);
2278     pslILEmit->EmitINITBLK();
2279
2280     pslILEmit->EmitLabel(pNullRefLabel);
2281 }
2282
2283 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit)
2284 {
2285     STANDARD_VM_CONTRACT;
2286
2287     UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2288     if (uNativeSize > s_cbStackAllocThreshold)
2289     {
2290         EmitConvertSpaceCLRToNative(pslILEmit);
2291     }
2292     else
2293     {
2294         ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2295
2296         pslILEmit->EmitLoadNullPtr();
2297         EmitStoreNativeValue(pslILEmit);
2298         
2299         EmitLoadManagedValue(pslILEmit);
2300         pslILEmit->EmitBRFALSE(pNullRefLabel);
2301
2302         pslILEmit->EmitLDC(uNativeSize);
2303         pslILEmit->EmitLOCALLOC();
2304         pslILEmit->EmitDUP();           // for INITBLK
2305         EmitStoreNativeValue(pslILEmit);
2306
2307         // initialize local block we just allocated
2308         pslILEmit->EmitLDC(0);
2309         pslILEmit->EmitLDC(uNativeSize);
2310         pslILEmit->EmitINITBLK();
2311
2312         pslILEmit->EmitLabel(pNullRefLabel);
2313     }
2314 }
2315
2316 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
2317 {
2318     STANDARD_VM_CONTRACT;
2319     
2320     EmitConvertSpaceCLRToNativeTemp(pslILEmit);
2321     EmitConvertContentsCLRToNative(pslILEmit);
2322 }
2323
2324 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
2325 {
2326     STANDARD_VM_CONTRACT;
2327
2328     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2329
2330     EmitLoadNativeValue(pslILEmit);
2331     pslILEmit->EmitBRFALSE(pNullRefLabel);
2332
2333     pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->m_pMT));
2334     pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
2335     // static object AllocateInternal(IntPtr typeHandle);
2336     pslILEmit->EmitCALL(METHOD__STUBHELPERS__ALLOCATE_INTERNAL, 1, 1);
2337     EmitStoreManagedValue(pslILEmit);
2338     pslILEmit->EmitLabel(pNullRefLabel);
2339 }
2340
2341
2342 bool ILLayoutClassPtrMarshalerBase::NeedsClearNative()
2343 {
2344     LIMITED_METHOD_CONTRACT;
2345     return true;
2346 }
2347
2348 void ILLayoutClassPtrMarshalerBase::EmitClearNative(ILCodeStream* pslILEmit)
2349 {
2350     STANDARD_VM_CONTRACT;
2351     
2352     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2353
2354     EmitLoadNativeValue(pslILEmit);
2355     pslILEmit->EmitBRFALSE(pNullRefLabel);
2356
2357     EmitClearNativeContents(pslILEmit);
2358     EmitLoadNativeValue(pslILEmit);
2359     pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
2360
2361     pslILEmit->EmitLabel(pNullRefLabel);
2362 }
2363
2364 void ILLayoutClassPtrMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit)
2365 {
2366     STANDARD_VM_CONTRACT;
2367
2368     UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2369     if (uNativeSize > s_cbStackAllocThreshold)
2370     {
2371         EmitClearNative(pslILEmit);
2372     }
2373     else
2374     {
2375         ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2376         EmitLoadNativeValue(pslILEmit);
2377         pslILEmit->EmitBRFALSE(pNullRefLabel);
2378         
2379         EmitClearNativeContents(pslILEmit);
2380         
2381         pslILEmit->EmitLabel(pNullRefLabel);
2382     }
2383 }
2384
2385
2386
2387 void ILLayoutClassPtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2388 {
2389     STANDARD_VM_CONTRACT;
2390
2391     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2392     UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2393
2394     EmitLoadNativeValue(pslILEmit);
2395     pslILEmit->EmitBRFALSE(pNullRefLabel);
2396
2397     EmitLoadNativeValue(pslILEmit);
2398     pslILEmit->EmitLDC(0);
2399     pslILEmit->EmitLDC(uNativeSize);
2400     pslILEmit->EmitINITBLK();        
2401
2402     EmitLoadManagedValue(pslILEmit);
2403     EmitLoadNativeValue(pslILEmit);
2404
2405     m_pslNDirect->LoadCleanupWorkList(pslILEmit);
2406
2407     // static void FmtClassUpdateNativeInternal(object obj, byte* pNative, IntPtr pOptionalCleanupList);
2408
2409     pslILEmit->EmitCALL(METHOD__STUBHELPERS__FMT_CLASS_UPDATE_NATIVE_INTERNAL, 3, 0);
2410     pslILEmit->EmitLabel(pNullRefLabel);
2411 }
2412
2413 void ILLayoutClassPtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2414 {
2415     STANDARD_VM_CONTRACT;
2416     
2417     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2418     
2419     EmitLoadManagedValue(pslILEmit);
2420     pslILEmit->EmitBRFALSE(pNullRefLabel);
2421
2422     EmitLoadManagedValue(pslILEmit);
2423     EmitLoadNativeValue(pslILEmit);
2424
2425     // static void FmtClassUpdateCLRInternal(object obj, byte* pNative);
2426     pslILEmit->EmitCALL(METHOD__STUBHELPERS__FMT_CLASS_UPDATE_CLR_INTERNAL, 2, 0);
2427     pslILEmit->EmitLabel(pNullRefLabel);
2428 }
2429
2430 void ILLayoutClassPtrMarshaler::EmitClearNativeContents(ILCodeStream * pslILEmit)
2431 {
2432     STANDARD_VM_CONTRACT;
2433
2434     int tokManagedType = pslILEmit->GetToken(m_pargs->m_pMT);
2435     
2436     EmitLoadNativeValue(pslILEmit);
2437     pslILEmit->EmitLDTOKEN(tokManagedType);
2438     pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
2439
2440     // static void LayoutDestroyNativeInternal(byte* pNative, IntPtr pMT);
2441     pslILEmit->EmitCALL(METHOD__STUBHELPERS__LAYOUT_DESTROY_NATIVE_INTERNAL, 2, 0);
2442 }
2443
2444
2445 void ILBlittablePtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2446 {
2447     STANDARD_VM_CONTRACT;
2448
2449     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2450     UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2451     int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__PINNING_HELPER__M_DATA));
2452
2453     EmitLoadNativeValue(pslILEmit);
2454     pslILEmit->EmitBRFALSE(pNullRefLabel);
2455
2456     EmitLoadNativeValue(pslILEmit);                             // dest
2457
2458     EmitLoadManagedValue(pslILEmit);
2459     pslILEmit->EmitLDFLDA(fieldDef);                            // src
2460
2461     pslILEmit->EmitLDC(uNativeSize);                            // size
2462     
2463     pslILEmit->EmitCPBLK();
2464     pslILEmit->EmitLabel(pNullRefLabel);
2465 }
2466
2467 void ILBlittablePtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2468 {
2469     STANDARD_VM_CONTRACT;
2470     
2471     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2472     UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2473     int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__PINNING_HELPER__M_DATA));
2474     
2475     EmitLoadManagedValue(pslILEmit);
2476     pslILEmit->EmitBRFALSE(pNullRefLabel);
2477
2478     EmitLoadManagedValue(pslILEmit);
2479     pslILEmit->EmitLDFLDA(fieldDef);                            // dest
2480
2481     EmitLoadNativeValue(pslILEmit);                             // src
2482
2483     pslILEmit->EmitLDC(uNativeSize);                            // size
2484
2485     pslILEmit->EmitCPBLK();
2486     pslILEmit->EmitLabel(pNullRefLabel);
2487 }
2488
2489 void ILBlittablePtrMarshaler::EmitMarshalArgumentCLRToNative()
2490 {
2491     CONTRACTL
2492     {
2493         STANDARD_VM_CHECK;
2494         PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2495     }
2496     CONTRACTL_END;
2497
2498     EmitSetupSigAndDefaultHomesCLRToNative();
2499
2500     //
2501     // marshal
2502     //
2503
2504     ILCodeLabel* pSkipAddLabel = m_pcsMarshal->NewCodeLabel();
2505     LocalDesc managedTypePinned = GetManagedType();
2506     managedTypePinned.MakePinned();
2507     DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedTypePinned);
2508
2509     EmitLoadManagedValue(m_pcsMarshal);
2510     
2511     m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
2512     m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
2513     m_pcsMarshal->EmitCONV_U();
2514     m_pcsMarshal->EmitDUP();
2515     m_pcsMarshal->EmitBRFALSE(pSkipAddLabel);
2516     m_pcsMarshal->EmitLDC(Object::GetOffsetOfFirstField());
2517     m_pcsMarshal->EmitADD();
2518     m_pcsMarshal->EmitLabel(pSkipAddLabel);
2519
2520     if (g_pConfig->InteropLogArguments())
2521     {
2522         m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
2523     }
2524
2525     EmitStoreNativeValue(m_pcsMarshal);
2526 }
2527
2528
2529
2530
2531 MarshalerOverrideStatus ILHandleRefMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2532                                                 BOOL               byref,
2533                                                 BOOL               fin,
2534                                                 BOOL               fout,
2535                                                 BOOL               fManagedToNative,
2536                                                 OverrideProcArgs*  pargs,
2537                                                 UINT*              pResID,
2538                                                 UINT               argidx,
2539                                                 UINT               nativeStackOffset)
2540 {
2541     CONTRACTL
2542     {
2543         THROWS;
2544         GC_TRIGGERS;
2545         MODE_ANY;
2546     }
2547     CONTRACTL_END;
2548
2549     ILCodeStream* pcsMarshal    = psl->GetMarshalCodeStream();
2550     ILCodeStream* pcsDispatch   = psl->GetDispatchCodeStream();
2551     ILCodeStream* pcsUnmarshal  = psl->GetUnmarshalCodeStream();
2552
2553     if (fManagedToNative && !byref)
2554     {
2555         pcsMarshal->SetStubTargetArgType(ELEMENT_TYPE_I);
2556
2557
2558         // HandleRefs are valuetypes, so pinning is not needed.
2559         // The argument address is on the stack and will not move.
2560         mdFieldDef handleField = pcsDispatch->GetToken(MscorlibBinder::GetField(FIELD__HANDLE_REF__HANDLE));
2561         pcsDispatch->EmitLDARG(argidx);
2562         pcsDispatch->EmitLDFLD(handleField);
2563
2564         mdFieldDef wrapperField = pcsUnmarshal->GetToken(MscorlibBinder::GetField(FIELD__HANDLE_REF__WRAPPER));
2565         pcsUnmarshal->EmitLDARG(argidx);
2566         pcsUnmarshal->EmitLDFLD(wrapperField);
2567         pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
2568
2569         return OVERRIDDEN;
2570     }
2571     else
2572     {
2573         *pResID = IDS_EE_BADMARSHAL_HANDLEREFRESTRICTION;
2574         return DISALLOWED;
2575     }
2576 }
2577
2578 MarshalerOverrideStatus ILHandleRefMarshaler::ReturnOverride(NDirectStubLinker* psl,
2579                                               BOOL               fManagedToNative,
2580                                               BOOL               fHresultSwap,
2581                                               OverrideProcArgs*  pargs,
2582                                               UINT*              pResID)
2583 {
2584     CONTRACTL
2585     {
2586         NOTHROW;
2587         GC_NOTRIGGER;
2588         MODE_ANY;
2589     }
2590     CONTRACTL_END;
2591
2592     *pResID = IDS_EE_BADMARSHAL_HANDLEREFRESTRICTION;
2593     return DISALLOWED;
2594 }
2595
2596 LocalDesc ILSafeHandleMarshaler::GetManagedType()
2597 {
2598     STANDARD_VM_CONTRACT;
2599
2600     return LocalDesc(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE));
2601 }
2602
2603 LocalDesc ILSafeHandleMarshaler::GetNativeType()
2604 {
2605     LIMITED_METHOD_CONTRACT;
2606
2607     return LocalDesc(ELEMENT_TYPE_I);
2608 }
2609
2610 bool ILSafeHandleMarshaler::NeedsClearNative()
2611 {
2612     LIMITED_METHOD_CONTRACT;
2613     return true;
2614 }
2615
2616 void ILSafeHandleMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
2617 {
2618     STANDARD_VM_CONTRACT;
2619
2620     _ASSERTE(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2621
2622     // call StubHelpers::SafeHandleRelease
2623     EmitLoadManagedValue(pslILEmit);
2624     pslILEmit->EmitCALL(METHOD__STUBHELPERS__SAFE_HANDLE_RELEASE, 1, 0);
2625 }
2626
2627 void ILSafeHandleMarshaler::EmitMarshalArgumentCLRToNative()
2628 {
2629     CONTRACTL
2630     {
2631         STANDARD_VM_CHECK;
2632         PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2633     }
2634     CONTRACTL_END;
2635
2636     EmitSetupSigAndDefaultHomesCLRToNative();
2637
2638     // by-value CLR-to-native SafeHandle is always passed in-only regardless of [In], [Out]
2639     // marshal and cleanup communicate via an extra local and are both emitted in this method
2640
2641     // bool <dwHandleAddRefedLocalNum> = false
2642     ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
2643     DWORD dwHandleAddRefedLocalNum = pcsSetup->NewLocal(ELEMENT_TYPE_BOOLEAN);
2644     
2645     pcsSetup->EmitLDC(0);
2646     pcsSetup->EmitSTLOC(dwHandleAddRefedLocalNum);
2647
2648     // <nativeHandle> = StubHelpers::SafeHandleAddRef(<managedSH>, ref <dwHandleAddRefedLocalNum>)
2649     EmitLoadManagedValue(m_pcsMarshal);
2650     m_pcsMarshal->EmitLDLOCA(dwHandleAddRefedLocalNum);
2651     m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__SAFE_HANDLE_ADD_REF, 2, 1);
2652     EmitStoreNativeValue(m_pcsMarshal);
2653
2654     // cleanup:
2655     // if (<dwHandleAddRefedLocalNum>) StubHelpers.SafeHandleRelease(<managedSH>)
2656     ILCodeStream *pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
2657     ILCodeLabel *pSkipClearNativeLabel = pcsCleanup->NewCodeLabel();
2658
2659     pcsCleanup->EmitLDLOC(dwHandleAddRefedLocalNum);
2660     pcsCleanup->EmitBRFALSE(pSkipClearNativeLabel);
2661
2662     EmitClearNativeTemp(pcsCleanup);
2663     m_pslNDirect->SetCleanupNeeded();
2664
2665     pcsCleanup->EmitLabel(pSkipClearNativeLabel);
2666 }
2667
2668 MarshalerOverrideStatus ILSafeHandleMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2669                                                 BOOL               byref,
2670                                                 BOOL               fin,
2671                                                 BOOL               fout,
2672                                                 BOOL               fManagedToNative,
2673                                                 OverrideProcArgs*  pargs,
2674                                                 UINT*              pResID,
2675                                                 UINT               argidx,
2676                                                 UINT               nativeStackOffset)
2677 {
2678     CONTRACTL
2679     {
2680         THROWS;
2681         GC_TRIGGERS;
2682         MODE_ANY;
2683     }
2684     CONTRACTL_END;
2685     
2686     ILCodeStream* pslIL         = psl->GetMarshalCodeStream();
2687     ILCodeStream* pslILDispatch = psl->GetDispatchCodeStream();
2688
2689     if (fManagedToNative)
2690     {
2691         if (byref)
2692         {
2693             pslIL->SetStubTargetArgType(ELEMENT_TYPE_I);
2694
2695             // The specific SafeHandle subtype we're dealing with here.
2696             MethodTable *pHandleType = pargs->m_pMT;
2697
2698             // Out SafeHandle parameters must not be abstract.
2699             if (fout && pHandleType->IsAbstract())
2700             {
2701                 *pResID = IDS_EE_BADMARSHAL_ABSTRACTOUTSAFEHANDLE;
2702                 return DISALLOWED;
2703             }
2704
2705             // We rely on the SafeHandle having a default constructor.
2706             if (!pHandleType->HasDefaultConstructor())
2707             {
2708                 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
2709                 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
2710             }
2711
2712             // Grab the token for the native handle field embedded inside the SafeHandle. We'll be using it to direct access the
2713             // native handle later.
2714             mdToken tkNativeHandleField = pslIL->GetToken(MscorlibBinder::GetField(FIELD__SAFE_HANDLE__HANDLE));
2715
2716             // The high level logic (note that the parameter may be in, out or both):
2717             // 1) If this is an input parameter we need to AddRef the SafeHandle and schedule a Release cleanup item.
2718             // 2) If this is an output parameter we need to preallocate a SafeHandle to wrap the new native handle value. We
2719             //    must allocate this before the native call to avoid a failure point when we already have a native resource
2720             //    allocated. We must allocate a new SafeHandle even if we have one on input since both input and output native
2721             //    handles need to be tracked and released by a SafeHandle.
2722             // 3) Initialize a local IntPtr that will be passed to the native call. If we have an input SafeHandle the value
2723             //    comes from there otherwise we get it from the new SafeHandle (which is guaranteed to be initialized to an
2724             //    invalid handle value).
2725             // 4) If this is a out parameter we also store the original handle value (that we just computed above) in a local
2726             //    variable.
2727             // 5) After the native call, if this is an output parameter and the handle value we passed to native differs from
2728             //    the local copy we made then the new handle value is written into the output SafeHandle and that SafeHandle
2729             //    is propagated back to the caller.
2730
2731             // Locals:
2732             DWORD           dwInputHandleLocal     = 0; // The input safe handle (in only)
2733             DWORD           dwOutputHandleLocal    = 0; // The output safe handle (out only)
2734             DWORD           dwOldNativeHandleLocal = 0; // The original native handle value for comparison (out only)
2735             DWORD           dwNativeHandleLocal;    // The input (and possibly updated) native handle value
2736
2737             if (fin)
2738             {
2739                 LocalDesc locInputHandle(pHandleType);
2740                 dwInputHandleLocal = pslIL->NewLocal(locInputHandle);
2741             }
2742             if (fout)
2743             {
2744                 LocalDesc locOutputHandle(pHandleType);
2745                 dwOutputHandleLocal = pslIL->NewLocal(locOutputHandle);
2746
2747                 dwOldNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2748             }
2749
2750             dwNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2751
2752             // Call StubHelpers.AddToCleanupList to atomically AddRef incoming SafeHandle and schedule a cleanup work item to
2753             // perform Release after the call. The helper also returns the native handle value to us so take the opportunity
2754             // to store this in the NativeHandle local we've allocated.
2755             if (fin)
2756             {
2757                 pslIL->EmitLDARG(argidx);
2758                 pslIL->EmitLDIND_REF();
2759
2760                 pslIL->EmitSTLOC(dwInputHandleLocal);
2761
2762                 // Release the original input SafeHandle after the call.
2763                 psl->LoadCleanupWorkList(pslIL);
2764                 pslIL->EmitLDLOC(dwInputHandleLocal);
2765
2766                 // This is realiable, i.e. the cleanup will happen if and only if the SH was actually AddRef'ed.
2767                 pslIL->EmitCALL(METHOD__STUBHELPERS__ADD_TO_CLEANUP_LIST_SAFEHANDLE, 2, 1);
2768
2769                 pslIL->EmitSTLOC(dwNativeHandleLocal);
2770
2771             }
2772
2773             // For output parameters we need to allocate a new SafeHandle to hold the result.
2774             if (fout)
2775             {
2776                 MethodDesc* pMDCtor = pHandleType->GetDefaultConstructor();
2777                 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
2778                 pslIL->EmitSTLOC(dwOutputHandleLocal);
2779
2780                 // If we didn't provide an input handle then we initialize the NativeHandle local with the (initially invalid)
2781                 // handle field set up inside the output handle by the constructor.
2782                 if (!fin)
2783                 {
2784                     pslIL->EmitLDLOC(dwOutputHandleLocal);
2785                     pslIL->EmitLDFLD(tkNativeHandleField);
2786                     pslIL->EmitSTLOC(dwNativeHandleLocal);
2787                 }
2788
2789                 // Remember the handle value we start out with so we know whether to back propagate after the native call.
2790                 pslIL->EmitLDLOC(dwNativeHandleLocal);
2791                 pslIL->EmitSTLOC(dwOldNativeHandleLocal);
2792             }
2793
2794             // Leave the address of the native handle local as the argument to the native method.
2795             pslILDispatch->EmitLDLOCA(dwNativeHandleLocal);
2796
2797             // On the output side we only backpropagate the native handle into the output SafeHandle and the output SafeHandle
2798             // to the caller if the native handle actually changed (otherwise we can end up with two SafeHandles wrapping the
2799             // same native handle, which is bad).
2800             if (fout)
2801             {
2802                 // We will use cleanup stream to avoid leaking the handle on thread abort.
2803                 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx);
2804
2805                 psl->SetCleanupNeeded();
2806                 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
2807
2808                 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
2809
2810                 psl->EmitCheckForArgCleanup(pslCleanupIL,
2811                                             NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx,
2812                                             NDirectStubLinker::BranchIfNotMarshaled,
2813                                             pDoneLabel);
2814
2815                 // If this is an [in, out] handle check if the native handles have changed. If not we're finished.
2816                 if (fin)
2817                 {
2818                     pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
2819                     pslCleanupIL->EmitLDLOC(dwOldNativeHandleLocal);
2820                     pslCleanupIL->EmitCEQ();
2821                     pslCleanupIL->EmitBRTRUE(pDoneLabel);
2822                 }
2823
2824                 // Propagate the native handle into the output SafeHandle.
2825                 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
2826                 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
2827                 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
2828
2829                 // Propagate the output SafeHandle back to the caller.
2830                 pslCleanupIL->EmitLDARG(argidx);
2831                 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
2832                 pslCleanupIL->EmitSTIND_REF();
2833
2834                 pslCleanupIL->EmitLabel(pDoneLabel);
2835             }
2836         }
2837         else
2838         {
2839             // Avoid using the cleanup list in this common case for perf reasons (cleanup list is
2840             // unmanaged and destroying it means excessive managed<->native transitions; in addition,
2841             // as X86 IL stubs do not use interop frames, there's nothing protecting the cleanup list
2842             // and the SafeHandle references must be GC handles which does not help perf either).
2843             //
2844             // This code path generates calls to StubHelpers.SafeHandleAddRef and SafeHandleRelease.
2845             // NICE: Could SafeHandle.DangerousAddRef and DangerousRelease be implemented in managed?
2846             return HANDLEASNORMAL;
2847         }
2848
2849         return OVERRIDDEN;
2850     }
2851     else
2852     {
2853         *pResID = IDS_EE_BADMARSHAL_SAFEHANDLENATIVETOCOM;
2854         return DISALLOWED;
2855     }
2856 }
2857
2858 //---------------------------------------------------------------------------------------
2859 // 
2860 MarshalerOverrideStatus 
2861 ILSafeHandleMarshaler::ReturnOverride(
2862     NDirectStubLinker * psl, 
2863     BOOL                fManagedToNative, 
2864     BOOL                fHresultSwap, 
2865     OverrideProcArgs *  pargs, 
2866     UINT       *        pResID)
2867 {
2868     CONTRACTL
2869     {
2870         THROWS;
2871         GC_TRIGGERS;
2872         MODE_ANY;
2873         PRECONDITION(CheckPointer(psl));
2874         PRECONDITION(CheckPointer(pargs));
2875         PRECONDITION(CheckPointer(pResID));            
2876     }
2877     CONTRACTL_END;
2878
2879     ILCodeStream * pslIL         = psl->GetMarshalCodeStream();
2880     ILCodeStream * pslPostIL     = psl->GetReturnUnmarshalCodeStream();
2881     ILCodeStream * pslILDispatch = psl->GetDispatchCodeStream();
2882
2883     if (!fManagedToNative)
2884     {
2885         *pResID = IDS_EE_BADMARSHAL_RETURNSHCOMTONATIVE;
2886         return DISALLOWED;
2887     }
2888
2889     // Returned SafeHandle parameters must not be abstract.
2890     if (pargs->m_pMT->IsAbstract())
2891     {
2892         *pResID = IDS_EE_BADMARSHAL_ABSTRACTRETSAFEHANDLE;
2893         return DISALLOWED;
2894     }
2895
2896     // 1) create local for new safehandle
2897     // 2) prealloc a safehandle
2898     // 3) create local to hold returned handle
2899     // 4) [byref] add byref IntPtr to native sig
2900     // 5) [byref] pass address of local as last arg
2901     // 6) store return value in safehandle
2902
2903     // 1) create local for new safehandle        
2904     MethodTable * pMT    = pargs->m_pMT;
2905     LocalDesc     locDescReturnHandle(pMT);
2906     DWORD         dwReturnHandleLocal;
2907     
2908     dwReturnHandleLocal = pslIL->NewLocal(locDescReturnHandle);
2909     
2910     if (!pMT->HasDefaultConstructor())
2911     {
2912         MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
2913         COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
2914     }
2915
2916     // 2) prealloc a safehandle
2917     MethodDesc* pMDCtor = pMT->GetDefaultConstructor();
2918     pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
2919     pslIL->EmitSTLOC(dwReturnHandleLocal);
2920
2921     mdToken tkNativeHandleField = pslPostIL->GetToken(MscorlibBinder::GetField(FIELD__SAFE_HANDLE__HANDLE));
2922
2923     // 3) create local to hold returned handle
2924     DWORD dwReturnNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2925
2926     if (fHresultSwap)
2927     {
2928         // initialize the native handle
2929         pslIL->EmitLDLOC(dwReturnHandleLocal);
2930         pslIL->EmitLDFLD(tkNativeHandleField);
2931         pslIL->EmitSTLOC(dwReturnNativeHandleLocal);
2932
2933         pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I4);    // native method returns an HRESULT
2934         
2935         // 4) [byref] add byref IntPtr to native sig
2936         locDescReturnHandle.ElementType[0]  = ELEMENT_TYPE_BYREF;
2937         locDescReturnHandle.ElementType[1]  = ELEMENT_TYPE_I;
2938         locDescReturnHandle.cbType          = 2;
2939         pslIL->SetStubTargetArgType(&locDescReturnHandle, false);   // extra arg is a byref IntPtr
2940
2941         // 5) [byref] pass address of local as last arg
2942         pslILDispatch->EmitLDLOCA(dwReturnNativeHandleLocal);
2943
2944         // We will use cleanup stream to avoid leaking the handle on thread abort.
2945         psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL);
2946
2947         psl->SetCleanupNeeded();
2948         ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
2949         ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
2950
2951         psl->EmitCheckForArgCleanup(pslCleanupIL,
2952                                     NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL,
2953                                     NDirectStubLinker::BranchIfNotMarshaled,
2954                                     pDoneLabel);
2955
2956         // 6) store return value in safehandle
2957         pslCleanupIL->EmitLDLOC(dwReturnHandleLocal);
2958         pslCleanupIL->EmitLDLOC(dwReturnNativeHandleLocal);
2959         pslCleanupIL->EmitSTFLD(tkNativeHandleField);
2960         pslCleanupIL->EmitLabel(pDoneLabel);
2961
2962         pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2963     }
2964     else
2965     {
2966         pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I);
2967         pslPostIL->EmitSTLOC(dwReturnNativeHandleLocal);
2968
2969         // 6) store return value in safehandle
2970         // The thread abort logic knows that it must not interrupt the stub so we will
2971         // always be able to execute this sequence after returning from the call.
2972         pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2973         pslPostIL->EmitLDLOC(dwReturnNativeHandleLocal);
2974         pslPostIL->EmitSTFLD(tkNativeHandleField);
2975         pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2976     }
2977
2978     return OVERRIDDEN;
2979 } // ILSafeHandleMarshaler::ReturnOverride
2980
2981
2982 //---------------------------------------------------------------------------------------
2983 // 
2984 MarshalerOverrideStatus ILCriticalHandleMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2985                                                 BOOL               byref,
2986                                                 BOOL               fin,
2987                                                 BOOL               fout,
2988                                                 BOOL               fManagedToNative,
2989                                                 OverrideProcArgs*  pargs,
2990                                                 UINT*              pResID,
2991                                                 UINT               argidx,
2992                                                 UINT               nativeStackOffset)
2993 {
2994     CONTRACTL
2995     {
2996         THROWS;
2997         GC_TRIGGERS;
2998         MODE_ANY;
2999     }
3000     CONTRACTL_END;
3001     
3002     ILCodeStream* pslIL         = psl->GetMarshalCodeStream();
3003     ILCodeStream* pslPostIL     = psl->GetUnmarshalCodeStream();
3004     ILCodeStream* pslILDispatch = psl->GetDispatchCodeStream();
3005
3006     if (fManagedToNative)
3007     {
3008         pslIL->SetStubTargetArgType(ELEMENT_TYPE_I);
3009
3010         // Grab the token for the native handle field embedded inside the CriticalHandle. We'll be using it to direct access
3011         // the native handle later.
3012         mdToken tkNativeHandleField = pslIL->GetToken(MscorlibBinder::GetField(FIELD__CRITICAL_HANDLE__HANDLE));
3013
3014         if (byref)
3015         {
3016             // The specific CriticalHandle subtype we're dealing with here.
3017             MethodTable *pHandleType = pargs->m_pMT;
3018
3019             // Out CriticalHandle parameters must not be abstract.
3020             if (fout && pHandleType->IsAbstract())
3021             {
3022                 *pResID = IDS_EE_BADMARSHAL_ABSTRACTOUTCRITICALHANDLE;
3023                 return DISALLOWED;
3024             }
3025
3026             // We rely on the CriticalHandle having a default constructor.
3027             if (!pHandleType->HasDefaultConstructor())
3028             {
3029                 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
3030                 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
3031             }
3032
3033             // The high level logic (note that the parameter may be in, out or both):
3034             // 1) If this is an output parameter we need to preallocate a CriticalHandle to wrap the new native handle value. We
3035             //    must allocate this before the native call to avoid a failure point when we already have a native resource
3036             //    allocated. We must allocate a new CriticalHandle even if we have one on input since both input and output native
3037             //    handles need to be tracked and released by a CriticalHandle.
3038             // 2) Initialize a local IntPtr that will be passed to the native call. If we have an input CriticalHandle the value
3039             //    comes from there otherwise we get it from the new CriticalHandle (which is guaranteed to be initialized to an
3040             //    invalid handle value).
3041             // 3) If this is a out parameter we also store the original handle value (that we just computed above) in a local
3042             //    variable.
3043             // 4) After the native call, if this is an output parameter and the handle value we passed to native differs from
3044             //    the local copy we made then the new handle value is written into the output CriticalHandle and that
3045             //    CriticalHandle is propagated back to the caller.
3046
3047             // Locals:
3048             LocalDesc       locOutputHandle;
3049             DWORD           dwOutputHandleLocal    = 0; // The output critical handle (out only)
3050             DWORD           dwOldNativeHandleLocal = 0; // The original native handle value for comparison (out only)
3051             DWORD           dwNativeHandleLocal;    // The input (and possibly updated) native handle value
3052
3053             if (fout)
3054             {
3055                 locOutputHandle.ElementType[0]  = ELEMENT_TYPE_INTERNAL;
3056                 locOutputHandle.cbType          = 1;
3057                 locOutputHandle.InternalToken   = pHandleType;
3058
3059                 dwOutputHandleLocal = pslIL->NewLocal(locOutputHandle);
3060
3061                 dwOldNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3062             }
3063
3064             dwNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3065
3066
3067             // If we have an input CriticalHandle then initialize our NativeHandle local with it.
3068             if (fin)
3069             {
3070                 pslIL->EmitLDARG(argidx);
3071                 pslIL->EmitLDIND_REF();
3072                 pslIL->EmitLDFLD(tkNativeHandleField);
3073                 pslIL->EmitSTLOC(dwNativeHandleLocal);
3074             }
3075
3076             // For output parameters we need to allocate a new CriticalHandle to hold the result.
3077             if (fout)
3078             {
3079                 MethodDesc* pMDCtor = pHandleType->GetDefaultConstructor();
3080                 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
3081                 pslIL->EmitSTLOC(dwOutputHandleLocal);
3082
3083                 // If we didn't provide an input handle then we initialize the NativeHandle local with the (initially invalid)
3084                 // handle field set up inside the output handle by the constructor.
3085                 if (!fin)
3086                 {
3087                     pslIL->EmitLDLOC(dwOutputHandleLocal);
3088                     pslIL->EmitLDFLD(tkNativeHandleField);
3089                     pslIL->EmitSTLOC(dwNativeHandleLocal);
3090                 }
3091
3092                 // Remember the handle value we start out with so we know whether to back propagate after the native call.
3093                 pslIL->EmitLDLOC(dwNativeHandleLocal);
3094                 pslIL->EmitSTLOC(dwOldNativeHandleLocal);
3095             }
3096
3097             // Leave the address of the native handle local as the argument to the native method.
3098             pslILDispatch->EmitLDLOCA(dwNativeHandleLocal);
3099
3100             if (fin)
3101             {
3102                 // prevent the CriticalHandle from being finalized during the call-out to native
3103                 pslPostIL->EmitLDARG(argidx);
3104                 pslPostIL->EmitLDIND_REF();
3105                 pslPostIL->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
3106             }
3107
3108             // On the output side we only backpropagate the native handle into the output CriticalHandle and the output
3109             // CriticalHandle to the caller if the native handle actually changed (otherwise we can end up with two
3110             // CriticalHandles wrapping the same native handle, which is bad).
3111             if (fout)
3112             {
3113                 // We will use cleanup stream to avoid leaking the handle on thread abort.
3114                 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx);
3115
3116                 psl->SetCleanupNeeded();
3117                 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
3118
3119                 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
3120
3121                 psl->EmitCheckForArgCleanup(pslCleanupIL,
3122                                             NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx,
3123                                             NDirectStubLinker::BranchIfNotMarshaled,
3124                                             pDoneLabel);
3125
3126                 // If this is an [in, out] handle check if the native handles have changed. If not we're finished.
3127                 if (fin)
3128                 {
3129                     pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
3130                     pslCleanupIL->EmitLDLOC(dwOldNativeHandleLocal);
3131                     pslCleanupIL->EmitCEQ();
3132                     pslCleanupIL->EmitBRTRUE(pDoneLabel);
3133                 }
3134
3135                 // Propagate the native handle into the output CriticalHandle.
3136                 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
3137                 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
3138                 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
3139
3140                 // Propagate the output CriticalHandle back to the caller.
3141                 pslCleanupIL->EmitLDARG(argidx);
3142                 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
3143                 pslCleanupIL->EmitSTIND_REF();
3144
3145                 pslCleanupIL->EmitLabel(pDoneLabel);
3146             }
3147         }
3148         else
3149         {
3150             pslILDispatch->EmitLDARG(argidx);
3151             pslILDispatch->EmitLDFLD(tkNativeHandleField);
3152
3153             // prevent the CriticalHandle from being finalized during the call-out to native
3154             pslPostIL->EmitLDARG(argidx);
3155             pslPostIL->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
3156         }
3157
3158         return OVERRIDDEN;
3159     }
3160     else
3161     {
3162         *pResID = IDS_EE_BADMARSHAL_CRITICALHANDLENATIVETOCOM;
3163         return DISALLOWED;
3164     }
3165 }
3166
3167 //---------------------------------------------------------------------------------------
3168 // 
3169 MarshalerOverrideStatus 
3170 ILCriticalHandleMarshaler::ReturnOverride(
3171     NDirectStubLinker * psl, 
3172     BOOL                fManagedToNative, 
3173     BOOL                fHresultSwap, 
3174     OverrideProcArgs *  pargs, 
3175     UINT       *        pResID)
3176 {
3177     CONTRACTL
3178     {
3179         THROWS;
3180         GC_TRIGGERS;
3181         MODE_ANY;
3182         PRECONDITION(CheckPointer(psl));
3183         PRECONDITION(CheckPointer(pargs));
3184         PRECONDITION(CheckPointer(pResID));            
3185     }
3186     CONTRACTL_END;
3187
3188     if (!fManagedToNative)
3189     {
3190         *pResID = IDS_EE_BADMARSHAL_RETURNSHCOMTONATIVE;
3191         return DISALLOWED;
3192     }
3193
3194     // Returned CriticalHandle parameters must not be abstract.
3195     if (pargs->m_pMT->IsAbstract())
3196     {
3197         *pResID = IDS_EE_BADMARSHAL_ABSTRACTRETCRITICALHANDLE;
3198         return DISALLOWED;
3199     }
3200
3201     ILCodeStream * pslIL         = psl->GetMarshalCodeStream();
3202     ILCodeStream * pslPostIL     = psl->GetReturnUnmarshalCodeStream();
3203     ILCodeStream * pslILDispatch = psl->GetDispatchCodeStream();
3204
3205     // 1) create local for new criticalhandle
3206     // 2) prealloc a criticalhandle
3207     // 3) create local to hold returned handle
3208     // 4) [byref] add byref IntPtr to native sig
3209     // 5) [byref] pass address of local as last arg
3210     // 6) store return value in criticalhandle
3211
3212     // 1) create local for new criticalhandle        
3213     MethodTable * pMT = pargs->m_pMT;
3214     LocalDesc     locDescReturnHandle(pMT);
3215     DWORD         dwReturnHandleLocal;
3216     
3217     dwReturnHandleLocal = pslIL->NewLocal(locDescReturnHandle);
3218     
3219     if (!pMT->HasDefaultConstructor())
3220     {
3221         MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
3222         COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
3223     }
3224
3225     // 2) prealloc a criticalhandle
3226     MethodDesc * pMDCtor = pMT->GetDefaultConstructor();
3227     pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
3228     pslIL->EmitSTLOC(dwReturnHandleLocal);
3229
3230     mdToken tkNativeHandleField = pslPostIL->GetToken(MscorlibBinder::GetField(FIELD__CRITICAL_HANDLE__HANDLE));
3231
3232     // 3) create local to hold returned handle
3233     DWORD dwReturnNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3234
3235     if (fHresultSwap)
3236     {
3237         // initialize the native handle
3238         pslIL->EmitLDLOC(dwReturnHandleLocal);
3239         pslIL->EmitLDFLD(tkNativeHandleField);
3240         pslIL->EmitSTLOC(dwReturnNativeHandleLocal);
3241
3242         pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I4);    // native method returns an HRESULT
3243         
3244         // 4) [byref] add byref IntPtr to native sig
3245         locDescReturnHandle.ElementType[0]  = ELEMENT_TYPE_BYREF;
3246         locDescReturnHandle.ElementType[1]  = ELEMENT_TYPE_I;
3247         locDescReturnHandle.cbType          = 2;
3248         pslIL->SetStubTargetArgType(&locDescReturnHandle, false);   // extra arg is a byref IntPtr
3249
3250         // 5) [byref] pass address of local as last arg
3251         pslILDispatch->EmitLDLOCA(dwReturnNativeHandleLocal);
3252
3253         // We will use cleanup stream to avoid leaking the handle on thread abort.
3254         psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL);
3255
3256         psl->SetCleanupNeeded();
3257         ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
3258         ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
3259
3260         // 6) store return value in criticalhandle
3261         psl->EmitCheckForArgCleanup(pslCleanupIL,
3262                                     NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL,
3263                                     NDirectStubLinker::BranchIfNotMarshaled,
3264                                     pDoneLabel);
3265
3266         pslCleanupIL->EmitLDLOC(dwReturnHandleLocal);
3267         pslCleanupIL->EmitLDLOC(dwReturnNativeHandleLocal);
3268         pslCleanupIL->EmitSTFLD(tkNativeHandleField);
3269         pslCleanupIL->EmitLabel(pDoneLabel);
3270
3271         pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3272     }
3273     else
3274     {
3275         pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I);
3276         pslPostIL->EmitSTLOC(dwReturnNativeHandleLocal);
3277
3278         // 6) store return value in criticalhandle
3279         // The thread abort logic knows that it must not interrupt the stub so we will
3280         // always be able to execute this sequence after returning from the call.
3281         pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3282         pslPostIL->EmitLDLOC(dwReturnNativeHandleLocal);
3283         pslPostIL->EmitSTFLD(tkNativeHandleField);
3284         pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3285     }
3286
3287     return OVERRIDDEN;
3288 } // ILCriticalHandleMarshaler::ReturnOverride
3289
3290
3291 LocalDesc ILArgIteratorMarshaler::GetNativeType()
3292 {
3293     LIMITED_METHOD_CONTRACT;
3294     
3295     return LocalDesc(ELEMENT_TYPE_I); // va_list
3296 }
3297
3298 LocalDesc ILArgIteratorMarshaler::GetManagedType()
3299 {
3300     STANDARD_VM_CONTRACT;
3301     
3302     return LocalDesc(MscorlibBinder::GetClass(CLASS__ARG_ITERATOR));
3303 }
3304
3305 bool ILArgIteratorMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3306 {
3307     LIMITED_METHOD_CONTRACT;
3308     
3309     if (IsByref(dwMarshalFlags))
3310     {
3311         *pErrorResID = IDS_EE_BADMARSHAL_ARGITERATORRESTRICTION;
3312         return false;
3313     }
3314
3315     return true;
3316 }
3317
3318 void ILArgIteratorMarshaler::EmitMarshalArgumentCLRToNative()
3319 {
3320     CONTRACTL
3321     {
3322         STANDARD_VM_CHECK;
3323         PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3324     }
3325     CONTRACTL_END;
3326
3327     EmitSetupSigAndDefaultHomesCLRToNative();
3328     
3329     //
3330     // marshal
3331     //
3332
3333     // Allocate enough memory for va_list
3334     DWORD dwVaListSizeLocal = m_pcsMarshal->NewLocal(LocalDesc(ELEMENT_TYPE_U4));
3335     EmitLoadManagedHomeAddr(m_pcsMarshal);
3336     m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__CALC_VA_LIST_SIZE, 1, 1);
3337     m_pcsMarshal->EmitSTLOC(dwVaListSizeLocal);    
3338     m_pcsMarshal->EmitLDLOC(dwVaListSizeLocal);
3339     m_pcsMarshal->EmitLOCALLOC();
3340     EmitStoreNativeValue(m_pcsMarshal);
3341     
3342     // void MarshalToUnmanagedVaListInternal(cbVaListSize, va_list, VARARGS* data)
3343     EmitLoadNativeValue(m_pcsMarshal);
3344     m_pcsMarshal->EmitLDLOC(dwVaListSizeLocal);
3345     EmitLoadManagedHomeAddr(m_pcsMarshal);
3346     m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_UNMANAGED_VA_LIST_INTERNAL, 3, 0);
3347 }
3348
3349 void ILArgIteratorMarshaler::EmitMarshalArgumentNativeToCLR()
3350 {
3351     CONTRACTL
3352     {
3353         STANDARD_VM_CHECK;
3354         PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3355     }
3356     CONTRACTL_END;
3357
3358     EmitSetupSigAndDefaultHomesNativeToCLR();
3359     
3360     EmitLoadNativeValue(m_pcsMarshal);
3361     EmitLoadManagedHomeAddr(m_pcsMarshal);
3362
3363     // void MarshalToManagedVaList(va_list va, VARARGS *dataout)
3364     m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_MANAGED_VA_LIST_INTERNAL, 2, 0);    
3365 }
3366
3367
3368 LocalDesc ILArrayWithOffsetMarshaler::GetNativeType()
3369 {
3370     LIMITED_METHOD_CONTRACT;
3371     
3372     return LocalDesc(ELEMENT_TYPE_I);
3373 }
3374
3375 LocalDesc ILArrayWithOffsetMarshaler::GetManagedType()
3376 {
3377     STANDARD_VM_CONTRACT;
3378     
3379     return LocalDesc(MscorlibBinder::GetClass(CLASS__ARRAY_WITH_OFFSET));
3380 }
3381
3382 bool ILArrayWithOffsetMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3383 {
3384     LIMITED_METHOD_CONTRACT;
3385     
3386     if (IsCLRToNative(dwMarshalFlags) && !IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && IsOut(dwMarshalFlags))
3387     {
3388         return true;
3389     }    
3390
3391     *pErrorResID = IDS_EE_BADMARSHAL_AWORESTRICTION;
3392
3393     return false;
3394 }
3395
3396 void ILArrayWithOffsetMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
3397 {
3398     CONTRACTL
3399     {
3400         STANDARD_VM_CHECK;
3401
3402         CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwCountLocalNum);
3403         CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwOffsetLocalNum);
3404         CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwPinnedLocalNum);
3405     }
3406     CONTRACTL_END;
3407     
3408     int tokArrayWithOffset_m_array = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_ARRAY));
3409     int tokArrayWithOffset_m_count = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_COUNT));
3410     
3411     ILCodeLabel* pNonNullLabel = pslILEmit->NewCodeLabel();
3412     ILCodeLabel* pSlowAllocPathLabel = pslILEmit->NewCodeLabel();
3413     ILCodeLabel* pDoneLabel = pslILEmit->NewCodeLabel();
3414
3415     m_dwCountLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
3416
3417     //
3418     // Convert the space
3419     //
3420
3421     EmitLoadManagedValue(pslILEmit);
3422     pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3423     pslILEmit->EmitBRTRUE(pNonNullLabel);
3424
3425     pslILEmit->EmitLoadNullPtr();
3426     pslILEmit->EmitBR(pDoneLabel);
3427     pslILEmit->EmitLabel(pNonNullLabel);
3428
3429     EmitLoadManagedValue(pslILEmit);
3430     pslILEmit->EmitLDFLD(tokArrayWithOffset_m_count);
3431     pslILEmit->EmitDUP();
3432     pslILEmit->EmitSTLOC(m_dwCountLocalNum);
3433     pslILEmit->EmitDUP();
3434     pslILEmit->EmitLDC(s_cbStackAllocThreshold);
3435     pslILEmit->EmitCGT_UN();
3436     pslILEmit->EmitBRTRUE(pSlowAllocPathLabel);
3437
3438     // localloc
3439     pslILEmit->EmitLOCALLOC();
3440
3441     pslILEmit->EmitBR(pDoneLabel);
3442     pslILEmit->EmitLabel(pSlowAllocPathLabel);
3443
3444     // AllocCoTaskMem
3445     pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
3446
3447     pslILEmit->EmitLabel(pDoneLabel);
3448     EmitStoreNativeValue(pslILEmit);
3449
3450     //
3451     // Convert the contents
3452     //
3453
3454     int tokArrayWithOffset_m_offset = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_OFFSET));
3455
3456     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
3457
3458     LocalDesc locDescPinned;
3459     locDescPinned.cbType = 2;
3460     locDescPinned.ElementType[0] = ELEMENT_TYPE_PINNED;
3461     locDescPinned.ElementType[1] = ELEMENT_TYPE_OBJECT;
3462     m_dwPinnedLocalNum = pslILEmit->NewLocal(locDescPinned);
3463     m_dwOffsetLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
3464
3465     EmitLoadManagedValue(pslILEmit);
3466     pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3467     pslILEmit->EmitBRFALSE(pNullRefLabel);
3468
3469     EmitLoadManagedValue(pslILEmit);
3470     pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3471     pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3472
3473     EmitLoadNativeValue(pslILEmit);                 // dest
3474
3475     pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3476     pslILEmit->EmitCONV_I();
3477     pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3478     pslILEmit->EmitCALL(METHOD__ARRAY__GET_DATA_PTR_OFFSET_INTERNAL, 1, 1);
3479     pslILEmit->EmitADD(); // TODO Phase5: Use UnsafeAddrOfPinnedArrayElement
3480
3481     EmitLoadManagedValue(pslILEmit);
3482     pslILEmit->EmitLDFLD(tokArrayWithOffset_m_offset);
3483     pslILEmit->EmitDUP();
3484     pslILEmit->EmitSTLOC(m_dwOffsetLocalNum);
3485     pslILEmit->EmitADD();                           // src
3486     pslILEmit->EmitLDLOC(m_dwCountLocalNum);        // len
3487
3488     // static void Memcpy(byte* dest, byte* src, int len)
3489     pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY, 3, 0);
3490
3491     pslILEmit->EmitLDNULL();
3492     pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3493
3494     pslILEmit->EmitLabel(pNullRefLabel);
3495 }
3496
3497 void ILArrayWithOffsetMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
3498 {
3499     CONTRACTL
3500     {
3501         STANDARD_VM_CHECK;
3502
3503         CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwCountLocalNum);
3504         CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwOffsetLocalNum);
3505         CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwPinnedLocalNum);
3506     }
3507     CONTRACTL_END;
3508
3509     int tokArrayWithOffset_m_array = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_ARRAY));
3510
3511     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
3512
3513     EmitLoadManagedValue(pslILEmit);
3514     pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3515     pslILEmit->EmitBRFALSE(pNullRefLabel);
3516     
3517     EmitLoadManagedValue(pslILEmit);
3518     pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3519     pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3520
3521     pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3522     pslILEmit->EmitCONV_I();
3523     pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3524     pslILEmit->EmitCALL(METHOD__ARRAY__GET_DATA_PTR_OFFSET_INTERNAL, 1, 1);
3525     pslILEmit->EmitADD(); // TODO Phase5: Use UnsafeAddrOfPinnedArrayElement
3526
3527     pslILEmit->EmitLDLOC(m_dwOffsetLocalNum);
3528     pslILEmit->EmitADD();                           // dest
3529
3530     EmitLoadNativeValue(pslILEmit);                 // src
3531
3532     pslILEmit->EmitLDLOC(m_dwCountLocalNum);        // len
3533
3534     // static void Memcpy(byte* dest, byte* src, int len)
3535     pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY, 3, 0);
3536
3537     pslILEmit->EmitLDNULL();
3538     pslILEmit->EmitSTLOC(m_dwPinnedLocalNum); 
3539
3540     pslILEmit->EmitLabel(pNullRefLabel);
3541 }
3542
3543 void ILArrayWithOffsetMarshaler::EmitClearNativeTemp(ILCodeStream* pslILEmit)
3544 {
3545     STANDARD_VM_CONTRACT;
3546
3547     ILCodeLabel* pDoneLabel = pslILEmit->NewCodeLabel();
3548     
3549     pslILEmit->EmitLDLOC(m_dwCountLocalNum);
3550     pslILEmit->EmitLDC(s_cbStackAllocThreshold);
3551     pslILEmit->EmitCGT_UN();
3552     pslILEmit->EmitBRFALSE(pDoneLabel);
3553
3554     // CoTaskMemFree
3555     EmitLoadNativeValue(pslILEmit);
3556     pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
3557
3558     pslILEmit->EmitLabel(pDoneLabel);
3559 }
3560
3561 LocalDesc ILAsAnyMarshalerBase::GetNativeType()
3562 {
3563     LIMITED_METHOD_CONTRACT;
3564     
3565     return LocalDesc(ELEMENT_TYPE_I);
3566 }
3567
3568 LocalDesc ILAsAnyMarshalerBase::GetManagedType()
3569 {
3570     LIMITED_METHOD_CONTRACT;
3571     
3572     return LocalDesc(ELEMENT_TYPE_OBJECT);
3573 }
3574
3575 bool ILAsAnyMarshalerBase::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3576 {
3577     WRAPPER_NO_CONTRACT;
3578     
3579     if (IsCLRToNative(dwMarshalFlags) && !IsByref(dwMarshalFlags))
3580     {
3581         return true;
3582     }
3583
3584     *pErrorResID = IDS_EE_BADMARSHAL_ASANYRESTRICTION;
3585     return false;
3586 }
3587
3588 bool ILAsAnyMarshalerBase::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3589 {
3590     LIMITED_METHOD_CONTRACT;
3591     *pErrorResID = IDS_EE_BADMARSHAL_ASANYRESTRICTION;
3592     return false;
3593 }
3594
3595 void ILAsAnyMarshalerBase::EmitMarshalArgumentCLRToNative()
3596 {
3597     CONTRACTL
3598     {
3599         STANDARD_VM_CHECK;
3600         PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3601         CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwMarshalerLocalNum);
3602     }
3603     CONTRACTL_END;
3604
3605     EmitSetupSigAndDefaultHomesCLRToNative();
3606
3607     BYTE inout      = (IsIn(m_dwMarshalFlags) ? ML_IN : 0) | (IsOut(m_dwMarshalFlags) ? ML_OUT : 0);
3608     BYTE fIsAnsi    = IsAnsi() ? 1 : 0;
3609     BYTE fBestFit   = m_pargs->m_pMarshalInfo->GetBestFitMapping();
3610     BYTE fThrow     = m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar();
3611
3612     DWORD dwFlags = 0;
3613     
3614     dwFlags |= inout    << 24;
3615     dwFlags |= fIsAnsi  << 16;
3616     dwFlags |= fThrow   <<  8;
3617     dwFlags |= fBestFit <<  0;
3618
3619     //
3620     // marshal
3621     //
3622
3623     LocalDesc marshalerType(MscorlibBinder::GetClass(CLASS__ASANY_MARSHALER));
3624     m_dwMarshalerLocalNum = m_pcsMarshal->NewLocal(marshalerType);
3625     DWORD dwTmpLocalNum = m_pcsMarshal->NewLocal(ELEMENT_TYPE_I);
3626
3627     m_pcsMarshal->EmitLDC(sizeof(MngdNativeArrayMarshaler));
3628     m_pcsMarshal->EmitLOCALLOC();
3629     m_pcsMarshal->EmitSTLOC(dwTmpLocalNum);
3630
3631     // marshaler = new AsAnyMarshaler(local_buffer)
3632     m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3633     m_pcsMarshal->EmitINITOBJ(m_pcsMarshal->GetToken(marshalerType.InternalToken));
3634
3635     m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3636     m_pcsMarshal->EmitLDLOC(dwTmpLocalNum);
3637     m_pcsMarshal->EmitCALL(METHOD__ASANY_MARSHALER__CTOR, 2, 0);
3638
3639     // nativeValue = marshaler.ConvertToNative(managedValue, flags);
3640     m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3641     EmitLoadManagedValue(m_pcsMarshal);
3642     m_pcsMarshal->EmitLDC(dwFlags);
3643     m_pcsMarshal->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_NATIVE, 3, 1);
3644     EmitStoreNativeValue(m_pcsMarshal);
3645
3646     //
3647     // unmarshal
3648     //
3649     if (IsOut(m_dwMarshalFlags))
3650     {
3651         // marshaler.ConvertToManaged(managedValue, nativeValue)
3652         m_pcsUnmarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3653         EmitLoadManagedValue(m_pcsUnmarshal);
3654         EmitLoadNativeValue(m_pcsUnmarshal);
3655         m_pcsUnmarshal->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_MANAGED, 3, 0);
3656     }
3657
3658     //
3659     // cleanup
3660     //
3661     EmitCleanupCLRToNativeTemp();
3662 }
3663
3664 bool ILAsAnyMarshalerBase::NeedsClearNative()
3665 {
3666     LIMITED_METHOD_CONTRACT;
3667     return true;
3668 }
3669
3670 void ILAsAnyMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit)
3671 {
3672     STANDARD_VM_CONTRACT;
3673
3674     // marshaler.ClearNative(nativeHome)
3675     pslILEmit->EmitLDLOCA(m_dwMarshalerLocalNum);
3676     EmitLoadNativeValue(pslILEmit);
3677     pslILEmit->EmitCALL(METHOD__ASANY_MARSHALER__CLEAR_NATIVE, 2, 0);
3678 }
3679
3680 // we can get away with putting the GetManagedType and GetNativeType on ILMngdMarshaler because
3681 // currently it is only used for reference marshaling where this is appropriate.  If it became
3682 // used for something else, we would want to move this down in the inheritence tree..
3683 LocalDesc ILMngdMarshaler::GetNativeType()
3684 {
3685     LIMITED_METHOD_CONTRACT;
3686     
3687     return LocalDesc(ELEMENT_TYPE_I);
3688 }
3689
3690 LocalDesc ILMngdMarshaler::GetManagedType()
3691 {
3692     LIMITED_METHOD_CONTRACT;
3693     
3694     return LocalDesc(ELEMENT_TYPE_OBJECT);
3695 }
3696
3697 void ILMngdMarshaler::EmitCallMngdMarshalerMethod(ILCodeStream* pslILEmit, MethodDesc *pMD)
3698 {
3699     STANDARD_VM_CONTRACT;
3700
3701     if (pMD != NULL)
3702     {
3703         MetaSig sig(pMD);
3704         UINT numArgs = sig.NumFixedArgs();
3705
3706         if (numArgs == 3)
3707         {
3708             EmitLoadMngdMarshaler(pslILEmit);
3709         }
3710         else
3711         {
3712             _ASSERTE(numArgs == 2);
3713         }
3714
3715         EmitLoadManagedHomeAddr(pslILEmit);
3716         EmitLoadNativeHomeAddr(pslILEmit);
3717
3718         pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), numArgs, 0);
3719     }
3720 }
3721
3722 bool ILNativeArrayMarshaler::UsePinnedArraySpecialCase()
3723 {
3724     if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && (NULL == OleVariant::GetMarshalerForVarType(m_pargs->na.m_vt, TRUE)))
3725     {
3726         return true;
3727     }
3728
3729     return false;
3730 }
3731
3732 void ILNativeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
3733 {
3734     STANDARD_VM_CONTRACT;
3735
3736     if (UsePinnedArraySpecialCase())
3737     {
3738         return;
3739     }
3740             
3741     m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
3742         
3743     pslILEmit->EmitLDC(sizeof(MngdNativeArrayMarshaler));
3744     pslILEmit->EmitLOCALLOC();
3745     pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
3746
3747     CREATE_MARSHALER_CARRAY_OPERANDS mops;
3748     m_pargs->m_pMarshalInfo->GetMops(&mops);
3749
3750     pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
3751
3752     pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(mops.methodTable));
3753     pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
3754
3755     DWORD dwFlags = mops.elementType;
3756     dwFlags |= (((DWORD)mops.bestfitmapping)        << 16);
3757     dwFlags |= (((DWORD)mops.throwonunmappablechar) << 24);
3758     
3759     if (!IsCLRToNative(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
3760     {
3761         // Unmanaged->managed in/out is the only case where we expect the native buffer to contain valid data.
3762         _ASSERTE((dwFlags & MngdNativeArrayMarshaler::FLAG_NATIVE_DATA_VALID) == 0);
3763         dwFlags |= MngdNativeArrayMarshaler::FLAG_NATIVE_DATA_VALID;
3764     }
3765
3766     pslILEmit->EmitLDC(dwFlags);
3767     
3768     pslILEmit->EmitCALL(METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CREATE_MARSHALER, 3, 0);
3769 }
3770
3771
3772 void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNative()
3773 {
3774     CONTRACTL
3775     {
3776         STANDARD_VM_CHECK;
3777         PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3778     }
3779     CONTRACTL_END;
3780
3781     if (UsePinnedArraySpecialCase())
3782     {
3783         //
3784         // Replicate ML_PINNEDISOMORPHICARRAY_C2N_EXPRESS behavior -- note that this
3785         // gives in/out semantics "for free" even if the app doesn't specify one or
3786         // the other.  Since there is no enforcement of this, apps blithely depend
3787         // on it.  
3788         //
3789         
3790         // The base offset should only be 0 for System.Array parameters for which
3791         // OleVariant::GetMarshalerForVarType(vt) should never return NULL.
3792         _ASSERTE(m_pargs->na.m_optionalbaseoffset != 0);
3793
3794         EmitSetupSigAndDefaultHomesCLRToNative();
3795
3796         LocalDesc managedType = GetManagedType();
3797         managedType.MakePinned();
3798
3799         DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedType);
3800         ILCodeLabel* pNullRefLabel = m_pcsMarshal->NewCodeLabel();
3801
3802         m_pcsMarshal->EmitLoadNullPtr();
3803         EmitStoreNativeValue(m_pcsMarshal);
3804
3805         EmitLoadManagedValue(m_pcsMarshal);
3806         m_pcsMarshal->EmitBRFALSE(pNullRefLabel);
3807
3808         EmitLoadManagedValue(m_pcsMarshal);
3809         m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
3810         m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
3811         m_pcsMarshal->EmitCONV_I();
3812         m_pcsMarshal->EmitLDC(m_pargs->na.m_optionalbaseoffset);
3813         m_pcsMarshal->EmitADD();
3814         EmitStoreNativeValue(m_pcsMarshal);
3815
3816         if (g_pConfig->InteropLogArguments())
3817         {
3818             m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
3819         }
3820
3821         m_pcsMarshal->EmitLabel(pNullRefLabel);
3822     }
3823     else
3824     {
3825         ILMngdMarshaler::EmitMarshalArgumentCLRToNative();
3826     }
3827 }
3828
3829 //
3830 // Peek at the SizeParamIndex argument
3831 // 1) See if the SizeParamIndex argument is being passed by ref
3832 // 2) Get the element type of SizeParamIndex argument
3833 // 
3834 BOOL ILNativeArrayMarshaler::CheckSizeParamIndexArg(
3835     const CREATE_MARSHALER_CARRAY_OPERANDS &mops, 
3836     CorElementType *pElementType)
3837 {
3838     CONTRACTL
3839     {
3840         THROWS;
3841         GC_TRIGGERS;
3842         MODE_ANY;
3843         PRECONDITION(m_pargs != NULL);
3844         PRECONDITION(m_pargs->m_pMarshalInfo != NULL);
3845     }
3846     CONTRACTL_END;
3847
3848     MethodDesc *pMD = m_pargs->m_pMarshalInfo->GetMethodDesc();
3849     _ASSERT(pMD);
3850     
3851     Module *pModule = m_pargs->m_pMarshalInfo->GetModule();
3852     _ASSERT(pModule);
3853
3854     SigTypeContext emptyTypeContext;  // this is an empty type context: ndirect and COM calls are guaranteed to not be generics.
3855     MetaSig msig(pMD->GetSignature(), 
3856                  pModule,
3857                  &emptyTypeContext);
3858
3859     //
3860     // Go to the SizeParamIndex argument
3861     // Note that we already have check in place to make sure SizeParamIndex is within range
3862     //
3863     if (msig.HasExplicitThis()) 
3864         msig.SkipArg();
3865
3866     for (int i = 0; i < mops.countParamIdx; ++i)
3867         msig.SkipArg();
3868
3869     msig.NextArg();
3870     
3871     SigPointer sigPointer = msig.GetArgProps();
3872
3873     // Peek into the SizeParamIndex argument
3874     CorElementType elementType;
3875     IfFailThrow(sigPointer.PeekElemType(&elementType));
3876
3877     if (elementType != ELEMENT_TYPE_BYREF)
3878     {
3879         if (elementType == ELEMENT_TYPE_STRING  ||
3880             elementType == ELEMENT_TYPE_ARRAY   ||
3881             elementType == ELEMENT_TYPE_FNPTR   ||
3882             elementType == ELEMENT_TYPE_OBJECT  ||
3883             elementType == ELEMENT_TYPE_SZARRAY ||
3884             elementType == ELEMENT_TYPE_TYPEDBYREF)
3885         {
3886             COMPlusThrow(kMarshalDirectiveException, IDS_EE_SIZECONTROLBADTYPE);
3887         }
3888         
3889         *pElementType = elementType;
3890         return FALSE;
3891     }
3892
3893     // Get the real type    
3894     IfFailThrow(sigPointer.GetElemType(NULL));
3895     IfFailThrow(sigPointer.PeekElemType(&elementType));
3896
3897     // All the integral types are supported
3898     switch(elementType)
3899     {
3900         case ELEMENT_TYPE_I1:
3901         case ELEMENT_TYPE_U1:
3902         case ELEMENT_TYPE_I2:
3903         case ELEMENT_TYPE_U2:
3904         case ELEMENT_TYPE_I4:
3905         case ELEMENT_TYPE_U4:
3906         case ELEMENT_TYPE_I8:
3907         case ELEMENT_TYPE_U8:
3908         case ELEMENT_TYPE_I:
3909         case ELEMENT_TYPE_U:
3910             break;
3911
3912         default :           
3913             COMPlusThrow(kMarshalDirectiveException, IDS_EE_SIZECONTROLBADTYPE);
3914     }
3915
3916     *pElementType = elementType;
3917     return TRUE;
3918 }
3919
3920 //
3921 // Calculate the number of elements and load it into stack
3922 //
3923 void ILNativeArrayMarshaler::EmitLoadElementCount(ILCodeStream* pslILEmit)
3924 {
3925     STANDARD_VM_CONTRACT;
3926
3927     //
3928     // Determine the element count and load into evaluation stack
3929     //    
3930     CREATE_MARSHALER_CARRAY_OPERANDS mops;
3931     m_pargs->m_pMarshalInfo->GetMops(&mops);
3932
3933     if (mops.multiplier != 0)
3934     {
3935         //
3936         // SizeParamIndex arg fix up for LCID
3937         //
3938         unsigned countParamIdx = mops.countParamIdx;
3939         if (!IsCLRToNative(m_dwMarshalFlags))
3940         {
3941             int lcidParamIdx = m_pslNDirect->GetLCIDParamIdx();
3942     
3943             if (lcidParamIdx >= 0 && (unsigned)lcidParamIdx <= countParamIdx)
3944             {
3945                 // the LCID is injected before the count parameter so the index
3946                 // has to be incremented to get the unmanaged parameter number
3947                 countParamIdx++;
3948             }
3949         }
3950
3951         //
3952         // Load SizeParamIndex argument
3953         //
3954         pslILEmit->EmitLDARG(countParamIdx);
3955
3956         //
3957         // By-Ref support
3958         //
3959         
3960         // Is the SizeParamIndex points to a by-ref parameter?
3961         CorElementType sizeParamIndexArgType; 
3962         if (CheckSizeParamIndexArg(mops, &sizeParamIndexArgType))
3963         {
3964             // Load the by-ref parameter
3965             switch (sizeParamIndexArgType)
3966             {                
3967                 case ELEMENT_TYPE_I1:
3968                     pslILEmit->EmitLDIND_I1();
3969                     break;
3970                     
3971                 case ELEMENT_TYPE_U1:
3972                     pslILEmit->EmitLDIND_U1();
3973                     break;
3974                     
3975                 case ELEMENT_TYPE_I2:
3976                     pslILEmit->EmitLDIND_I2();
3977                     break;
3978                     
3979                 case ELEMENT_TYPE_U2:
3980                     pslILEmit->EmitLDIND_U2();
3981                     break;
3982
3983                 case ELEMENT_TYPE_I4:
3984                     pslILEmit->EmitLDIND_I4();
3985                     break;
3986                     
3987                 case ELEMENT_TYPE_U4:
3988                     pslILEmit->EmitLDIND_U4();
3989                     break;
3990
3991                 case ELEMENT_TYPE_U8:
3992                 case ELEMENT_TYPE_I8:   
3993                     pslILEmit->EmitLDIND_I8();
3994                     break;
3995                     
3996                 case ELEMENT_TYPE_I:
3997                 case ELEMENT_TYPE_U:    
3998                     pslILEmit->EmitLDIND_I();
3999                     break;
4000                     
4001                 default :
4002                     // Should not go here because we should've thrown exception
4003                     _ASSERT(FALSE);
4004             }
4005                 
4006         }
4007
4008         pslILEmit->EmitCONV_OVF_I4();
4009         
4010         // multiplier * arg + additive        
4011         pslILEmit->EmitLDC(mops.multiplier);
4012         pslILEmit->EmitMUL_OVF();
4013         pslILEmit->EmitLDC(mops.additive);
4014         pslILEmit->EmitADD_OVF();
4015     }    
4016     else
4017     {
4018         pslILEmit->EmitLDC((int)mops.additive);
4019     }
4020 }
4021
4022 void ILNativeArrayMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
4023 {
4024     STANDARD_VM_CONTRACT;
4025
4026     EmitLoadMngdMarshaler(pslILEmit);
4027     EmitLoadManagedHomeAddr(pslILEmit);
4028     EmitLoadNativeHomeAddr(pslILEmit);
4029
4030     if (IsByref(m_dwMarshalFlags))
4031     {
4032         //
4033         // Reset the element count just in case there is an exception thrown in the code emitted by
4034         // EmitLoadElementCount. The best thing we can do here is to avoid a crash.
4035         //
4036         _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4037         pslILEmit->EmitLDC(0);
4038         pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4039     }
4040
4041     // Dynamically calculate element count using SizeParamIndex argument
4042     EmitLoadElementCount(pslILEmit);
4043
4044     if (IsByref(m_dwMarshalFlags))
4045     {
4046         //
4047         // Save the native array size before converting it to managed and load it again
4048         //
4049         _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4050         pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4051         pslILEmit->EmitLDLOC(m_dwSavedSizeArg);
4052     }
4053     
4054     // MngdNativeArrayMarshaler::ConvertSpaceToManaged
4055     pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0);
4056 }
4057
4058 void ILNativeArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
4059 {
4060     STANDARD_VM_CONTRACT;
4061
4062     if (IsByref(m_dwMarshalFlags))
4063     {
4064         _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4065         
4066         //
4067         // Save the array size before converting it to native
4068         //
4069         EmitLoadManagedValue(pslILEmit);
4070         ILCodeLabel *pManagedHomeIsNull = pslILEmit->NewCodeLabel();
4071         pslILEmit->EmitBRFALSE(pManagedHomeIsNull);        
4072         EmitLoadManagedValue(pslILEmit);
4073         pslILEmit->EmitLDLEN();
4074         pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4075         pslILEmit->EmitLabel(pManagedHomeIsNull);
4076     }
4077
4078         
4079     ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit);
4080 }
4081
4082 void ILNativeArrayMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
4083 {
4084     STANDARD_VM_CONTRACT;
4085
4086     EmitLoadMngdMarshaler(pslILEmit);
4087     EmitLoadNativeHomeAddr(pslILEmit);
4088     EmitLoadNativeSize(pslILEmit);
4089     
4090     pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 3, 0);
4091 }
4092
4093 void ILNativeArrayMarshaler::EmitLoadNativeSize(ILCodeStream* pslILEmit)
4094 {
4095     STANDARD_VM_CONTRACT;
4096  
4097    if (IsByref(m_dwMarshalFlags))
4098     {
4099         _ASSERT(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4100         pslILEmit->EmitLDLOC(m_dwSavedSizeArg);            
4101     }
4102     else
4103     {
4104         pslILEmit->EmitLDC(0);
4105         EmitLoadManagedValue(pslILEmit);
4106         ILCodeLabel *pManagedHomeIsNull = pslILEmit->NewCodeLabel();
4107         pslILEmit->EmitBRFALSE(pManagedHomeIsNull);
4108         pslILEmit->EmitPOP();                       // Pop the 0 on the stack
4109         EmitLoadManagedValue(pslILEmit);       
4110         pslILEmit->EmitLDLEN();
4111         pslILEmit->EmitCONV_OVF_I4();
4112         pslILEmit->EmitLabel(pManagedHomeIsNull);   // Keep the 0 on the stack    
4113     }
4114 }
4115
4116 void ILNativeArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
4117 {
4118     STANDARD_VM_CONTRACT;
4119
4120     EmitLoadMngdMarshaler(pslILEmit);
4121     EmitLoadNativeHomeAddr(pslILEmit);
4122     EmitLoadNativeSize(pslILEmit);
4123    
4124     pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeContentsMethod()), 3, 0);
4125 }
4126
4127 void ILNativeArrayMarshaler::EmitNewSavedSizeArgLocal()
4128 {
4129     STANDARD_VM_CONTRACT;
4130
4131     _ASSERTE(m_dwSavedSizeArg == LOCAL_NUM_UNUSED);
4132     ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
4133     m_dwSavedSizeArg = pcsSetup->NewLocal(ELEMENT_TYPE_I4);
4134     pcsSetup->EmitLDC(0);
4135     pcsSetup->EmitSTLOC(m_dwSavedSizeArg);
4136 }
4137
4138 void ILNativeArrayMarshaler::EmitMarshalArgumentNativeToCLRByref()
4139 {
4140     STANDARD_VM_CONTRACT;
4141
4142     if (IsByref(m_dwMarshalFlags))
4143     {
4144         EmitNewSavedSizeArgLocal();
4145     }
4146     
4147     ILMngdMarshaler::EmitMarshalArgumentNativeToCLRByref();
4148 }
4149
4150 void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNativeByref()
4151 {
4152     STANDARD_VM_CONTRACT;
4153
4154     if (IsByref(m_dwMarshalFlags))
4155     {
4156         EmitNewSavedSizeArgLocal();
4157     }
4158     
4159     ILMngdMarshaler::EmitMarshalArgumentCLRToNativeByref();
4160 }
4161
4162
4163 #ifndef CROSSGEN_COMPILE
4164
4165 FCIMPL3(void, MngdNativeArrayMarshaler::CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags)
4166 {
4167     FCALL_CONTRACT;
4168
4169     // Don't check whether the input values are negative - passing negative size-controlling
4170     // arguments and compensating them with a positive SizeConst has always worked.
4171     pThis->m_pElementMT            = pMT;
4172     pThis->m_vt                    = (VARTYPE)(dwFlags);
4173     pThis->m_NativeDataValid       = (BYTE)((dwFlags & FLAG_NATIVE_DATA_VALID) != 0);
4174     dwFlags &= ~FLAG_NATIVE_DATA_VALID;
4175     pThis->m_BestFitMap            = (BYTE)(dwFlags >> 16);
4176     pThis->m_ThrowOnUnmappableChar = (BYTE)(dwFlags >> 24);
4177     pThis->m_Array                 = TypeHandle();
4178 }
4179 FCIMPLEND
4180
4181 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertSpaceToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4182 {
4183     FCALL_CONTRACT;
4184
4185     HELPER_METHOD_FRAME_BEGIN_0();
4186    
4187     BASEARRAYREF arrayRef = (BASEARRAYREF) *pManagedHome;
4188
4189     if (arrayRef == NULL)
4190     {
4191         *pNativeHome = NULL;
4192     }
4193     else
4194     {
4195         SIZE_T cElements = arrayRef->GetNumComponents();
4196         SIZE_T cbElement = OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT);
4197
4198         if (cbElement == 0)
4199             COMPlusThrow(kArgumentException, IDS_EE_COM_UNSUPPORTED_SIG);
4200
4201         SIZE_T cbArray = cElements;
4202         if ( (!SafeMulSIZE_T(&cbArray, cbElement)) || cbArray > MAX_SIZE_FOR_INTEROP)
4203             COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4204
4205         *pNativeHome = CoTaskMemAlloc(cbArray);
4206         if (*pNativeHome == NULL)
4207             ThrowOutOfMemory();
4208
4209         // initialize the array
4210         FillMemory(*pNativeHome, cbArray, 0);
4211     }
4212
4213     HELPER_METHOD_FRAME_END();
4214 }
4215 FCIMPLEND
4216     
4217 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertContentsToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4218 {
4219     FCALL_CONTRACT;
4220
4221     HELPER_METHOD_FRAME_BEGIN_0();
4222
4223     BASEARRAYREF* pArrayRef = (BASEARRAYREF *) pManagedHome;
4224     
4225     if (*pArrayRef != NULL)
4226     {
4227         const OleVariant::Marshaler* pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, TRUE);
4228         SIZE_T cElements = (*pArrayRef)->GetNumComponents();
4229         if (pMarshaler == NULL || pMarshaler->ComToOleArray == NULL)
4230         {
4231             if ( (!SafeMulSIZE_T(&cElements, OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT))) || cElements > MAX_SIZE_FOR_INTEROP)
4232                 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4233     
4234             _ASSERTE(!GetTypeHandleForCVType(OleVariant::GetCVTypeForVarType(pThis->m_vt)).GetMethodTable()->ContainsPointers());
4235             memcpyNoGCRefs(*pNativeHome, (*pArrayRef)->GetDataPtr(), cElements);
4236         }
4237         else
4238         {
4239             pMarshaler->ComToOleArray(pArrayRef, *pNativeHome, pThis->m_pElementMT, pThis->m_BestFitMap, 
4240                                       pThis->m_ThrowOnUnmappableChar, pThis->m_NativeDataValid, cElements);
4241         }
4242     }
4243     HELPER_METHOD_FRAME_END();
4244 }
4245 FCIMPLEND
4246     
4247 FCIMPL4(void, MngdNativeArrayMarshaler::ConvertSpaceToManaged, MngdNativeArrayMarshaler* pThis,
4248         OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements)
4249 {
4250     FCALL_CONTRACT;
4251
4252     HELPER_METHOD_FRAME_BEGIN_0();
4253
4254     if (*pNativeHome == NULL)
4255     {
4256         SetObjectReference(pManagedHome, NULL, GetAppDomain());
4257     }
4258     else
4259     {
4260         // <TODO>@todo: lookup this class before marshal time</TODO>
4261         if (pThis->m_Array.IsNull())
4262         {
4263             // Get proper array class name & type
4264             pThis->m_Array = OleVariant::GetArrayForVarType(pThis->m_vt, TypeHandle(pThis->m_pElementMT));
4265             if (pThis->m_Array.IsNull())
4266                 COMPlusThrow(kTypeLoadException);
4267         }
4268         //
4269         // Allocate array
4270         //
4271         SetObjectReference(pManagedHome, AllocateArrayEx(pThis->m_Array, &cElements, 1), GetAppDomain());
4272     }    
4273     HELPER_METHOD_FRAME_END();
4274 }
4275 FCIMPLEND
4276     
4277 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertContentsToManaged, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4278 {
4279     FCALL_CONTRACT;
4280
4281     HELPER_METHOD_FRAME_BEGIN_0();
4282     
4283     if (*pNativeHome != NULL)
4284     {
4285         const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, TRUE);
4286     
4287         BASEARRAYREF* pArrayRef = (BASEARRAYREF*) pManagedHome;
4288     
4289         if (pMarshaler == NULL || pMarshaler->OleToComArray == NULL)
4290         {
4291             SIZE_T cElements = (*pArrayRef)->GetNumComponents();
4292             if ( (!SafeMulSIZE_T(&cElements, OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT))) || cElements > MAX_SIZE_FOR_INTEROP)
4293                 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4294     
4295                 // If we are copying variants, strings, etc, we need to use write barrier
4296             _ASSERTE(!GetTypeHandleForCVType(OleVariant::GetCVTypeForVarType(pThis->m_vt)).GetMethodTable()->ContainsPointers());
4297             memcpyNoGCRefs((*pArrayRef)->GetDataPtr(), *pNativeHome, cElements);
4298         }
4299         else
4300         {
4301             pMarshaler->OleToComArray(*pNativeHome, pArrayRef, pThis->m_pElementMT);
4302         }
4303     }
4304     
4305     HELPER_METHOD_FRAME_END();
4306 }
4307 FCIMPLEND
4308
4309 FCIMPL3(void, MngdNativeArrayMarshaler::ClearNative, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4310 {
4311     FCALL_CONTRACT;
4312
4313     HELPER_METHOD_FRAME_BEGIN_0();
4314     
4315     if (*pNativeHome != NULL)
4316     {
4317         DoClearNativeContents(pThis, pNativeHome, cElements);
4318         CoTaskMemFree(*pNativeHome);
4319     }
4320     
4321     HELPER_METHOD_FRAME_END();
4322 }
4323 FCIMPLEND
4324     
4325 FCIMPL3(void, MngdNativeArrayMarshaler::ClearNativeContents, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4326 {
4327     FCALL_CONTRACT;
4328
4329     HELPER_METHOD_FRAME_BEGIN_0();
4330
4331     DoClearNativeContents(pThis, pNativeHome, cElements);
4332     
4333     HELPER_METHOD_FRAME_END();
4334 }
4335 FCIMPLEND
4336
4337 void MngdNativeArrayMarshaler::DoClearNativeContents(MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4338 {
4339     CONTRACTL
4340     {
4341         THROWS;
4342         GC_TRIGGERS;
4343         MODE_COOPERATIVE;
4344     }
4345     CONTRACTL_END;
4346     
4347     if (*pNativeHome != NULL)
4348     {
4349         const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, FALSE);
4350
4351         if (pMarshaler != NULL && pMarshaler->ClearOleArray != NULL)
4352         {
4353             pMarshaler->ClearOleArray(*pNativeHome, cElements, pThis->m_pElementMT);
4354         }
4355     }
4356 }
4357
4358 #endif // CROSSGEN_COMPILE
4359
4360
4361 #ifdef FEATURE_COMINTEROP
4362 void ILSafeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
4363 {
4364     STANDARD_VM_CONTRACT;
4365
4366     m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4367         
4368     pslILEmit->EmitLDC(sizeof(MngdSafeArrayMarshaler));
4369     pslILEmit->EmitLOCALLOC();
4370     pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
4371
4372     CREATE_MARSHALER_CARRAY_OPERANDS mops;
4373     m_pargs->m_pMarshalInfo->GetMops(&mops);
4374
4375     DWORD dwFlags = mops.elementType;
4376     BYTE  fStatic = 0;
4377     
4378     if (NeedsCheckForStatic())
4379     {
4380         fStatic |= MngdSafeArrayMarshaler::SCSF_CheckForStatic;
4381     }
4382     
4383     if (!IsCLRToNative(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
4384     {
4385         // Unmanaged->managed in/out is the only case where we expect the native buffer to contain valid data.
4386         fStatic |= MngdSafeArrayMarshaler::SCSF_NativeDataValid;
4387     }
4388
4389     dwFlags |= fStatic << 16;
4390     dwFlags |= ((BYTE)!!m_pargs->m_pMarshalInfo->GetNoLowerBounds()) << 24;
4391     
4392     pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
4393     pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(mops.methodTable));
4394     pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
4395     pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetArrayRank());
4396     pslILEmit->EmitLDC(dwFlags);
4397
4398     pslILEmit->EmitCALL(METHOD__MNGD_SAFE_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0);
4399 }
4400
4401 void ILSafeArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
4402 {
4403     STANDARD_VM_CONTRACT;
4404     
4405     ILMngdMarshaler::EmitConvertContentsNativeToCLR(pslILEmit);
4406
4407     if (NeedsCheckForStatic())
4408     {
4409         CONSISTENCY_CHECK(-1 == m_dwOriginalManagedLocalNum);
4410         m_dwOriginalManagedLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_OBJECT);
4411         EmitLoadManagedValue(pslILEmit);
4412         pslILEmit->EmitSTLOC(m_dwOriginalManagedLocalNum);
4413     }
4414 }
4415
4416 void ILSafeArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
4417 {
4418     STANDARD_VM_CONTRACT;
4419
4420     EmitLoadMngdMarshaler(pslILEmit);
4421     EmitLoadManagedHomeAddr(pslILEmit);
4422     EmitLoadNativeHomeAddr(pslILEmit);
4423     if (NeedsCheckForStatic())
4424     {
4425         CONSISTENCY_CHECK(-1 != m_dwOriginalManagedLocalNum);
4426         pslILEmit->EmitLDLOC(m_dwOriginalManagedLocalNum);
4427     }
4428     else
4429     {
4430         pslILEmit->EmitLDNULL();
4431     }
4432     pslILEmit->EmitCALL(METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE, 4, 0);
4433 }
4434
4435
4436 #ifndef CROSSGEN_COMPILE
4437
4438 FCIMPL4(void, MngdSafeArrayMarshaler::CreateMarshaler, MngdSafeArrayMarshaler* pThis, MethodTable* pMT, UINT32 iRank, UINT32 dwFlags)
4439 {
4440     FCALL_CONTRACT;
4441
4442     pThis->m_pElementMT    = pMT;
4443     pThis->m_iRank         = iRank;
4444     pThis->m_vt            = (VARTYPE)dwFlags;
4445     pThis->m_fStatic       = (BYTE)(dwFlags >> 16);
4446     pThis->m_nolowerbounds = (BYTE)(dwFlags >> 24);
4447 }
4448 FCIMPLEND
4449
4450 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertSpaceToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4451 {
4452     FCALL_CONTRACT;
4453
4454     if (pThis->m_fStatic & SCSF_IsStatic)
4455         return;
4456     
4457     HELPER_METHOD_FRAME_BEGIN_0();
4458
4459     CONTRACTL
4460     {
4461         THROWS;
4462         GC_TRIGGERS;
4463         MODE_COOPERATIVE;
4464         PRECONDITION(pThis->m_vt != VT_EMPTY);
4465         PRECONDITION(CheckPointer(pThis->m_pElementMT));
4466     }
4467     CONTRACTL_END;
4468     
4469     if (*pManagedHome != NULL)
4470     {
4471         *pNativeHome = (void *) OleVariant::CreateSafeArrayForArrayRef((BASEARRAYREF*) pManagedHome, pThis->m_vt, pThis->m_pElementMT);
4472     }
4473     else
4474     {
4475         *pNativeHome = NULL;
4476     }
4477
4478     HELPER_METHOD_FRAME_END();
4479 }
4480 FCIMPLEND
4481     
4482 FCIMPL4(void, MngdSafeArrayMarshaler::ConvertContentsToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, Object* pOriginalManagedUNSAFE)
4483 {
4484     CONTRACTL
4485     {
4486         FCALL_CHECK;
4487         PRECONDITION(pThis->m_vt != VT_EMPTY);
4488         PRECONDITION(CheckPointer(pThis->m_pElementMT));
4489     }
4490     CONTRACTL_END;
4491
4492     OBJECTREF pOriginalManaged = ObjectToOBJECTREF(pOriginalManagedUNSAFE);
4493     HELPER_METHOD_FRAME_BEGIN_1(pOriginalManaged);
4494
4495     if ((pThis->m_fStatic & SCSF_IsStatic) &&
4496         (*pManagedHome != pOriginalManaged))
4497     {
4498         COMPlusThrow(kInvalidOperationException, IDS_INVALID_REDIM);
4499     }
4500    
4501     if (*pManagedHome != NULL)
4502     {
4503         OleVariant::MarshalSafeArrayForArrayRef((BASEARRAYREF *) pManagedHome,
4504                                                 (SAFEARRAY*)*pNativeHome,
4505                                                 pThis->m_vt,
4506                                                 pThis->m_pElementMT,
4507                                                 (pThis->m_fStatic & SCSF_NativeDataValid));
4508     }
4509
4510     HELPER_METHOD_FRAME_END();
4511 }
4512 FCIMPLEND
4513     
4514 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertSpaceToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4515 {
4516     CONTRACTL
4517     {
4518         FCALL_CHECK;
4519         PRECONDITION(pThis->m_vt != VT_EMPTY);
4520         PRECONDITION(CheckPointer(pThis->m_pElementMT));
4521     }
4522     CONTRACTL_END;
4523     
4524     HELPER_METHOD_FRAME_BEGIN_0();
4525
4526     if (*pNativeHome != NULL)
4527     {
4528         // If the managed array has a rank defined then make sure the rank of the
4529         // SafeArray matches the defined rank.
4530         if (pThis->m_iRank != -1)
4531         {
4532             int iSafeArrayRank = SafeArrayGetDim((SAFEARRAY*) *pNativeHome);
4533             if (pThis->m_iRank != iSafeArrayRank)
4534             {                    
4535                 WCHAR strExpectedRank[64];
4536                 WCHAR strActualRank[64];
4537                 _ltow_s(pThis->m_iRank, strExpectedRank, COUNTOF(strExpectedRank), 10);
4538                 _ltow_s(iSafeArrayRank, strActualRank, COUNTOF(strActualRank), 10);
4539                 COMPlusThrow(kSafeArrayRankMismatchException, IDS_EE_SAFEARRAYRANKMISMATCH, strActualRank, strExpectedRank);
4540             }
4541         }
4542     
4543         if (pThis->m_nolowerbounds)
4544         {
4545             LONG lowerbound;
4546             if ( (SafeArrayGetDim( (SAFEARRAY*)*pNativeHome ) != 1) ||
4547                  (FAILED(SafeArrayGetLBound( (SAFEARRAY*)*pNativeHome, 1, &lowerbound))) ||
4548                  lowerbound != 0 )
4549             {
4550                 COMPlusThrow(kSafeArrayRankMismatchException, IDS_EE_SAFEARRAYSZARRAYMISMATCH);
4551             }
4552         }
4553     
4554         SetObjectReference(pManagedHome,
4555             (OBJECTREF) OleVariant::CreateArrayRefForSafeArray((SAFEARRAY*) *pNativeHome,
4556                                                             pThis->m_vt,
4557                                                             pThis->m_pElementMT), GetAppDomain());
4558     }
4559     else
4560     {
4561         SetObjectReference(pManagedHome, NULL, GetAppDomain());
4562     }
4563
4564     HELPER_METHOD_FRAME_END();
4565 }
4566 FCIMPLEND
4567     
4568 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertContentsToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4569 {
4570     CONTRACTL
4571     {
4572         FCALL_CHECK;
4573         PRECONDITION(pThis->m_vt != VT_EMPTY);
4574         PRECONDITION(CheckPointer(pThis->m_pElementMT));
4575     }
4576     CONTRACTL_END;
4577
4578     SAFEARRAY* pNative = *(SAFEARRAY**)pNativeHome;
4579     HELPER_METHOD_FRAME_BEGIN_0();
4580
4581     if (pNative && pNative->fFeatures & FADF_STATIC)
4582     {
4583         pThis->m_fStatic |= SCSF_IsStatic;
4584     }
4585
4586     if (*pNativeHome != NULL)
4587     {
4588         OleVariant::MarshalArrayRefForSafeArray((SAFEARRAY*)*pNativeHome,
4589                                                 (BASEARRAYREF *) pManagedHome,
4590                                                 pThis->m_vt,
4591                                                 pThis->m_pElementMT);
4592     }
4593     
4594     HELPER_METHOD_FRAME_END();
4595 }
4596 FCIMPLEND
4597     
4598 FCIMPL3(void, MngdSafeArrayMarshaler::ClearNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4599 {
4600     FCALL_CONTRACT;
4601
4602     if (pThis->m_fStatic & SCSF_IsStatic)
4603         return;
4604
4605     HELPER_METHOD_FRAME_BEGIN_0();
4606
4607     if (*pNativeHome != NULL)
4608     {
4609         GCX_PREEMP();
4610         _ASSERTE(GetModuleHandleA("oleaut32.dll") != NULL);
4611         // SafeArray has been created.  Oleaut32.dll must have been loaded.
4612         CONTRACT_VIOLATION(ThrowsViolation);
4613         SafeArrayDestroy((SAFEARRAY*)*pNativeHome);
4614     }
4615     
4616     HELPER_METHOD_FRAME_END();
4617 }
4618 FCIMPLEND
4619
4620 #endif // CROSSGEN_COMPILE
4621
4622
4623 LocalDesc ILHiddenLengthArrayMarshaler::GetNativeType()
4624 {
4625     LIMITED_METHOD_CONTRACT;
4626     return LocalDesc(ELEMENT_TYPE_I);
4627 }
4628
4629 LocalDesc ILHiddenLengthArrayMarshaler::GetManagedType()
4630 {
4631     LIMITED_METHOD_CONTRACT;
4632     return LocalDesc(ELEMENT_TYPE_OBJECT);
4633 }
4634
4635 void ILHiddenLengthArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
4636 {
4637     STANDARD_VM_CONTRACT;
4638
4639     if (!CanUsePinnedArray())
4640     {
4641         m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4642         
4643         pslILEmit->EmitLDC(sizeof(MngdHiddenLengthArrayMarshaler));
4644         pslILEmit->EmitLOCALLOC();
4645         pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
4646
4647         MethodTable *pElementMT = m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().GetMethodTable();
4648         pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
4649         pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(pElementMT));
4650         pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
4651
4652         pslILEmit->EmitLDC(m_pargs->na.m_cbElementSize);
4653         pslILEmit->EmitLDC(m_pargs->na.m_vt);
4654
4655         pslILEmit->EmitCALL(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0);
4656     }
4657 }
4658
4659 void ILHiddenLengthArrayMarshaler::EmitMarshalArgumentCLRToNative()
4660 {
4661     STANDARD_VM_CONTRACT;
4662
4663     // If we can pin the array, then do that rather than marshaling it in a more heavy weight way
4664     // Otherwise, fall back to doing a full marshal
4665     if (CanUsePinnedArray())
4666     {
4667         EmitSetupSigAndDefaultHomesCLRToNative();
4668
4669         LocalDesc managedType = GetManagedType();
4670         managedType.MakePinned();
4671         DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedType);
4672
4673         ILCodeLabel* pMarshalDoneLabel = m_pcsMarshal->NewCodeLabel();
4674
4675         // native = NULL
4676         m_pcsMarshal->EmitLoadNullPtr();
4677         EmitStoreNativeValue(m_pcsMarshal);
4678
4679         // if (managed == null) goto MarshalDone
4680         EmitLoadManagedValue(m_pcsMarshal);
4681         m_pcsMarshal->EmitBRFALSE(pMarshalDoneLabel);
4682
4683         // pinnedLocal = managed;
4684         EmitLoadManagedValue(m_pcsMarshal);
4685         m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
4686
4687         // native = pinnedLocal + dataOffset
4688         m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
4689         m_pcsMarshal->EmitCONV_I();
4690         m_pcsMarshal->EmitLDC(m_pargs->na.m_optionalbaseoffset);
4691         m_pcsMarshal->EmitADD();
4692         EmitStoreNativeValue(m_pcsMarshal);
4693
4694         if (g_pConfig->InteropLogArguments())
4695         {
4696             m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
4697         }
4698
4699         // MarshalDone:
4700         m_pcsMarshal->EmitLabel(pMarshalDoneLabel);
4701     }
4702     else
4703     {
4704         ILMngdMarshaler::EmitMarshalArgumentCLRToNative();
4705     }
4706
4707 }
4708
4709 void ILHiddenLengthArrayMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
4710 {
4711     STANDARD_VM_CONTRACT;
4712
4713     if (!CanUsePinnedArray())
4714     {
4715         EmitLoadMngdMarshaler(pslILEmit);
4716         EmitLoadManagedHomeAddr(pslILEmit);
4717         EmitLoadNativeHomeAddr(pslILEmit);
4718         EmitLoadNativeArrayLength(pslILEmit);
4719         
4720         // MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged
4721         pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0);
4722     }
4723 }
4724
4725 void ILHiddenLengthArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
4726 {
4727     STANDARD_VM_CONTRACT;
4728
4729     // If we're marshaling out to native code, then we need to set the length out parameter
4730     if (!IsCLRToNative(m_dwMarshalFlags))
4731     {
4732         if (IsByref(m_dwMarshalFlags) || IsRetval(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags))
4733         {
4734             ILCodeLabel *pSkipGetLengthLabel = m_pcsMarshal->NewCodeLabel();
4735
4736             // nativeLen = 0
4737             pslILEmit->EmitLDC(0);
4738             pslILEmit->EmitCONV_T(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4739             pslILEmit->EmitSTLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4740
4741             // if (array == null) goto SkipGetLength
4742             EmitLoadManagedValue(pslILEmit);
4743             pslILEmit->EmitBRFALSE(pSkipGetLengthLabel);
4744
4745             // nativeLen = array.Length
4746             // SkipGetLength:
4747             EmitLoadManagedValue(pslILEmit);
4748             pslILEmit->EmitLDLEN();
4749             pslILEmit->EmitCONV_T(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4750             pslILEmit->EmitSTLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4751             pslILEmit->EmitLabel(pSkipGetLengthLabel);
4752
4753             // nativeLenParam = nativeLen
4754             LocalDesc nativeParamType(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4755             pslILEmit->EmitLDARG(m_pargs->m_pMarshalInfo->HiddenLengthParamIndex());
4756             pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4757             pslILEmit->EmitSTIND_T(&nativeParamType);
4758         }
4759     }
4760
4761     if (!CanUsePinnedArray())
4762     {
4763         ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit);
4764     }
4765 }
4766
4767 void ILHiddenLengthArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
4768 {
4769     STANDARD_VM_CONTRACT;
4770
4771     if (!CanUsePinnedArray())
4772     {
4773         if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE &&
4774             (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri ||
4775              m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs ||
4776              m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs))
4777         {
4778             // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop
4779             DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
4780             DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4781             ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel();
4782             ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel();
4783
4784             // for (IntPtr ptr = pNative, int i = 0; ...
4785             pslILEmit->EmitLDC(0);
4786             pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4787             EmitLoadNativeValue(pslILEmit);
4788             pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4789             pslILEmit->EmitBR(pConditionLabel);
4790
4791             // *ptr = EmitConvertCLR*ToWinRT*(pManaged[i]);
4792             pslILEmit->EmitLabel(pLoopBodyLabel);
4793             pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4794             EmitLoadManagedValue(pslILEmit);
4795             pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4796             pslILEmit->EmitLDELEM_REF();
4797
4798             switch (m_pargs->na.m_redirectedTypeIndex)
4799             {
4800                 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4801                     ILUriMarshaler::EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4802                     break;
4803
4804                 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4805                     ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4806                     break;
4807
4808                 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4809                     ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4810                     break;
4811
4812                 default: UNREACHABLE();
4813             }
4814
4815             pslILEmit->EmitSTIND_I();
4816
4817             // ... i++, ptr += IntPtr.Size ...
4818             pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4819             pslILEmit->EmitLDC(1);
4820             pslILEmit->EmitADD();
4821             pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4822             pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4823             pslILEmit->EmitLDC(sizeof(LPVOID));
4824             pslILEmit->EmitADD();
4825             pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4826
4827             // ... i < pManaged.Length; ...
4828             pslILEmit->EmitLabel(pConditionLabel);
4829             pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4830             EmitLoadNativeArrayLength(pslILEmit);
4831             pslILEmit->EmitBLT(pLoopBodyLabel);
4832         }            
4833         else
4834         {
4835             ILMngdMarshaler::EmitConvertContentsCLRToNative(pslILEmit);
4836         }
4837     }
4838 }
4839
4840 void ILHiddenLengthArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
4841 {
4842     STANDARD_VM_CONTRACT;
4843
4844     if (!CanUsePinnedArray())
4845     {
4846         if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE &&
4847             (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri ||
4848              m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs ||
4849              m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs))
4850         {
4851             // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop
4852             DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
4853             DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4854             ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel();
4855             ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel();
4856
4857             // for (IntPtr ptr = pNative, int i = 0; ...
4858             pslILEmit->EmitLDC(0);
4859             pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4860             EmitLoadNativeValue(pslILEmit);
4861             pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4862             pslILEmit->EmitBR(pConditionLabel);
4863
4864             // pManaged[i] = EmitConvertWinRT*ToCLR*(*ptr);
4865             pslILEmit->EmitLabel(pLoopBodyLabel);
4866             EmitLoadManagedValue(pslILEmit);
4867             pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4868             pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4869             pslILEmit->EmitLDIND_I();
4870
4871             switch (m_pargs->na.m_redirectedTypeIndex)
4872             {
4873                 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4874                     ILUriMarshaler::EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4875                     break;
4876
4877                 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4878                     ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4879                     break;
4880
4881                 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4882                     ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4883                     break;
4884
4885                 default: UNREACHABLE();
4886             }
4887             
4888             pslILEmit->EmitSTELEM_REF();
4889
4890             // ... i++, ptr += IntPtr.Size)
4891             pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4892             pslILEmit->EmitLDC(1);
4893             pslILEmit->EmitADD();
4894             pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4895             pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4896             pslILEmit->EmitLDC(sizeof(LPVOID));
4897             pslILEmit->EmitADD();
4898             pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4899
4900             // ... i < pManaged.Length; ...
4901             pslILEmit->EmitLabel(pConditionLabel);
4902             pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4903             EmitLoadNativeArrayLength(pslILEmit);
4904             pslILEmit->EmitBLT(pLoopBodyLabel);
4905         }            
4906         else
4907         {
4908             ILMngdMarshaler::EmitConvertContentsNativeToCLR(pslILEmit);
4909         }
4910     }
4911 }
4912
4913 void ILHiddenLengthArrayMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
4914 {
4915     STANDARD_VM_CONTRACT;
4916
4917     EmitClearNativeContents(pslILEmit);
4918
4919     if (!CanUsePinnedArray())
4920     {
4921         EmitLoadNativeValue(pslILEmit);
4922         pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 1, 0);
4923     }
4924 }
4925
4926 void ILHiddenLengthArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
4927 {
4928     STANDARD_VM_CONTRACT;
4929
4930     if (!CanUsePinnedArray())
4931     {
4932         MethodDesc *pMD = GetClearNativeContentsMethod();
4933         if (pMD != NULL)
4934         {
4935             MetaSig sig(pMD);
4936             UINT numArgs = sig.NumFixedArgs();
4937
4938             if (numArgs == 3)
4939             {
4940                 EmitLoadMngdMarshaler(pslILEmit);
4941             }
4942             else
4943             {
4944                 _ASSERTE(numArgs == 2);
4945             }
4946
4947             EmitLoadNativeHomeAddr(pslILEmit);
4948             EmitLoadNativeArrayLength(pslILEmit);
4949             pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), numArgs, 0);
4950         }
4951     }
4952 }
4953
4954 // Determine if we can simply pin the managed array, rather than doing a full marshal
4955 bool ILHiddenLengthArrayMarshaler::CanUsePinnedArray()
4956 {
4957     STANDARD_VM_CONTRACT;
4958
4959     // If the array is only going from managed to native, and it contains only blittable data, and
4960     // we know where that data is located in the array then we can take the fast path
4961     if (!IsCLRToNative(m_dwMarshalFlags))
4962     {
4963         return false;
4964     }
4965
4966     if (m_pargs->na.m_vt != VTHACK_BLITTABLERECORD)
4967     {
4968         return false;
4969     }
4970
4971     if (IsByref(m_dwMarshalFlags))
4972     {
4973         return false;
4974     }
4975
4976     if (!IsIn(m_dwMarshalFlags))
4977     {
4978         return false;
4979     }
4980
4981     if (IsRetval(m_dwMarshalFlags))
4982     {
4983         return false;
4984     }
4985
4986     if (m_pargs->na.m_optionalbaseoffset == 0)
4987     {
4988         return false;
4989     }
4990
4991     return true;
4992 }
4993
4994 void ILHiddenLengthArrayMarshaler::EmitLoadNativeArrayLength(ILCodeStream *pslILEmit)
4995 {
4996     STANDARD_VM_CONTRACT;
4997
4998     // For return values, the native length won't yet be marshaled back to its managed home
4999     // so it needs to be read directly
5000     if (IsRetval(m_dwMarshalFlags))
5001     {
5002         pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
5003     }
5004     else
5005     {
5006         pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthManagedHome());
5007     }
5008
5009     pslILEmit->EmitCONV_OVF_I4();
5010 }
5011
5012 MethodDesc *ILHiddenLengthArrayMarshaler::GetConvertContentsToManagedMethod()
5013 {
5014     STANDARD_VM_CONTRACT;
5015
5016     if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE)
5017     {
5018         switch (m_pargs->na.m_redirectedTypeIndex)
5019         {
5020             case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
5021                 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_DATETIME);
5022
5023             case WinMDAdapter::RedirectedTypeIndex_System_Type:
5024                 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_TYPE);
5025
5026             case WinMDAdapter::RedirectedTypeIndex_System_Exception:
5027                 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_EXCEPTION);
5028
5029             case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5030             {
5031                 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_NULLABLE);
5032                 return GetExactMarshalerMethod(pMD);
5033             }
5034
5035             case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5036             {
5037                 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_KEYVALUEPAIR);
5038                 return GetExactMarshalerMethod(pMD);
5039             }
5040
5041             default:
5042                 UNREACHABLE_MSG("Unrecognized redirected type.");
5043         }
5044     }
5045     return ILMngdMarshaler::GetConvertContentsToManagedMethod();
5046 }
5047
5048 MethodDesc *ILHiddenLengthArrayMarshaler::GetConvertContentsToNativeMethod()
5049 {
5050     STANDARD_VM_CONTRACT;
5051
5052     if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE)
5053     {
5054         switch (m_pargs->na.m_redirectedTypeIndex)
5055         {
5056             case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
5057                 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_DATETIME);
5058
5059             case WinMDAdapter::RedirectedTypeIndex_System_Type:
5060                 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_TYPE);
5061
5062             case WinMDAdapter::RedirectedTypeIndex_System_Exception:
5063                 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_EXCEPTION);
5064
5065             case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5066             {
5067                 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_NULLABLE);
5068                 return GetExactMarshalerMethod(pMD);
5069             }
5070
5071             case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5072             {
5073                 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_KEYVALUEPAIR);
5074                 return GetExactMarshalerMethod(pMD);
5075             }
5076
5077             default:
5078                 UNREACHABLE_MSG("Unrecognized redirected type.");
5079         }
5080     }
5081     return ILMngdMarshaler::GetConvertContentsToNativeMethod();
5082 }
5083
5084 MethodDesc *ILHiddenLengthArrayMarshaler::GetClearNativeContentsMethod()
5085 {
5086     switch (m_pargs->na.m_vt)
5087     {
5088         // HSTRINGs, interface pointers, and non-blittable structs need contents cleanup
5089         case VTHACK_HSTRING:
5090         case VTHACK_INSPECTABLE:
5091         case VTHACK_NONBLITTABLERECORD:
5092             break;
5093
5094         // blittable structs don't need contents cleanup
5095         case VTHACK_BLITTABLERECORD:
5096             return NULL;
5097
5098         case VTHACK_REDIRECTEDTYPE:
5099         {
5100             switch (m_pargs->na.m_redirectedTypeIndex)
5101             {
5102                 // System.Type, Uri, Nullable, KeyValuePair, NCCEventArgs, and PCEventArgs need cleanup
5103                 case WinMDAdapter::RedirectedTypeIndex_System_Type:
5104                     return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS_TYPE);
5105
5106                 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
5107                 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5108                 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5109                 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
5110                 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
5111                     break;
5112
5113                 // other redirected types don't
5114                 default:
5115                     return NULL;
5116             }
5117             break;
5118         }
5119
5120         default:
5121             UNREACHABLE_MSG("Unexpected hidden-length array element VT");
5122     }
5123
5124     return ILMngdMarshaler::GetClearNativeContentsMethod();
5125 }
5126
5127 MethodDesc *ILHiddenLengthArrayMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
5128 {
5129     STANDARD_VM_CONTRACT;
5130
5131     return MethodDesc::FindOrCreateAssociatedMethodDesc(
5132         pGenericMD,
5133         pGenericMD->GetMethodTable(),
5134         FALSE,                                 // forceBoxedEntryPoint
5135         m_pargs->na.m_pMT->GetInstantiation(), // methodInst
5136         FALSE,                                 // allowInstParam
5137         TRUE);                                 // forceRemotableMethod
5138 }
5139
5140 #ifndef CROSSGEN_COMPILE
5141
5142 FCIMPL4(void, MngdHiddenLengthArrayMarshaler::CreateMarshaler, MngdHiddenLengthArrayMarshaler* pThis, MethodTable* pMT, SIZE_T cbElementSize, UINT16 vt)
5143 {
5144     FCALL_CONTRACT;
5145
5146     pThis->m_pElementMT = pMT;
5147     pThis->m_cbElementSize = cbElementSize;
5148     pThis->m_vt = (VARTYPE)vt;
5149 }
5150 FCIMPLEND
5151
5152 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertSpaceToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5153 {
5154     FCALL_CONTRACT;
5155
5156     BASEARRAYREF arrayRef = (BASEARRAYREF) *pManagedHome;
5157     HELPER_METHOD_FRAME_BEGIN_1(arrayRef);
5158
5159     if (arrayRef == NULL)
5160     {
5161         *pNativeHome = NULL;
5162     }
5163     else
5164     {
5165         SIZE_T cbArray = pThis->GetArraySize(arrayRef->GetNumComponents());
5166
5167         *pNativeHome = CoTaskMemAlloc(cbArray);
5168         if (*pNativeHome == NULL)
5169         {
5170             ThrowOutOfMemory();
5171         }
5172
5173         // initialize the array
5174         FillMemory(*pNativeHome, cbArray, 0);
5175     }
5176
5177     HELPER_METHOD_FRAME_END();
5178 }
5179 FCIMPLEND
5180     
5181 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertContentsToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5182 {
5183     FCALL_CONTRACT;
5184     
5185     struct
5186     {
5187         PTRARRAYREF arrayRef;
5188         STRINGREF currentStringRef;
5189         OBJECTREF currentObjectRef;
5190     }
5191     gc;
5192     ZeroMemory(&gc, sizeof(gc));
5193     gc.arrayRef = (PTRARRAYREF)*pManagedHome;
5194
5195     HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
5196
5197     if (gc.arrayRef != NULL)
5198     {
5199         // There are these choices:
5200         //  * the array is made up of entirely blittable data, in which case we can directly copy it, 
5201         //  * it is an array of strings that need to be marshaled as HSTRING, 
5202         //  * it is an array of non-blittable structures
5203         //  * it is an array of interface pointers (interface, runtime class, delegate, System.Object)
5204         switch (pThis->m_vt)
5205         {
5206             case VTHACK_BLITTABLERECORD:
5207             {
5208                 // Just do a raw memcpy into the array
5209                 SIZE_T cbArray = pThis->GetArraySize(gc.arrayRef->GetNumComponents());
5210                 memcpyNoGCRefs(*pNativeHome, gc.arrayRef->GetDataPtr(), cbArray);
5211                 break;
5212             }
5213
5214             case VTHACK_HSTRING:
5215             {
5216                 // Marshal a string array as an array of HSTRINGs
5217                 if (!WinRTSupported())
5218                 {
5219                     COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
5220                 }
5221
5222                 HSTRING *pDestinationStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5223
5224                 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5225                 {
5226                     gc.currentStringRef = (STRINGREF)gc.arrayRef->GetAt(i);
5227                     if (gc.currentStringRef == NULL)
5228                     {
5229                         StackSString ssIndex;
5230                         ssIndex.Printf(W("%d"), i);
5231                         COMPlusThrow(kMarshalDirectiveException, IDS_EE_BADMARSHALARRAY_NULL_HSTRING, ssIndex.GetUnicode());
5232                     }
5233
5234                     IfFailThrow(WindowsCreateString(gc.currentStringRef->GetBuffer(), gc.currentStringRef->GetStringLength(), &(pDestinationStrings[i])));
5235                 }
5236                 break;
5237             }
5238
5239             case VTHACK_NONBLITTABLERECORD:
5240             {
5241                 BYTE *pNativeStart = reinterpret_cast<BYTE *>(*pNativeHome);
5242                 SIZE_T managedOffset = ArrayBase::GetDataPtrOffset(gc.arrayRef->GetMethodTable());
5243                 SIZE_T nativeOffset = 0;
5244                 SIZE_T managedSize = gc.arrayRef->GetComponentSize();
5245                 SIZE_T nativeSize = pThis->m_pElementMT->GetNativeSize();
5246                 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5247                 {
5248                     LayoutUpdateNative(reinterpret_cast<LPVOID *>(&gc.arrayRef), managedOffset, pThis->m_pElementMT, pNativeStart + nativeOffset, NULL);
5249                     managedOffset += managedSize;
5250                     nativeOffset += nativeSize;
5251                 }
5252                 break;
5253             }
5254
5255             case VTHACK_INSPECTABLE:
5256             {
5257                 // interface pointers
5258                 IUnknown **pDestinationIPs = reinterpret_cast<IUnknown **>(*pNativeHome);
5259                 
5260                 // If this turns out to be a perf issue, we can precompute the ItfMarshalInfo
5261                 // and generate code that passes it to the marshaler at creation time.
5262                 ItfMarshalInfo itfInfo;
5263                 MarshalInfo::GetItfMarshalInfo(TypeHandle(pThis->m_pElementMT), TypeHandle(), FALSE, TRUE, MarshalInfo::MARSHAL_SCENARIO_WINRT, &itfInfo);
5264
5265                 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5266                 {
5267                     gc.currentObjectRef = gc.arrayRef->GetAt(i);
5268                     pDestinationIPs[i] = MarshalObjectToInterface(
5269                         &gc.currentObjectRef, 
5270                         itfInfo.thNativeItf.GetMethodTable(),  
5271                         itfInfo.thClass.GetMethodTable(),
5272                         itfInfo.dwFlags);
5273                 }
5274                 break;
5275             }
5276
5277             default:
5278                 UNREACHABLE_MSG("Unrecognized array element VARTYPE");
5279
5280         }
5281     }
5282     HELPER_METHOD_FRAME_END();
5283 }
5284 FCIMPLEND
5285     
5286 FCIMPL4(void, MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements)
5287 {
5288     FCALL_CONTRACT;
5289
5290     HELPER_METHOD_FRAME_BEGIN_0();
5291
5292     if (*pNativeHome == NULL)
5293     {
5294         SetObjectReference(pManagedHome, NULL, GetAppDomain());
5295     }
5296     else
5297     {
5298         TypeHandle elementType(pThis->m_pElementMT);
5299         TypeHandle arrayType = ClassLoader::LoadArrayTypeThrowing(elementType);
5300         SetObjectReference(pManagedHome, AllocateArrayEx(arrayType, &cElements, 1), GetAppDomain());
5301     }
5302
5303     HELPER_METHOD_FRAME_END();
5304 }
5305 FCIMPLEND
5306     
5307 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertContentsToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5308 {
5309     FCALL_CONTRACT;
5310
5311     struct
5312     {
5313         PTRARRAYREF arrayRef;
5314         STRINGREF   stringRef;
5315         OBJECTREF   objectRef;
5316     }
5317     gc;
5318     ZeroMemory(&gc, sizeof(gc));
5319     gc.arrayRef = (PTRARRAYREF)*pManagedHome;
5320
5321     HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
5322
5323     if (*pNativeHome != NULL)
5324     {
5325         // There are these choices:
5326         //  * the array is made up of entirely blittable data, in which case we can directly copy it, 
5327         //  * it is an array of strings that need to be marshaled as HSTRING, 
5328         //  * it is an array of non-blittable structures
5329         //  * it is an array of interface pointers (interface, runtime class, delegate, System.Object)
5330         switch (pThis->m_vt)
5331         {
5332             case VTHACK_BLITTABLERECORD:
5333             {
5334                 // Just do a raw memcpy into the array
5335                 SIZE_T cbArray = pThis->GetArraySize(gc.arrayRef->GetNumComponents());
5336                 memcpyNoGCRefs(gc.arrayRef->GetDataPtr(), *pNativeHome, cbArray);
5337                 break;
5338             }
5339
5340             case VTHACK_HSTRING:
5341             {
5342                 // Strings are in HSRING format on the native side
5343                 if (!WinRTSupported())
5344                 {
5345                     COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
5346                 }
5347
5348                 HSTRING *pSourceStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5349
5350                 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5351                 {
5352                     // NULL HSTRINGS are equivilent to empty strings
5353                     UINT32 cchString = 0;
5354                     LPCWSTR pwszString = W("");
5355
5356                     if (pSourceStrings[i] != NULL)
5357                     {
5358                         pwszString = WindowsGetStringRawBuffer(pSourceStrings[i], &cchString);
5359                     }
5360
5361                     gc.stringRef = StringObject::NewString(pwszString, cchString);
5362                     gc.arrayRef->SetAt(i, gc.stringRef);
5363                 }
5364                 break;
5365             }
5366
5367             case VTHACK_NONBLITTABLERECORD:
5368             {
5369                 // Defer to the field marshaler to handle structures
5370                 BYTE *pNativeStart = reinterpret_cast<BYTE *>(*pNativeHome);
5371                 SIZE_T managedOffset = ArrayBase::GetDataPtrOffset(gc.arrayRef->GetMethodTable());
5372                 SIZE_T nativeOffset = 0;
5373                 SIZE_T managedSize = gc.arrayRef->GetComponentSize();
5374                 SIZE_T nativeSize = pThis->m_pElementMT->GetNativeSize();
5375                 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5376                 {
5377                     LayoutUpdateCLR(reinterpret_cast<LPVOID *>(&gc.arrayRef), managedOffset, pThis->m_pElementMT, pNativeStart + nativeOffset);
5378                     managedOffset += managedSize;
5379                     nativeOffset += nativeSize;
5380                 }
5381                 break;
5382             }
5383
5384             case VTHACK_INSPECTABLE:
5385             {
5386                 // interface pointers
5387                 IUnknown **pSourceIPs = reinterpret_cast<IUnknown **>(*pNativeHome);
5388
5389                 // If this turns out to be a perf issue, we can precompute the ItfMarshalInfo
5390                 // and generate code that passes it to the marshaler at creation time.
5391                 ItfMarshalInfo itfInfo;
5392                 MarshalInfo::GetItfMarshalInfo(TypeHandle(pThis->m_pElementMT), TypeHandle(), FALSE, TRUE, MarshalInfo::MARSHAL_SCENARIO_WINRT, &itfInfo);
5393
5394                 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5395                 {
5396                     gc.objectRef = gc.arrayRef->GetAt(i);
5397                     UnmarshalObjectFromInterface(
5398                         &gc.objectRef,
5399                         &pSourceIPs[i],
5400                         itfInfo.thItf.GetMethodTable(),  
5401                         itfInfo.thClass.GetMethodTable(),
5402                         itfInfo.dwFlags);
5403                     gc.arrayRef->SetAt(i, gc.objectRef);
5404                 }
5405                 break;
5406             }
5407
5408             default:
5409                 UNREACHABLE_MSG("Unrecognized array element VARTYPE");
5410         }
5411     }
5412     
5413     HELPER_METHOD_FRAME_END();
5414 }
5415 FCIMPLEND
5416
5417 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ClearNativeContents, MngdHiddenLengthArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
5418 {
5419     FCALL_CONTRACT;
5420     
5421     HELPER_METHOD_FRAME_BEGIN_0();
5422
5423     if (*pNativeHome != NULL)
5424     {
5425         pThis->DoClearNativeContents(pNativeHome, cElements);
5426     }
5427
5428     HELPER_METHOD_FRAME_END();
5429 }
5430 FCIMPLEND
5431
5432 #endif // CROSSGEN_COMPILE
5433
5434
5435 SIZE_T MngdHiddenLengthArrayMarshaler::GetArraySize(SIZE_T elements)
5436 {
5437     CONTRACTL
5438     {
5439         THROWS;
5440         GC_TRIGGERS;
5441         MODE_COOPERATIVE;
5442     }
5443     CONTRACTL_END;
5444
5445     _ASSERTE_MSG(m_cbElementSize != 0, "You have to set the native size for your array element type");
5446
5447     SIZE_T cbArray;
5448
5449     if (!ClrSafeInt<SIZE_T>::multiply(elements, m_cbElementSize, cbArray))
5450     {
5451         COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
5452     }
5453
5454     // This array size limit is carried over from the equivilent limit for other array marshaling code
5455     if (cbArray > MAX_SIZE_FOR_INTEROP)
5456     {
5457         COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
5458     }
5459
5460     return cbArray;
5461 }
5462
5463 #ifndef CROSSGEN_COMPILE
5464 void MngdHiddenLengthArrayMarshaler::DoClearNativeContents(void** pNativeHome, INT32 cElements)
5465 {
5466     CONTRACTL
5467     {
5468         THROWS;
5469         GC_TRIGGERS;
5470         MODE_COOPERATIVE;
5471         PRECONDITION(pNativeHome != NULL);
5472     }
5473     CONTRACTL_END;
5474
5475     VARTYPE vt = m_vt;
5476     if (vt == VTHACK_REDIRECTEDTYPE)
5477     {
5478         // the redirected types that use this helper are interface pointers on the WinRT side
5479         vt = VTHACK_INSPECTABLE;
5480     }
5481
5482     switch (vt)
5483     {
5484         case VTHACK_HSTRING:
5485         {
5486             if (WinRTSupported())
5487             {
5488                 HSTRING *pStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5489                 for (INT32 i = 0; i < cElements; ++i)
5490                 {
5491                     if (pStrings[i] != NULL)
5492                     {
5493                         WindowsDeleteString(pStrings[i]);
5494                     }
5495                 }
5496             }
5497             break;
5498         }
5499
5500         case VTHACK_NONBLITTABLERECORD:
5501         {
5502             SIZE_T cbArray = GetArraySize(cElements);
5503             BYTE *pNativeCurrent = reinterpret_cast<BYTE *>(*pNativeHome);
5504             BYTE *pNativeEnd = pNativeCurrent + cbArray;
5505
5506             while (pNativeCurrent < pNativeEnd)
5507             {
5508                 LayoutDestroyNative(pNativeCurrent, m_pElementMT);
5509                 pNativeCurrent += m_pElementMT->GetNativeSize();
5510             }
5511             break;
5512         }
5513     
5514         case VTHACK_INSPECTABLE:
5515         {
5516             IInspectable **pIPs = reinterpret_cast<IInspectable **>(*pNativeHome);
5517             for (INT32 i = 0; i < cElements; ++i)
5518             {
5519                 if (pIPs[i] != NULL)
5520                 {
5521                     SafeRelease(pIPs[i]);
5522                 }
5523             }
5524             break;
5525         }
5526             
5527         default:
5528             UNREACHABLE_MSG("Unexpected hidden-length array element VT");
5529     }    
5530 }
5531 #endif //CROSSGEN_COMPILE
5532 #endif // FEATURE_COMINTEROP
5533
5534 void ILReferenceCustomMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
5535 {
5536     CONTRACTL
5537     {
5538         STANDARD_VM_CHECK;
5539         PRECONDITION(-1 == m_dwMngdMarshalerLocalNum);
5540     }
5541     CONTRACTL_END;
5542     
5543     //
5544     // allocate space for marshaler
5545     //
5546
5547     m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
5548
5549     pslILEmit->EmitLDC(sizeof(MngdRefCustomMarshaler));
5550     pslILEmit->EmitLOCALLOC();
5551     pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
5552
5553     pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);    // arg to CreateMarshaler
5554     
5555     //
5556     // call CreateCustomMarshalerHelper
5557     //
5558
5559     pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->rcm.m_pMD));
5560     pslILEmit->EmitCALL(METHOD__METHOD_HANDLE__GETVALUEINTERNAL, 1, 1);
5561
5562     pslILEmit->EmitLDC(m_pargs->rcm.m_paramToken);
5563
5564     pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(TypeHandle::FromPtr(m_pargs->rcm.m_hndManagedType)));
5565     pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
5566
5567     pslILEmit->EmitCALL(METHOD__STUBHELPERS__CREATE_CUSTOM_MARSHALER_HELPER, 3, 1);  // arg to CreateMarshaler
5568
5569     //
5570     // call MngdRefCustomMarshaler::CreateMarshaler
5571     //
5572
5573     pslILEmit->EmitCALL(METHOD__MNGD_REF_CUSTOM_MARSHALER__CREATE_MARSHALER, 2, 0);
5574 }
5575
5576
5577 #ifndef CROSSGEN_COMPILE
5578
5579 FCIMPL2(void, MngdRefCustomMarshaler::CreateMarshaler, MngdRefCustomMarshaler* pThis, void* pCMHelper)
5580 {
5581     FCALL_CONTRACT;
5582
5583     pThis->m_pCMHelper = (CustomMarshalerHelper*)pCMHelper;
5584 }
5585 FCIMPLEND
5586
5587     
5588 FCIMPL3(void, MngdRefCustomMarshaler::ConvertContentsToNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5589 {
5590     CONTRACTL
5591     {
5592         FCALL_CHECK;
5593         PRECONDITION(CheckPointer(pManagedHome));
5594     }
5595     CONTRACTL_END;
5596     
5597     HELPER_METHOD_FRAME_BEGIN_0();
5598
5599     *pNativeHome = pThis->m_pCMHelper->InvokeMarshalManagedToNativeMeth(*pManagedHome);
5600
5601     HELPER_METHOD_FRAME_END();
5602 }
5603 FCIMPLEND
5604     
5605     
5606 FCIMPL3(void, MngdRefCustomMarshaler::ConvertContentsToManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5607 {
5608     CONTRACTL
5609     {
5610         FCALL_CHECK;
5611         PRECONDITION(CheckPointer(pManagedHome));
5612     }
5613     CONTRACTL_END;
5614     
5615     HELPER_METHOD_FRAME_BEGIN_0();
5616
5617     SetObjectReference(pManagedHome, pThis->m_pCMHelper->InvokeMarshalNativeToManagedMeth(*pNativeHome), GetAppDomain());
5618     
5619     HELPER_METHOD_FRAME_END();
5620 }
5621 FCIMPLEND
5622     
5623 FCIMPL3(void, MngdRefCustomMarshaler::ClearNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5624 {
5625     FCALL_CONTRACT;
5626
5627     HELPER_METHOD_FRAME_BEGIN_0();
5628
5629     CONTRACTL
5630     {
5631         THROWS;
5632         GC_TRIGGERS;
5633         MODE_ANY;
5634     }
5635     CONTRACTL_END;
5636
5637     pThis->m_pCMHelper->InvokeCleanUpNativeMeth(*pNativeHome);
5638     
5639     HELPER_METHOD_FRAME_END();
5640 }
5641 FCIMPLEND
5642     
5643 FCIMPL3(void, MngdRefCustomMarshaler::ClearManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5644 {
5645     CONTRACTL
5646     {
5647         FCALL_CHECK;
5648         PRECONDITION(CheckPointer(pManagedHome));
5649     }
5650     CONTRACTL_END;
5651
5652     HELPER_METHOD_FRAME_BEGIN_0();
5653     
5654     pThis->m_pCMHelper->InvokeCleanUpManagedMeth(*pManagedHome);
5655     
5656     HELPER_METHOD_FRAME_END();
5657 }
5658 FCIMPLEND
5659
5660 #endif // CROSSGEN_COMPILE
5661
5662
5663 #ifdef FEATURE_COMINTEROP
5664
5665 ///////////////////////////////////////////////////////////////////////////////////////////////////
5666 // ILUriMarshaler implementation
5667 ///////////////////////////////////////////////////////////////////////////////////////////////////
5668
5669 LocalDesc ILUriMarshaler::GetNativeType()
5670 {
5671     LIMITED_METHOD_CONTRACT;
5672     return LocalDesc(ELEMENT_TYPE_I);
5673 }
5674
5675 LocalDesc ILUriMarshaler::GetManagedType()
5676 {
5677     STANDARD_VM_CONTRACT;;    
5678     BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5679     TypeHandle  hndUriType = pDomain->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriType();
5680
5681     return LocalDesc(hndUriType); // System.Uri
5682 }
5683
5684 bool ILUriMarshaler::NeedsClearNative()
5685 {
5686     LIMITED_METHOD_CONTRACT;
5687     return true;
5688 }
5689
5690 // Note that this method expects the CLR Uri on top of the evaluation stack and leaves the WinRT Uri there.
5691 //static
5692 void ILUriMarshaler::EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5693 {
5694     STANDARD_VM_CONTRACT;
5695
5696     UriMarshalingInfo* marshalingInfo = pDomain->GetMarshalingData()->GetUriMarshalingInfo();
5697
5698     ILCodeLabel *pNotNullLabel = pslILEmit->NewCodeLabel();
5699     ILCodeLabel *pDoneLabel = pslILEmit->NewCodeLabel();
5700
5701     pslILEmit->EmitDUP();
5702     pslILEmit->EmitBRTRUE(pNotNullLabel);
5703
5704     pslILEmit->EmitPOP();
5705     pslILEmit->EmitLoadNullPtr();
5706     pslILEmit->EmitBR(pDoneLabel);
5707
5708     pslILEmit->EmitLabel(pNotNullLabel);
5709
5710     // System.Uri.get_OriginalString()
5711     MethodDesc* pSystemUriOriginalStringMD = marshalingInfo->GetSystemUriOriginalStringMD();
5712     pslILEmit->EmitCALL(pslILEmit->GetToken(pSystemUriOriginalStringMD), 1, 1);
5713
5714     pslILEmit->EmitCALL(METHOD__URIMARSHALER__CREATE_NATIVE_URI_INSTANCE, 1, 1);
5715
5716     pslILEmit->EmitLabel(pDoneLabel);
5717 }
5718
5719 void ILUriMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
5720 {
5721     STANDARD_VM_CONTRACT;
5722
5723     EmitLoadManagedValue(pslILEmit);
5724     EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5725     EmitStoreNativeValue(pslILEmit);
5726 }
5727
5728 // Note that this method expects the WinRT Uri on top of the evaluation stack and leaves the CLR Uri there.
5729 //static
5730 void ILUriMarshaler::EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5731 {
5732     STANDARD_VM_CONTRACT;
5733
5734     MethodDesc* pSystemUriCtorMD = pDomain->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriCtorMD();
5735
5736     ILCodeLabel *pNotNullLabel = pslILEmit->NewCodeLabel();
5737     ILCodeLabel *pDoneLabel = pslILEmit->NewCodeLabel();
5738
5739     pslILEmit->EmitDUP();
5740     pslILEmit->EmitBRTRUE(pNotNullLabel);
5741
5742     pslILEmit->EmitPOP();
5743     pslILEmit->EmitLDNULL();
5744     pslILEmit->EmitBR(pDoneLabel);
5745
5746     pslILEmit->EmitLabel(pNotNullLabel);
5747
5748     // string UriMarshaler.GetRawUriFromNative(IntPtr)
5749     pslILEmit->EmitCALL(METHOD__URIMARSHALER__GET_RAWURI_FROM_NATIVE, 1, 1);
5750
5751     // System.Uri..ctor(string)
5752     pslILEmit->EmitNEWOBJ(pslILEmit->GetToken(pSystemUriCtorMD), 1);
5753
5754     pslILEmit->EmitLabel(pDoneLabel);
5755 }
5756
5757 void ILUriMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5758 {
5759     STANDARD_VM_CONTRACT;
5760
5761     EmitLoadNativeValue(pslILEmit);
5762     EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5763     EmitStoreManagedValue(pslILEmit);
5764 }
5765
5766 void ILUriMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5767 {
5768     STANDARD_VM_CONTRACT;
5769     EmitInterfaceClearNative(pslILEmit);
5770 }
5771
5772 ///////////////////////////////////////////////////////////////////////////////////////////////////
5773 // ILNCCEventArgsMarshaler implementation
5774 ///////////////////////////////////////////////////////////////////////////////////////////////////
5775
5776 LocalDesc ILNCCEventArgsMarshaler::GetNativeType()
5777 {
5778     LIMITED_METHOD_CONTRACT;
5779     return LocalDesc(ELEMENT_TYPE_I);
5780 }
5781
5782 LocalDesc ILNCCEventArgsMarshaler::GetManagedType()
5783 {
5784     STANDARD_VM_CONTRACT;;    
5785     
5786     BaseDomain *pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5787     TypeHandle  hndNCCEventArgType = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsType();
5788
5789     return LocalDesc(hndNCCEventArgType); // System.Collections.Specialized.NotifyCollectionChangedEventArgs
5790 }
5791
5792 bool ILNCCEventArgsMarshaler::NeedsClearNative()
5793 {
5794     LIMITED_METHOD_CONTRACT;
5795     return true;
5796 }
5797
5798 // Note that this method expects the CLR NotifyCollectionChangedEventArgs on top of the evaluation stack and
5799 // leaves the WinRT NotifyCollectionChangedEventArgs IP there.
5800 //static
5801 void ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, BaseDomain *pDomain)
5802 {
5803     STANDARD_VM_CONTRACT;
5804
5805     MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsToWinRTNCCEventArgsMD();
5806
5807     // IntPtr System.Runtime.InteropServices.WindowsRuntime.NotifyCollectionChangedEventArgsMarshaler.ConvertToNative(NotifyCollectionChangedEventArgs)
5808     pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5809 }
5810
5811 void ILNCCEventArgsMarshaler::EmitConvertContentsCLRToNative(ILCodeStream *pslILEmit)
5812 {
5813     STANDARD_VM_CONTRACT;
5814
5815     EmitLoadManagedValue(pslILEmit);
5816     EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5817     EmitStoreNativeValue(pslILEmit);
5818 }
5819
5820 // Note that this method expects the WinRT NotifyCollectionChangedEventArgs on top of the evaluation stack and
5821 // leaves the CLR NotifyCollectionChangedEventArgs there.
5822 //static
5823 void ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5824 {
5825     STANDARD_VM_CONTRACT;
5826
5827     MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTNCCEventArgsToSystemNCCEventArgsMD();
5828
5829     // NotifyCollectionChangedEventArgs System.Runtime.InteropServices.WindowsRuntime.NotifyCollectionChangedEventArgsMarshaler.ConvertToManaged(IntPtr)
5830     pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5831 }
5832
5833 void ILNCCEventArgsMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5834 {
5835     STANDARD_VM_CONTRACT;
5836
5837     EmitLoadNativeValue(pslILEmit);
5838     EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5839     EmitStoreManagedValue(pslILEmit);
5840 }
5841
5842 void ILNCCEventArgsMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5843 {
5844     STANDARD_VM_CONTRACT;
5845     EmitInterfaceClearNative(pslILEmit);
5846 }
5847
5848 ///////////////////////////////////////////////////////////////////////////////////////////////////
5849 // ILPCEventArgsMarshaler implementation
5850 ///////////////////////////////////////////////////////////////////////////////////////////////////
5851
5852 LocalDesc ILPCEventArgsMarshaler::GetNativeType()
5853 {
5854     LIMITED_METHOD_CONTRACT;
5855     return LocalDesc(ELEMENT_TYPE_I);
5856 }
5857
5858 LocalDesc ILPCEventArgsMarshaler::GetManagedType()
5859 {
5860     STANDARD_VM_CONTRACT;;    
5861     
5862     BaseDomain *pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5863     TypeHandle  hndPCEventArgType = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsType();
5864
5865     return LocalDesc(hndPCEventArgType); // System.ComponentModel.PropertyChangedEventArgs
5866 }
5867
5868 bool ILPCEventArgsMarshaler::NeedsClearNative()
5869 {
5870     LIMITED_METHOD_CONTRACT;
5871     return true;
5872 }
5873
5874 // Note that this method expects the CLR PropertyChangedEventArgs on top of the evaluation stack and
5875 // leaves the WinRT PropertyChangedEventArgs IP there.
5876 //static
5877 void ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, BaseDomain *pDomain)
5878 {
5879     STANDARD_VM_CONTRACT;
5880
5881     MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsToWinRTPCEventArgsMD();
5882
5883     // IntPtr System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToNative(PropertyChangedEventArgs)
5884     pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5885 }
5886
5887 void ILPCEventArgsMarshaler::EmitConvertContentsCLRToNative(ILCodeStream *pslILEmit)
5888 {
5889     STANDARD_VM_CONTRACT;
5890
5891     EmitLoadManagedValue(pslILEmit);
5892     EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5893     EmitStoreNativeValue(pslILEmit);
5894 }
5895
5896 // Note that this method expects the WinRT PropertyChangedEventArgs on top of the evaluation stack and
5897 // leaves the CLR PropertyChangedEventArgs there.
5898 //static
5899 void ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5900 {
5901     STANDARD_VM_CONTRACT;
5902
5903     MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTPCEventArgsToSystemPCEventArgsMD();
5904
5905     // PropertyChangedEventArgs System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToManaged(IntPtr)
5906     pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5907 }
5908
5909 void ILPCEventArgsMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5910 {
5911     STANDARD_VM_CONTRACT;
5912
5913     EmitLoadNativeValue(pslILEmit);
5914     EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5915     EmitStoreManagedValue(pslILEmit);
5916 }
5917
5918 void ILPCEventArgsMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5919 {
5920     STANDARD_VM_CONTRACT;
5921     EmitInterfaceClearNative(pslILEmit);
5922 }
5923
5924 ///////////////////////////////////////////////////////////////////////////////////////////////////
5925 // ILDateTimeMarshaler implementation
5926 ///////////////////////////////////////////////////////////////////////////////////////////////////
5927
5928 LocalDesc ILDateTimeMarshaler::GetNativeType()
5929 {
5930     STANDARD_VM_CONTRACT;;    
5931     return LocalDesc(MscorlibBinder::GetClass(CLASS__DATETIMENATIVE));
5932 }
5933
5934 LocalDesc ILDateTimeMarshaler::GetManagedType()
5935 {
5936     STANDARD_VM_CONTRACT;;    
5937     return LocalDesc(MscorlibBinder::GetClass(CLASS__DATE_TIME_OFFSET));
5938 }
5939
5940 bool ILDateTimeMarshaler::NeedsClearNative()
5941 {
5942     LIMITED_METHOD_CONTRACT;
5943     return false;
5944 }
5945
5946 void ILDateTimeMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
5947 {
5948     CONTRACTL
5949     {
5950         STANDARD_VM_CHECK;
5951         PRECONDITION(CheckPointer(pslILEmit));
5952     }
5953     CONTRACTL_END;
5954
5955     // DateTimeOffsetMarshaler.ConvertManagedToNative(ref managedDTO, out nativeTicks);
5956     EmitLoadManagedHomeAddr(pslILEmit);
5957     EmitLoadNativeHomeAddr(pslILEmit);    
5958     pslILEmit->EmitCALL(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_NATIVE, 2, 0);
5959 }
5960
5961 void ILDateTimeMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5962 {
5963     STANDARD_VM_CONTRACT;
5964
5965     // DateTimeOffsetMarshaler.ConvertNativeToManaged(out managedLocalDTO, ref nativeTicks);
5966     EmitLoadManagedHomeAddr(pslILEmit);
5967     EmitLoadNativeHomeAddr(pslILEmit);
5968     pslILEmit->EmitCALL(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_MANAGED, 2, 0);
5969 }
5970
5971 void ILDateTimeMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
5972 {
5973     STANDARD_VM_CONTRACT;
5974
5975     EmitLoadNativeHomeAddr(pslILEmit);
5976     pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__DATETIMENATIVE)));
5977 }
5978
5979 ///////////////////////////////////////////////////////////////////////////////////////////////////
5980 // ILNullableMarshaler implementation
5981 ///////////////////////////////////////////////////////////////////////////////////////////////////
5982
5983 LocalDesc ILNullableMarshaler::GetNativeType()
5984 {
5985     LIMITED_METHOD_CONTRACT;
5986     return LocalDesc(ELEMENT_TYPE_I);
5987 }
5988
5989 LocalDesc ILNullableMarshaler::GetManagedType()
5990 {
5991     LIMITED_METHOD_CONTRACT;;    
5992     return LocalDesc(m_pargs->m_pMT);
5993 }
5994
5995 bool ILNullableMarshaler::NeedsClearNative()
5996 {
5997     LIMITED_METHOD_CONTRACT;
5998     return true;
5999 }
6000
6001 void ILNullableMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6002 {
6003     CONTRACTL
6004     {
6005         STANDARD_VM_CHECK;
6006         PRECONDITION(CheckPointer(pslILEmit));
6007     }
6008     CONTRACTL_END;
6009     
6010     // pNative = NullableMarshaler<T>.ConvertToNative(ref pManaged);
6011     EmitLoadManagedHomeAddr(pslILEmit);
6012
6013     MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_NATIVE));
6014     pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6015
6016     EmitStoreNativeValue(pslILEmit);
6017 }
6018
6019 void ILNullableMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6020 {
6021     STANDARD_VM_CONTRACT;
6022
6023     // pManaged = NullableMarshaler.ConvertToManaged(pNative);
6024     EmitLoadNativeValue(pslILEmit);
6025
6026     MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_MANAGED));
6027     pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6028
6029     EmitStoreManagedValue(pslILEmit);
6030 }
6031
6032 void ILNullableMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
6033 {
6034     STANDARD_VM_CONTRACT;
6035     EmitInterfaceClearNative(pslILEmit);
6036 }
6037
6038 MethodDesc *ILNullableMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
6039 {
6040     STANDARD_VM_CONTRACT;
6041
6042     return MethodDesc::FindOrCreateAssociatedMethodDesc(
6043         pGenericMD,
6044         pGenericMD->GetMethodTable(),
6045         FALSE,                              // forceBoxedEntryPoint
6046         m_pargs->m_pMT->GetInstantiation(), // methodInst
6047         FALSE,                              // allowInstParam
6048         TRUE);                              // forceRemotableMethod
6049 }
6050
6051 ///////////////////////////////////////////////////////////////////////////////////////////////////
6052 // ILSystemTypeMarshaler implementation
6053 ///////////////////////////////////////////////////////////////////////////////////////////////////
6054
6055 LocalDesc ILSystemTypeMarshaler::GetNativeType()
6056 {
6057     STANDARD_VM_CONTRACT;
6058     
6059     return LocalDesc(MscorlibBinder::GetClass(CLASS__TYPENAMENATIVE));
6060 }
6061
6062 LocalDesc ILSystemTypeMarshaler::GetManagedType()
6063 {
6064     STANDARD_VM_CONTRACT;
6065     
6066     return LocalDesc(MscorlibBinder::GetClass(CLASS__TYPE));
6067 }
6068
6069 bool ILSystemTypeMarshaler::NeedsClearNative()
6070 {
6071     LIMITED_METHOD_CONTRACT;
6072     return true;
6073 }
6074
6075 void ILSystemTypeMarshaler::EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit)
6076 {
6077     STANDARD_VM_CONTRACT;
6078
6079     // SystemTypeMarshaler.ConvertToNative(Type, pTypeName);    
6080     EmitLoadManagedValue(pslILEmit);
6081     EmitLoadNativeHomeAddr(pslILEmit);
6082     pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_NATIVE, 2, 0);
6083 }
6084
6085 void ILSystemTypeMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit)
6086 {
6087     STANDARD_VM_CONTRACT;
6088     
6089     // type = SystemTypeMarshaler.ConvertNativeToManaged(pTypeName, ref Type);
6090     EmitLoadNativeHomeAddr(pslILEmit);
6091     EmitLoadManagedHomeAddr(pslILEmit);
6092     pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_MANAGED, 2, 0);
6093 }
6094
6095
6096 void ILSystemTypeMarshaler::EmitClearNative(ILCodeStream * pslILEmit)
6097 {
6098     STANDARD_VM_CONTRACT;
6099     
6100     // SystemTypeMarshaler.ClearNative(pTypeName)
6101     EmitLoadNativeHomeAddr(pslILEmit);
6102     pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CLEAR_NATIVE, 1, 0);
6103 }
6104
6105 void ILSystemTypeMarshaler::EmitReInitNative(ILCodeStream * pslILEmit)
6106 {
6107     EmitLoadNativeHomeAddr(pslILEmit);
6108     pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__TYPENAMENATIVE)));
6109 }
6110
6111 ///////////////////////////////////////////////////////////////////////////////////////////////////
6112 // ILHResultExceptionMarshaler implementation
6113 ///////////////////////////////////////////////////////////////////////////////////////////////////
6114
6115 LocalDesc ILHResultExceptionMarshaler::GetNativeType()
6116 {
6117     LIMITED_METHOD_CONTRACT;
6118     return LocalDesc(ELEMENT_TYPE_I4);
6119 }
6120
6121 LocalDesc ILHResultExceptionMarshaler::GetManagedType()
6122 {
6123     LIMITED_METHOD_CONTRACT;
6124     _ASSERTE(m_pargs->m_pMT != NULL);
6125     return LocalDesc(m_pargs->m_pMT);
6126 }
6127
6128 bool ILHResultExceptionMarshaler::NeedsClearNative()
6129 {
6130     LIMITED_METHOD_CONTRACT;
6131     return false;
6132 }
6133
6134 void ILHResultExceptionMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6135 {
6136     CONTRACTL
6137     {
6138         STANDARD_VM_CHECK;
6139         PRECONDITION(CheckPointer(pslILEmit));
6140     }
6141     CONTRACTL_END;
6142     
6143     // int HResultExceptionMarshaler.ConvertManagedToNative(Exception);
6144     EmitLoadManagedValue(pslILEmit);
6145     pslILEmit->EmitCALL(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_NATIVE, 1, 1);
6146     EmitStoreNativeValue(pslILEmit);
6147 }
6148
6149 void ILHResultExceptionMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6150 {
6151     CONTRACTL
6152     {
6153         STANDARD_VM_CHECK;
6154         PRECONDITION(CheckPointer(pslILEmit));
6155     }
6156     CONTRACTL_END;
6157
6158     // Exception HResultExceptionMarshaler.ConvertNativeToManaged(int hr);
6159     EmitLoadNativeValue(pslILEmit);
6160     pslILEmit->EmitCALL(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_MANAGED, 1, 1);
6161     EmitStoreManagedValue(pslILEmit);
6162 }
6163
6164 ///////////////////////////////////////////////////////////////////////////////////////////////////
6165 // ILKeyValuePairMarshaler implementation
6166 ///////////////////////////////////////////////////////////////////////////////////////////////////
6167
6168 LocalDesc ILKeyValuePairMarshaler::GetNativeType()
6169 {
6170     LIMITED_METHOD_CONTRACT;
6171     return LocalDesc(ELEMENT_TYPE_I);
6172 }
6173
6174 LocalDesc ILKeyValuePairMarshaler::GetManagedType()
6175 {
6176     LIMITED_METHOD_CONTRACT;;    
6177     return LocalDesc(m_pargs->m_pMT);
6178 }
6179
6180 bool ILKeyValuePairMarshaler::NeedsClearNative()
6181 {
6182     LIMITED_METHOD_CONTRACT;
6183     return true;
6184 }
6185
6186 void ILKeyValuePairMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6187 {
6188     STANDARD_VM_CONTRACT;
6189     
6190     // Native = KeyValueMarshaler<K, V>.ConvertToNative([In] ref Managed);
6191     EmitLoadManagedHomeAddr(pslILEmit);
6192
6193     MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__KEYVALUEPAIRMARSHALER__CONVERT_TO_NATIVE));
6194     pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6195
6196     EmitStoreNativeValue(pslILEmit);    
6197 }
6198
6199 void ILKeyValuePairMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6200 {
6201     STANDARD_VM_CONTRACT;
6202
6203     // Managed = KeyValuePairMarshaler<K, V>.ConvertToManaged(Native);
6204     EmitLoadNativeValue(pslILEmit);
6205
6206     MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__KEYVALUEPAIRMARSHALER__CONVERT_TO_MANAGED));
6207     pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6208
6209     EmitStoreManagedValue(pslILEmit);    
6210 }
6211
6212 void ILKeyValuePairMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
6213 {
6214     STANDARD_VM_CONTRACT;
6215     EmitInterfaceClearNative(pslILEmit);
6216 }
6217
6218 MethodDesc *ILKeyValuePairMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
6219 {
6220     STANDARD_VM_CONTRACT;
6221
6222     // KeyValuePairMarshaler methods are generic - find/create the exact method.
6223     return MethodDesc::FindOrCreateAssociatedMethodDesc(
6224         pGenericMD,
6225         pGenericMD->GetMethodTable(),
6226         FALSE,                              // forceBoxedEntryPoint
6227         m_pargs->m_pMT->GetInstantiation(), // methodInst
6228         FALSE,                              // allowInstParam
6229         TRUE);                              // forceRemotableMethod
6230 }
6231
6232 #endif  // FEATURE_COMINTEROP