Gnash 0.8.10dev
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 Free Software Foundation, Inc.
00004 // 
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 3 of the License, or
00008 // (at your option) any later version.
00009 // 
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 #ifndef GNASH_MACHINE_H
00020 #define GNASH_MACHINE_H
00021 
00022 #include <string>
00023 #include <vector>
00024 #include "SafeStack.h"
00025 #include "as_value.h"
00026 #include "log.h"
00027 
00028 namespace gnash {
00029     namespace abc {
00030         class AbcBlock;
00031         class MultiName;
00032         class Class;
00033         class abc_function;
00034         class Method;
00035         class Namespace;
00036     }
00037     class Global_as;
00038     class DisplayObject;
00039     class as_object;
00040     class Property;
00041     class CodeStream;
00042     class VM;
00043     template <typename T> class FunctionArgs;
00044     class string_table;
00045 }
00046 
00047 
00048 namespace gnash {
00049 
00050 namespace abc {
00051 
00053 //
00072 class Machine
00073 {
00074 public:
00075 
00077         Machine(VM& vm);
00078 
00080     //
00087     //
00089     void init();
00090 
00091 
00092         // Flash specific members.
00094         DisplayObject *getTarget();
00095 
00098         void setTarget(DisplayObject* target);
00099 
00114         int completeName(MultiName& name, int initial = 0);
00115 
00126         Class* findSuper(as_value& obj, bool find_primitive);
00127 
00144         void getMember(Class* pDefinition, MultiName& name, as_value& source);
00145 
00162         void setMember(Class*, MultiName&, as_value& target, as_value& val);
00163 
00164         Property* findProperty(MultiName&) { return NULL; }
00165 
00166         void execute();
00167 
00187         void pushGet(as_object *this_obj, as_value& return_slot, Property *prop);
00188 
00203         void pushSet(as_object *this_obj, as_value& value, Property *prop);
00204 
00230         void pushCall(as_function *func, as_object *pThis, as_value& return_slot,
00231                 unsigned char stack_in, short stack_out);
00232 
00233         void immediateFunction(const as_function *to_call, as_object* pThis,
00234                 as_value& storage, unsigned char stack_in, short stack_out);
00235 
00236         void immediateProcedure(const as_function *to_call, as_object *pthis,
00237                 unsigned char stack_in, short stack_out) {
00238         immediateFunction(to_call, pthis, mIgnoreReturn, stack_in, stack_out);
00239     }
00240 
00241         void initMachine(AbcBlock* pool_block);
00242 
00243         as_value executeFunction(Method* function, const fn_call& fn);
00244 
00245         void instantiateClass(std::string className, as_object* global);
00247     //
00252     Global_as* global();
00253 
00254     void markReachableResources() const;
00255 
00256 private:
00258         class State
00259         {
00260         public:
00261                 unsigned int _stackDepth;
00262                 unsigned int _stackTotalSize;
00263                 unsigned int _scopeStackDepth;
00264                 unsigned int mScopeTotalSize;
00265                 bool mReturn;
00266                 CodeStream *mStream;
00267                 Namespace *mDefaultXMLNamespace;
00268                 as_object *mCurrentScope;
00269                 as_value *mGlobalReturn;
00270                 as_object *mThis;
00271                 std::vector<as_value> _registers;
00272                 abc_function* mFunction;
00273         void to_debug_string(){
00274                 log_abc("StackDepth=%u StackTotalSize=%u ScopeStackDepth=%u ScopeTotalSize=%u",_stackDepth,_stackTotalSize,_scopeStackDepth,mScopeTotalSize);
00275 
00276         }
00277         };
00278 
00279         class Scope
00280         {
00281         public:
00282                 unsigned int mHeightAfterPop;
00283                 as_object *mScope;
00284 
00285                 Scope() : mHeightAfterPop(0), mScope(NULL) {}
00286                 Scope(unsigned int i, as_object *o) : mHeightAfterPop(i),
00287                         mScope(o)
00288                 {}
00289         };
00290 
00291         void saveState();
00292         void restoreState();
00293 
00294         as_value find_prop_strict(MultiName multiname);
00295 
00296         void print_stack();
00297 
00298         void print_scope_stack();
00299 
00300         void get_args(size_t argc, FunctionArgs<as_value>& args);
00301         
00302         void load_function(CodeStream* stream, boost::uint32_t maxRegisters);
00303 
00304         void executeCodeblock(CodeStream* stream);
00305 
00306         void clearRegisters(boost::uint32_t maxRegsiters);
00307 
00308         const as_value& getRegister(int index){
00309                 log_abc("Getting value at a register %d ", index);
00310                 return _registers[index];
00311         }
00312 
00313     void setRegister(size_t index, const as_value& val) {
00314         log_abc("Putting %s in register %s", val, index);
00315         if (_registers.size() <= index) {
00316             log_abc("Register doesn't exist! Adding new registers!");
00317             _registers.resize(index + 1);
00318         }
00319         _registers[index] = val;
00320     }
00321 
00322         void push_stack(as_value object){
00323                 log_abc("Pushing value %s onto stack.", object);
00324                 _stack.push(object);
00325         }
00326 
00327         as_value pop_stack(){
00328                 as_value value = _stack.pop();
00329                 log_abc("Popping value %s off the stack.", value);
00330                 return value;
00331         }
00332 
00333         void push_scope_stack(as_value object);
00334 
00335         as_object* pop_scope_stack() {
00336                 log_abc("Popping value %s off the scope stack.  There will be "
00337                 "%u items left.", as_value(_scopeStack.top(0)),
00338                 _scopeStack.size()-1);
00339                 return _scopeStack.pop();
00340         }
00341 
00342         as_object* get_scope_stack(boost::uint8_t depth) const {
00343                 log_abc("Getting value from scope stack %u from the bottom.",
00344                 depth | 0x0);
00345                 return _scopeStack.value(depth);
00346         }
00347 
00348         SafeStack<as_value> _stack;
00349         SafeStack<State> mStateStack;
00350         std::vector<as_value> _registers;
00351 
00353     //
00360         SafeStack<as_object*> _scopeStack;
00361 
00362     CodeStream *mStream;
00363 
00364         string_table& mST;
00365 
00366         Namespace* mDefaultXMLNamespace;
00367         as_object* mCurrentScope;
00368         as_object* mGlobalScope;
00369         as_object* mDefaultThis;
00370         as_object* mThis;
00371 
00373         Global_as* _global;
00374 
00375         as_value mGlobalReturn;
00376         as_value mIgnoreReturn; // Throw away returns go here.
00377 
00378         bool mExitWithReturn;
00379     AbcBlock* mPoolObject; // Where all of the pools are stored.
00380 
00381         abc_function* mCurrentFunction;
00382 
00383         VM& _vm;
00384 };
00385 } // namespace abc
00386 } // namespace gnash
00387 #endif