@@ -23,6 +23,8 @@ mov edi, [ecx+ebx]
23
23
Special version of ST() macro whose x parameter is in units of "sizeof(SV *)".
24
24
This saves a *4 or *8 on x */
25
25
#define W32A_ST (x ) *(SV**)((size_t)PL_stack_base+(size_t)(x))
26
+ #define IS_CALL sizeof(SV *) // must be SV *, subbed from a SV **
27
+ #define NEEDS_POST_CALL_LOOP 0x1
26
28
27
29
/*all callbacks in Call() that use Call()'s SP (not a dSP SP)
28
30
must call SPAGAIN after the ENTER, incase of a earlier callback
@@ -40,6 +42,9 @@ mov edi, [ecx+ebx]
40
42
update above /|\
41
43
*/
42
44
45
+ /* SPLIT_HEAD is only for compilers that will optimize to a jmp, not a call,
46
+ none on 32 bits known right now*/
47
+ #ifndef W32A_SPLITHEAD
43
48
XS (XS_Win32__API_Call )
44
49
{
45
50
WIN32_API_PROFF (QueryPerformanceFrequency (& my_freq ));
@@ -59,13 +64,11 @@ XS(XS_Win32__API_Call)
59
64
ax_p ++ ;
60
65
PERL_UNUSED_VAR (cv ); /* -W */
61
66
{
62
- {
63
67
APIPARAM * params ;
64
68
const APICONTROL * control ;
65
69
APIPARAM * param ;
66
- //SV * retsv ;
70
+ size_t param_len ;
67
71
SV * in_type ;
68
- //AV* intypes;
69
72
70
73
AV * pparray ;
71
74
SV * * ppref ;
@@ -77,8 +80,6 @@ XS(XS_Win32__API_Call)
77
80
SV * * ax_end ;
78
81
long_ptr tin ;
79
82
UCHAR rt_flags ;
80
- #define IS_CALL sizeof(SV *) // must be SV *, subbed from a SV **
81
- #define NEEDS_POST_CALL_LOOP 0x1
82
83
SV * sentinal ;
83
84
if (!XSANY .any_ptr ){ /* ->Call( */
84
85
SV * api ;
@@ -94,6 +95,83 @@ XS(XS_Win32__API_Call)
94
95
rt_flags = 0 ;
95
96
control = (const APICONTROL * )XSANY .any_ptr ;
96
97
}
98
+
99
+
100
+ #else //is W32A_SPLITHEAD
101
+ STATIC void Call_body (pTHX_ const APICONTROL * const control , UCHAR rt_flags , SV * * ax_p ,
102
+ SV * * items_sv );
103
+
104
+ XS (XS_Win32__API_ImportCall )
105
+ {
106
+ WIN32_API_PROFF (QueryPerformanceFrequency (& my_freq ));
107
+ WIN32_API_PROFF (W32A_Prof_GT (& start ));
108
+ {
109
+ dVAR ;
110
+ SV * * ax_p = (SV * * )((size_t )(POPMARK )* sizeof (SV * )); /*ax_p = pointer, not the normal ax */
111
+ if (PL_markstack_ptr + 1 == PL_markstack_max )
112
+ markstack_grow ();
113
+ {
114
+ dSP ;
115
+ EXTEND (SP ,CALL_PL_ST_EXTEND );//the one and only EXTEND, all users must
116
+ //static assert against the constant
117
+ {//compiler can toss some variables that EXTEND used
118
+ SV * * mark = & (W32A_ST (ax_p ));
119
+ SV * * items_sv = (size_t )sp - (size_t )mark ;
120
+ ax_p ++ ;
121
+ PERL_UNUSED_VAR (cv ); /* -W */
122
+ Call_body (aTHX_ (const APICONTROL * )XSANY .any_ptr , 0 , ax_p , items_sv );
123
+ }
124
+ }
125
+ }
126
+ }
127
+
128
+ XS (XS_Win32__API_Call )
129
+ {
130
+ WIN32_API_PROFF (QueryPerformanceFrequency (& my_freq ));
131
+ WIN32_API_PROFF (W32A_Prof_GT (& start ));
132
+ {
133
+ dVAR ;
134
+ SV * * ax_p = (SV * * )((size_t )(POPMARK )* sizeof (SV * )); /*ax_p = pointer, not the normal ax */
135
+ if (PL_markstack_ptr + 1 == PL_markstack_max )
136
+ markstack_grow ();
137
+ {
138
+ dSP ;
139
+ EXTEND (SP ,CALL_PL_ST_EXTEND );//the one and only EXTEND, all users must
140
+ //static assert against the constant
141
+ {//compiler can toss some variables that EXTEND used
142
+ SV * * mark = & (W32A_ST (ax_p ));
143
+ SV * * items_sv = (size_t )sp - (size_t )mark ;
144
+ SV * api ;
145
+ ax_p ++ ;
146
+ if (items_sv == 0 )
147
+ croak_xs_usage (cv , "api, ..." );
148
+ api = W32A_ST (ax_p );
149
+ items_sv -- ; /* make ST(0)/api obj on Perl Stack disapper */
150
+ ax_p ++ ;
151
+ Call_body (aTHX_ (APICONTROL * ) SvPVX (SvRV (api )), IS_CALL , ax_p , items_sv );
152
+ }
153
+ }
154
+ }
155
+
156
+ }
157
+
158
+ STATIC void Call_body (pTHX_ const APICONTROL * const control , UCHAR rt_flags , SV * * ax_p ,
159
+ SV * * items_sv ) {
160
+ dVAR ;
161
+ dSP ;
162
+ APIPARAM * params ;
163
+ APIPARAM * param ;
164
+ size_t param_len ;
165
+ SV * in_type ;
166
+
167
+ AV * pparray ;
168
+ SV * * ppref ;
169
+
170
+ SV * * code ;
171
+
172
+ long_ptr tin ;
173
+ SV * sentinal ;
174
+ #endif //#ifndef W32A_SPLITHEAD
97
175
{
98
176
/* all but -1 are unsigned, so we have ~65K params, not 32K
99
177
turn short -1 into int -1, but turn short -2 into unsigned int 65534 */
@@ -104,8 +182,6 @@ XS(XS_Win32__API_Call)
104
182
croak ("Wrong number of parameters: expected %d, got %d.\n" , nin , items );
105
183
}
106
184
}
107
- //intypes = control->intypes;
108
-
109
185
if (nin ) {
110
186
{
111
187
SV * * ax_i ;
@@ -120,26 +196,28 @@ XS(XS_Win32__API_Call)
120
196
Call_asm(), so the ST() slots ARENT always what the caller passed in
121
197
*/
122
198
params = (APIPARAM * ) _alloca (nin * sizeof (APIPARAM ));
199
+ // SSE copying, unknown if i386 or SSE copying is faster
200
+ /* {
201
+ __m128i * param_dst = (__m128i *)param;
202
+ __m128i * param_src = (__m128i *)&(control->param);
203
+ __m128i * params_end = (__m128i *)((size_t)&(control->param)+param_len);
204
+ do {
205
+ *param_dst = *param_src;
206
+ param_src++;
207
+ param_dst++;
208
+ } while (param_src != params_end);
209
+ }*/
123
210
{
124
211
__m128i * param_dst = params ;
125
212
__m128i * param_src = & (control -> param );
126
213
__m128i * params_end = (size_t )& (control -> param )+ (size_t )(nin * sizeof (APIPARAM ));
127
214
do {
215
+ //todo, make it copy 16 bytes in 1 loop pass, not 8
128
216
* param_dst = * param_src ;
129
217
param_src ++ ;
130
218
param_dst ++ ;
131
219
} while (param_src != params_end );
132
220
}
133
- //{
134
- // __int64 * param_dst = params;
135
- // __int64 * param_src = &(control->param);
136
- // __int64 * params_end = (size_t)&(control->param)+(size_t)(nin * sizeof(APIPARAM));
137
- // do {
138
- // *param_dst = *param_src;
139
- // param_src++;
140
- // param_dst++;
141
- // } while (param_src != params_end);
142
- //}
143
221
//memcpy(params, &(control->param), nin * sizeof(APIPARAM));
144
222
145
223
/* #### FIRST PASS: initialize params #### */
@@ -404,7 +482,7 @@ XS(XS_Win32__API_Call)
404
482
WIN32_API_PROFF (W32A_Prof_GT (& Call_asm_after ));
405
483
/* #### THIRD PASS: postfix pointers/structures #### */
406
484
if (rt_flags & NEEDS_POST_CALL_LOOP ) {
407
- #ifndef WIN32_API_DEBUG
485
+ #ifdef WIN32_API_DEBUG
408
486
int i = 0 ;
409
487
#endif
410
488
SV * * ax_i ;
@@ -420,15 +498,16 @@ XS(XS_Win32__API_Call)
420
498
char * sen = SvPVX (sentinal );
421
499
char * end = SvEND (sv );
422
500
end -= (sizeof (SENTINAL_STRUCT ));
501
+ //todo replace with inline comparison
423
502
if (memcmp (end , sen , sizeof (SENTINAL_STRUCT ))){
424
503
HV * env = get_hv ("ENV" , GV_ADD );
425
504
SV * * buf_check = hv_fetchs (env , "WIN32_API_SORRY_I_WAS_AN_IDIOT" , 0 );
426
505
if (buf_check && sv_true (* buf_check )) {0 ;}
427
- else {croak ("Win32::API::Call: parameter %d had a buffer overflow" , i + 1 );}
506
+ else {croak ("Win32::API::Call: parameter %d had a buffer overflow" , param -> idx1 );}
428
507
}else { //remove the sentinal off the buffer
429
508
SvCUR_set (sv , SvCUR (sv )- sizeof (SENTINAL_STRUCT ));
430
509
}
431
- if (control -> has_proto && control -> is_more ){ /* bad VC optimizer && is always a branch */
510
+ if (* ( char * ) & control -> whole_bf & ( CTRL_IS_MORE | CTRL_HAS_PROTO ) ){ /* bad VC optimizer && is always a branch */
432
511
callPack (aTHX_ control , param , sv , PARAM3_UNPACK );
433
512
//pointerCall3Param(aTHX_ control->api, AvARRAY(control->intypes)[i], sv, PARAM3_UNPACK );
434
513
}
@@ -477,29 +556,25 @@ XS(XS_Win32__API_Call)
477
556
#ifdef WIN32_API_DEBUG
478
557
printf ("(XS)Win32::API::Call: returning %Id.\n" , retval .l );
479
558
#endif
480
- //retsv = newSViv(retval.l);
481
559
sv_setiv (TARG , retval .l );
482
560
break ;
483
561
case (T_INTEGER |T_FLAG_UNSIGNED ):
484
562
case (T_NUMBER |T_FLAG_UNSIGNED ):
485
563
#ifdef WIN32_API_DEBUG
486
564
printf ("(XS)Win32::API::Call: returning %Iu.\n" , retval .l );
487
565
#endif
488
- //retsv = newSVuv(retval.l);
489
566
sv_setuv (TARG , retval .l );
490
567
break ;
491
568
case T_SHORT :
492
569
#ifdef WIN32_API_DEBUG
493
570
printf ("(XS)Win32::API::Call: returning %hd.\n" , retval .l );
494
571
#endif
495
- //retsv = newSViv((IV)(short)retval.l);
496
572
sv_setiv (TARG , (IV )(short )retval .l );
497
573
break ;
498
574
case (T_SHORT |T_FLAG_UNSIGNED ):
499
575
#ifdef WIN32_API_DEBUG
500
576
printf ("(XS)Win32::API::Call: returning %hu.\n" , retval .l );
501
577
#endif
502
- //retsv = newSVuv((UV)(unsigned short)retval.l);
503
578
sv_setuv (TARG , (UV )(unsigned short )retval .l );
504
579
break ;
505
580
#ifdef T_QUAD
@@ -509,7 +584,6 @@ XS(XS_Win32__API_Call)
509
584
#ifdef WIN32_API_DEBUG
510
585
printf ("(XS)Win32::API::Call: returning %I64d.\n" , retval .q );
511
586
#endif
512
- //retsv = newSVpvn((char *)&retval.q, sizeof(retval.q));
513
587
sv_setpvn (TARG , (char * )& retval .q , sizeof (retval .q ));
514
588
if (control -> UseMI64 ){
515
589
SP -- ; /*remove TARG from PL stack */
@@ -529,14 +603,12 @@ XS(XS_Win32__API_Call)
529
603
#ifdef WIN32_API_DEBUG
530
604
printf ("(XS)Win32::API::Call: returning %I64d.\n" , retval .q );
531
605
#endif
532
- //retsv = newSViv(retval.q);
533
606
sv_setiv (TARG , retval .q );
534
607
break ;
535
608
case (T_QUAD |T_FLAG_UNSIGNED ):
536
609
#ifdef WIN32_API_DEBUG
537
610
printf ("(XS)Win32::API::Call: returning %I64d.\n" , retval .q );
538
611
#endif
539
- //retsv = newSVuv(retval.q);
540
612
sv_setiv (TARG , retval .q );
541
613
break ;
542
614
#endif //USEMI64
@@ -545,14 +617,12 @@ XS(XS_Win32__API_Call)
545
617
#ifdef WIN32_API_DEBUG
546
618
printf ("(XS)Win32::API::Call: returning %f.\n" , retval .f );
547
619
#endif
548
- //retsv = newSVnv((double) retval.f);
549
620
sv_setnv (TARG , (double ) retval .f );
550
621
break ;
551
622
case T_DOUBLE :
552
623
#ifdef WIN32_API_DEBUG
553
624
printf ("(XS)Win32::API::Call: returning %f.\n" , retval .d );
554
625
#endif
555
- //retsv = newSVnv(retval.d);
556
626
sv_setnv (TARG , retval .d );
557
627
break ;
558
628
case T_POINTER :
@@ -562,7 +632,7 @@ XS(XS_Win32__API_Call)
562
632
#endif
563
633
RET_PTR_NULL :
564
634
if (!control -> is_more ) sv_setiv (TARG , 0 );
565
- else goto return_undef ; //undef much clearer
635
+ else goto return_undef ; //undef much clearer, IV 0 is for back compat reasons
566
636
} else {
567
637
#ifdef WIN32_API_DEBUG
568
638
printf ("(XS)Win32::API::Call: returning 0x%x '%s'\n" , retval .p , retval .p );
@@ -601,8 +671,7 @@ XS(XS_Win32__API_Call)
601
671
printf ("(XS)Win32::API::Call: returning UNDEF.\n" );
602
672
#endif
603
673
W32A_ST (ax_p ) = & PL_sv_undef ;
604
- return ;
605
- //goto return_no_mortal;
674
+ return ; /*dont call SvSETMAGIC or use TARG */
606
675
}
607
676
//retsv = sv_2mortal(retsv);
608
677
//return_no_mortal:
@@ -613,7 +682,7 @@ XS(XS_Win32__API_Call)
613
682
WIN32_API_PROFF (W32A_Prof_GT (& return_time2 ));
614
683
///*
615
684
WIN32_API_PROFF (printf ("freq %I64u start %I64u loopprep %I64u loopstart %I64u Call_asm_b4 %I64u Call_asm_after %I64u rtn_time %I64u rtn_time2\n" ,
616
- my_freq , /* 12 is bulk88's Core 2 TSC increment unit*/
685
+ my_freq , /* 12 is bulk88's Core 2 TSC increment unit, eyes hurt less comparing the numbers */
617
686
(loopprep .QuadPart - start .QuadPart - (return_time2 .QuadPart - return_time .QuadPart ))/12 ,
618
687
(loopstart .QuadPart - loopprep .QuadPart - (return_time2 .QuadPart - return_time .QuadPart ))/12 ,
619
688
(Call_asm_b4 .QuadPart - loopstart .QuadPart - (return_time2 .QuadPart - return_time .QuadPart ))/12 ,
@@ -625,10 +694,11 @@ XS(XS_Win32__API_Call)
625
694
return ; /* don't use CODE:'s boilerplate */
626
695
}//tout scope
627
696
}//call_asm scope
697
+ #ifndef W32A_SPLITHEAD
628
698
}
629
699
}
630
700
}
631
701
}
632
- }
702
+ #endif
633
703
}
634
704
#undef W32AST
0 commit comments