use ObjectURI more consistently
[gnash.git] / libcore / vm / VM.h
blob2e6699095ff939210926bb37f415729a4ace1be3
1 // VM.h: the Virtual Machine class, for Gnash
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
4 // Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #ifndef GNASH_VM_H
21 #define GNASH_VM_H
23 #ifdef HAVE_CONFIG_H
24 #include "gnashconfig.h"
25 #endif
27 #include <map>
28 #include <vector>
29 #include <memory>
30 #include <locale>
31 #include <boost/cstdint.hpp>
32 #include <boost/random.hpp>
33 #include <boost/noncopyable.hpp>
34 #include <boost/intrusive_ptr.hpp>
35 #include <boost/array.hpp>
37 #include "GC.h"
38 #include "string_table.h"
39 #include "SafeStack.h"
40 #include "CallStack.h"
41 #include "smart_ptr.h"
42 #include "as_value.h"
43 #include "namedStrings.h"
44 #include "ObjectURI.h"
46 // Forward declarations
47 namespace gnash {
48 class Global_as;
49 class VM;
50 class fn_call;
51 class movie_root;
52 class NativeFunction;
53 class SharedObjectLibrary;
54 class as_value;
55 class as_object;
56 class VirtualClock;
57 class UserFunction;
60 namespace gnash {
62 /// The AVM1 virtual machine
64 /// The VM class has no code for execution, but rather stores the resources
65 /// needed for execution:
67 /// 1. The stack
68 /// 2. Global registers
69 /// 3. The call stack.
71 /// Actual execution is done by ActionExec.
73 /// This header also contains a few utility functions for ActionScript
74 /// operations.
75 class DSOEXPORT VM : boost::noncopyable
77 public:
79 typedef as_value (*as_c_function_ptr)(const fn_call& fn);
81 /// Initializes the VM
83 /// @param version The initial version of the VM
84 /// @param root The movie_root that owns this VM
85 /// @param clock The clock to use for advances.
86 VM(int version, movie_root& root, VirtualClock& clock);
88 ~VM();
90 /// Accessor for the VM's stack
92 /// TODO: drop
93 SafeStack<as_value>& getStack() {
94 return _stack;
97 /// Get the VM clock
99 /// NOTE: this clock should drive all internal operations
100 /// but maybe accessing it trough VM isn't the best idea.
101 /// TODO: consider making this accessible trough RunResources
102 /// instead.
103 VirtualClock& getClock() {
104 return _clock;
107 /// Get SWF version context for the currently running actions.
109 /// This information will drive operations of the virtual machine
111 int getSWFVersion() const {
112 return _swfversion;
115 /// Set SWF version of the currently executing code
116 void setSWFVersion(int v);
118 /// Get the number of milliseconds since VM was started
119 unsigned long int getTime() const;
121 /// Get a reference to the string table used by the VM.
122 string_table& getStringTable() const { return _stringTable; }
124 /// Get version of the player, in a compatible representation
126 /// This information will be used for the System.capabilities.version
127 /// and $version ActionScript variables.
129 const std::string& getPlayerVersion() const;
131 /// Get current OS name. This is used for System.capabilites.os. If
132 /// defined in gnashrc, that takes precedence. For Linux, the string
133 /// includes the kernel version (unname -sr). Only works for systems
134 /// with sys/utsname.h (POSIX 4.4).
135 std::string getOSName() const;
137 /// Return the current language of the system. This is used for
138 /// System.capabilities.language. Only works for systems with
139 /// a language environment variable.
140 std::string getSystemLanguage() const;
142 // The boost Random Number Generator to use.
144 // http://www.boost.org/libs/random/random-generators.html
146 // TODO: boost/nondet_random.hpp provides access to a random device,
147 // which can be used in preference to a pseudo-RNG. It is only
148 // presently available on some platforms.
149 // http://www.boost.org/libs/random/nondet_random.html
151 // Generators have different limits on the size of the seed. Please
152 // check if replacing the generator.
154 // The mt11213b provides a pseudo-random number cycle
155 // of length 2^11213-1 and requires approx 352*sizeof(uint32_t) memory
156 // once initialized. It is more than adequate for most purposes.
157 typedef boost::mt11213b RNG;
159 // Get a pointer to the random number generator for
160 // use by Math.random() and random().
161 RNG& randomNumberGenerator();
163 /// Get a pointer to this VM's Root movie (stage)
164 movie_root& getRoot() const;
166 /// Return the Shared Object Library
167 SharedObjectLibrary& getSharedObjectLibrary() const {
168 assert(_shLib.get());
169 return *_shLib;
172 /// Get a pointer to this VM's _global Object
173 Global_as* getGlobal() const;
175 /// Mark all reachable resources (for GC)
177 /// - root movie / stage (_rootMovie)
178 /// - Global object (_global)
179 /// - Class Hierarchy object
180 void markReachableResources() const;
182 void registerNative(as_c_function_ptr fun, unsigned int x, unsigned int y);
184 /// Return a native function or null
185 NativeFunction* getNative(unsigned int x, unsigned int y) const;
187 /// Get value of a register (local or global).
189 /// When not in a function context the selected register will be
190 /// global or not at all (if index is not in the valid range
191 /// of global registers).
193 /// When in a function context defining no registers,
194 /// we'll behave the same as for a non-function context.
196 /// When in a function context defining non-zero number
197 /// of local registers, the register set will be either local
198 /// or not at all (if index is not in the valid range of local
199 /// registers).
201 /// @param index The index of the register to retrieve.
202 /// @return A pointer to the as_value at the specified position, or
203 /// 0 if the index is invalid
204 const as_value* getRegister(size_t index);
206 /// Set value of a register (local or global).
208 /// When not in a function context the set register will be
209 /// global or not at all (if index is not in the valid range
210 /// of global registers).
212 /// When in a function context defining no registers,
213 /// we'll behave the same as for a non-function context.
215 /// When in a function context defining non-zero number
216 /// of local registers, the register set will be either local
217 /// or not at all (if index is not in the valid range of local
218 /// registers).
220 /// @param index The index of the register to set. If the index
221 /// is invalid, this is a no-op.
222 /// @param val The value to set the register to.
223 void setRegister(size_t index, const as_value& val);
225 /// Add a function call to the call frame.
227 /// This should be called for all user-defined functions before the
228 /// function is executed
230 /// @return The pushed CallFrame. This is identical to currentCall().
231 CallFrame& pushCallFrame(UserFunction& f);
233 /// Remove a function call from the call frame.
235 /// This should be called on return from the function.
236 void popCallFrame();
238 /// Return the CallFrame of the currently executing function.
240 /// Callers must ensure that there is a current function before calling
241 /// this!
242 CallFrame& currentCall();
244 /// Whether a function call is in progress.
245 bool calling() const {
246 return !_callStack.empty();
249 /// Print stack, call stack, and registers to the specified ostream
250 void dumpState(std::ostream& o, size_t limit = 0);
252 private:
254 /// Stage associated with this VM
255 movie_root& _rootMovie;
257 /// The _global ActionScript object for AVM1
258 Global_as* _global;
260 /// Target SWF version
261 int _swfversion;
263 typedef std::map<unsigned int, as_c_function_ptr> FuncMap;
264 typedef std::map<unsigned int, FuncMap> AsNativeTable;
265 AsNativeTable _asNativeTable;
267 /// Mutable since it should not affect how the VM runs.
268 mutable string_table _stringTable;
270 VirtualClock& _clock;
272 SafeStack<as_value> _stack;
274 typedef boost::array<as_value, 4> GlobalRegisters;
275 GlobalRegisters _globalRegisters;
277 CallStack _callStack;
279 /// Library of SharedObjects. Owned by the VM.
280 std::auto_ptr<SharedObjectLibrary> _shLib;
282 RNG _rng;
286 // @param lowerCaseHint if true the caller guarantees
287 // that the lowercase equivalent of `str' is `str' again
289 inline ObjectURI
290 getURI(const VM& vm, const std::string& str, bool lowerCaseHint=false)
292 lowerCaseHint=lowerCaseHint; // TODO pass hint to ObjectURI ctor
293 // Possible optimization here is to directly compute
294 // noCase value if VM version is < 7
295 return ObjectURI((NSV::NamedStrings)vm.getStringTable().find(str));
298 inline ObjectURI
299 getURI(const VM&, NSV::NamedStrings s)
301 // Possible optimization here is to directly
302 // compute noCase values if VM version is < 7
303 // (using the known information in NSV)
304 return ObjectURI(s);
307 inline const std::string&
308 toString(VM& vm, const ObjectURI& uri)
310 return uri.toString(vm.getStringTable());
314 /// A class to wrap frame access. Stack allocating a frame guard
315 /// will ensure that all CallFrame pushes have a corresponding
316 /// CallFrame pop, even in the presence of extraordinary returns.
317 class FrameGuard
319 public:
321 FrameGuard(VM& vm, UserFunction& func)
323 _vm(vm),
324 _callFrame(_vm.pushCallFrame(func))
328 /// Get the CallFrame we've just pushed.
329 CallFrame& callFrame() {
330 return _callFrame;
333 ~FrameGuard() {
334 _vm.popCallFrame();
337 private:
338 VM& _vm;
339 CallFrame& _callFrame;
342 /////////////////////////////////////////////////////////////////////////////
344 /// VM ops on as_value.
346 /// These are currently used in:
347 /// 1. VM (AVM1)
348 /// 2. Gnash's C++ implementation of ActionScript.
350 /// Usage 2 replicates VM behaviour, but does not use the VM's stack or other
351 /// resources. This can lead to different behaviour, for instance when there
352 /// are limits on the stack size. Such cases are probably rare.
354 /////////////////////////////////////////////////////////////////////////////
356 /// Carry out ActionNewAdd
358 /// @param op1 The as_value to add to.
359 /// @param op2 The as_value to add.
360 /// @param vm The VM executing the operation.
362 /// TODO: Consider whether it would be better to pass something
363 /// other than the VM. But it is a VM operation, so it
364 /// is logically sound.
365 void newAdd(as_value& op1, const as_value& op2, const VM& vm);
367 /// Carry out ActionSubtract
369 /// @param op1 The as_value to subtract from.
370 /// @param op2 The as_value to subtract.
371 /// @param vm The VM executing the operation.
372 void subtract(as_value& op1, const as_value& op2, const VM& vm);
374 /// Carry out ActionSubtract
376 /// @param op1 The first comparand.
377 /// @param op2 The second comparand.
378 /// @param vm The VM executing the operation.
379 as_value newLessThan(const as_value& op1, const as_value& op2, const VM& vm);
381 /// Check if two values are equal
383 /// Note that conversions are performed as necessary, which can result in
384 /// function calls, which can have any conceivable side effect. The order of
385 /// the values affects the order the conversions are performed in, so can
386 /// under some circumstances change the result of the comparison.
388 /// Equality comparisons depend strongly on the SWF version.
390 /// @param a The first value to compare
391 /// @param b The second value to compare
392 /// @param vm The VM to use for the comparison.
393 /// @return Whether the values are considered equal.
394 bool equals(const as_value& a, const as_value& b, const VM& vm);
396 /// Convert an as_value to boolean type
398 /// @param val The value to return as a boolean
399 /// @param vm The VM to use for the conversion.
400 /// @return The boolean value of the passed as_value.
401 bool toBool(const as_value& v, const VM& vm);
403 /// Convert an as_value to a double
405 /// @param val The value to return as a double
406 /// @param vm The VM to use for the conversion.
407 /// @return The double value of the passed as_value.
408 double toNumber(const as_value& v, const VM& vm);
410 /// Convert an as_value to an object
412 /// @param val The value to return as an object
413 /// @param vm The VM to use for the conversion.
414 /// @return The Object representation value of the passed as_value.
415 as_object* toObject(const as_value& v, VM& vm);
417 /// AS2-compatible conversion to 32bit integer
419 /// This truncates large numbers to fit in the 32-bit space. It is not a
420 /// proper function of as_value because it is simply a further operation on
421 /// the stored number type.
423 /// This function calls to_number(), so performs a conversion if necessary.
425 /// @param val The value to return as an int.
426 /// @param vm The VM to use for the conversion.
427 /// @return The integer value of the passed as_value.
428 boost::int32_t toInt(const as_value& val, const VM& vm);
430 /// Force type to number.
432 /// @param v The value to change to a number type.
433 /// @param vm The VM to use for the conversion.
434 /// @return The value passed as v.
435 as_value& convertToNumber(as_value& v, const VM& vm);
437 /// Force type to string.
439 /// @param v The value to change to a string type.
440 /// @param vm The VM to use for the conversion.
441 /// @return The value passed as v.
442 as_value& convertToString(as_value& v, const VM& vm);
444 /// Force type to bool.
446 /// @param v The value to change to a bool type.
447 /// @param vm The VM to use for the conversion.
448 /// @return The value passed as v.
449 as_value& convertToBoolean(as_value& v, const VM& vm);
451 /// Convert to the appropriate primitive type
453 /// @param v The value to change to a primitive type.
454 /// @param vm The VM to use for the conversion.
455 /// @return The value passed as v.
456 as_value& convertToPrimitive(as_value& v, const VM& vm);
458 } // namespace gnash
460 #endif
462 // Local Variables:
463 // mode: C++
464 // indent-tabs-mode: t
465 // End: