00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <spl/interp/jsfunctions/GlobalToString.h>
00018 #include <spl/interp/VarInterp.h>
00019
00020 StackFrame::StackFrame()
00021 : m_stack(),
00022 m_program(),
00023 m_context(),
00024 m_contextObj(),
00025 m_pc(0),
00026 m_outer(NULL),
00027 m_enterStack()
00028 {
00029 }
00030
00031 StackFrame::StackFrame(JsMethodPtr context)
00032 : m_stack(),
00033 m_program(context->GetProgramPtr()),
00034 m_context(),
00035 m_contextObj(),
00036 m_pc(0),
00037 m_outer(NULL),
00038 m_enterStack()
00039 {
00040 JsObjectPtr op = (JsObjectPtr)context;
00041 m_contextObj = (IJsObjectPtr)op;
00042 m_context = VariantPtr(new Variant(m_contextObj));
00043 }
00044
00045 StackFrame::StackFrame(JsMethodPtr context, StackFrame *outer)
00046 : m_stack(),
00047 m_program(context->GetProgramPtr()),
00048 m_context(),
00049 m_contextObj(),
00050 m_pc(0),
00051 m_outer(outer),
00052 m_enterStack()
00053 {
00054 JsObjectPtr op = (JsObjectPtr)context;
00055 m_contextObj = (IJsObjectPtr)op;
00056 m_context = VariantPtr(new Variant(m_contextObj));
00057 }
00058
00059 StackFrame::StackFrame(const StackFrame& frm)
00060 : m_stack(frm.m_stack),
00061 m_program(frm.m_program),
00062 m_context(frm.m_context),
00063 m_contextObj(frm.m_contextObj),
00064 m_pc(frm.m_pc),
00065 m_outer(frm.m_outer),
00066 m_enterStack(frm.m_enterStack)
00067 {
00068 }
00069
00070 StackFrame::~StackFrame()
00071 {
00072 while (GetStack().Count() > 0)
00073 {
00074 PopStack();
00075 }
00076 }
00077
00078 StackFrame& StackFrame::operator =(const StackFrame& frm)
00079 {
00080 m_context = frm.m_context;
00081 m_contextObj = frm.m_contextObj;
00082 m_pc = frm.m_pc;
00083 m_outer = frm.m_outer;
00084 m_stack = frm.m_stack;
00085 m_enterStack = frm.m_enterStack;
00086 m_program = frm.m_program;
00087 return *this;
00088 }
00089
00090 void StackFrame::DefineProperty()
00091 {
00092 StringPtr name = GetStack().Peek()->ToString();
00093 PopStack();
00094 m_stack.Add(ContextObject()->GetProperty(*name));
00095 }
00096
00097 VariantPtr StackFrame::FindProperty(const Variant& propName)
00098 {
00099 StringPtr name = propName.ToString();
00100
00101 if (ContextObject()->HasProperty(*name))
00102 {
00103 return ContextObject()->GetProperty(*name);
00104 }
00105
00106 StackFrame *outer = m_outer;
00107
00108 while (NULL != outer)
00109 {
00110 if (outer->ContextObject()->HasProperty(*name))
00111 {
00112 return outer->ContextObject()->GetProperty(*name);
00113 }
00114 outer = outer->NextFrame();
00115 }
00116
00117 return ContextObject()->GetProperty(*name);
00118 }
00119
00120 void StackFrame::InitArgs(Vector<VariantPtr> args)
00121 {
00122 ASSERT(NULL != m_program);
00123
00124 int x = 0;
00125 for(; x < args.Count(); x++)
00126 {
00127 m_stack.Add(args.ElementAt(x));
00128 }
00129 while (x < m_program->ArgumentCount())
00130 {
00131 m_stack.Add(VariantPtr(new Variant()));
00132 x++;
00133 }
00134 }
00135
00136 VariantPtr StackFrame::GetThis()
00137 {
00138 ASSERT (m_contextObj->MajicNumber() == JSMETHOD_MAJIC);
00139 return m_context;
00140 }
00141
00142 Vector<VariantPtr> StackFrame::GetArgs()
00143 {
00144 Vector<VariantPtr> args;
00145 ASSERT (0 != m_enterStack.Count());
00146
00147 int pos = m_enterStack.Peek() + 1;
00148
00149 for (int x = pos; x < m_stack.Count(); x++)
00150 {
00151 args.Add(m_stack.ElementAt(x));
00152 }
00153 return args;
00154 }
00155
00156 #if defined(DEBUG) || defined(_DEBUG)
00157 void StackFrame::CheckMem() const
00158 {
00159 m_context.CheckMem();
00160 m_stack.CheckMem();
00161 m_enterStack.CheckMem();
00162 }
00163
00164 void StackFrame::ValidateMem() const
00165 {
00166 m_context.ValidateMem();
00167 m_stack.ValidateMem();
00168 m_enterStack.ValidateMem();
00169 }
00170 #endif
00171
00172 VarInterp::VarInterp()
00173 : m_stackFrames()
00174 {
00175 }
00176
00177 VarInterp::VarInterp(VariantPtr method, Vector<VariantPtr>& args)
00178 : m_stackFrames()
00179 {
00180 PrepareToExecute(method, args);
00181 }
00182
00183 VarInterp::~VarInterp()
00184 {
00185 }
00186
00187 #if defined(DEBUG) || defined(_DEBUG)
00188 void VarInterp::CheckMem() const
00189 {
00190 m_stackFrames.CheckMem();
00191 }
00192
00193 void VarInterp::ValidateMem() const
00194 {
00195 m_stackFrames.ValidateMem();
00196 }
00197 #endif
00198
00199 RefCountPtr<IJsObject> VarInterp::CreateDefaultContext(Program& prog)
00200 {
00201 JsMethod *method = new JsMethod(prog);
00202 RefCountPtr<IJsObject> ctx(method);
00203
00204 RefCountPtr<IJsObject> obj(new JsMethod(Program()));
00205 ctx->SetProperty("Object", VariantPtr(new Variant(obj)));
00206
00207 ctx->SetProperty("toString", VariantPtr(new Variant(IJsObjectPtr(new GlobalToString()))));
00208
00209 return ctx;
00210 }
00211
00212 void VarInterp::PrepareToExecute(VariantPtr method, Vector<VariantPtr>& args)
00213 {
00214 m_stackFrames.Clear();
00215
00216 IJsObjectPtr methodObj = method->ToObject();
00217 ASSERT(methodObj->MajicNumber() == JSMETHOD_MAJIC);
00218
00219 m_stackFrames.Add((JsMethodPtr)methodObj);
00220
00221 Frame().InitArgs(args);
00222 }
00223
00224 bool VarInterp::Execute(bool continueAfterLine)
00225 {
00226 while (Frame().CanContinue())
00227 {
00228 Instruction i = Frame().PreExecute();
00229 switch (i.opCode)
00230 {
00231 case JSOP_NOP:
00232 break;
00233
00234 case JSOP_PUSH:
00235 break;
00236
00237 case JSOP_THIS:
00238 Frame().GetStack().Add(Frame().GetThis());
00239 break;
00240
00241 case JSOP_DEREF:
00242 ValidateMem();
00243 {
00244 VariantPtr propName = Frame().GetStack().Peek();
00245 PopStack();
00246 VariantPtr prop = Frame().GetStack().Peek();
00247 PopStack();
00248
00249 if (prop->IsObject())
00250 {
00251 VariantPtr innerProp = prop->ToObject()->GetProperty(*propName->ToString());
00252 Frame().GetStack().Add(innerProp);
00253 }
00254 else
00255 {
00256 Frame().GetStack().Add(VariantPtr(new Variant()));
00257 }
00258 ValidateMem();
00259 }
00260 break;
00261
00262 case JSOP_FINDPROP:
00263 ValidateMem();
00264 {
00265 VariantPtr prop = Frame().FindProperty(*Frame().GetStack().Peek());
00266 PopStack();
00267 ValidateMem();
00268 prop.ValidateMem();
00269 Frame().GetStack().Add(prop);
00270 ValidateMem();
00271 }
00272 break;
00273
00274 case JSOP_DEFPROP:
00275 Frame().DefineProperty();
00276 break;
00277
00278 case JSOP_NEW:
00279 {
00280 VariantPtr prop = Frame().FindProperty(*Frame().GetStack().Peek());
00281 PopStack();
00282 ValidateMem();
00283 prop.ValidateMem();
00284
00285 if (prop->IsObject())
00286 {
00287 IJsObjectPtr ijsprop = prop->ToObject();
00288 PushStack(ijsprop->New());
00289 }
00290 else
00291 {
00292 PushStack(VariantPtr(new Variant()));
00293 }
00294 }
00295 break;
00296
00297 case JSOP_ASSIGN:
00298 {
00299 ValidateMem();
00300 VariantPtr val = Frame().GetStack().Peek();
00301 PopStack();
00302 ValidateMem();
00303 *Frame().GetStack().PeekRef() = *val->ToRValue();
00304 ValidateMem();
00305 PopStack();
00306 }
00307 ValidateMem();
00308 break;
00309
00310 case JSOP_ADD:
00311 {
00312 VariantPtr v1 = Frame().GetStack().Pop();
00313 *Frame().GetStack().Peek() = *v1->Add(*Frame().GetStack().Peek());
00314 }
00315 break;
00316
00317 case JSOP_ENTER:
00318 Frame().EnterBlock();
00319 break;
00320
00321 case JSOP_LEAVE:
00322 Frame().LeaveBlock();
00323 break;
00324
00325 case JSOP_CALL:
00326 {
00327 VariantPtr vpm(Frame().GetCallThis());
00328
00329 if (!vpm->IsObject())
00330 {
00331 PushStack(VariantPtr(new Variant()));
00332 break;
00333 }
00334
00335 IJsObjectPtr jom = vpm->ToObject();
00336 if(jom->MajicNumber() != JSMETHOD_MAJIC)
00337 {
00338 PushStack(VariantPtr(new Variant()));
00339 break;
00340 }
00341
00342 JsMethod *pm = (JsMethod *)jom.Get();
00343 if (pm->IsNative())
00344 {
00345 VariantPtr ret = pm->Call(pm, Frame().GetArgs());
00346 Frame().LeaveBlock();
00347 PushStack(ret);
00348 }
00349 else
00350 {
00351 StackFrame frm((JsMethodPtr)jom, &m_stackFrames.ElementAtRef(m_stackFrames.Count()-1));
00352 frm.InitArgs(Frame().GetArgs());
00353 m_stackFrames.Add(frm);
00354 }
00355 }
00356 break;
00357
00358 case JSOP_RET:
00359 {
00360 VariantPtr ret = ReturnValue();
00361 m_stackFrames.Pop();
00362 Frame().LeaveBlock();
00363 PushStack(ret);
00364 }
00365 break;
00366
00367 case JSOP_LINE:
00368
00369 return true;
00370
00371 default:
00372 throw new Exception("Internal error in VarInterp::Execute");
00373 }
00374 }
00375
00376
00377 return false;
00378 }