update copyright date
[gnash.git] / libcore / vm / Machine.h
blob306eb6f4cb1a34f29a1eca028ff832b39ff4dbe1
1 // Machine.h A VM to run AS3 code, and AS2 code in the future.
2 //
3 // Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #ifndef GNASH_MACHINE_H
20 #define GNASH_MACHINE_H
22 #include <string>
23 #include <vector>
24 #include <sstream>
25 #include "SafeStack.h"
26 #include "as_value.h"
27 #include "log.h"
29 namespace gnash {
30 namespace abc {
31 class AbcBlock;
32 class MultiName;
33 class Class;
34 class abc_function;
35 class Method;
36 class Namespace;
38 class Global_as;
39 class DisplayObject;
40 class as_object;
41 class Property;
42 class CodeStream;
43 class VM;
44 template <typename T> class FunctionArgs;
45 class string_table;
49 namespace gnash {
51 namespace abc {
53 /// The virtual machine for executing ABC (ActionScript Bytecode).
55 /// This machine is intended to work without relying on the C++ call stack,
56 /// by resetting its Stream and Stack members (actually, by limiting the stack)
57 /// to make function calls, rather than calling them directly in C++.
58 /// As a result, many of the internal calls are void functions even though they
59 /// will be returning some value.
60 /// The exception to this is that C++ native functions defined in ActionScript
61 /// objects will be called in the typical way.
62 ///
63 /// The C++ exceptions mechanism is used for exception handling, since this
64 /// allows both ActionScript code and C++ code to use the exception handling
65 /// with a minimum of hassle, and it helps with correctness.
66 ///
67 /// It was intended that this Machine should run both AS2 and AS3 code.
68 /// However, as the two codestreams must be strictly separated - different
69 /// global objects, no sharing of resources, and no ability to communicate
70 /// directly, there is no sense in using a single instance of this machine
71 /// for both AS2 and AS3 interpretation. It's questionable whether there is
72 /// any advantage in using this Machine for AS2; it is not a near-term goal.
73 class Machine
75 public:
77 /// Create an AS3 interpreter.
78 Machine(VM& vm);
80 /// Initialize the AS resources
82 /// This extra step is necessary because the Machine is initialized
83 /// and owned by the AVM1 machine(VM). All access to Machine currently
84 /// occurs through VM, but since the VM's Machine pointer is null until
85 /// the Machine ctor has completed, we cannot construct AS resources
86 /// until after the ctor is complete, because AS resource creation
87 /// accesses the Machine through the VM's pointer...
89 /// TODO: fix the mess.
90 void init();
93 // Flash specific members.
94 /// The DisplayObject which initiated these actions.
95 DisplayObject *getTarget();
97 /// Set the DisplayObject which initiated the actions.
98 /// Not null.
99 void setTarget(DisplayObject* target);
101 /// This will complete a name in AS3, where a part of the name
102 /// is stored in the stream and another part may be stored on
103 /// the stack.
105 /// @param name
106 /// A partially filled MultiName, this should be the id
107 /// from the stream.
109 /// @param initial
110 /// The depth in the stack where the stack objects may be found.
112 /// @return
113 /// The number of stack elements used by the name.
114 /// At present, always 0, 1, or 2. These are not dropped.
115 int completeName(MultiName& name, int initial = 0);
117 /// Given a value v, find the class object of the superclass of v.
119 /// @param obj
120 /// The object whose superclass is desired.
122 /// @param find_primitive
123 /// If true, the ActionScript prototype will be found for primitive values.
125 /// @return
126 /// Null if the superclass was not found, or the superclass.
127 Class* findSuper(as_value& obj, bool find_primitive);
129 /// Get a member from an object.
131 /// @param pDefinition
132 /// The definition of the class which is to be used. This should be the
133 /// one which has the property.
135 /// @param name
136 /// The bound name of the member
138 /// @param source
139 /// The source object -- the specific instance of the pDefinition class.
141 /// @return
142 /// This returns the value, but on the stack.
143 /// (Since the return value is not known until after control has left
144 /// the caller of this, it's impossible to return a meaningful value.
145 void getMember(Class* pDefinition, MultiName& name, as_value& source);
147 /// Set a member in an object.
149 /// @param pDefinition
150 /// The definition of the class which is to be used.
152 /// @param name
153 /// The bound name of the member
155 /// @param source
156 /// The source object -- where the instance should be set
158 /// @param newvalue
159 /// The new value
161 /// @return
162 /// Nothing.
163 void setMember(Class*, MultiName&, as_value& target, as_value& val);
165 Property* findProperty(MultiName&) { return NULL; }
167 void execute();
169 /// push a get call to be executed next.
171 /// Any Property can be pushed, and it will put an appropriate value
172 /// into return_slot. This ensures that getter properties
173 /// can be accessed in the same way as other properties, and hides
174 /// the difference between ActionScript methods and native C++ methods.
176 /// @param this_obj
177 /// The 'this' to use for a getter/setter if it exists.
179 /// @param return_slot
180 /// A space for the return value. An assignment will always be made here,
181 /// but mVoidSlot can be used for values that will be discarded.
183 /// @param prop
184 /// The property. If this is a value, it simply returns that value in
185 /// the return_slot immediately. Otherwise, it may immediately call
186 /// the gettter or it may push that onto the call stack and transfer
187 /// control. Callers can be agnostic as to which happens.
188 void pushGet(as_object *this_obj, as_value& return_slot, Property *prop);
190 /// push a set call to be executed next.
192 /// Any Property can be pushed, and it will set the property, if possible.
193 /// setter properties and simple properties alike will be handled by this.
195 /// @param this_obj
196 /// The 'this' to use for a getter/setter if it exists.
198 /// @param value
199 /// The value which should be set
201 /// @param prop
202 /// The property desired to be set.
204 void pushSet(as_object *this_obj, as_value& value, Property *prop);
206 /// push a call to be executed next
208 /// Push a call to be executed as soon as execution of the current opcode
209 /// finishes. At the end, transfer will return to the previous context.
211 /// @param func
212 /// The function to call
214 /// @param pThis
215 /// The object to act as the 'this' pointer.
217 /// @param return_slot
218 /// The slot to use for returns. Use mIgnoreReturn if you don't care
219 /// what happens here.
221 /// @param stack_in
222 /// How many of the values on the stack are for the new context
224 /// @param stack_out
225 /// How much of the stack should be left behind when the function exits.
226 /// For example: 0 will leave a stack which is stack_in shorter than it
227 /// was on call. 1 will leave a stack which is 1 taller than it was on
228 /// call.
230 /// RESTRICTION: stack_in - stack_out must not be negative
231 void pushCall(as_function *func, as_object *pThis, as_value& return_slot,
232 unsigned char stack_in, short stack_out);
234 void immediateFunction(const as_function *to_call, as_object* pThis,
235 as_value& storage, unsigned char stack_in, short stack_out);
237 void immediateProcedure(const as_function *to_call, as_object *pthis,
238 unsigned char stack_in, short stack_out) {
239 immediateFunction(to_call, pthis, mIgnoreReturn, stack_in, stack_out);
242 void initMachine(AbcBlock* pool_block);
244 as_value executeFunction(Method* function, const fn_call& fn);
246 void instantiateClass(std::string className, as_object* global);
247 /// Return the Global object for this Machine.
249 /// This should be different from the AVM1 global object because the VMs
250 /// do not share any ActionScript resources. It should be the same
251 /// for a complete run of the Machine so that modifications carried out
252 /// by scripts are preserved for subsequent scripts.
253 Global_as* global();
255 void markReachableResources() const;
257 private:
258 /// The state of the machine.
259 class State
261 public:
262 unsigned int _stackDepth;
263 unsigned int _stackTotalSize;
264 unsigned int _scopeStackDepth;
265 unsigned int mScopeTotalSize;
266 bool mReturn;
267 CodeStream *mStream;
268 Namespace *mDefaultXMLNamespace;
269 as_object *mCurrentScope;
270 as_value *mGlobalReturn;
271 as_object *mThis;
272 std::vector<as_value> _registers;
273 abc_function* mFunction;
274 void to_debug_string(){
275 log_abc("StackDepth=%u StackTotalSize=%u ScopeStackDepth=%u ScopeTotalSize=%u",_stackDepth,_stackTotalSize,_scopeStackDepth,mScopeTotalSize);
280 class Scope
282 public:
283 unsigned int mHeightAfterPop;
284 as_object *mScope;
286 Scope() : mHeightAfterPop(0), mScope(NULL) {/**/}
287 Scope(unsigned int i, as_object *o) : mHeightAfterPop(i),
288 mScope(o)
289 {/**/}
292 void saveState();
293 void restoreState();
295 as_value find_prop_strict(MultiName multiname);
297 void print_stack();
299 void print_scope_stack();
301 void get_args(size_t argc, FunctionArgs<as_value>& args);
303 void load_function(CodeStream* stream, boost::uint32_t maxRegisters);
305 void executeCodeblock(CodeStream* stream);
307 void clearRegisters(boost::uint32_t maxRegsiters);
309 const as_value& getRegister(int index){
310 log_abc("Getting value at a register %d ", index);
311 return _registers[index];
314 void setRegister(size_t index, const as_value& val) {
315 log_abc("Putting %s in register %s", val, index);
316 if (_registers.size() <= index) {
317 log_abc("Register doesn't exist! Adding new registers!");
318 _registers.resize(index + 1);
320 _registers[index] = val;
323 void push_stack(as_value object){
324 log_abc("Pushing value %s onto stack.", object);
325 _stack.push(object);
328 as_value pop_stack(){
329 as_value value = _stack.pop();
330 log_abc("Popping value %s off the stack.", value);
331 return value;
334 void push_scope_stack(as_value object);
336 as_object* pop_scope_stack() {
337 log_abc("Popping value %s off the scope stack. There will be "
338 "%u items left.", as_value(_scopeStack.top(0)),
339 _scopeStack.size()-1);
340 return _scopeStack.pop();
343 as_object* get_scope_stack(boost::uint8_t depth) const {
344 log_abc("Getting value from scope stack %u from the bottom.",
345 depth | 0x0);
346 return _scopeStack.value(depth);
349 SafeStack<as_value> _stack;
350 SafeStack<State> mStateStack;
351 std::vector<as_value> _registers;
353 /// The scope stack is used to look for objects as properties
355 /// This stack is not cleared before a function call, class instantiation
356 /// etc, but anything on the stack cannot be altered by the function call.
357 /// On return from the function, the stack should be the same as it was
358 /// before.
359 /// Most importantly, the complete stack is used for lookups, including
360 /// the section that is not changeable.
361 SafeStack<as_object*> _scopeStack;
363 CodeStream *mStream;
365 string_table& mST;
367 Namespace* mDefaultXMLNamespace;
368 as_object* mCurrentScope;
369 as_object* mGlobalScope;
370 as_object* mDefaultThis;
371 as_object* mThis;
373 /// The global object for this machine.
374 Global_as* _global;
376 as_value mGlobalReturn;
377 as_value mIgnoreReturn; // Throw away returns go here.
379 bool mExitWithReturn;
380 AbcBlock* mPoolObject; // Where all of the pools are stored.
382 abc_function* mCurrentFunction;
384 VM& _vm;
386 } // namespace abc
387 } // namespace gnash
388 #endif