root/src/VM/cil/cilVMInvokeMethod.cpp

Revision 195, 5.9 kB (checked in by hak, 4 months ago)

Ver.0.91.0.137
- Added OSX/GCC support!
- Can compile in XCode 3.1/GCC 4.0.1 & Visual Studio 2005.
- Runs in OSX 10.5.4 & Windows XP/Vista
- Number::toString support a radix.
- BRFALSE bug fix
- Minor code clean up

Line 
1 /****************************************************************************
2  *
3  * CRI Middleware SDK
4  *
5  * Copyright (c) 2008 CRI Middleware, Inc. All rights reserved.
6  *
7  * Use, modification and distribution are subject to the CRI Script Software
8  * License, Version 1.0(see accompanying file "CriScript_License_1_0.txt" or
9  * copy at www.criscript.com/trac/wiki/CRI%20Script%20Software%20License%201.0 ).
10  *
11  *
12  * Library  : CRIScript
13  * Module   : cil, invoke a method with RID
14  * File     : cilVMInvokeMethod.cpp
15  * Date     :
16  * Version  :
17  *
18  ****************************************************************************/
19
20 /***************************************************************************
21  *      Include file
22  ***************************************************************************/
23 #include "stdafx.h"
24 #include "criScript.h"
25 #include "cilVM.h"
26 namespace cri {
27 /***************************************************************************
28  *      Variables
29  ***************************************************************************/
30
31 /***************************************************************************
32  *      Methods
33  ***************************************************************************/
34 CVariable* CCilVm::invokeMethod( const RID ridMethod, const int32_t iNumArg,
35                                                                    CVariable* pArguments )
36 {
37         //Get Method parameters
38         CVariable* pThis;
39         METHOD_DEF* pMethod;
40         int32_t iIndex;
41
42         //NOTE:
43         //Currently invokeMethod only support a function invocation in the current execution context.
44         //If you need to invoke the function from different context, i.e.Should not destroy current
45         //context by Throw etc, need to save/restore current execution context.
46
47         switch( TypeFromToken( ridMethod ) )
48         {
49         case MDT_METHODDEF:
50                 pMethod = &m_MetaData.getMethod( ridMethod );
51                 pThis = NULL;
52                 break;
53         case MDT_FIELDDEF:
54                 {
55                 //Retrieve static field value
56                 iIndex = RidFromToken( ridMethod );
57                 CVariable& var = m_pStaticFieldTable[ iIndex ];
58                 assert( OperandType( var.iOperandType ) == OPERAND_OBJECTREF );
59                 assert( var.refObject != NULL );
60
61                 RID ridCall = var.refObject->getCall();
62                 assert( TypeFromToken( ridCall ) == MDT_METHODDEF );
63                 pMethod = &m_MetaData.getMethod( ridCall );
64                 pThis = &var;
65                 }
66                 break;
67         default:
68         //TODO
69         //Should throw exception rather than assert
70                 Debug_Fatal( "Not supported call type" );
71         }
72
73         VM_CALLSTACK callstack;
74         int32_t evalStackEntries = (int32_t)getEvalStackSize();
75         int32_t iCurrentInstructionIndex = (uint32_t)(m_pCurrentInstruction - &m_CurrentILPool.ILPool[0]);
76         int32_t iSavedNumGivenArguments = m_iNumGivenArguments;
77        
78         switch( MethodType( pMethod->MethodType ) )
79         {
80         case METHOD_NATIVE:
81                 {
82                 assert( pMethod->lpFunction != NULL );
83                 m_iNumGivenArguments = 0;
84                 ((PDEFAULTMETHOD)pMethod->lpFunction)( this,
85                                                                                         iNumArg,
86                                                                                         pArguments );           
87                 VM_CALLSTACK* pCurrentCallstack = getCurrentCallStack( VM_CALLSTACK_CALLSTACK );
88                 m_iNumGivenArguments = iSavedNumGivenArguments;
89                 }
90                 break;
91         case METHOD_WRAPPED:
92                 {
93                 assert( pMethod->lpFunction != NULL );
94                 m_iNumGivenArguments = 0;
95                 ((PWRAPPEDMETHOD)pMethod->lpFunction)( this,
96                                                                                         iNumArg,
97                                                                                         pArguments,
98                                                                                         (PMETHOD)pMethod->lpFunctionBody );             
99                 VM_CALLSTACK* pCurrentCallstack = getCurrentCallStack( VM_CALLSTACK_CALLSTACK );
100                 m_iNumGivenArguments = iSavedNumGivenArguments;
101                 }
102                 break;
103         case METHOD_CIL:
104                 {
105
106                 //Copy arguments over arglist
107                 for( int32_t i = 0; i < iNumArg; ++i )
108                 {
109                         storeArgumentList( *pArguments );
110                         ++pArguments;
111                 }
112
113                 if( !pMethod->bRestArgments )
114                 {
115                         //Regular pass
116
117                         //Fill in arguments if not supplied enough
118                         if( iNumArg < (int32_t)pMethod->iNumArgments )
119                         {
120                                 for( int32_t i = 0; i < pMethod->iNumArgments - iNumArg; i ++ )
121                                         pushArgumentListUndefined();
122                         } else if( iNumArg > (int32_t)pMethod->iNumArgments )
123                         {
124                                 for( int32_t i = 0; i <  iNumArg - pMethod->iNumArgments; i ++ )
125                                         popArgumentList();
126                         }
127                 }
128                 else
129                 {
130                         //Need to generate restArgs
131                         //Fill in arguments if not supplied enough
132                         if( m_iNumGivenArguments < pMethod->iNumArgments )
133                         {
134                                 for( int32_t i = 0; i < pMethod->iNumArgments - m_iNumGivenArguments; i ++ )
135                                         pushArgumentListUndefined();
136                         } else
137                         {
138                                 generateRestArguments( m_iNumGivenArguments - pMethod->iNumArgments + 1 );
139                         }
140                 }
141
142                 callstack.type          = VM_CALLSTACK_CALLSTACK;
143                 callstack.status        = VM_EHCLAUSE_NORMAL;
144                 callstack.pInstruction = m_pCurrentInstruction;
145                 callstack.ridMethod = ridMethod;
146                 callstack.iLocalVariableStartIndex = getCurrentLocalVariableIndex();
147                 callstack.iArgumentListStartIndex = getCurrentArgumentListIndex() - pMethod->iNumArgments;
148                 callstack.iNumArgument = pMethod->iNumArgments;
149                 callstack.bConstructor = false;
150                 m_CallStack.push_back( callstack );
151
152                 uint8_t* pSavedInstruction = m_pCurrentInstruction;
153                 m_pCurrentInstruction = &m_CurrentILPool.ILPool[ pMethod->iILOffset ];
154                 m_iCurrentThisPointerIndex = callstack.iArgumentListStartIndex;
155
156                 //Note
157                 //Arguments are already in the arglist in the last call stack
158
159                 //Reserve local variable slot
160                 reserveLocalVariables( pMethod->ridLocalVariableList );
161
162                 //Change callstack root
163                 m_iCallStackRoot = (int32_t)m_CallStack.size();
164
165                 //Keep current status
166                 VM_STATUS_TYPE status = m_status;
167                
168                 execute();
169                
170                 //Restore call stack root
171                 m_iCallStackRoot = 1;
172                
173                 //restore execution status
174                 m_status = status;
175                
176                 //Dispose local variable
177                 disposeLocalVariables( pMethod->iNumLocals );
178                 //Dispose arglist
179                 disposeArgumentList( pMethod->iNumArgments );
180
181                 m_CallStack.pop_back();
182
183                 //Restore IP
184                 m_pCurrentInstruction = pSavedInstruction;
185                 m_iNumGivenArguments = iSavedNumGivenArguments;
186
187                 }
188                 break;
189         case METHOD_EHCLAUSE:
190         default:
191                 Debug_Fatal( "Illegal Method type" );
192                 break;
193         }
194
195         CVariable* pVar = new( CVariable );
196         evalStackEntries = int32_t( getEvalStackSize() ) - evalStackEntries;
197         if( evalStackEntries > 0 )
198         {
199                 getEvalStackFirstEntry().moveTo( *pVar );
200                 popEvalStackFast();
201         }
202         return pVar;
203 }
204
205
206 } //namespace CRI
Note: See TracBrowser for help on using the browser.