------------------------------------------------------------------------------------------- [ENHANCED] VFP 9.0 FIX - THE VARIABLE BEHAVIOR FOR THE VARIABLE NAME WITHOUT MDOT January 2024 ------------------------------------------------------------------------------------------- CCB 1. BUG: In vfp9 (and vfp6, vfp7, vfp8), when we run the code: x2=x1 it will run slower than the code: x2=m.x1 The bug was reported by Mike Yearwood. 2. CAUSE: In vfp9 (and vfp6, vfp7, vfp8), when we run the code: x2=x1 vfp will check the field x1 first, if there is the field x1 in the current work area, it will store the field x1 to the variable x2, if there is no the field x1 in the current work area, it will store the variable x1 to the variable x2. So it will run slower. In Visual FoxPro Advanced, if we set SYS(9062,0), when we run the code: x2=x1 vfp will not check the field x1, it will check the variable x1 only, it will store the variable x1 to the variable x2. So it will run faster. But for some code, for example, REPLACE fld2 WITH fld1 it will cause an error, because there is no the variable fld1. 3. RESOLUTION: We can write some code to fix the BUG. Fun421386 :: ; proc near push ebp ;0x00421386 : 55 mov ebp , esp ;0x00421387 : 8bec sub esp , 064h ;0x00421389 : 83ec64 mov ecx , dword ptr [ Data9370f0 ] ;0x0042138c : 8b0df0709300 mov eax , dword ptr [ Data9393ac ] ;0x00421392 : a1ac939300 add ecx , 02Ch ;0x00421397 : 83c12c push ebx ;0x0042139a : 53 mov ebx , ecx ;0x0042139b : 8bd9 mov dword ptr [ Data9370f0 ] , ecx ;0x0042139d : 890df0709300 movzx ecx ,word ptr [eax] ;0x004213a3 : 0fb708 add eax , 02h ;0x004213a6 : 83c002 mov dword ptr [ Data9393ac ] , eax ;0x004213a9 : a3ac939300 mov al , byte ptr [ Data936f10 ] ;0x004213ae : a0106f9300 test al , al ;0x004213b3 : 84c0 push esi ;0x004213b5 : 56 push edi ;0x004213b6 : 57 mov dword ptr [ ebp - 4 ] , ebx ;0x004213b7 : 895dfc mov dword ptr [ ebp - 8 ] , ecx ;0x004213ba : 894df8 js Label58f640 ;0x004213bd : 0f887de21600 mov eax , dword ptr [ Data936dec ] ;0x004213c3 : a1ec6d9300 test eax , eax ;0x004213c8 : 85c0 mov edx , dword ptr [ Data9370f8 ] ;0x004213ca : 8b15f8709300 jne Label58f66c ;0x004213d0 : 0f8596e21600 Label4213d6 :: mov edi , dword ptr [edx] ;0x004213d6 : 8b3a mov eax , dword ptr [ edi + 0158h ] ;0x004213d8 : 8b8758010000 test eax , eax ;0x004213de : 85c0 jne Label58f6d6 ;0x004213e0 : 0f85f0e21600 Label4213e6 :: mov edx , dword ptr [ Data9370f8 ] ;0x004213e6 : 8b15f8709300 mov eax , dword ptr [edx] ;0x004213ec : 8b02 mov dword ptr [ ebp - 12 ] , eax ;0x004213ee : 8945f4 mov eax , dword ptr [ eax + 32 ] ;0x004213f1 : 8b4020 xor edi , edi ;0x004213f4 : 33ff test eax , eax ;0x004213f6 : 85c0 je Label421432 ;0x004213f8 : 7438 test byte ptr [ eax + 16 ] , 020h ;0x004213fa : f6401020 je Label421432 ;0x004213fe : 7432 ; ; -------------------------------------------------------------------------------- ; VFP 9.0 FIX - THE VARIABLE BEHAVIOR FOR THE VARIABLE NAME WITHOUT MDOT ; June 2021 ; -------------------------------------------------------------------------------- ; CCB ; ; The variable behavior for the variable name without mdot. ; ; 2021/6/26, by ccb ; mov edx , dword ptr [ Data9370f8 ] mov edx , dword ptr [edx] cmp dword ptr [edx] , 00h je Label421400 cmp dword ptr vfpa_sys9062_data,00h je Label421432 cmp dword ptr vfpa_sys9062_data,02h je Label4213ff jmp Label421400 Label4213ff :: mov esi , dword ptr [ ebp - 8 ] mov edx , dword ptr [ Data9388e4 ] lea ecx , dword ptr [ esi + 4 * esi ] movzx ecx ,word ptr [ edx + 4 * ecx + 14 ] pushd 00h dec ecx call Fun53c57a cmp eax , 0FFFFFFFFh jne Label421432 mov edx , dword ptr [ Data9370f8 ] mov eax , dword ptr [edx] mov eax , dword ptr [ eax + 32 ] jmp Label421400 Label421400 :: mov eax , dword ptr [eax] ;0x00421400 : 8b00 mov ecx , dword ptr [ eax + 52 ] ;0x00421402 : 8b4834 xor esi , esi ;0x00421405 : 33f6 test ecx , ecx ;0x00421407 : 85c9 jle Label421432 ;0x00421409 : 7e27 xor ecx , ecx ;0x0042140b : 33c9 lea esp , dword ptr [ esp ] ;0x0042140d : 8d2424 Label421410 :: mov edx , dword ptr [ eax + 76 ] ;0x00421410 : 8b504c mov edx , dword ptr [edx] ;0x00421413 : 8b12 mov bx , word ptr [ ebp - 8 ] ;0x00421415 : 668b5df8 cmp word ptr [ ecx + edx ] , bx ;0x00421419 : 66391c11 je Label42142c ;0x0042141d : 740d mov edx , dword ptr [ eax + 52 ] ;0x0042141f : 8b5034 inc esi ;0x00421422 : 46 add ecx , 034h ;0x00421423 : 83c134 cmp esi , edx ;0x00421426 : 3bf2 jnl Label42142f ;0x00421428 : 7d05 jmp Label421410 ;0x0042142a : ebe4 Label42142c :: lea edi , dword ptr [ esi + 1 ] ;0x0042142c : 8d7e01 Label42142f :: mov ebx , dword ptr [ ebp - 4 ] ;0x0042142f : 8b5dfc Label421432 :: test edi , edi ;0x00421432 : 85ff je Label53c8bc ;0x00421434 : 0f8482b41100 lea eax , dword ptr [ edi - 1 ] ;0x0042143a : 8d47ff push eax ;0x0042143d : 50 mov eax , dword ptr [ ebp - 12 ] ;0x0042143e : 8b45f4 mov ecx , dword ptr [ eax + 32 ] ;0x00421441 : 8b4820 push ecx ;0x00421444 : 51 push ebx ;0x00421445 : 53 call Fun421694 ;0x00421446 : e849020000 test eax , eax ;0x0042144b : 85c0 je Label53c8bc ;0x0042144d : 0f8469b41100 Label421453 :: pop edi ;0x00421453 : 5f pop esi ;0x00421454 : 5e pop ebx ;0x00421455 : 5b mov esp , ebp ;0x00421456 : 8be5 pop ebp ;0x00421458 : 5d ret ;0x00421459 : c3 4. APPLIES TO: VFP 6.0.8167.0 VFP 6.0.8961.0 (SP5) VFP 7.0.0.9262 VFP 7.0.0.9465 (SP1) VFP 8.0.0.2521 VFP 8.0.0.3117 (SP1) VFP 9.0.0.2412 VFP 9.0.0.3504 (SP1) VFP 9.0.0.4611 (SP2) VFP 9.0.0.5015 (SP2) VFP 9.0.0.5411 (SP2) VFP 9.0.0.5721 (SP2) VFP 9.0.0.5815 (SP2) VFP 9.0.0.6303 (SP2) VFP 9.0.0.6602 (SP2) VFP 9.0.0.7423 (SP2) The bug has been fixed in VFP Advanced. IMPORTANT NOTE: Recommend to only use SYS(9062,0) for some code, for example, PRIVATE m.q_oldsys9062 m.q_oldsys9062=VAL(SYS(9062)) =SYS(9062,0) && For the variable name without mdot, vfp will not check the field name, it will check the variable name only. * the code block start... * ... * the code block end. =SYS(9062,m.q_oldsys9062) It is similar to the following code: PRIVATE m.q_oldsele m.q_oldsele=SELE() SELE 0 * the code block start... * ... * the code block end. SELE (m.q_oldsele) There is only a little difference for some statements, for example, 1, x2=x1 and m.x2=x1 the vfp source code: x2=x1 the compiled p-code: 0D 00 54 F7 00 00 10 FC F7 01 00 FD FE -------------------------------------- the length of the compiled p-code is 0x0D (13) bytes. the vfp source code: m.x2=x1 the compiled p-code: 0F 00 54 F5 0D F7 00 00 10 FC F7 01 00 FD FE -------------------------------------------- the length of the compiled p-code is 0x0F (15) bytes. F5 0D : it's M., and then it's the same as x2=x1. 2, PUBLIC x2 and PUBLIC m.x2 the vfp source code: PUBLIC x2 the compiled p-code: 07 00 37 F7 00 00 FE -------------------- the length of the compiled p-code is 0x07 (7) bytes. the vfp source code: PUBLIC m.x2 the compiled p-code: 09 00 37 F5 0D F7 00 00 FE -------------------------- the length of the compiled p-code is 0x09 (9) bytes. F5 0D : it's M., and then it's the same as PUBLIC x2. 3, x2=m.x1 and STORE m.x1 TO x2 the vfp source code: x2=m.x1 get nti (an integer) of the var x2, save to tmp2 (an integer), calculate the expression m.x1, save the result to a Value structure val1, set the var x2 (its nti is tmp2) from val1. the vfp source code: STORE m.x1 TO x2 calculate the expression m.x1, save the result to a Value structure val1, get nti (an integer) of the var x2, set the var x2 (its nti is eax) from val1. 5. REFERENCE WEBSITES: 1, baiyujia.com: http://www.baiyujia.com http://www.baiyujia.com/vfpdocuments/f_vfp9fix180.asp 2, foxite.com: https://www.foxite.com/archives/memory-variable-0000292846.htm https://www.foxite.com/archives/mdot-0000322640.htm https://www.foxite.com/archives/it-is-not-wise-not-to-use-mdot-0000219998.htm https://www.foxite.com/archives/magical-m-0000180204.htm https://www.foxite.com/archives/m-prefix-of-local-variables-0000079314.htm https://www.foxite.com/archives/a-confession-0000382571.htm https://www.foxite.com/archives/another-thread-on-mdot-0000237222.htm https://www.foxite.com/archives/best-coding-practices-for-newbies-0000160033.htm https://www.foxite.com/archives/best-practice-to-declare-variables-0000369623.htm https://www.foxite.com/archives/debugruntime-differences-and-mdot-0000431500.htm https://www.foxite.com/archives/for-statement-variable-0000447907.htm https://www.foxite.com/archives/foxypreviewer-v279-and-mdots-0000323617.htm 3, microsoft.com: https://docs.microsoft.com/en-us/archive/blogs/calvin_hsia/foxpro-performance-tip-field-name-lookup-for-tables https://social.msdn.microsoft.com/Forums/en-US/cc859679-4c22-4410-addd-7d013d91ca67/question-on-mem 4, blogspot.com: https://sandstorm36.blogspot.com/2011/09/learning-mdot-usage-repost.html 6. OTHER: For reference only, there is no guarantees. Any questions or suggestions, please send me an email at ccb2000@163.com. |