Gnash  0.8.10
Machine.h
Go to the documentation of this file.
00001 // Machine.h A VM to run AS3 code, and AS2 code in the future.
00002 //
00003 //   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
00004 //   Free Software Foundation, Inc.
00005 // 
00006 // This program is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License as published by
00008 // the Free Software Foundation; either version 3 of the License, or
00009 // (at your option) any later version.
00010 // 
00011 // This program is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 // 
00016 // You should have received a copy of the GNU General Public License
00017 // along with this program; if not, write to the Free Software
00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019 
00020 #ifndef GNASH_MACHINE_H
00021 #define GNASH_MACHINE_H
00022 
00023 #include <string>
00024 #include <vector>
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         // Flash specific members.
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; // Throw away returns go here.
00378 
00379         bool mExitWithReturn;
00380     AbcBlock* mPoolObject; // Where all of the pools are stored.
00381 
00382         abc_function* mCurrentFunction;
00383 
00384         VM& _vm;
00385 };
00386 } // namespace abc
00387 } // namespace gnash
00388 #endif