00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef GNASH_MACHINE_H
00020 #define GNASH_MACHINE_H
00021
00022 #include <string>
00023 #include <vector>
00024 #include <sstream>
00025 #include "SafeStack.h"
00026 #include "as_value.h"
00027 #include "log.h"
00028
00029 namespace gnash {
00030 namespace abc {
00031 class AbcBlock;
00032 class MultiName;
00033 class Class;
00034 class abc_function;
00035 class Method;
00036 class Namespace;
00037 }
00038 class Global_as;
00039 class DisplayObject;
00040 class as_object;
00041 class Property;
00042 class CodeStream;
00043 class VM;
00044 template <typename T> class FunctionArgs;
00045 class string_table;
00046 }
00047
00048
00049 namespace gnash {
00050
00051 namespace abc {
00052
00054
00073 class Machine
00074 {
00075 public:
00076
00078 Machine(VM& vm);
00079
00081
00088
00090 void init();
00091
00092
00093
00095 DisplayObject *getTarget();
00096
00099 void setTarget(DisplayObject* target);
00100
00115 int completeName(MultiName& name, int initial = 0);
00116
00127 Class* findSuper(as_value& obj, bool find_primitive);
00128
00145 void getMember(Class* pDefinition, MultiName& name, as_value& source);
00146
00163 void setMember(Class*, MultiName&, as_value& target, as_value& val);
00164
00165 Property* findProperty(MultiName&) { return NULL; }
00166
00167 void execute();
00168
00188 void pushGet(as_object *this_obj, as_value& return_slot, Property *prop);
00189
00204 void pushSet(as_object *this_obj, as_value& value, Property *prop);
00205
00231 void pushCall(as_function *func, as_object *pThis, as_value& return_slot,
00232 unsigned char stack_in, short stack_out);
00233
00234 void immediateFunction(const as_function *to_call, as_object* pThis,
00235 as_value& storage, unsigned char stack_in, short stack_out);
00236
00237 void immediateProcedure(const as_function *to_call, as_object *pthis,
00238 unsigned char stack_in, short stack_out) {
00239 immediateFunction(to_call, pthis, mIgnoreReturn, stack_in, stack_out);
00240 }
00241
00242 void initMachine(AbcBlock* pool_block);
00243
00244 as_value executeFunction(Method* function, const fn_call& fn);
00245
00246 void instantiateClass(std::string className, as_object* global);
00248
00253 Global_as* global();
00254
00255 void markReachableResources() const;
00256
00257 private:
00259 class State
00260 {
00261 public:
00262 unsigned int _stackDepth;
00263 unsigned int _stackTotalSize;
00264 unsigned int _scopeStackDepth;
00265 unsigned int mScopeTotalSize;
00266 bool mReturn;
00267 CodeStream *mStream;
00268 Namespace *mDefaultXMLNamespace;
00269 as_object *mCurrentScope;
00270 as_value *mGlobalReturn;
00271 as_object *mThis;
00272 std::vector<as_value> _registers;
00273 abc_function* mFunction;
00274 void to_debug_string(){
00275 log_abc("StackDepth=%u StackTotalSize=%u ScopeStackDepth=%u ScopeTotalSize=%u",_stackDepth,_stackTotalSize,_scopeStackDepth,mScopeTotalSize);
00276
00277 }
00278 };
00279
00280 class Scope
00281 {
00282 public:
00283 unsigned int mHeightAfterPop;
00284 as_object *mScope;
00285
00286 Scope() : mHeightAfterPop(0), mScope(NULL) {}
00287 Scope(unsigned int i, as_object *o) : mHeightAfterPop(i),
00288 mScope(o)
00289 {}
00290 };
00291
00292 void saveState();
00293 void restoreState();
00294
00295 as_value find_prop_strict(MultiName multiname);
00296
00297 void print_stack();
00298
00299 void print_scope_stack();
00300
00301 void get_args(size_t argc, FunctionArgs<as_value>& args);
00302
00303 void load_function(CodeStream* stream, boost::uint32_t maxRegisters);
00304
00305 void executeCodeblock(CodeStream* stream);
00306
00307 void clearRegisters(boost::uint32_t maxRegsiters);
00308
00309 const as_value& getRegister(int index){
00310 log_abc("Getting value at a register %d ", index);
00311 return _registers[index];
00312 }
00313
00314 void setRegister(size_t index, const as_value& val) {
00315 log_abc("Putting %s in register %s", val, index);
00316 if (_registers.size() <= index) {
00317 log_abc("Register doesn't exist! Adding new registers!");
00318 _registers.resize(index + 1);
00319 }
00320 _registers[index] = val;
00321 }
00322
00323 void push_stack(as_value object){
00324 log_abc("Pushing value %s onto stack.", object);
00325 _stack.push(object);
00326 }
00327
00328 as_value pop_stack(){
00329 as_value value = _stack.pop();
00330 log_abc("Popping value %s off the stack.", value);
00331 return value;
00332 }
00333
00334 void push_scope_stack(as_value object);
00335
00336 as_object* pop_scope_stack() {
00337 log_abc("Popping value %s off the scope stack. There will be "
00338 "%u items left.", as_value(_scopeStack.top(0)),
00339 _scopeStack.size()-1);
00340 return _scopeStack.pop();
00341 }
00342
00343 as_object* get_scope_stack(boost::uint8_t depth) const {
00344 log_abc("Getting value from scope stack %u from the bottom.",
00345 depth | 0x0);
00346 return _scopeStack.value(depth);
00347 }
00348
00349 SafeStack<as_value> _stack;
00350 SafeStack<State> mStateStack;
00351 std::vector<as_value> _registers;
00352
00354
00361 SafeStack<as_object*> _scopeStack;
00362
00363 CodeStream *mStream;
00364
00365 string_table& mST;
00366
00367 Namespace* mDefaultXMLNamespace;
00368 as_object* mCurrentScope;
00369 as_object* mGlobalScope;
00370 as_object* mDefaultThis;
00371 as_object* mThis;
00372
00374 Global_as* _global;
00375
00376 as_value mGlobalReturn;
00377 as_value mIgnoreReturn;
00378
00379 bool mExitWithReturn;
00380 AbcBlock* mPoolObject;
00381
00382 abc_function* mCurrentFunction;
00383
00384 VM& _vm;
00385 };
00386 }
00387 }
00388 #endif