Compare commits

..
267 Commits
Author SHA1 Message Date
hiker 9ef1b65eba Fixed compilation ... again :P 2015-06-25 23:03:55 +10:00
hiker 4d10a680c1 Fixed non-debug compilation. 2015-06-25 22:11:52 +10:00
hiker b8e4aa589d Added a very rough logging feature for SFXs to debug bug #2169. 2015-06-25 16:54:47 +10:00
auriamg 4070933364 Merge pull request #2212 from Flakebi/remove-icc
Strip ICC headers from png files to silence warning
2015-06-23 21:15:14 -04:00
Marianne Gagnon be81a7fd11 Increase size of popup, text was truncated at least in french 2015-06-23 18:46:36 -04:00
Marianne Gagnon 64adbb4238 Remove anchor as weapon from help menu, fixes #2173 2015-06-23 18:32:38 -04:00
Marianne Gagnon 74f19f0cbc Start working on scripting API to move objects 2015-06-22 19:36:30 -04:00
Marianne Gagnon 0fdc7a2d98 Use plural form for resolution change message, fixes #2219. ALso fix crash in tinygettext code handling plural forms 2015-06-22 19:26:20 -04:00
Marianne Gagnon ae18901bb2 Try fixing travis build 2015-06-21 19:57:06 -04:00
Marianne Gagnon b73469caf1 Extend scripting API with random and timeout functions 2015-06-21 19:44:22 -04:00
Marianne Gagnon 9119f5f291 Fixes for scripting documentation 2015-06-21 18:43:31 -04:00
Marianne Gagnon 90cf3176d1 Start adding an audio scripting API, and also fix a deadlock in sfx_manager due to improper release of locks 2015-06-21 18:31:16 -04:00
Marianne Gagnon 789384a7bf Fix loading scripts in local library nodes 2015-06-18 19:24:39 -04:00
Marianne Gagnon 8119b59af0 More fixes on intially hidden objects 2015-06-18 19:09:13 -04:00
Marianne Gagnon 403d61e754 Allow creating initially hidden objects, that can later be shown through scripting 2015-06-17 19:33:53 -04:00
Marianne Gagnon b3cc5f9f0d Try to fix Travis build 2015-06-15 20:09:22 -04:00
Marianne Gagnon 01b9ee2a63 RTT: calculate diffuse coefficients only once 2015-06-15 19:47:52 -04:00
Marianne Gagnon fa027c11da Work on hiding/showing library nodes (especially when they contain movable children, which are a special case) 2015-06-15 19:44:31 -04:00
Marianne Gagnon db55c35ed1 Disable bloom / depth-of-field when using physics debug modes, makes lines easier to see 2015-06-15 19:38:12 -04:00
Marianne Gagnon 97100db507 RTT: avoid computing diffuse coefficients every frame 2015-06-15 19:21:34 -04:00
Marianne Gagnon f651321ceb Using system angelscript must now be explicitely requested through an option, shouldn't be enabled by default as this will mostly lead to build errors due to finding a different version 2015-06-15 18:46:06 -04:00
hiker edbb6892e0 Added comments. 2015-06-13 12:34:33 +10:00
Marianne Gagnon e35d5a07b4 Little hack : make the kart selection screen seem faster by moving the cursor immediately, and loading the kart model only on next frame. See #2216 2015-06-11 20:22:30 -04:00
samuncle da6133d72e Merge pull request #2215 from tobbi/fix_2214
Fix flags on GetModule call. Thanks to seebi for the fix
2015-06-12 00:48:29 +02:00
Tobias Markus b32fff8dad Fix flags on GetModule call 2015-06-12 00:28:55 +02:00
hiker d95bdc2ea9 Merge branch 'master' of github.com:supertuxkart/stk-code 2015-06-10 23:18:48 +10:00
hiker 09227fa19d Finally fully fixed #2213. 2015-06-10 23:18:06 +10:00
hiker 860135376d Start to fix resolution change by properly freeing data. 2015-06-10 10:33:47 +10:00
hiker 0162407ff3 Added proper ref-counting. 2015-06-10 10:33:06 +10:00
Marianne Gagnon 32edaa25fe Adjust load and cleanup sequence for scripts, enabling scripts in library objects 2015-06-09 20:24:17 -04:00
Marianne Gagnon cb510840ae Work on scripting, namely improving interaction with library objects 2015-06-05 19:34:46 -04:00
Flakebi 41002fc262 Strip ICC headers from png files to silence warning 2015-06-05 03:32:26 +02:00
Marianne Gagnon 238578c921 More work towards handling library nodes in scripting 2015-06-04 20:12:03 -04:00
hiker 9531f0b3a4 Merge remote-tracking branch 'origin/master' into refactor_shaders 2015-06-05 09:13:27 +10:00
Marianne Gagnon bd006c875e Let track objects know what library object they are part of, paving the way for scripting to interact with library objects 2015-06-03 20:34:58 -04:00
hiker 9a1cba3ac8 Merge remote-tracking branch 'origin/master' into refactor_shaders 2015-06-03 15:11:27 +10:00
hiker 9094cbd31a Added NoCopy to FrameBuffer objects (copying a frame buffer e.g.
as a parameter to a function can lead to incorrect results, likely
because on exit of the function, data in the (copied) frame buffer
object is freed, and then not available for OpenGL anymore.
2015-06-03 15:10:11 +10:00
hiker f59d277f3e Improve handling of sudden steeper uphill section by increasing the
suspension force, which makes it less likely for the kart to hit
the terrain.
2015-06-03 09:03:40 +10:00
hiker d4f3fc88d6 Merged pull requests #2191. 2015-06-02 14:50:32 +10:00
hiker 2cf4341916 Merge remote-tracking branch 'origin/master' into refactor_shaders 2015-06-02 14:49:50 +10:00
hiker 1dabb39ed4 Fixed warnings most likely caused by copying a frame buffer object
(missing &), added several const to frame buffer references.
2015-06-02 14:19:15 +10:00
hiker 8fd0b9186a Merge pull request #2198 from nado/Fix-#2164
Fix #2164 : Resized max length of mail address up to 254 chars
2015-06-02 13:47:54 +10:00
hiker 0f5a44ea1f Merge pull request #2209 from AMDmi3/errno
Include cerrno for errno; fixes clang compilation error
2015-06-02 13:46:51 +10:00
Dmitry Marakasov cfbec1f470 Include cerrno for errno; fixes clang compilation error 2015-06-02 04:36:30 +03:00
hiker a51d56a6e5 Merge remote-tracking branch 'origin/master' into refactor_shaders
Conflicts:
	src/tracks/track_object_presentation.cpp
2015-06-01 09:28:23 +10:00
Marianne Gagnon b3d97241d7 Scripting : cleanup, add poweruptype enum 2015-05-31 18:39:40 -04:00
Marianne Gagnon 501dd14bb6 More scripting work on item-object collisions 2015-05-31 18:20:52 -04:00
hiker 9b2994c975 Added documentation to shader base classes. 2015-06-01 08:19:31 +10:00
hiker 2f287fbee6 Removed unused clean-shader functionality (which is now done by
shader.?pp), removed global shader name variable.
2015-06-01 08:14:56 +10:00
Marianne Gagnon 8ef16c146e Scripting work : improve flyable vs object collision callbacks. More work to do still. 2015-05-31 18:09:51 -04:00
hiker 51fb693455 Remove all kill functions for shader reloading after all shaders
have been deleted.
2015-05-30 12:37:39 +10:00
hiker 642216da83 Minor coding style change. 2015-05-30 12:16:38 +10:00
hiker e5a7f27f19 Renamed files to follow our coding style. 2015-05-30 12:16:11 +10:00
hiker 48235a5d77 Turned ShadowMatrices into a stand-alone proper class. 2015-05-30 11:29:08 +10:00
Marianne Gagnon 40ea7f94f0 Scripting work : improve object-kart collision callbacks 2015-05-28 19:57:36 -04:00
Marianne Gagnon 1ada542fa5 Continue porting overworld to scripting 2015-05-24 19:15:50 -04:00
Marianne Gagnon 4c02204eff Start porting the overworld to scripting 2015-05-24 18:34:01 -04:00
hiker 855c59db09 Removed global variable shadowSplit (missing in previous commit). 2015-05-22 16:45:09 +10:00
hiker 0b2c44ed71 Removed unused function, minor coding style cleanup. 2015-05-22 16:44:22 +10:00
hiker 5ba3dee122 Moved global variable at least into a class. 2015-05-22 16:37:54 +10:00
hiker ced9e55639 Moved shared shaders into Shaders class. 2015-05-22 16:26:30 +10:00
hiker cbd5670764 DIE global function - rest in peace, push up the daisies, kick the bucket. 2015-05-22 11:09:51 +10:00
Marianne Gagnon 0a3daf9484 Scripting work : the tutorial is now completely scripting-powered, nothing hardcoded anymore 2015-05-21 20:26:28 -04:00
Marianne Gagnon 17cfc130d0 Merge remote-tracking branch 'ignatenkobrain/ubundle_angelscript'
Conflicts:
	src/scriptengine/scriptarray.cpp
2015-05-21 20:20:03 -04:00
hiker e4f29d4dea Removed one more reference to global functions. 2015-05-22 10:00:26 +10:00
hiker 30fa3345e4 Removed more references to global function. 2015-05-22 09:57:28 +10:00
hiker 0f8d36889f Remved references to global function. 2015-05-22 09:51:09 +10:00
hiker 813d80a792 Removed two more references to global function. 2015-05-22 09:45:48 +10:00
hiker c21f6abeb7 Removed one more reference to global function. 2015-05-22 09:42:42 +10:00
hiker 8577f0d185 Removed one more reference to global function. 2015-05-22 09:40:46 +10:00
hiker 9048b6ffcd Removed one more reference to global function. 2015-05-22 09:37:34 +10:00
hiker cc9163ca77 Removed one more reference to global function, renamed functions
Bind and BindLayer to bind and bindLayer.
2015-05-22 09:29:42 +10:00
Marianne Gagnon 722cd0e181 Merge branch 'Scripting' 2015-05-21 19:29:01 -04:00
hiker 3a64d2c70e Removed one more reference to global function. 2015-05-22 09:18:21 +10:00
hiker d2a7e21632 Removed one more reference to global function. 2015-05-21 17:16:03 +10:00
hiker 18179bd18d Removed one more reference. 2015-05-21 17:12:59 +10:00
hiker 2c68bd194c Move more code into shader, removed one more reference to global function. 2015-05-21 17:09:53 +10:00
hiker 6f84a4dca1 Moved functionality into shader. 2015-05-21 16:59:40 +10:00
hiker 959d17ccb5 Moved one more reference to global function, minor coding style adjustments. 2015-05-21 16:46:46 +10:00
hiker abbd54ffa0 Replaced another global function reference. 2015-05-21 16:43:41 +10:00
hiker 4d6a9726b6 Renamed shader. 2015-05-21 16:37:59 +10:00
hiker dc8361b941 Fixed spelling of shader. 2015-05-21 11:19:40 +10:00
Marianne Gagnon 8113ea128b Minor scripting work 2015-05-20 20:17:00 -04:00
hiker 101fcf5df7 Removed more references to global function. 2015-05-21 10:09:43 +10:00
hiker e9c2f0ecf1 One less DrawFullScreenEffect function. 2015-05-20 17:18:55 +10:00
hiker d437ffa3bf Removed more accesses to global DrawFulLScreenEffect function. 2015-05-20 17:11:06 +10:00
hiker 8e6d9d2f41 Removed more references to global DrawFullScreenEffect function. 2015-05-20 16:53:30 +10:00
hiker dec62d63ea Fixed linux compilation. 2015-05-20 10:08:38 +10:00
hiker 063fb6b65f Try to fix linux compilation. 2015-05-20 09:19:59 +10:00
hiker 4ef85d692c Replaced one more call to DrawFulLScreenEffect. 2015-05-20 09:09:34 +10:00
hiker e241f167a7 Started to remove global DrawFullScreenEffect template. 2015-05-20 08:41:03 +10:00
hiker d64428db34 Moved more shaders, cleaned up unused code and other left-over bits. 2015-05-19 23:01:36 +10:00
hiker e0b1e876f0 Moved more shaders. 2015-05-19 21:10:49 +10:00
hiker ab4f77e80e Moved more shaders. 2015-05-19 18:55:32 +10:00
hiker 0c2e6c1640 Moved more shaders. 2015-05-19 18:51:26 +10:00
hiker 553a0a8b58 Moved more shaders. 2015-05-19 16:40:47 +10:00
hiker 52017e31ea Removed unused shader. 2015-05-19 16:36:24 +10:00
hiker a401096487 Moved more shaders, minor cleanup of coding style in irr_driver.hpp. 2015-05-19 16:34:07 +10:00
hiker e94c3e5d3f Removed unused global variables. 2015-05-19 16:11:54 +10:00
hiker 6d8d78be73 Moved more shaders, moved createVAO into Shader. 2015-05-19 16:07:24 +10:00
hiker 2224f4ebfa Removed unused shader. 2015-05-19 09:39:04 +10:00
hiker 283a7c58b9 Moved more shaders. 2015-05-19 09:36:28 +10:00
hiker b40f84e89d Moved more shaders. 2015-05-19 09:20:29 +10:00
Igor Gnatenko 7005f3b069 build: allow to use system angelscript
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2015-05-18 17:23:28 +03:00
Igor Gnatenko 65c25065ee angelscript: don't use deprecated GetParamTypeId
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2015-05-18 17:17:19 +03:00
hiker 8e4ee298e0 Moved shaders into render_lighting, fixed coding style for
render_lighting.
2015-05-18 21:33:26 +10:00
Nado 2b36759ba3 Resized max length of mail address up to 254 chars 2015-05-18 09:33:21 +02:00
hiker 6def0c752c Moved more shaders. 2015-05-18 16:52:42 +10:00
hiker 90d7fac6c4 Fixed coding style. 2015-05-18 16:43:30 +10:00
Marianne Gagnon e290e9003d Tweak for scripting documentation 2015-05-17 20:12:39 -04:00
Marianne Gagnon db4c6f4799 Work on scripting console 2015-05-17 20:03:53 -04:00
Marianne Gagnon 080936f144 Work on scripting 2015-05-17 19:27:25 -04:00
hiker 78220d5ed7 Moved more shaders. 2015-05-18 08:49:41 +10:00
hiker 3cb0c6f4c2 Fixed coding style in stkmesh. 2015-05-18 08:22:52 +10:00
hiker 37d787ff38 Fixed linux compilation. 2015-05-17 10:28:37 +10:00
hiker a50d11df36 Try a different linux fix. 2015-05-17 10:04:01 +10:00
hiker f0f230b042 Try to fix linux compilation. 2015-05-17 00:56:42 +10:00
hiker 1a09a09dd9 Removed now unnecessary parameter for assignSamplerNames. 2015-05-17 00:22:14 +10:00
hiker e0ef910137 Renamed TextureRead to TextureShader. 2015-05-17 00:04:19 +10:00
hiker 329a4ac047 Removed multiple inheritance, instead made TextureRead inherit from
Shader. work in progress!
2015-05-16 10:39:33 +10:00
Marianne Gagnon e23f854845 Scripting work 2015-05-14 19:27:32 -04:00
hiker dc211f2000 Improved coding style. 2015-05-15 08:16:23 +10:00
hiker 488f506932 Moved more shaders into PostProcessing. 2015-05-14 16:43:32 +10:00
hiker f0d0e7e601 Moved SharedObjects into separate file shared_gpu_object.
This also fixes the missing loading screen (likely caused by
not initialising all objects, or not in the right order).
2015-05-14 16:27:32 +10:00
auriamg 0ca0b21327 Merge pull request #2188 from huftis/removestringsorting
Don’t sort strings alphabetically (makes the translators’ work much easier)
2015-05-12 21:01:05 -04:00
auriamg dd80daa5d9 Merge pull request #2189 from huftis/addmissingglyph
Add ‘Æ’ glyph to the title font
2015-05-12 21:00:07 -04:00
hiker 3b682ff084 Moved more shaders into PostProcessing. 2015-05-13 09:57:53 +10:00
Marianne Gagnon 7d66dfec0e Make scripting work on OS X, hoping this doesn't break windows or linux 2015-05-12 19:49:14 -04:00
hiker 56bc14ff31 Moved more shaders into PostProcessing. 2015-05-13 08:55:59 +10:00
Marianne Gagnon 0ea991adee More work for scripting compatibility on Linux/GCC 2015-05-12 18:31:08 -04:00
hiker ea69eb3178 Minor style changes. 2015-05-13 08:22:58 +10:00
hiker 26d63ce844 Fixed linux compilation, and some more coding style issues. 2015-05-13 08:14:39 +10:00
Karl Ove Hufthammer 6106ed3ec6 Don’t sort strings alphabetically (makes the translators’ work much easier). 2015-05-12 18:20:11 +02:00
Karl Ove Hufthammer 465130a4a2 Added ‘Æ’ glyph to the title font
The glyph was created by combining the existing
‘A’ glyph and ‘E’ glyph, and then retouching the
result to make it look good (both the glyph heights
and the gradients differed for the two letters).
2015-05-12 18:17:20 +02:00
hiker 827b9adce2 Moved more shaders into 2dutils. 2015-05-12 16:48:12 +10:00
hiker 320dd6d1df Moved more shaders into 2dutils. 2015-05-12 16:43:03 +10:00
hiker fbad97a4a7 Moved Primitive2DList into 2dutils, fixed coding style of 2dutils. 2015-05-12 16:24:40 +10:00
Marianne Gagnon 6ccebd09b6 Improve scripting compatibility with Linux/GCC 2015-05-11 21:49:13 -04:00
hiker ee26611759 Moved billboard shader into stkbillboard, cleaned up coding style somewhat. 2015-05-12 10:01:24 +10:00
hiker f4cf41e466 Moved more shaders into render_gemoetry. 2015-05-12 09:50:18 +10:00
Marianne Gagnon c48037984d Update to latest angelscript 2015-05-11 19:40:43 -04:00
hiker ac3984b403 Fixed linux compilation. 2015-05-11 21:08:52 +10:00
hiker e337b72789 Moved *Detailed* shader into render_geometry, renamed all detailled
to detailed.
2015-05-11 17:17:08 +10:00
hiker 77bfa84609 Moved more render-geometry specific shader into render geometry. 2015-05-11 17:07:31 +10:00
Marianne Gagnon f269b44208 SCripting branch fix 2015-05-10 20:04:44 -04:00
Marianne Gagnon a29fa5c4a3 More work on scripting 2015-05-10 19:19:35 -04:00
hiker f3f30a8057 Moved GrassPass1Shader into render_geometry; fixed up coding style
somewhat.
2015-05-11 09:14:43 +10:00
hiker 400f9c612b Moved SpecularIBLGenerator-shader into IBL.cpp, and ColoredLine
shader into Shaders. Fixed codying style of IBL somewhat.
2015-05-11 08:09:09 +10:00
Marianne Gagnon 78f9500b1d Work on scripting 2015-05-09 21:29:37 -04:00
hiker 93f24f2a74 Removed Shaders instance out of irr-driver, and use a class
with static members instead.
2015-05-08 23:46:52 +10:00
Deve 199cda80b1 Merge pull request #2101 from konstin/fix_2095
add --log to --help message; fixes 2095
2015-05-08 10:32:05 +02:00
hiker 824b6906c1 Fixed compiler warning. 2015-05-08 13:59:19 +10:00
hiker 7453853c6d Fixed linux build. 2015-05-08 13:45:43 +10:00
hiker ba957ca0dc Merge branch 'refactor_shaders' of github.com:supertuxkart/stk-code into refactor_shaders 2015-05-08 13:21:54 +10:00
hiker 3607cadf62 Merge branch 'origin/refactor_shaders' into refactor_shaders 2015-05-08 13:21:13 +10:00
hiker 310a58541d Cleanup, part 1 - shaders_util is gone :) 2015-05-08 13:21:08 +10:00
hiker a16bbf71a4 Converted remaining shaders. 2015-05-08 08:30:51 +10:00
hiker 5070531ad7 Converted more shaders. 2015-05-08 08:02:56 +10:00
hiker 38a1deeff5 Converted more shaders. 2015-05-07 19:18:24 +10:00
hiker b441dba764 More shaders converted. 2015-05-07 16:40:38 +10:00
hiker 4338fe6144 Migrated more TextureReads to the new shader infrastructure. 2015-05-07 09:54:29 +10:00
auriamg 43add89cc2 Merge pull request #2181 from Flakebi/rtl-fix
Fix Random Grand Prix being reversed in RTL languages
2015-05-06 19:07:18 -04:00
hiker 8b9e5acd1a Converted more shaders to use the new template. 2015-05-07 07:41:51 +10:00
Flakebi a311281aa7 Fix Random Grand Prix being reversed 2015-05-06 20:39:40 +02:00
hiker 08ea768e16 Moved create*Sampler functions into TextureRead. 2015-05-06 22:33:15 +10:00
hiker a6b8783d46 Moved bind functions into TextureRead class. 2015-05-06 22:08:03 +10:00
hiker dfe4f09ed5 Start to re-implement TextureRead without variadic templates for
BindTexture and CreateSampler. VERY MESSY ATM, work in progress.
2015-05-06 16:51:54 +10:00
deve f019f8622c Make sure that window size is larger than 0 2015-05-04 11:09:53 +02:00
hiker 0ace0aeb5b Added comments. 2015-05-04 16:51:50 +10:00
Deve 6082a4502b Merge pull request #2172 from Flakebi/fix-font_tool
Fix Font tool build failure with CMake 3.2
2015-05-03 08:53:15 +02:00
Flakebi eea9069265 Fix #2171 - Font tool build failure with CMake 3.2 2015-05-03 02:52:15 +02:00
Marianne Gagnon d98c1044e6 More work on scripting 2015-04-30 20:36:54 -04:00
Marianne Gagnon 1559d03ea1 More work on scripting, test ways to pass arguments to script functions 2015-04-30 20:24:02 -04:00
Marianne Gagnon 585d1c5016 Scripting cleanup, remove hardcoded stuff in favor of more generic approaches 2015-04-30 19:37:11 -04:00
Marianne Gagnon 85cf5b181e Support extracting translations from scripts 2015-04-30 19:03:54 -04:00
hiker d32a76cd16 Rearranged order of functions in header to have the dependent/recursive
functions closer to each other. Removed unnecessary assignTextureUnit
function (with one argument).
2015-04-29 16:36:48 +10:00
hiker c91f9655d8 Unlock all karts in multiplayer mode. 2015-04-29 08:18:52 +10:00
hiker 75b24c96ad Unlock all tracks and GPs in split screen mode. 2015-04-29 08:07:06 +10:00
hiker aaf20dc919 Fixed #2118. 2015-04-27 17:14:23 +10:00
hiker 0b7c03b34c Fixed linux compilation. 2015-04-27 09:40:12 +10:00
auriamg 38e4e4e03c Merge pull request #2133 from Flakebi/translation-fixes
Fix some translation and bidi issues
2015-04-26 19:29:02 -04:00
Marianne Gagnon dfcaf44058 Scripting work 2015-04-26 19:06:51 -04:00
hiker eacd599b93 Removed version number warning for Radeon cards on osx (since they
have completely different version numbers).
2015-04-27 09:04:16 +10:00
hiker b14acf2a67 Moved TextureRead into a new file, fixed coding style. 2015-04-27 09:03:33 +10:00
Flakebi d19112760f Include algorithm in translation.cpp 2015-04-27 00:14:52 +02:00
Flakebi 5462a62c75 Fix TEST_BIDI in multiplayer KartSelection 2015-04-27 00:13:23 +02:00
Flakebi af88b4a16f Fix translation issues with grand-prixs 2015-04-26 23:31:57 +02:00
Flakebi 0b9876c53e Use isRTLText in the BubbleWidget 2015-04-26 22:55:28 +02:00
Flakebi fae12f3714 Fix RTL texts with multiple lines 2015-04-26 22:34:17 +02:00
Flakebi 56aecdb692 Fix achievements RTL display 2015-04-25 16:10:54 +02:00
Flakebi 6e0b96c21f Fix TEST_BIDI option 2015-04-25 16:01:50 +02:00
hiker e1ef2aa305 Removed TexUnit data structure. 2015-04-25 18:49:18 +10:00
auriamg f97db81ce3 Merge pull request #2103 from nado/fix_NoFribidi_compilation
Fix compilation with -DUSE_FRIBIDI=0
2015-04-24 21:07:12 -04:00
auriamg e769f995ec Merge pull request #2104 from nado/fix_#2102
Fix #2102.
2015-04-24 21:06:43 -04:00
auriamg a4559fc09d Merge pull request #2107 from Flakebi/fribidi
Mark text as RTL when at least one character is RTL
2015-04-24 21:04:46 -04:00
Marianne Gagnon 9f883db6f7 Start work to enable scripting 2015-04-24 20:59:32 -04:00
Marianne Gagnon fc942433e2 Tweak over previous commit 2015-04-24 20:17:55 -04:00
Marianne Gagnon 30431adc69 Add forgotten credit to Divvy81 2015-04-24 20:17:22 -04:00
hiker 45d6c863b3 Moved AssignTextureUnit to new Shader base class. 2015-04-25 00:57:53 +10:00
hiker 118233fb24 Removed now duplicated code. 2015-04-24 14:57:36 +10:00
hiker 865760ffa4 Fixed reloadShader functionality. 2015-04-24 12:36:25 +10:00
Flakebi 819156106d Mark text as RTL when at least one character is RTL 2015-04-24 03:45:05 +02:00
hiker 5d098488e6 Use new Shader baseclass for all shaders. 2015-04-24 10:31:37 +10:00
Marianne Gagnon 1cc3a0f0b8 Tweak times of scotland challenge 2015-04-23 19:20:42 -04:00
hiker bbaf061ae9 Added printFileList to Shader, renamed old global function. 2015-04-24 08:38:04 +10:00
hiker 1a96ed6249 Made SimpleParticleRender based on the new shader base class. 2015-04-24 08:26:17 +10:00
Nado 1a395efbfd Fix #2102.
Moving output modifier and early exit options (--help, --version,
--log, etc) earlier in the execution so nothing useless is printed.
2015-04-23 20:13:37 +02:00
Nado 76270ce0ec Fix compilation with -DUSE_FRIBIDI=0 2015-04-23 19:55:12 +02:00
konstin adceb35812 add --log to --help message 2015-04-23 17:40:20 +02:00
hiker a51225ec36 Added bypassUBO method to new shader base class. 2015-04-23 17:11:19 +10:00
hiker 262fc0c373 Started refactoring of shaders to follow our coding style.
One transform feedback buffer shader in particles is done.
2015-04-23 16:44:26 +10:00
hiker 959c86d816 Merge branch 'use_log_in_tinygettext' 2015-04-20 17:36:08 +10:00
hiker b6a10b7603 Use stk font to display menu - which is at least a readable size ;)
Hacked the GUI to be a bit easier to scale, but it's still hacky.
Changed default to be what is typically used in stk.
2015-04-20 17:34:51 +10:00
hiker 63406b40f1 Fixed line ending style. 2015-04-17 16:13:57 +10:00
hiker 55079289da List all GSoC students. 2015-04-17 09:48:45 +10:00
hiker 50ff2e6e35 Fixed donations, udpated samuncle's credits. 2015-04-17 09:40:28 +10:00
hiker 513df96c53 Fixed font tool (by requesting an old opengl context), increased size
and added some constants to change the size easier.
2015-04-17 09:24:12 +10:00
hiker 543bb8d303 Updated donations. 2015-04-17 08:29:40 +10:00
hiker 52f77f7d43 Fixed duplicated translator-credits strings. 2015-04-17 08:19:49 +10:00
hiker fbac4d791c Updated Asian fonts. 2015-04-16 16:59:12 +10:00
hiker 4ea1145af1 Updated translations credits by running update_po_authors.py script. 2015-04-16 15:29:38 +10:00
hiker 00782180f7 Fixed crash when using translation debugging (only happens if
DEBUG_TRANSLATIONS is defined).
2015-04-16 15:28:49 +10:00
hiker 418ccf284e Remove unnecessary \n after "Launchpad Contributions" (which caused
an empty line to be shown in stk); ignore "FIRST AUTHOR" as author.
2015-04-16 15:11:25 +10:00
Marianne Gagnon 4b956ebfce Update translations 2015-04-15 18:45:29 -04:00
hiker ad2ca0f394 Merge branch 'fix_2073' 2015-04-16 08:17:36 +10:00
hiker d4c33b294d Fixed compiler warning. 2015-04-16 08:15:20 +10:00
hiker 50acbea315 Fix crash in case of invalid kart types (e.g. 'default', which the
exporter actually writes if 'default' is selected).
2015-04-16 07:56:41 +10:00
hiker e8b8bbdd3b Added display of normals at the vertices of the triangles the kart is driving on
to the debug display, which is useful to find why interpolated normals are wrong.
2015-04-15 07:44:50 +10:00
hiker 8f090525fb Added more skidding particle debug code. 2015-04-14 16:40:50 +10:00
hiker fb9d422f9b Made interpolated normals white to make them easier to distinguish. 2015-04-14 16:39:28 +10:00
hiker ecdf32c01e Fixed size of shader parameter (though de-facto doesn't matter much). 2015-04-14 16:37:54 +10:00
hiker 0627bd85f3 Added some (commented out) debug features for gpu particles. 2015-04-14 16:35:05 +10:00
hiker 2c44bd1201 Removed unnecessary copy, precompue area of triangle to reduce
work when smoothing normals.
2015-04-14 16:21:43 +10:00
hiker a4264cc063 Visualise the (interpolated) normal at the points where the wheels touch the ground. 2015-04-14 09:33:55 +10:00
Marianne Gagnon cdde932908 Tentative fix for #2079 2015-04-09 19:58:07 -04:00
Marianne Gagnon 9a905cb579 Merge remote-tracking branch 'Flakebi/bidi-updown' 2015-04-08 20:09:15 -04:00
Flakebi effe131e4a Dynamically test if text is rtl or not 2015-04-09 01:57:33 +02:00
Flakebi 66dd089902 Move rtl debug option to a more general method 2015-04-09 01:26:55 +02:00
Flakebi dffd431f3c Add isRTLText function 2015-04-09 01:14:56 +02:00
Deve a4536d7752 Disable texture compression for mesa. 2015-04-08 22:20:04 +02:00
Marianne Gagnon 66db970564 Add context to help translators 2015-04-07 19:32:55 -04:00
Marianne Gagnon d746ea8aa1 Fix #2068 2015-04-07 19:11:59 -04:00
hiker 67d5e41d2c Try an improvement for #2073 (stk does not start if /data
exists).
2015-04-05 22:14:48 +10:00
hiker ddcd6f9ca3 Removed empty files. 2015-04-03 00:05:47 +11:00
hiker fb58e4b3b3 Use STK's log function in tinyugettext (so all errors/warnings
are logged to stdout.log).
2015-04-02 23:59:55 +11:00
hiker 4135ed4be2 Merge branch 'master' of github.com:supertuxkart/stk-code 2015-04-02 10:50:22 +11:00
hiker 3f76b0c68d Used better icon for achievements in tabs. 2015-04-02 10:46:30 +11:00
auriamg 6af71fe582 Merge pull request #2053 from tobbi/fix_redefinition_warning
Fix glVertexAttribDivisor redefinition warning
2015-04-01 19:07:34 -04:00
hiker d8a918758d Merge branch 'master' of github.com:supertuxkart/stk-code 2015-04-02 10:03:36 +11:00
hiker cbd45c26a2 Merge and sort old and new translation credits. Fixed handling of "
and some other minor fixes.
2015-04-01 22:24:02 +11:00
samuncle 4b735861cd Add a particle system 2015-04-01 04:30:17 +02:00
hiker 09a70b8aac Merge branch 'master' of github.com:supertuxkart/stk-code 2015-04-01 09:44:23 +11:00
hiker 414522e823 First version of a simple script that adds the transifex authors
to the list of launchpad authors in the translator-credits string.
The latter is used to display the appropriate in-game credits.
2015-04-01 09:41:37 +11:00
Deve 5e56f8904a MinGW: Allow to compile wiiuse.
Still disabled by default because it requires mingw-w64 and it may not work with other versions.
2015-03-31 19:27:07 +02:00
hiker c7e785b59c Fixed translator credits display (translators were repeated before).
Added #undef'ed debug mode to only see translations.
2015-03-31 16:16:30 +11:00
Deve cd67daf4a3 MinGW: Don't show console window in release mode.
Removed unused cmake option.
2015-03-30 20:12:25 +02:00
hiker 9cb862f708 Fix travis build. 2015-03-30 11:50:47 +11:00
hiker 8d07d26c25 Updated (c) year to include 2015. 2015-03-30 11:42:50 +11:00
hiker bcd9654a86 Added missing GPL license. 2015-03-30 11:42:28 +11:00
Marianne Gagnon 2d2624f71c Merge remote-tracking branch 'Flakebi/fribidi-text' 2015-03-29 20:06:21 -04:00
Marianne Gagnon 3a6fd75f10 Merge remote-tracking branch 'Flakebi/motionblur-fix' 2015-03-29 19:52:16 -04:00
hiker c579eba6db Removed empty file. 2015-03-30 09:58:28 +11:00
hiker 1971254a7f Fixed compiler warning. 2015-03-30 09:43:58 +11:00
Marianne Gagnon c08b898742 Merge branch 'Fix_2055' 2015-03-28 21:14:42 -04:00
Marianne Gagnon e1eec44d1a Tweak challenges 2015-03-28 20:16:45 -04:00
Marianne Gagnon dda3bb0f31 Tweak more challenges 2015-03-28 19:21:48 -04:00
Tobias Markus cedb7e7123 Fix glVertexAttribDivisor redefinition warning 2015-03-28 16:56:51 +01:00
279 changed files with 115135 additions and 16588 deletions
+12 -5
View File
@@ -1,6 +1,6 @@
# root CMakeLists for the SuperTuxKart project
project(SuperTuxKart)
set(PROJECT_VERSION "0.9")
set(PROJECT_VERSION "0.8.1")
cmake_minimum_required(VERSION 2.8.4)
if(NOT (CMAKE_MAJOR_VERSION VERSION_LESS 3))
@@ -18,6 +18,7 @@ endif()
option(USE_WIIUSE "Support for wiimote input devices" ON)
option(USE_FRIBIDI "Support for right-to-left languages" ON)
option(CHECK_ASSETS "Check if assets are installed in ../stk-assets" ON)
option(USE_SYSTEM_ANGELSCRIPT "Use system angelscript instead of built-in angelscript. If you enable this option, make sure to use a compatible version." OFF)
if(MSVC)
# Normally hide the option to build wiiuse on VS, since it depends
@@ -121,9 +122,15 @@ elseif(MSVC)
endif()
# Build the angelscript library
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/angelscript/projects/cmake")
include_directories("${PROJECT_SOURCE_DIR}/lib/angelscript/include")
# Build the angelscript library if not in system
find_package(Angelscript)
if(USE_SYSTEM_ANGELSCRIPT AND ANGELSCRIPT_FOUND)
include_directories(${Angelscript_INCLUDE_DIRS})
else()
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/angelscript/projects/cmake")
include_directories("${PROJECT_SOURCE_DIR}/lib/angelscript/include")
set(Angelscript_LIBRARIES angelscript)
endif()
# OpenAL
if(APPLE)
@@ -310,7 +317,7 @@ target_link_libraries(supertuxkart
enet
glew
stkirrlicht
angelscript
${Angelscript_LIBRARIES}
${CURL_LIBRARIES}
${OGGVORBIS_LIBRARIES}
${OPENAL_LIBRARY}
+33
View File
@@ -0,0 +1,33 @@
# - Try to find angelscript
# Once done this will define
#
# ANGELSCRIPT_FOUND - system has angelscript
# Angelscript_INCLUDE_DIRS - the angelscript include directory
# Angelscript_LIBRARIES - the libraries needed to use angelscript
#
FIND_PATH(Angelscript_INCLUDE_DIRS angelscript.h
PATHS
/usr/local
/usr
PATH_SUFFIXES include
)
FIND_LIBRARY(Angelscript_LIBRARY
NAMES angelscript
PATHS
/usr/local
/usr
PATH_SUFFIXES lib
)
# handle the QUIETLY and REQUIRED arguments and set ANGELSCRIPT_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Angelscript DEFAULT_MSG Angelscript_LIBRARY Angelscript_INCLUDE_DIRS)
IF (ANGELSCRIPT_FOUND)
SET(Angelscript_LIBRARIES ${Angelscript_LIBRARY})
ENDIF (ANGELSCRIPT_FOUND)
MARK_AS_ADVANCED(Angelscript_LIBRARY Angelscript_LIBRARIES Angelscript_INCLUDE_DIRS)
BIN
View File
Binary file not shown.
+2 -2
View File
@@ -17,11 +17,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.9</string>
<string>0.8.1</string>
<key>CFBundleSignature</key>
<string>SPTK</string>
<key>CFBundleVersion</key>
<string>0.9</string>
<string>0.8.1</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSMinimumSystemVersion</key>
+1 -1
View File
@@ -40,7 +40,7 @@
<skidding goal="5"/>
</achievement>
<achievement id="6" check-type="all-at-least" reset-type="never"
name="Gold driver" description="Win in all single player modes, against at least 3 opponents.">
name="Gold driver" description="Win against at least 3 opponents in all single player modes.">
<standard goal="1"/>
<std_timetrial goal="1"/>
<follow_leader goal="1"/>
+2 -2
View File
@@ -10,10 +10,10 @@
</hard>
<medium>
<karts number="4"/>
<requirements time="175"/>
<requirements time="185"/>
</medium>
<easy>
<karts number="4"/>
<requirements time="225"/>
<requirements time="270"/>
</easy>
</challenge>
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 154 KiB

+4 -1
View File
@@ -17,6 +17,9 @@
<card contains="Gallium" os="linux" version="<10.3" disable="DriverRecentEnough"/>
<card contains="Gallium" os="linux" version="<10.6" disable="GeometryShader4"/>
<card contains="Gallium" os="linux" disable="TextureCompressionS3TC"/>
<card contains="Radeon" version="<14.300" disable="DriverRecentEnough"/>
<!-- On osx radeon appears to have different version numbers, e.g.
1.32.20 -->
<card contains="Radeon" os="linux" version="<14.300" disable="DriverRecentEnough"/>
<card contains="Radeon" os="windows" version="<14.300" disable="DriverRecentEnough"/>
</graphical-restrictions>
+1 -1
View File
@@ -4,7 +4,7 @@
<div x="5%" y="2%" width="90%" height="96%" layout="vertical-row" >
<header I18N="Title for challenges screen" text="Challenges : Trophy Room" text_align="center" align="center" width="80%" />
<header I18N="Title for challenges screen" text="Challenges - Trophy Room" text_align="center" align="center" width="80%" />
<spacer height="5" width="100%"/>
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -7,7 +7,7 @@
<div width="100%" proportion="2" layout="horizontal-row">
<box id="info" proportion="2" height="100%" layout="vertical-row">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Server name :"/>
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Server name:"/>
<label proportion="2" text_align="left" id="server_name" text=""/>
</div>
</box>
+1 -1
View File
@@ -17,7 +17,7 @@
<box proportion="1" width="100%" layout="vertical-row">
<div x="1%" y="2%" width="98%" height="96%" layout="vertical-row" >
<div width="fit" height="fit" layout="horizontal-row" >
<label proportion="1" height="fit" text_align="left" I18N="In the online account settings screen" text="Password :"/>
<label proportion="1" height="fit" text_align="left" I18N="In the online account settings screen" text="Password:"/>
<spacer width="20" height="1"/>
<button id="change_password_button" height="100%" width="fit" text="Change" />
</div>
+1 -1
View File
@@ -30,7 +30,7 @@
<button id="add_device" I18N="In the input configuration screen" text="Add a device" align="center"/>
<label text="* Which config to use will be inferred from which 'Select' key is pressed to join the game."
<label I18N="In the input configuration screen" text="* Which config to use will be inferred from which 'Select' key is pressed to join the game."
proportion="2" word_wrap="true"/>
</box>
</div>
+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<div x="2%" y="10%" width="96%" height="80%" layout="vertical-row" >
<label raw_text="Run script"/>
<textbox id="textfield" width="75%" I18N="In the 'add new grand prix' dialog" align="center"/>
<spacer height="20" width="20" />
<div align="center" height="fit" width="100%" layout="horizontal-row">
<button id="run" raw_text="Run" align="center" proportion="1"/>
<spacer height="20" width="20" />
<button id="close" raw_text="Close" align="center" proportion="1"/>
</div>
</div>
</stkgui>
+1 -1
View File
@@ -7,7 +7,7 @@
<spacer height="2%" width="1"/>
<div width="100%" layout="horizontal-row" height="fit">
<label id="race_type" text="Type :" I18N="Type of race, in a challenge"/>
<label id="race_type" text="Type:" I18N="Type of race, in a challenge"/>
<spacer width="5" height="1"/>
<label id="race_type_val" proportion="1"/>
</div>
+1 -1
View File
@@ -4,7 +4,7 @@
<div x="5%" y="2%" width="90%" height="96%" layout="vertical-row" >
<header I18N="Title for tutorials screen" text="Tutorial : Selection Room" text_align="center" width="100%" />
<header I18N="Title for tutorials screen" text="Tutorial - Selection Room" text_align="center" width="100%" />
<spacer proportion="1" width="100%"/>
+27 -5
View File
@@ -20,8 +20,9 @@ jpegtran=true
advdef=true
advzip=true
optipng=true
convert=true
#WARNING! SETTING TO TRUE MAY POSSIBLY INCREASE LOAD TIMES ON A SLOW CPU (UNTESTED) OR LEAD TO FILE NOT FOUND ERRORS WHEN RUNNING SUPERTUXKART!
#WARNING! SETTING TO TRUE MAY POSSIBLY INCREASE LOAD TIMES ON A SLOW CPU (UNTESTED) OR LEAD TO FILE NOT FOUND ERRORS WHEN RUNNING SUPERTUXKART!
compress_b3d=false
@@ -58,10 +59,17 @@ then
sleep 2
fi
#check for convert
if [ ! $(which convert) ]
then
echo "convert is not installed, therefore it will not be used."; convert=false
sleep 2
fi
#check for optipng
if [ ! $(which optipng) ]
then
echo "optipng is not installed, therefore it will not be used."; optipng=false
echo "optipng is not installed, therefore it will not be used."; optipng=false
sleep 2
fi
@@ -83,10 +91,18 @@ BEFORE=`du -sk | awk '{print $1}'`
#functions for xargs multithreading, used instead of GNU parallel for cross-compatibility
#TODO: let next set of optimization scripts run if one set is stuck on a single file at the end to decrease total runtime
#strip ICC information off PNG's
strippng () {
for arg; do
convert "$arg" -strip "$arg"
done
}
export -f strippng
#optimize PNG's
optimpng () {
for arg; do
optipng -quiet -o3 "$arg"
optipng -quiet -o3 "$arg"
#level 3 = 16 trials, which according to http://optipng.sourceforge.net/pngtech/optipng.html (retrieved October 2014) should be satisfactory for all users
done
}
@@ -96,7 +112,7 @@ export -f optimpng
#compress PNG in-stream data
comprpng () {
for arg; do
advdef -z4 "$arg"
advdef -z4 "$arg"
done
}
export -f comprpng
@@ -121,6 +137,12 @@ done
export -f recomprb3dz
#END MULTITHREADING FUNCTIONS
#strip png icc information
if [ "$convert" = true ]; then
find . -path .svn -prune -o -name "*.png" -print0 | xargs -0 -n 1 -P "$threads" bash -c 'strippng "$@"' -- #multithread the png stripping
else echo "convert not installed. Ignoring commands using convert..."; sleep 1
fi
#lossless png image optimization
if [ "$optipng" = true ]; then
find . -path .svn -prune -o -name "*.png" -print0 | xargs -0 -n 1 -P "$threads" bash -c 'optimpng "$@"' -- #multithread the png optimization
@@ -142,7 +164,7 @@ else echo "jpegtran not installed. Ignoring commands using jpegtran..."; sleep 1
fi
#b3dz to b3dz compression
#b3dz to b3dz compression
#WARNING: BETA, MAY CAUSE MISSING FILE WARNINGS!
if [ "$compress_b3d" = true ]; then
for xmls in $(find . -name "*.xml"); do
+3370
View File
File diff suppressed because it is too large Load Diff
+3370
View File
File diff suppressed because it is too large Load Diff
+3373
View File
File diff suppressed because it is too large Load Diff
+3369
View File
File diff suppressed because it is too large Load Diff
+3370
View File
File diff suppressed because it is too large Load Diff
+3370
View File
File diff suppressed because it is too large Load Diff
+3370
View File
File diff suppressed because it is too large Load Diff
+3367
View File
File diff suppressed because it is too large Load Diff
+3369
View File
File diff suppressed because it is too large Load Diff
+3378
View File
File diff suppressed because it is too large Load Diff
+419 -415
View File
@@ -1,70 +1,4 @@
//I18N: ./data/achievements.xml
_("Christoffel Columbus")
//I18N: ./data/achievements.xml
_("Play every official track at least once.")
//I18N: ./data/achievements.xml
_("Strike!")
//I18N: ./data/achievements.xml
_("Hit 10 karts with a bowling-ball.")
//I18N: ./data/achievements.xml
_("Arch Enemy")
//I18N: ./data/achievements.xml
_("Hit the same kart at least 5 times in one race.")
//I18N: ./data/achievements.xml
_("Marathoner")
//I18N: ./data/achievements.xml
_("Make a race with 5 laps or more.")
//I18N: ./data/achievements.xml
_("Skid-row")
//I18N: ./data/achievements.xml
_("Make 5 skidding in a single lap.")
//I18N: ./data/achievements.xml
_("Gold driver")
//I18N: ./data/achievements.xml
_("Win in all single player modes, against at least 3 opponents.")
//I18N: ./data/achievements.xml
_("Powerup Love")
//I18N: ./data/achievements.xml
_("Use 10 or more powerups in a race.")
//I18N: ./data/achievements.xml
_("Unstoppable")
//I18N: ./data/achievements.xml
_("Win 5 single races in a row.")
//I18N: ./data/achievements.xml
_("Banana Lover")
//I18N: ./data/achievements.xml
_("Collect at least 5 bananas in one race.")
//I18N: ./data/achievements.xml
_("It's secret")
//I18N: ./data/achievements.xml
_("Really ... a secret.")
//I18N: ./data/achievements.xml
_("Mosquito Hunter")
//I18N: ./data/achievements.xml
_("Take your opponents for mosquitos! With the swatter, squash at least 5 of them in a race.")
//I18N: ./data/grandprix/1_penguinplayground.grandprix
//I18N: ./data/grandprix/1_penguinplayground.grandprix
_("Penguin Playground")
//I18N: ./data/grandprix/2_offthebeatentrack.grandprix
@@ -127,10 +61,6 @@ _("Add-Ons");
//I18N: track group
_("All");
//I18N: ./data/gui/challenges.stkgui
//I18N: Title for challenges screen
_("Challenges : Trophy Room");
//I18N: ./data/gui/confirm_dialog.stkgui
//I18N: In a 'are you sure?' dialog
_("Yes");
@@ -286,6 +216,30 @@ _("Cancel");
//I18N: ./data/gui/feature_unlocked.stkgui
_("Continue")
//I18N: ./data/gui/gp_info.stkgui
//I18N: In the grand prix info screen
_("AI karts");
//I18N: ./data/gui/gp_info.stkgui
//I18N: In the grand prix info screen
_("Reverse");
//I18N: ./data/gui/gp_info.stkgui
//I18N: In the grand prix info screen
_("Tracks");
//I18N: ./data/gui/gp_info.stkgui
//I18N: In the grand prix info screen
_("Track group");
//I18N: ./data/gui/gp_info.stkgui
//I18N: In the grand prix info screen
_("Start Race");
//I18N: ./data/gui/gp_info.stkgui
//I18N: In the grand prix info screen
_("Continue saved GP");
//I18N: ./data/gui/gpedit.stkgui
//I18N: Title in edit grand prix screen
_("Edit Grand Prix");
@@ -338,30 +292,6 @@ _("Remove");
//I18N: Menu item
_("Rename");
//I18N: ./data/gui/gp_info.stkgui
//I18N: In the grand prix info screen
_("AI karts");
//I18N: ./data/gui/gp_info.stkgui
//I18N: In the grand prix info screen
_("Reverse");
//I18N: ./data/gui/gp_info.stkgui
//I18N: In the grand prix info screen
_("Tracks");
//I18N: ./data/gui/gp_info.stkgui
//I18N: In the grand prix info screen
_("Track group");
//I18N: ./data/gui/gp_info.stkgui
//I18N: In the grand prix info screen
_("Start Race");
//I18N: ./data/gui/gp_info.stkgui
//I18N: In the grand prix info screen
_("Continue saved GP");
//I18N: ./data/gui/grand_prix_lose.stkgui
_("Continue")
@@ -374,152 +304,6 @@ _("Continue")
//I18N: ./data/gui/grand_prix_win.stkgui
_("Save Grand Prix")
//I18N: ./data/gui/help1.stkgui
_("SuperTuxKart Help")
//I18N: ./data/gui/help1.stkgui
//I18N: Tab in help menu
_("General");
//I18N: ./data/gui/help1.stkgui
//I18N: Tab in help menu
_("Weapons");
//I18N: ./data/gui/help1.stkgui
//I18N: Tab in help menu
_("Game Modes");
//I18N: ./data/gui/help1.stkgui
//I18N: Tab in help menu
_("Multi­player");
//I18N: ./data/gui/help1.stkgui
_("Click here to play the tutorial")
//I18N: ./data/gui/help1.stkgui
//I18N: In the help menu
_("Collect blue boxes : they will give you weapons or other powerups");
//I18N: ./data/gui/help1.stkgui
//I18N: In the help menu
_("Avoid bananas!");
//I18N: ./data/gui/help1.stkgui
//I18N: In the help menu
_("Collecting nitro allows you to get speed boosts whenever you wish by pressing the appropriate key. You can see your current level of nitro in the bar at the right of the game screen.");
//I18N: ./data/gui/help1.stkgui
//I18N: In the help menu
_("If you see a button with a lock like this one, you need to complete a challenge to unlock it.");
//I18N: ./data/gui/help1.stkgui
//I18N: in the help menu
_("The 'skidding' key allows you to skid in sharp turns and get a boost.");
//I18N: ./data/gui/help1.stkgui
//I18N: in the help screen
_("* Current key bindings can be seen/changed in menu Options");
//I18N: ./data/gui/help2.stkgui
_("SuperTuxKart Help")
//I18N: ./data/gui/help2.stkgui
//I18N: Tab in help menu
_("General");
//I18N: ./data/gui/help2.stkgui
//I18N: Tab in help menu
_("Weapons");
//I18N: ./data/gui/help2.stkgui
//I18N: Tab in help menu
_("Game Modes");
//I18N: ./data/gui/help2.stkgui
//I18N: Tab in help menu
_("Multi­player");
//I18N: ./data/gui/help2.stkgui
//I18N: In the help menu
_("To help you win, there are some powerups you can collect :");
//I18N: ./data/gui/help2.stkgui
_("BubbleGum - protect yourself with a shield, or use while looking back to leave a sticky pink puddle behind you.")
//I18N: ./data/gui/help2.stkgui
_("Cake - thrown at the closest rival, best on short ranges and long straights.")
//I18N: ./data/gui/help2.stkgui
_("Plunger - throw straight to pull an opponent back, or throw while looking back to make one lose sight.")
//I18N: ./data/gui/help2.stkgui
_("Bowling Ball - bounces off walls. If you are looking back, it will be thrown backwards.")
//I18N: ./data/gui/help2.stkgui
_("Parachute - slows down all karts in a better position.")
//I18N: ./data/gui/help2.stkgui
_("Anchor - slows down greatly the kart in the first position.")
//I18N: ./data/gui/help2.stkgui
_("Swapper - gift boxes are transformed into bananas and vice versa for a short time.")
//I18N: ./data/gui/help2.stkgui
_("Basket Ball - bounces after the leader, and might squash and slow down karts down on the way.")
//I18N: ./data/gui/help2.stkgui
_("Swatter - will squash karts close by, slowing them down.")
//I18N: ./data/gui/help3.stkgui
_("SuperTuxKart Help")
//I18N: ./data/gui/help3.stkgui
//I18N: Tab in help menu
_("General");
//I18N: ./data/gui/help3.stkgui
//I18N: Tab in help menu
_("Weapons");
//I18N: ./data/gui/help3.stkgui
//I18N: Tab in help menu
_("Game Modes");
//I18N: ./data/gui/help3.stkgui
//I18N: Tab in help menu
_("Multi­player");
//I18N: ./data/gui/help3.stkgui
_("SuperTuxKart features several game modes")
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("Regular Race: All blows allowed, so catch weapons and make clever use of them!");
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("Time Trial: Contains no powerups, so only your driving skills matter!");
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("Follow the leader: Run for second place, as the last kart will be disqualified every time the counter hits zero. Beware : going in front of the leader will get you eliminated too!");
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("3 Strikes Battle: Only in multiplayer games. Hit others with weapons until they lose all their lives.");
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("Soccer: Only in multiplayer games. Use your kart to push the ball into the goal.");
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("Egg hunt: Explore tracks to find all hidden eggs.");
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("* Most of these game modes can also be played in a Grand Prix fashion: instead of playing a single race, you play many in a row. The better you rank, the more points you get. In the end, the player with the most points wins the cup.");
//I18N: ./data/gui/help4.stkgui
_("SuperTuxKart Help")
@@ -684,22 +468,6 @@ _("Log In");
//I18N: In the login dialog
_("Close");
//I18N: ./data/gui/online/lobby.stkgui
//I18N: In networking lobby
_("Lobby");
//I18N: ./data/gui/online/lobby.stkgui
//I18N: In the networking lobby
_("Server name :");
//I18N: ./data/gui/online/lobby.stkgui
//I18N: In networking lobby
_("actions");
//I18N: ./data/gui/online/lobby.stkgui
//I18N: In the networking lobby
_("Exit");
//I18N: ./data/gui/online/lobby_settings.stkgui
//I18N: In the lobby settings screen
_("Lobby Settings");
@@ -775,20 +543,6 @@ _("...")
//I18N: Section in the profile screen
_("Overview");
//I18N: ./data/gui/online/profile_settings.stkgui
_("...")
//I18N: ./data/gui/online/profile_settings.stkgui
//I18N: Section in the profile screen
_("Account Settings");
//I18N: ./data/gui/online/profile_settings.stkgui
//I18N: In the online account settings screen
_("Password :");
//I18N: ./data/gui/online/profile_settings.stkgui
_("Change")
//I18N: ./data/gui/online/recovery_info.stkgui
//I18N: In the recovery dialog
_("Account Recovery");
@@ -953,6 +707,36 @@ _("Vote");
//I18N: Vote dialog
_("Close");
//I18N: ./data/gui/online/lobby.stkgui
//I18N: In networking lobby
_("Lobby");
//I18N: ./data/gui/online/lobby.stkgui
//I18N: In the networking lobby
_("Server name:");
//I18N: ./data/gui/online/lobby.stkgui
//I18N: In networking lobby
_("actions");
//I18N: ./data/gui/online/lobby.stkgui
//I18N: In the networking lobby
_("Exit");
//I18N: ./data/gui/online/profile_settings.stkgui
_("...")
//I18N: ./data/gui/online/profile_settings.stkgui
//I18N: Section in the profile screen
_("Account Settings");
//I18N: ./data/gui/online/profile_settings.stkgui
//I18N: In the online account settings screen
_("Password:");
//I18N: ./data/gui/online/profile_settings.stkgui
_("Change")
//I18N: ./data/gui/options_audio.stkgui
_("SuperTuxKart Options")
@@ -1015,7 +799,8 @@ _("Press enter or double-click on a device to configure it");
_("Add a device");
//I18N: ./data/gui/options_input.stkgui
_("* Which config to use will be inferred from which 'Select' key is pressed to join the game.")
//I18N: In the input configuration screen
_("* Which config to use will be inferred from which 'Select' key is pressed to join the game.");
//I18N: ./data/gui/options_players.stkgui
_("SuperTuxKart Options")
@@ -1139,31 +924,6 @@ _("Assign nothing");
//I18N: When configuring input
_("Press ESC to cancel");
//I18N: ./data/gui/racesetup.stkgui
_("Race Setup")
//I18N: ./data/gui/racesetup.stkgui
_("Select a difficulty")
//I18N: ./data/gui/racesetup.stkgui
//I18N: Difficulty
_("Novice");
//I18N: ./data/gui/racesetup.stkgui
//I18N: Difficulty
_("Intermediate");
//I18N: ./data/gui/racesetup.stkgui
//I18N: Difficulty
_("Expert");
//I18N: ./data/gui/racesetup.stkgui
//I18N: Difficulty
_("SuperTux");
//I18N: ./data/gui/racesetup.stkgui
_("Select a game mode")
//I18N: ./data/gui/race_paused_dialog.stkgui
_("Paused")
@@ -1195,25 +955,31 @@ _("Help");
//I18N: Race paused button
_("Exit Race");
//I18N: ./data/gui/select_challenge.stkgui
//I18N: ./data/gui/racesetup.stkgui
_("Race Setup")
//I18N: ./data/gui/select_challenge.stkgui
//I18N: Type of race, in a challenge
_("Type :");
//I18N: ./data/gui/racesetup.stkgui
_("Select a difficulty")
//I18N: ./data/gui/select_challenge.stkgui
//I18N: ./data/gui/racesetup.stkgui
//I18N: Difficulty
_("Novice");
//I18N: ./data/gui/select_challenge.stkgui
//I18N: ./data/gui/racesetup.stkgui
//I18N: Difficulty
_("Intermediate");
//I18N: ./data/gui/select_challenge.stkgui
//I18N: ./data/gui/racesetup.stkgui
//I18N: Difficulty
_("Expert");
//I18N: ./data/gui/racesetup.stkgui
//I18N: Difficulty
_("SuperTux");
//I18N: ./data/gui/racesetup.stkgui
_("Select a game mode")
//I18N: ./data/gui/soccer_setup.stkgui
_("Race Setup")
@@ -1240,14 +1006,6 @@ _("VS")
//I18N: In soccer setup screen
_("Continue");
//I18N: ./data/gui/tracks.stkgui
//I18N: In the track selection screen
_("Grand Prix");
//I18N: ./data/gui/tracks.stkgui
//I18N: In the track selection screen
_("All Tracks");
//I18N: ./data/gui/track_info.stkgui
_("= Highscores =")
@@ -1276,12 +1034,13 @@ _("Drive in reverse");
//I18N: In the track info screen
_("Start Race");
//I18N: ./data/gui/tutorial.stkgui
//I18N: Title for tutorials screen
_("Tutorial : Selection Room");
//I18N: ./data/gui/tracks.stkgui
//I18N: In the track selection screen
_("Grand Prix");
//I18N: ./data/gui/tutorial.stkgui
_("Play all")
//I18N: ./data/gui/tracks.stkgui
//I18N: In the track selection screen
_("All Tracks");
//I18N: ./data/gui/tutorial_message_dialog.stkgui
//I18N: Button in tutorial
@@ -1369,74 +1128,343 @@ _("Rename");
//I18N: In the user screen
_("Cancel");
//I18N: ../stk-assets/tracks/battleisland/track.xml
_("Battle Island")
//I18N: ./data/gui/challenges.stkgui
//I18N: Title for challenges screen
_("Challenges - Trophy Room");
//I18N: ../stk-assets/tracks/cave/track.xml
_("Cave X")
//I18N: ./data/gui/tutorial.stkgui
//I18N: Title for tutorials screen
_("Tutorial - Selection Room");
//I18N: ../stk-assets/tracks/city/track.xml
_("Shiny Suburbs")
//I18N: ./data/gui/tutorial.stkgui
_("Play all")
//I18N: ../stk-assets/tracks/cocoa_temple/track.xml
_("Cocoa Temple")
//I18N: ./data/gui/help1.stkgui
_("SuperTuxKart Help")
//I18N: ../stk-assets/tracks/farm/track.xml
_("Bovine Barnyard")
//I18N: ./data/gui/help1.stkgui
//I18N: Tab in help menu
_("General");
//I18N: ../stk-assets/tracks/fortmagma/track.xml
_("Fort Magma")
//I18N: ./data/gui/help1.stkgui
//I18N: Tab in help menu
_("Weapons");
//I18N: ../stk-assets/tracks/gran_paradiso_island/track.xml
_("Gran Paradiso Island")
//I18N: ./data/gui/help1.stkgui
//I18N: Tab in help menu
_("Game Modes");
//I18N: ../stk-assets/tracks/greenvalley/track.xml
_("Green Valley")
//I18N: ./data/gui/help1.stkgui
//I18N: Tab in help menu
_("Multi­player");
//I18N: ../stk-assets/tracks/hacienda/track.xml
_("Hacienda")
//I18N: ./data/gui/help1.stkgui
_("Click here to play the tutorial")
//I18N: Cutscene subtitle from ../stk-assets/tracks/introcutscene2/scene.xml
_("What's wrong, little hippies? Your great gnu leader is missing?")
//I18N: ./data/gui/help1.stkgui
//I18N: In the help menu
_("Collect blue boxes. They will give you weapons or other powerups.");
//I18N: ../stk-assets/tracks/introcutscene2/scene.xml
_("What's wrong, little hippies? Your great gnu leader is missing?")
//I18N: ./data/gui/help1.stkgui
//I18N: In the help menu
_("Avoid bananas!");
//I18N: Cutscene subtitle from ../stk-assets/tracks/introcutscene2/scene.xml
_("Oh yes, see, he's in my castle now and will be served for supper...")
//I18N: ./data/gui/help1.stkgui
//I18N: In the help menu
_("Collecting nitro allows you to get speed boosts whenever you wish by pressing the appropriate key. You can see your current level of nitro in the bar at the right of the game screen.");
//I18N: ../stk-assets/tracks/introcutscene2/scene.xml
_("Oh yes, see, he's in my castle now and will be served for supper...")
//I18N: ./data/gui/help1.stkgui
//I18N: In the help menu
_("If you see a button with a lock like this one, you need to complete a challenge to unlock it.");
//I18N: Cutscene subtitle from ../stk-assets/tracks/introcutscene2/scene.xml
_("But I'm a fair creature, so I'll make you a deal.")
//I18N: ./data/gui/help1.stkgui
//I18N: in the help menu
_("The 'skidding' key allows you to skid in sharp turns and get a boost.");
//I18N: ../stk-assets/tracks/introcutscene2/scene.xml
_("But I'm a fair creature, so I'll make you a deal.")
//I18N: ./data/gui/help1.stkgui
//I18N: in the help screen
_("* Current key bindings can be seen/changed in menu Options");
//I18N: Cutscene subtitle from ../stk-assets/tracks/introcutscene2/scene.xml
_("If you can beat me at racing, I will free the old codger.")
//I18N: ./data/gui/help2.stkgui
_("SuperTuxKart Help")
//I18N: ../stk-assets/tracks/introcutscene2/scene.xml
_("If you can beat me at racing, I will free the old codger.")
//I18N: ./data/gui/help2.stkgui
//I18N: Tab in help menu
_("General");
//I18N: Cutscene subtitle from ../stk-assets/tracks/introcutscene2/scene.xml
_(" But you pathetic little twerps will never be able to beat me - King of the Karts!")
//I18N: ./data/gui/help2.stkgui
//I18N: Tab in help menu
_("Weapons");
//I18N: ../stk-assets/tracks/introcutscene2/scene.xml
_(" But you pathetic little twerps will never be able to beat me - King of the Karts!")
//I18N: ./data/gui/help2.stkgui
//I18N: Tab in help menu
_("Game Modes");
//I18N: ../stk-assets/tracks/lighthouse/track.xml
_("Around the lighthouse")
//I18N: ./data/gui/help2.stkgui
//I18N: Tab in help menu
_("Multi­player");
//I18N: ./data/gui/help2.stkgui
//I18N: In the help menu
_("To help you win, there are some powerups you can collect:");
//I18N: ./data/gui/help2.stkgui
_("BubbleGum - protect yourself with a shield, or use while looking back to leave a sticky pink puddle behind you.")
//I18N: ./data/gui/help2.stkgui
_("Cake - thrown at the closest rival, best on short ranges and long straights.")
//I18N: ./data/gui/help2.stkgui
_("Plunger - throw straight to pull an opponent back, or throw while looking back to make one lose sight.")
//I18N: ./data/gui/help2.stkgui
_("Bowling Ball - bounces off walls. If you are looking back, it will be thrown backwards.")
//I18N: ./data/gui/help2.stkgui
_("Parachute - slows down all karts in a better position.")
//I18N: ./data/gui/help2.stkgui
_("Anchor - greatly slows down the kart in the first position.")
//I18N: ./data/gui/help2.stkgui
_("Swapper - gift boxes are transformed into bananas and vice versa for a short time.")
//I18N: ./data/gui/help2.stkgui
_("Basket Ball - bounces after the leader, and might squash and slow down karts down on the way.")
//I18N: ./data/gui/help2.stkgui
_("Swatter - will squash karts close by, slowing them down.")
//I18N: ./data/gui/help3.stkgui
_("SuperTuxKart Help")
//I18N: ./data/gui/help3.stkgui
//I18N: Tab in help menu
_("General");
//I18N: ./data/gui/help3.stkgui
//I18N: Tab in help menu
_("Weapons");
//I18N: ./data/gui/help3.stkgui
//I18N: Tab in help menu
_("Game Modes");
//I18N: ./data/gui/help3.stkgui
//I18N: Tab in help menu
_("Multi­player");
//I18N: ./data/gui/help3.stkgui
_("SuperTuxKart features several game modes")
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("Regular Race: All blows allowed, so catch weapons and make clever use of them!");
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("Time Trial: Contains no powerups, so only your driving skills matter!");
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("Follow the leader: Run for second place, as the last kart will be disqualified every time the counter hits zero. Beware: going in front of the leader will get you eliminated too!");
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("3 Strikes Battle: Only in multiplayer games. Hit others with weapons until they lose all their lives.");
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("Soccer: Only in multiplayer games. Use your kart to push the ball into the goal.");
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("Egg hunt: Explore tracks to find all hidden eggs.");
//I18N: ./data/gui/help3.stkgui
//I18N: In the help menu
_("* Most of these game modes can also be played in a Grand Prix fashion: instead of playing a single race, you play many in a row. The better you rank, the more points you get. In the end, the player with the most points wins the cup.");
//I18N: ./data/gui/select_challenge.stkgui
_("Race Setup")
//I18N: ./data/gui/select_challenge.stkgui
//I18N: Type of race, in a challenge
_("Type:");
//I18N: ./data/gui/select_challenge.stkgui
//I18N: Difficulty
_("Novice");
//I18N: ./data/gui/select_challenge.stkgui
//I18N: Difficulty
_("Intermediate");
//I18N: ./data/gui/select_challenge.stkgui
//I18N: Difficulty
_("Expert");
//I18N: ./data/achievements.xml
_("Christoffel Columbus")
//I18N: ./data/achievements.xml
_("Play every official track at least once.")
//I18N: ./data/achievements.xml
_("Strike!")
//I18N: ./data/achievements.xml
_("Hit 10 karts with a bowling-ball.")
//I18N: ./data/achievements.xml
_("Arch Enemy")
//I18N: ./data/achievements.xml
_("Hit the same kart at least 5 times in one race.")
//I18N: ./data/achievements.xml
_("Marathoner")
//I18N: ./data/achievements.xml
_("Make a race with 5 laps or more.")
//I18N: ./data/achievements.xml
_("Skid-row")
//I18N: ./data/achievements.xml
_("Make 5 skidding in a single lap.")
//I18N: ./data/achievements.xml
_("Gold driver")
//I18N: ./data/achievements.xml
_("Win against at least 3 opponents in all single player modes.")
//I18N: ./data/achievements.xml
_("Powerup Love")
//I18N: ./data/achievements.xml
_("Use 10 or more powerups in a race.")
//I18N: ./data/achievements.xml
_("Unstoppable")
//I18N: ./data/achievements.xml
_("Win 5 single races in a row.")
//I18N: ./data/achievements.xml
_("Banana Lover")
//I18N: ./data/achievements.xml
_("Collect at least 5 bananas in one race.")
//I18N: ./data/achievements.xml
_("It's secret")
//I18N: ./data/achievements.xml
_("Really ... a secret.")
//I18N: ./data/achievements.xml
_("Mosquito Hunter")
//I18N: ./data/achievements.xml
_("Take your opponents for mosquitos! With the swatter, squash at least 5 of them in a race.")
//I18N: ../stk-assets/tracks/soccer_field/track.xml
_("Soccer field")
//I18N: ../stk-assets/tracks/subsea/track.xml
_("Subsea")
//I18N: ../stk-assets/tracks/snowmountain/track.xml
_("Northern Resort")
//I18N: ../stk-assets/tracks/minigolf/track.xml
_("Minigolf")
//I18N: ../stk-assets/tracks/mansion/track.xml
_("Blackhill Mansion")
//I18N: ../stk-assets/tracks/stadium/track.xml
_("The Stadium")
//I18N: ../stk-assets/tracks/battleisland/track.xml
_("Battle Island")
//I18N: ../stk-assets/tracks/scotland/track.xml
_("Nessie's pond")
//I18N: ../stk-assets/tracks/city/track.xml
_("Shiny Suburbs")
//I18N: ../stk-assets/tracks/lighthouse/track.xml
_("Around the lighthouse")
//I18N: ../stk-assets/tracks/mines/track.xml
_("Old Mine")
//I18N: ../stk-assets/tracks/minigolf/track.xml
_("Minigolf")
//I18N: ../stk-assets/tracks/zengarden/track.xml
_("Zen Garden")
//I18N: ../stk-assets/tracks/greenvalley/track.xml
_("Green Valley")
//I18N: ../stk-assets/tracks/fortmagma/track.xml
_("Fort Magma")
//I18N: ../stk-assets/tracks/farm/track.xml
_("Bovine Barnyard")
//I18N: ../stk-assets/tracks/temple/track.xml
_("Temple")
//I18N: ../stk-assets/tracks/snowtuxpeak/track.xml
_("Snow Peak")
//I18N: ../stk-assets/tracks/xr591/track.xml
_("XR591")
//I18N: ../stk-assets/tracks/cocoa_temple/track.xml
_("Cocoa Temple")
//I18N: ../stk-assets/tracks/hacienda/track.xml
_("Hacienda")
//I18N: ../stk-assets/tracks/stk_enterprise/track.xml
_("STK Enterprise")
//I18N: ../stk-assets/tracks/gran_paradiso_island/track.xml
_("Gran Paradiso Island")
//I18N: Cutscene subtitle from ../stk-assets/tracks/introcutscene2/scene.xml
_("What's wrong, little hippies? Your great gnu leader is missing?")
//I18N: ../stk-assets/tracks/introcutscene2/scene.xml
_("What's wrong, little hippies? Your great gnu leader is missing?")
//I18N: Cutscene subtitle from ../stk-assets/tracks/introcutscene2/scene.xml
_("Oh yes, see, he's in my castle now and will be served for supper...")
//I18N: ../stk-assets/tracks/introcutscene2/scene.xml
_("Oh yes, see, he's in my castle now and will be served for supper...")
//I18N: Cutscene subtitle from ../stk-assets/tracks/introcutscene2/scene.xml
_("But I'm a fair creature, so I'll make you a deal.")
//I18N: ../stk-assets/tracks/introcutscene2/scene.xml
_("But I'm a fair creature, so I'll make you a deal.")
//I18N: Cutscene subtitle from ../stk-assets/tracks/introcutscene2/scene.xml
_("If you can beat me at racing, I will free the old codger.")
//I18N: ../stk-assets/tracks/introcutscene2/scene.xml
_("If you can beat me at racing, I will free the old codger.")
//I18N: Cutscene subtitle from ../stk-assets/tracks/introcutscene2/scene.xml
_(" But you pathetic little twerps will never be able to beat me - King of the Karts!")
//I18N: ../stk-assets/tracks/introcutscene2/scene.xml
_(" But you pathetic little twerps will never be able to beat me - King of the Karts!")
//I18N: ../stk-assets/tracks/olivermath/track.xml
_("Oliver's Math Class")
@@ -1444,56 +1472,17 @@ _("Oliver's Math Class")
//I18N: ../stk-assets/tracks/sandtrack/track.xml
_("Shifting Sands")
//I18N: ../stk-assets/tracks/scotland/track.xml
_("Nessie's pond")
//I18N: ../stk-assets/tracks/cave/track.xml
_("Cave X")
//I18N: ../stk-assets/tracks/snowmountain/track.xml
_("Northern Resort")
//I18N: ../stk-assets/tracks/snowtuxpeak/track.xml
_("Snow Peak")
//I18N: ../stk-assets/tracks/soccer_field/track.xml
_("Soccer field")
//I18N: ../stk-assets/tracks/stadium/track.xml
_("The Stadium")
//I18N: ../stk-assets/tracks/stk_enterprise/track.xml
_("STK Enterprise")
//I18N: ../stk-assets/tracks/subsea/track.xml
_("Subsea")
//I18N: ../stk-assets/tracks/temple/track.xml
_("Temple")
//I18N: ../stk-assets/tracks/xr591/track.xml
_("XR591")
//I18N: ../stk-assets/tracks/zengarden/track.xml
_("Zen Garden")
//I18N: ../stk-assets/karts/adiumy/kart.xml
_("Adiumy")
//I18N: ../stk-assets/karts/amanda/kart.xml
_("Amanda")
//I18N: ../stk-assets/karts/beastie/kart.xml
_("Beastie")
//I18N: ../stk-assets/karts/tux/kart.xml
_("Tux")
//I18N: ../stk-assets/karts/elephpant/kart.xml
_("Elephpant")
//I18N: ../stk-assets/karts/emule/kart.xml
_("Emule")
//I18N: ../stk-assets/karts/gnu/kart.xml
_("Gnu")
//I18N: ../stk-assets/karts/hexley/kart.xml
_("Hexley")
//I18N: ../stk-assets/karts/amanda/kart.xml
_("Amanda")
//I18N: ../stk-assets/karts/konqi/kart.xml
_("Konqi")
@@ -1501,27 +1490,42 @@ _("Konqi")
//I18N: ../stk-assets/karts/nolok/kart.xml
_("Nolok")
//I18N: ../stk-assets/karts/pidgin/kart.xml
_("Pidgin")
//I18N: ../stk-assets/karts/suzanne/kart.xml
_("Suzanne")
//I18N: ../stk-assets/karts/wilber/kart.xml
_("Wilber")
//I18N: ../stk-assets/karts/adiumy/kart.xml
_("Adiumy")
//I18N: ../stk-assets/karts/gnu/kart.xml
_("Gnu")
//I18N: ../stk-assets/karts/puffy/kart.xml
_("Puffy")
//I18N: ../stk-assets/karts/gavroche/kart.xml
_("Gavroche")
//I18N: ../stk-assets/karts/hexley/kart.xml
_("Hexley")
//I18N: ../stk-assets/karts/xue/kart.xml
_("Xue")
//I18N: ../stk-assets/karts/sara_the_racer/kart.xml
_("Sara the Racer")
//I18N: ../stk-assets/karts/sara_the_wizard/kart.xml
_("Sara the Wizard")
//I18N: ../stk-assets/karts/suzanne/kart.xml
_("Suzanne")
//I18N: ../stk-assets/karts/emule/kart.xml
_("Emule")
//I18N: ../stk-assets/karts/tux/kart.xml
_("Tux")
//I18N: ../stk-assets/karts/pidgin/kart.xml
_("Pidgin")
//I18N: ../stk-assets/karts/wilber/kart.xml
_("Wilber")
//I18N: ../stk-assets/karts/xue/kart.xml
_("Xue")
//I18N: ../stk-assets/karts/beastie/kart.xml
_("Beastie")
+3370
View File
File diff suppressed because it is too large Load Diff
+3373
View File
File diff suppressed because it is too large Load Diff
+3370
View File
File diff suppressed because it is too large Load Diff
+3370
View File
File diff suppressed because it is too large Load Diff
+3371
View File
File diff suppressed because it is too large Load Diff
+3367
View File
File diff suppressed because it is too large Load Diff
+3372
View File
File diff suppressed because it is too large Load Diff
+3369
View File
File diff suppressed because it is too large Load Diff
+3369
View File
File diff suppressed because it is too large Load Diff
+3370
View File
File diff suppressed because it is too large Load Diff
+3372
View File
File diff suppressed because it is too large Load Diff
+3370
View File
File diff suppressed because it is too large Load Diff
+3373
View File
File diff suppressed because it is too large Load Diff
+3370
View File
File diff suppressed because it is too large Load Diff
+2956 -2928
View File
File diff suppressed because it is too large Load Diff
+3369
View File
File diff suppressed because it is too large Load Diff
+3367
View File
File diff suppressed because it is too large Load Diff
+8 -2
View File
@@ -17,11 +17,13 @@ XML_FILE_LIST="`find ./data ../stk-assets/tracks ../stk-assets/karts \
-name '*.grandprix' -or \
-name '*.stkgui' \
`"
ANGELSCRIPT_FILE_LIST="`find ./data ../stk-assets/tracks -name '*.as'`"
echo "--------------------"
echo " Source Files :"
echo "--------------------"
echo $CPP_FILE_LIST
echo $ANGELSCRIPT_FILE_LIST
echo "--------------------"
echo " XML Files :"
@@ -37,18 +39,22 @@ echo "---------------------------"
echo " Generating .pot file..."
# XML Files
xgettext -d supertuxkart -s --keyword=_ --add-comments="I18N:" \
xgettext -d supertuxkart --keyword=_ --add-comments="I18N:" \
-p ./data/po -o supertuxkart.pot \
--no-location --from-code=UTF-8 ./data/po/gui_strings.h \
--package-name=supertuxkart
# C++ Files
xgettext -j -d supertuxkart -s --keyword=_ --keyword=N_ --keyword=_LTR \
xgettext -j -d supertuxkart --keyword=_ --keyword=N_ --keyword=_LTR \
--keyword=_C:1c,2 --keyword=_P:1,2 \
--keyword=_CP:1c,2,3 --add-comments="I18N:" \
-p ./data/po -o supertuxkart.pot $CPP_FILE_LIST \
--package-name=supertuxkart
# Angelscript files (xgettext doesn't support AS so pretend it's c++)
xgettext -j -d supertuxkart -s --keyword="translate" --add-comments="I18N:" \
-p ./data/po -o supertuxkart.pot $ANGELSCRIPT_FILE_LIST \
--package-name=supertuxkart --language=c++
echo " Done"
+3367
View File
File diff suppressed because it is too large Load Diff
-55
View File
@@ -1,55 +0,0 @@
uniform sampler2D depth;
layout (local_size_x = 32, local_size_y = 32) in;
layout (std430) buffer Histogram
{
int bin[1024];
int mindepth;
int maxdepth;
int count;
};
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
shared int sbin[1024];
shared int smindepth;
shared int smaxdepth;
shared int scount;
void main()
{
int x = int(gl_GlobalInvocationID.x), y = int(gl_GlobalInvocationID.y);
vec2 uv = vec2(x, y) / screen;
float z = texture(depth, uv).x;
vec4 xpos = getPosFromUVDepth(vec3(uv, z), InverseProjectionMatrix);
int lineardepth = int(xpos.z * 4);
sbin[gl_LocalInvocationIndex] = 0;
if (gl_LocalInvocationIndex == 0) {
smindepth = 1000;
smaxdepth = 0;
scount = 0;
}
barrier();
if (lineardepth < 1000) {
atomicAdd(sbin[lineardepth], 1);
atomicAdd(scount, 1);
atomicMin(smindepth, lineardepth);
atomicMax(smaxdepth, lineardepth);
}
barrier();
atomicAdd(bin[gl_LocalInvocationIndex], sbin[gl_LocalInvocationIndex]);
if (gl_LocalInvocationIndex == 0) {
atomicAdd(count, scount);
atomicMin(mindepth, smindepth);
atomicMax(maxdepth, smaxdepth);
}
}
File diff suppressed because it is too large Load Diff
+130 -91
View File
@@ -1,116 +1,155 @@
cmake_minimum_required(VERSION 2.6)
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE)
cmake_policy(SET CMP0003 NEW)
project(angelscript)
option(BUILD_SHARED_LIBS "Build shared library" OFF)
if(APPLE)
option(BUILD_FRAMEWORK "Build Framework bundle for OSX" OFF)
endif()
set(ANGELSCRIPT_VERSION_MAJOR 2)
set(ANGELSCRIPT_VERSION_MINOR 30)
set(ANGELSCRIPT_VERSION_PATCH 0)
set(PROJECT_VERSION ${ANGELSCRIPT_VERSION_MAJOR}.${ANGELSCRIPT_VERSION_MINOR}.${ANGELSCRIPT_VERSION_PATCH})
find_package(Threads)
set(ANGELSCRIPT_HEADERS
../../include/angelscript.h
../../source/as_array.h
../../source/as_builder.h
../../source/as_bytecode.h
../../source/as_callfunc.h
../../source/as_compiler.h
../../source/as_config.h
../../source/as_configgroup.h
../../source/as_context.h
../../source/as_criticalsection.h
../../source/as_datatype.h
../../source/as_debug.h
../../source/as_generic.h
../../source/as_map.h
../../source/as_memory.h
../../source/as_module.h
../../source/as_objecttype.h
../../source/as_outputbuffer.h
../../source/as_parser.h
../../source/as_property.h
../../source/as_restore.h
../../source/as_scriptcode.h
../../source/as_scriptengine.h
../../source/as_scriptfunction.h
../../source/as_scriptnode.h
../../source/as_scriptobject.h
../../source/as_string.h
../../source/as_string_util.h
../../source/as_texts.h
../../source/as_thread.h
../../source/as_tokendef.h
../../source/as_tokenizer.h
../../source/as_typeinfo.h
../../source/as_variablescope.h
)
set(ANGELSCRIPT_SOURCE
../../source/as_atomic.cpp
../../source/as_builder.cpp
../../source/as_bytecode.cpp
../../source/as_callfunc.cpp
../../source/as_callfunc_x86.cpp
../../source/as_callfunc_x64_gcc.cpp
../../source/as_callfunc_x64_msvc.cpp
../../source/as_callfunc_x64_mingw.cpp
../../source/as_compiler.cpp
../../source/as_configgroup.cpp
../../source/as_context.cpp
../../source/as_datatype.cpp
../../source/as_gc.cpp
../../source/as_generic.cpp
../../source/as_globalproperty.cpp
../../source/as_memory.cpp
../../source/as_module.cpp
../../source/as_objecttype.cpp
../../source/as_outputbuffer.cpp
../../source/as_parser.cpp
../../source/as_restore.cpp
../../source/as_scriptcode.cpp
../../source/as_scriptengine.cpp
../../source/as_scriptfunction.cpp
../../source/as_scriptnode.cpp
../../source/as_scriptobject.cpp
../../source/as_string.cpp
../../source/as_string_util.cpp
../../source/as_thread.cpp
../../source/as_tokenizer.cpp
../../source/as_typeinfo.cpp
../../source/as_variablescope.cpp
../../source/as_atomic.cpp
../../source/as_builder.cpp
../../source/as_bytecode.cpp
../../source/as_callfunc.cpp
../../source/as_callfunc_x86.cpp
../../source/as_callfunc_x64_gcc.cpp
../../source/as_callfunc_x64_msvc.cpp
../../source/as_callfunc_x64_mingw.cpp
../../source/as_compiler.cpp
../../source/as_configgroup.cpp
../../source/as_context.cpp
../../source/as_datatype.cpp
../../source/as_gc.cpp
../../source/as_generic.cpp
../../source/as_globalproperty.cpp
../../source/as_memory.cpp
../../source/as_module.cpp
../../source/as_objecttype.cpp
../../source/as_outputbuffer.cpp
../../source/as_parser.cpp
../../source/as_restore.cpp
../../source/as_scriptcode.cpp
../../source/as_scriptengine.cpp
../../source/as_scriptfunction.cpp
../../source/as_scriptnode.cpp
../../source/as_scriptobject.cpp
../../source/as_string.cpp
../../source/as_string_util.cpp
../../source/as_thread.cpp
../../source/as_tokenizer.cpp
../../source/as_typeinfo.cpp
../../source/as_variablescope.cpp
)
if(MSVC AND CMAKE_CL_64)
enable_language(ASM_MASM)
if(CMAKE_ASM_MASM_COMPILER_WORKS)
set(ANGELSCRIPT_SOURCE ${ANGELSCRIPT_SOURCE} ../../source/as_callfunc_x64_msvc_asm.asm)
else()
message(FATAL ERROR "MSVC x86_64 target requires a working assembler")
endif()
enable_language(ASM_MASM)
if(CMAKE_ASM_MASM_COMPILER_WORKS)
set(ANGELSCRIPT_SOURCE ${ANGELSCRIPT_SOURCE} ../../source/as_callfunc_x64_msvc_asm.asm)
else()
message(FATAL ERROR "MSVC x86_64 target requires a working assembler")
endif()
endif()
if(ANDROID)
enable_language(ASM)
if(CMAKE_ASM_COMPILER_WORKS)
set(ANGELSCRIPT_SOURCE ${ANGELSCRIPT_SOURCE} ../../source/as_callfunc_arm.cpp ../../source/as_callfunc_arm_gcc.S)
else()
message(FATAL ERROR "Android target requires a working assembler")
endif(CMAKE_ASM_COMPILER_WORKS)
enable_language(ASM)
if(CMAKE_ASM_COMPILER_WORKS)
set(ANGELSCRIPT_SOURCE ${ANGELSCRIPT_SOURCE} ../../source/as_callfunc_arm.cpp ../../source/as_callfunc_arm_gcc.S)
else()
message(FATAL ERROR "Android target requires a working assembler")
endif()
endif()
set(ANGELSCRIPT_HEADERS
../../include/angelscript.h
../../source/as_array.h
../../source/as_builder.h
../../source/as_bytecode.h
../../source/as_callfunc.h
../../source/as_compiler.h
../../source/as_config.h
../../source/as_configgroup.h
../../source/as_context.h
../../source/as_criticalsection.h
../../source/as_datatype.h
../../source/as_debug.h
../../source/as_generic.h
../../source/as_map.h
../../source/as_memory.h
../../source/as_module.h
../../source/as_objecttype.h
../../source/as_outputbuffer.h
../../source/as_parser.h
../../source/as_property.h
../../source/as_restore.h
../../source/as_scriptcode.h
../../source/as_scriptengine.h
../../source/as_scriptfunction.h
../../source/as_scriptnode.h
../../source/as_scriptobject.h
../../source/as_string.h
../../source/as_string_util.h
../../source/as_texts.h
../../source/as_thread.h
../../source/as_tokendef.h
../../source/as_tokenizer.h
../../source/as_typeinfo.h
../../source/as_variablescope.h
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../include)
add_definitions("-D_CRT_SECURE_NO_WARNINGS -DANGELSCRIPT_EXPORT -D_LIB")
if(MSVC)
set(CMAKE_DEBUG_POSTFIX "d")
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
add_definitions(-DANGELSCRIPT_EXPORT -D_LIB)
# Fix x64 issues on Linux
if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" AND NOT APPLE)
add_definitions(-fPIC)
add_definitions(-fPIC)
endif()
add_library(angelscript STATIC ${ANGELSCRIPT_SOURCE} ${ANGELSCRIPT_HEADERS})
if(NOT BUILD_FRAMEWORK)
set(ANGELSCRIPT_LIBRARY_NAME angelscript)
else()
set(ANGELSCRIPT_LIBRARY_NAME Angelscript) # OS X frameworks should have capitalized name
set(BUILD_SHARED_LIBS TRUE)
endif()
#set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../../lib)
add_library(${ANGELSCRIPT_LIBRARY_NAME} ${ANGELSCRIPT_SOURCE} ${ANGELSCRIPT_HEADERS})
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../../lib)
target_link_libraries(${ANGELSCRIPT_LIBRARY_NAME} ${CMAKE_THREAD_LIBS_INIT})
#find_package(Threads)
#target_link_libraries(Angelscript ${CMAKE_THREAD_LIBS_INIT})
set_target_properties(${ANGELSCRIPT_LIBRARY_NAME} PROPERTIES VERSION ${PROJECT_VERSION})
#if(MSVC)
# set_target_properties(Angelscript PROPERTIES COMPILE_FLAGS "/MP")
#endif(MSVC)
if(BUILD_FRAMEWORK)
set_target_properties(${ANGELSCRIPT_LIBRARY_NAME} PROPERTIES
FRAMEWORK TRUE
FRAMEWORK_VERSION ${PROJECT_VERSION}
MACOSX_FRAMEWORK_IDENTIFIER com.angelcode.Angelscript
MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${PROJECT_VERSION}
MACOSX_FRAMEWORK_BUNDLE_VERSION ${PROJECT_VERSION}
XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
PUBLIC_HEADER ../../include/angelscript.h
)
endif()
#set(RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../../bin)
if(MSVC)
set_target_properties(${ANGELSCRIPT_LIBRARY_NAME} PROPERTIES COMPILE_FLAGS "/MP")
endif()
set(RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../../bin)
+58 -46
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2012 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -47,46 +47,46 @@ template <class T> class asCArray
public:
asCArray();
asCArray(const asCArray<T> &);
asCArray(size_t reserve);
asCArray(asUINT reserve);
~asCArray();
void Allocate(size_t numElements, bool keepData);
void AllocateNoConstruct(size_t numElements, bool keepData);
size_t GetCapacity() const;
void Allocate(asUINT numElements, bool keepData);
void AllocateNoConstruct(asUINT numElements, bool keepData);
asUINT GetCapacity() const;
void PushLast(const T &element);
T PopLast();
bool SetLength(size_t numElements);
bool SetLengthNoConstruct(size_t numElements);
size_t GetLength() const;
bool SetLength(asUINT numElements);
bool SetLengthNoConstruct(asUINT numElements);
asUINT GetLength() const;
void Copy(const T*, size_t count);
void Copy(const T*, asUINT count);
asCArray<T> &operator =(const asCArray<T> &);
void SwapWith(asCArray<T> &other);
const T &operator [](size_t index) const;
T &operator [](size_t index);
const T &operator [](asUINT index) const;
T &operator [](asUINT index);
T *AddressOf();
const T *AddressOf() const;
void Concatenate(const asCArray<T> &);
bool Concatenate(const asCArray<T> &);
void Concatenate(T*, unsigned int count);
bool Exists(const T &element) const;
int IndexOf(const T &element) const;
void RemoveIndex(size_t index); // Removes the entry without reordering the array
void RemoveIndex(asUINT index); // Removes the entry without reordering the array
void RemoveValue(const T &element); // Removes the value without reordering the array
void RemoveIndexUnordered(size_t index); // Removes the entry without keeping the order
void RemoveIndexUnordered(asUINT index); // Removes the entry without keeping the order
bool operator==(const asCArray<T> &) const;
bool operator!=(const asCArray<T> &) const;
protected:
T *array;
size_t length;
size_t maxLength;
char buf[8];
asUINT length; // 32bits is enough for all uses of this array
asUINT maxLength;
char buf[2*4*AS_PTR_SIZE]; // Avoid dynamically allocated memory for tiny arrays
};
// Implementation
@@ -122,7 +122,7 @@ asCArray<T>::asCArray(const asCArray<T> &copy)
}
template <class T>
asCArray<T>::asCArray(size_t reserve)
asCArray<T>::asCArray(asUINT reserve)
{
array = 0;
length = 0;
@@ -139,13 +139,13 @@ asCArray<T>::~asCArray(void)
}
template <class T>
size_t asCArray<T>::GetLength() const
asUINT asCArray<T>::GetLength() const
{
return length;
}
template <class T>
const T &asCArray<T>::operator [](size_t index) const
const T &asCArray<T>::operator [](asUINT index) const
{
asASSERT(index < length);
@@ -153,7 +153,7 @@ const T &asCArray<T>::operator [](size_t index) const
}
template <class T>
T &asCArray<T>::operator [](size_t index)
T &asCArray<T>::operator [](asUINT index)
{
asASSERT(index < length);
@@ -189,7 +189,7 @@ T asCArray<T>::PopLast()
}
template <class T>
void asCArray<T>::Allocate(size_t numElements, bool keepData)
void asCArray<T>::Allocate(asUINT numElements, bool keepData)
{
// We have 4 situations
// 1. The previous array is 8 bytes or smaller and the new array is also 8 bytes or smaller
@@ -200,7 +200,7 @@ void asCArray<T>::Allocate(size_t numElements, bool keepData)
T *tmp = 0;
if( numElements )
{
if( sizeof(T)*numElements <= 8 )
if( sizeof(T)*numElements <= sizeof(buf) )
// Use the internal buffer
tmp = reinterpret_cast<T*>(buf);
else
@@ -217,20 +217,20 @@ void asCArray<T>::Allocate(size_t numElements, bool keepData)
if( array == tmp )
{
// Construct only the newly allocated elements
for( size_t n = length; n < numElements; n++ )
for( asUINT n = length; n < numElements; n++ )
new (&tmp[n]) T();
}
else
{
// Construct all elements
for( size_t n = 0; n < numElements; n++ )
for( asUINT n = 0; n < numElements; n++ )
new (&tmp[n]) T();
}
}
if( array )
{
size_t oldLength = length;
asUINT oldLength = length;
if( array == tmp )
{
@@ -243,7 +243,7 @@ void asCArray<T>::Allocate(size_t numElements, bool keepData)
length = 0;
// Call the destructor for elements that are no longer used
for( size_t n = length; n < oldLength; n++ )
for( asUINT n = length; n < oldLength; n++ )
array[n].~T();
}
else
@@ -253,14 +253,14 @@ void asCArray<T>::Allocate(size_t numElements, bool keepData)
if( length > numElements )
length = numElements;
for( size_t n = 0; n < length; n++ )
for( asUINT n = 0; n < length; n++ )
tmp[n] = array[n];
}
else
length = 0;
// Call the destructor for all elements
for( size_t n = 0; n < oldLength; n++ )
for( asUINT n = 0; n < oldLength; n++ )
array[n].~T();
if( array != reinterpret_cast<T*>(buf) )
@@ -273,7 +273,7 @@ void asCArray<T>::Allocate(size_t numElements, bool keepData)
}
template <class T>
void asCArray<T>::AllocateNoConstruct(size_t numElements, bool keepData)
void asCArray<T>::AllocateNoConstruct(asUINT numElements, bool keepData)
{
// We have 4 situations
// 1. The previous array is 8 bytes or smaller and the new array is also 8 bytes or smaller
@@ -284,7 +284,7 @@ void asCArray<T>::AllocateNoConstruct(size_t numElements, bool keepData)
T *tmp = 0;
if( numElements )
{
if( sizeof(T)*numElements <= 8 )
if( sizeof(T)*numElements <= sizeof(buf) )
// Use the internal buffer
tmp = reinterpret_cast<T*>(buf);
else
@@ -333,13 +333,13 @@ void asCArray<T>::AllocateNoConstruct(size_t numElements, bool keepData)
}
template <class T>
size_t asCArray<T>::GetCapacity() const
asUINT asCArray<T>::GetCapacity() const
{
return maxLength;
}
template <class T>
bool asCArray<T>::SetLength(size_t numElements)
bool asCArray<T>::SetLength(asUINT numElements)
{
if( numElements > maxLength )
{
@@ -356,7 +356,7 @@ bool asCArray<T>::SetLength(size_t numElements)
}
template <class T>
bool asCArray<T>::SetLengthNoConstruct(size_t numElements)
bool asCArray<T>::SetLengthNoConstruct(asUINT numElements)
{
if( numElements > maxLength )
{
@@ -373,7 +373,7 @@ bool asCArray<T>::SetLengthNoConstruct(size_t numElements)
}
template <class T>
void asCArray<T>::Copy(const T *data, size_t count)
void asCArray<T>::Copy(const T *data, asUINT count)
{
if( maxLength < count )
{
@@ -385,7 +385,7 @@ void asCArray<T>::Copy(const T *data, size_t count)
}
}
for( size_t n = 0; n < count; n++ )
for( asUINT n = 0; n < count; n++ )
array[n] = data[n];
length = count;
@@ -403,8 +403,8 @@ template <class T>
void asCArray<T>::SwapWith(asCArray<T> &other)
{
T *tmpArray = array;
size_t tmpLength = length;
size_t tmpMaxLength = maxLength;
asUINT tmpLength = length;
asUINT tmpMaxLength = maxLength;
char tmpBuf[sizeof(buf)];
memcpy(tmpBuf, buf, sizeof(buf));
@@ -430,7 +430,7 @@ bool asCArray<T>::operator ==(const asCArray<T> &other) const
{
if( length != other.length ) return false;
for( size_t n = 0; n < length; n++ )
for( asUINT n = 0; n < length; n++ )
if( array[n] != other.array[n] )
return false;
@@ -443,16 +443,28 @@ bool asCArray<T>::operator !=(const asCArray<T> &other) const
return !(*this == other);
}
// Returns false if the concatenation wasn't successful due to out of memory
template <class T>
void asCArray<T>::Concatenate(const asCArray<T> &other)
bool asCArray<T>::Concatenate(const asCArray<T> &other)
{
if( maxLength < length + other.length )
{
Allocate(length + other.length, true);
if( maxLength < length + other.length )
{
// Out of memory
return false;
}
}
for( size_t n = 0; n < other.length; n++ )
for( asUINT n = 0; n < other.length; n++ )
array[length+n] = other.array[n];
length += other.length;
// Success
return true;
}
template <class T>
@@ -471,18 +483,18 @@ bool asCArray<T>::Exists(const T &e) const
template <class T>
int asCArray<T>::IndexOf(const T &e) const
{
for( size_t n = 0; n < length; n++ )
for( asUINT n = 0; n < length; n++ )
if( array[n] == e ) return static_cast<int>(n);
return -1;
}
template <class T>
void asCArray<T>::RemoveIndex(size_t index)
void asCArray<T>::RemoveIndex(asUINT index)
{
if( index < length )
{
for( size_t n = index; n < length-1; n++ )
for( asUINT n = index; n < length-1; n++ )
array[n] = array[n+1];
PopLast();
@@ -492,7 +504,7 @@ void asCArray<T>::RemoveIndex(size_t index)
template <class T>
void asCArray<T>::RemoveValue(const T &e)
{
for( size_t n = 0; n < length; n++ )
for( asUINT n = 0; n < length; n++ )
{
if( array[n] == e )
{
@@ -503,7 +515,7 @@ void asCArray<T>::RemoveValue(const T &e)
}
template <class T>
void asCArray<T>::RemoveIndexUnordered(size_t index)
void asCArray<T>::RemoveIndexUnordered(asUINT index)
{
if( index == length - 1 )
PopLast();
+17 -1
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -45,21 +45,37 @@ asCAtomic::asCAtomic()
asDWORD asCAtomic::get() const
{
// A very high ref count is highly unlikely. It most likely a problem with
// memory that has been overwritten or is being accessed after it was deleted.
asASSERT(value < 1000000);
return value;
}
void asCAtomic::set(asDWORD val)
{
// A very high ref count is highly unlikely. It most likely a problem with
// memory that has been overwritten or is being accessed after it was deleted.
asASSERT(value < 1000000);
value = val;
}
asDWORD asCAtomic::atomicInc()
{
// A very high ref count is highly unlikely. It most likely a problem with
// memory that has been overwritten or is being accessed after it was deleted.
asASSERT(value < 1000000);
return asAtomicInc((int&)value);
}
asDWORD asCAtomic::atomicDec()
{
// A very high ref count is highly unlikely. It most likely a problem with
// memory that has been overwritten or is being accessed after it was deleted.
asASSERT(value < 1000000);
return asAtomicDec((int&)value);
}
File diff suppressed because it is too large Load Diff
+17 -16
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2015 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -51,6 +51,11 @@
BEGIN_AS_NAMESPACE
#ifdef AS_NO_COMPILER
// Forward declare the structure, as it is part of some function signatures used even without the compiler
struct sGlobalVariableDescription;
#endif
#ifndef AS_NO_COMPILER
struct sFunctionDescription
@@ -72,6 +77,7 @@ struct sGlobalVariableDescription
asCString name;
asCGlobalProperty *property;
asCDataType datatype;
asSNameSpace *ns;
int index;
bool isCompiled;
bool isPureConstant;
@@ -160,14 +166,16 @@ protected:
void WriteError(const asCString &scriptname, const asCString &msg, int r, int c);
void WriteError(const asCString &msg, asCScriptCode *file, asCScriptNode *node);
void WriteWarning(const asCString &scriptname, const asCString &msg, int r, int c);
void WriteWarning(const asCString &msg, asCScriptCode *file, asCScriptNode *node);
bool DoesGlobalPropertyExist(const char *prop, asSNameSpace *ns, asCGlobalProperty **outProp = 0, sGlobalVariableDescription **outDesc = 0, bool *isAppProp = 0);
asCGlobalProperty *GetGlobalProperty(const char *prop, asSNameSpace *ns, bool *isCompiled, bool *isPureConstant, asQWORD *constantValue, bool *isAppProp);
int ValidateDefaultArgs(asCScriptCode *script, asCScriptNode *node, asCScriptFunction *func);
asCString GetCleanExpressionString(asCScriptNode *n, asCScriptCode *file);
asSNameSpace *GetNameSpaceFromNode(asCScriptNode *node, asCScriptCode *script, asSNameSpace *implicitNs, asCScriptNode **next);
asSNameSpace *GetNameSpaceByString(const asCString &nsName, asSNameSpace *implicitNs, asCScriptNode *errNode, asCScriptCode *script);
asCString GetScopeFromNode(asCScriptNode *n, asCScriptCode *script, asCScriptNode **next = 0);
asSNameSpace *GetParentNameSpace(asSNameSpace *ns);
asCObjectType *GetObjectType(const char *type, asSNameSpace *ns);
asCScriptFunction *GetFuncDef(const char *type);
@@ -175,15 +183,6 @@ protected:
asCDataType CreateDataTypeFromNode(asCScriptNode *node, asCScriptCode *file, asSNameSpace *implicitNamespace, bool acceptHandleForScope = false, asCObjectType *currentType = 0);
asCDataType ModifyDataTypeFromNode(const asCDataType &type, asCScriptNode *node, asCScriptCode *file, asETypeModifiers *inOutFlag, bool *autoHandle);
struct preMessage_t
{
bool isSet;
asCString message;
asCString scriptname;
int r;
int c;
} preMessage;
int numErrors;
int numWarnings;
bool silent;
@@ -195,6 +194,7 @@ protected:
protected:
friend class asCCompiler;
int CheckForConflictsDueToDefaultArgs(asCScriptCode *script, asCScriptNode *node, asCScriptFunction *func, asCObjectType *objType);
int GetNamespaceAndNameFromNode(asCScriptNode *n, asCScriptCode *script, asSNameSpace *implicitNs, asSNameSpace *&outNs, asCString &outName);
int RegisterMixinClass(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
sMixinClass *GetMixinClass(const char *name, asSNameSpace *ns);
@@ -204,7 +204,7 @@ protected:
void AddInterfaceFromMixinToClass(sClassDeclaration *decl, asCScriptNode *errNode, sMixinClass *mixin);
int RegisterScriptFunctionFromNode(asCScriptNode *node, asCScriptCode *file, asCObjectType *object = 0, bool isInterface = false, bool isGlobalFunction = false, asSNameSpace *ns = 0, bool isExistingShared = false, bool isMixin = false);
int RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool isConstMethod, bool isConstructor, bool isDestructor, bool isPrivate, bool isOverride, bool isFinal, bool isShared);
int RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool isConstMethod, bool isConstructor, bool isDestructor, bool isPrivate, bool isProtected, bool isOverride, bool isFinal, bool isShared);
int RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file, asCObjectType *object = 0, bool isInterface = false, bool isGlobalFunction = false, asSNameSpace *ns = 0, bool isExistingShared = false);
int RegisterImportedFunction(int funcID, asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
int RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
@@ -215,11 +215,11 @@ protected:
int RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
void CompleteFuncDef(sFuncDef *funcDef);
void CompileInterfaces();
void CompileClasses();
void GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool &isConstMethod, bool &isConstructor, bool &isDestructor, bool &isPrivate, bool &isOverride, bool &isFinal, bool &isShared, asSNameSpace *implicitNamespace);
void CompileClasses(asUINT originalNumTempl);
void GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool &isConstMethod, bool &isConstructor, bool &isDestructor, bool &isPrivate, bool &isProtected, bool &isOverride, bool &isFinal, bool &isShared, asSNameSpace *implicitNamespace);
bool DoesMethodExist(asCObjectType *objType, int methodId, asUINT *methodIndex = 0);
void AddDefaultConstructor(asCObjectType *objType, asCScriptCode *file);
asCObjectProperty *AddPropertyToClass(sClassDeclaration *c, const asCString &name, const asCDataType &type, bool isPrivate, asCScriptCode *file = 0, asCScriptNode *node = 0);
asCObjectProperty *AddPropertyToClass(sClassDeclaration *c, const asCString &name, const asCDataType &type, bool isPrivate, bool isProtected, bool isInherited, asCScriptCode *file = 0, asCScriptNode *node = 0);
int CreateVirtualFunction(asCScriptFunction *func, int idx);
void ParseScripts();
void RegisterTypesFromScript(asCScriptNode *node, asCScriptCode *script, asSNameSpace *ns);
@@ -232,7 +232,8 @@ protected:
asCObjectProperty *GetObjectProperty(asCDataType &obj, const char *prop);
asCScriptFunction *GetFunctionDescription(int funcId);
void GetFunctionDescriptions(const char *name, asCArray<int> &funcs, asSNameSpace *ns);
void GetObjectMethodDescriptions(const char *name, asCObjectType *objectType, asCArray<int> &methods, bool objIsConst, const asCString &scope = "");
void GetObjectMethodDescriptions(const char *name, asCObjectType *objectType, asCArray<int> &methods, bool objIsConst, const asCString &scope = "", asCScriptNode *errNode = 0, asCScriptCode *script = 0);
void EvaluateTemplateInstances(asUINT startIdx, bool keepSilent);
asCArray<asCScriptCode *> scripts;
asCArray<sFunctionDescription *> functions;
+66 -13
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2015 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -864,7 +864,6 @@ void asCByteCode::OptimizeLocally(const asCArray<int> &tempVariableOffsets)
instr = GoForward(curr);
}
}
else if( currOp == asBC_RDSPtr )
{
@@ -1553,6 +1552,7 @@ int asCByteCode::GetSize()
void asCByteCode::AddCode(asCByteCode *bc)
{
if( bc == this ) return;
if( bc->first )
{
if( first == 0 )
@@ -2037,7 +2037,14 @@ void asCByteCode::PostProcess()
DeleteInstruction(curr);
}
else
{
#ifndef AS_DEBUG
// If the stackSize is negative, then there is a problem with the bytecode.
// If AS_DEBUG is turned on, this same check is done in DebugOutput.
asASSERT( instr->stackSize >= 0 || asBCInfo[instr->op].type == asBCTYPE_INFO );
#endif
instr = instr->next;
}
}
}
@@ -2079,7 +2086,9 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
fprintf(file, "Variables: \n");
for( n = 0; n < func->scriptData->variables.GetLength(); n++ )
{
fprintf(file, " %.3d: %s %s\n", func->scriptData->variables[n]->stackOffset, func->scriptData->variables[n]->type.Format().AddressOf(), func->scriptData->variables[n]->name.AddressOf());
int idx = func->scriptData->objVariablePos.IndexOf(func->scriptData->variables[n]->stackOffset);
bool isOnHeap = asUINT(idx) < func->scriptData->objVariablesOnHeap ? true : false;
fprintf(file, " %.3d: %s%s %s\n", func->scriptData->variables[n]->stackOffset, isOnHeap ? "(heap) " : "", func->scriptData->variables[n]->type.Format(func->nameSpace).AddressOf(), func->scriptData->variables[n]->name.AddressOf());
}
asUINT offset = 0;
if( func->objectType )
@@ -2099,7 +2108,11 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
}
}
if( !found )
fprintf(file, " %.3d: %s {noname param}\n", offset, func->parameterTypes[n].Format().AddressOf());
{
int idx = func->scriptData->objVariablePos.IndexOf(offset);
bool isOnHeap = asUINT(idx) < func->scriptData->objVariablesOnHeap ? true : false;
fprintf(file, " %.3d: %s%s {noname param}\n", offset, isOnHeap ? "(heap) " : "", func->parameterTypes[n].Format(func->nameSpace).AddressOf());
}
offset -= func->parameterTypes[n].GetSizeOnStackDWords();
}
@@ -2115,10 +2128,20 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
}
}
if( !found )
fprintf(file, " %.3d: %s {noname}\n", func->scriptData->objVariablePos[n], func->scriptData->objVariableTypes[n]->name.AddressOf());
{
if( func->scriptData->objVariableTypes[n] )
{
int idx = func->scriptData->objVariablePos.IndexOf(func->scriptData->objVariablePos[n]);
bool isOnHeap = asUINT(idx) < func->scriptData->objVariablesOnHeap ? true : false;
fprintf(file, " %.3d: %s%s {noname}\n", func->scriptData->objVariablePos[n], isOnHeap ? "(heap) " : "", func->scriptData->objVariableTypes[n]->name.AddressOf());
}
else
fprintf(file, " %.3d: null handle {noname}\n", func->scriptData->objVariablePos[n]);
}
}
fprintf(file, "\n\n");
bool invalidStackSize = false;
int pos = 0;
asUINT lineIndex = 0;
asCByteInstruction *instr = first;
@@ -2131,10 +2154,19 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
lineIndex += 2;
}
fprintf(file, "%5d ", pos);
pos += instr->GetSize();
if( instr->GetSize() > 0 )
{
fprintf(file, "%5d ", pos);
pos += instr->GetSize();
fprintf(file, "%3d %c ", int(instr->stackSize + func->scriptData->variableSpace), instr->marked ? '*' : ' ');
fprintf(file, "%3d %c ", int(instr->stackSize + func->scriptData->variableSpace), instr->marked ? '*' : ' ');
if( instr->stackSize < 0 )
invalidStackSize = true;
}
else
{
fprintf(file, " ");
}
switch( asBCInfo[instr->op].type )
{
@@ -2182,7 +2214,10 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
switch( instr->op )
{
case asBC_OBJTYPE:
fprintf(file, " %-8s 0x%x\n", asBCInfo[instr->op].name, (asUINT)*ARG_DW(instr->arg));
{
asCObjectType *ot = *(asCObjectType**)ARG_DW(instr->arg);
fprintf(file, " %-8s 0x%x (type:%s)\n", asBCInfo[instr->op].name, (asUINT)*ARG_DW(instr->arg), ot->GetName());
}
break;
case asBC_PshC4:
@@ -2229,6 +2264,16 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
break;
case asBCTYPE_QW_ARG:
switch( instr->op )
{
case asBC_OBJTYPE:
{
asCObjectType *ot = *(asCObjectType**)ARG_DW(instr->arg);
fprintf(file, " %-8s 0x%x (type:%s)\n", asBCInfo[instr->op].name, (asUINT)*ARG_QW(instr->arg), ot->GetName());
}
break;
default:
#ifdef __GNUC__
#ifdef _LP64
fprintf(file, " %-8s 0x%lx (i:%ld, f:%g)\n", asBCInfo[instr->op].name, *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
@@ -2238,6 +2283,7 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
#else
fprintf(file, " %-8s 0x%I64x (i:%I64d, f:%g)\n", asBCInfo[instr->op].name, *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
#endif
}
break;
case asBCTYPE_wW_QW_ARG:
@@ -2257,7 +2303,8 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
if( instr->op == asBC_ALLOC )
{
asCObjectType *ot = *(asCObjectType**)ARG_DW(instr->arg);
fprintf(file, " %-8s 0x%x, %d (type:%s)\n", asBCInfo[instr->op].name, *(int*)ARG_DW(instr->arg), *(int*)(ARG_DW(instr->arg)+1), ot->GetName());
asCScriptFunction *func = engine->scriptFunctions[instr->wArg[0]];
fprintf(file, " %-8s 0x%x, %d (type:%s, %s)\n", asBCInfo[instr->op].name, *(int*)ARG_DW(instr->arg), *(int*)(ARG_DW(instr->arg)+1), ot->GetName(), func ? func->GetDeclaration() : "{no func}");
}
else
fprintf(file, " %-8s %u, %d\n", asBCInfo[instr->op].name, *(int*)ARG_DW(instr->arg), *(int*)(ARG_DW(instr->arg)+1));
@@ -2271,14 +2318,15 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
if( instr->op == asBC_ALLOC )
{
asCObjectType *ot = *(asCObjectType**)ARG_QW(instr->arg);
asCScriptFunction *func = engine->scriptFunctions[instr->wArg[0]];
#ifdef __GNUC__
#ifdef AS_64BIT_PTR
fprintf(file, " %-8s 0x%lx, %d (type:%s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName());
fprintf(file, " %-8s 0x%lx, %d (type:%s, %s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName(), func ? func->GetDeclaration() : "{no func}");
#else
fprintf(file, " %-8s 0x%llx, %d (type:%s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName());
fprintf(file, " %-8s 0x%llx, %d (type:%s, %s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName(), func ? func->GetDeclaration() : "{no func}");
#endif
#else
fprintf(file, " %-8s 0x%I64x, %d (type:%s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName());
fprintf(file, " %-8s 0x%I64x, %d (type:%s, %s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName(), func ? func->GetDeclaration() : "{no func}");
#endif
}
else
@@ -2333,6 +2381,11 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
}
fclose(file);
// If the stackSize is negative then there is something wrong with the
// bytecode, i.e. there is a bug in the compiler or in the optimizer. We
// only check this here to have the bytecode available on file for verification
asASSERT( !invalidStackSize );
}
#endif
+261 -98
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2014 Andreas Jonsson
Copyright (c) 2003-2015 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -45,6 +45,14 @@
BEGIN_AS_NAMESPACE
// ref: Member Function Pointers and the Fastest Possible C++ Delegates
// describes the structure of class method pointers for most compilers
// http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible
// ref: The code comments for ItaniumCXXABI::EmitLoadOfMemberFunctionPointer in the LLVM compiler
// describes the structure for class method pointers on Itanium and arm64 ABI
// http://clang.llvm.org/doxygen/CodeGen_2ItaniumCXXABI_8cpp_source.html#l00937
int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, void *objForThiscall, asSSystemFunctionInterface *internal)
{
memset(internal, 0, sizeof(asSSystemFunctionInterface));
@@ -57,9 +65,9 @@ int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv,
{
if( ptr.flag == 1 && callConv != asCALL_GENERIC )
return asWRONG_CALLING_CONV;
else if( ptr.flag == 2 && (callConv == asCALL_GENERIC || callConv == asCALL_THISCALL || callConv == asCALL_THISCALL_ASGLOBAL) )
else if( ptr.flag == 2 && (callConv == asCALL_GENERIC || callConv == asCALL_THISCALL || callConv == asCALL_THISCALL_ASGLOBAL || callConv == asCALL_THISCALL_OBJFIRST || callConv == asCALL_THISCALL_OBJLAST) )
return asWRONG_CALLING_CONV;
else if( ptr.flag == 3 && !(callConv == asCALL_THISCALL || callConv == asCALL_THISCALL_ASGLOBAL) )
else if( ptr.flag == 3 && !(callConv == asCALL_THISCALL || callConv == asCALL_THISCALL_ASGLOBAL || callConv == asCALL_THISCALL_OBJFIRST || callConv == asCALL_THISCALL_OBJLAST) )
return asWRONG_CALLING_CONV;
}
@@ -90,20 +98,44 @@ int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv,
if( isMethod )
{
#ifndef AS_NO_CLASS_METHODS
if( base == asCALL_THISCALL )
if( base == asCALL_THISCALL || base == asCALL_THISCALL_OBJFIRST || base == asCALL_THISCALL_OBJLAST )
{
internal->callConv = ICC_THISCALL;
internalCallConv thisCallConv;
if( base == asCALL_THISCALL )
{
if( callConv != asCALL_THISCALL_ASGLOBAL && objForThiscall )
return asINVALID_ARG;
thisCallConv = ICC_THISCALL;
}
else
{
#ifdef AS_NO_THISCALL_FUNCTOR_METHOD
return asNOT_SUPPORTED;
#else
if( objForThiscall == 0 )
return asINVALID_ARG;
internal->objForThiscall = objForThiscall;
if( base == asCALL_THISCALL_OBJFIRST )
thisCallConv = ICC_THISCALL_OBJFIRST;
else //if( base == asCALL_THISCALL_OBJLAST )
thisCallConv = ICC_THISCALL_OBJLAST;
#endif
}
internal->callConv = thisCallConv;
#ifdef GNU_STYLE_VIRTUAL_METHOD
if( (size_t(ptr.ptr.f.func) & 1) )
internal->callConv = ICC_VIRTUAL_THISCALL;
internal->callConv = (internalCallConv)(thisCallConv + 2);
#endif
internal->baseOffset = ( int )MULTI_BASE_OFFSET(ptr);
#if defined(AS_ARM) && defined(__GNUC__)
#if defined(AS_ARM) && (defined(__GNUC__) || defined(AS_PSVITA))
// As the least significant bit in func is used to switch to THUMB mode
// on ARM processors, the LSB in the __delta variable is used instead of
// the one in __pfn on ARM processors.
if( (size_t(internal->baseOffset) & 1) )
internal->callConv = ICC_VIRTUAL_THISCALL;
internal->callConv = (internalCallConv)(thisCallConv + 2);
#endif
#ifdef HAVE_VIRTUAL_BASE_OFFSET
@@ -135,6 +167,49 @@ int PrepareSystemFunctionGeneric(asCScriptFunction *func, asSSystemFunctionInter
// Calculate the size needed for the parameters
internal->paramSize = func->GetSpaceNeededForArguments();
// Prepare the clean up instructions for the function arguments
internal->cleanArgs.SetLength(0);
int offset = 0;
for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
{
asCDataType &dt = func->parameterTypes[n];
if( dt.IsObject() && !dt.IsReference() )
{
asSTypeBehaviour *beh = &dt.GetObjectType()->beh;
if( dt.GetObjectType()->flags & asOBJ_REF )
{
asASSERT( (dt.GetObjectType()->flags & asOBJ_NOCOUNT) || beh->release );
if( beh->release )
{
asSSystemFunctionInterface::SClean clean;
clean.op = 0; // call release
clean.ot = dt.GetObjectType();
clean.off = short(offset);
internal->cleanArgs.PushLast(clean);
}
}
else
{
asSSystemFunctionInterface::SClean clean;
clean.op = 1; // call free
clean.ot = dt.GetObjectType();
clean.off = short(offset);
// Call the destructor then free the memory
if( beh->destruct )
clean.op = 2; // call destruct, then free
internal->cleanArgs.PushLast(clean);
}
}
if( dt.IsObject() && !dt.IsObjectHandle() && !dt.IsReference() )
offset += AS_PTR_SIZE;
else
offset += dt.GetSizeOnStackDWords();
}
return 0;
}
@@ -142,11 +217,14 @@ int PrepareSystemFunctionGeneric(asCScriptFunction *func, asSSystemFunctionInter
int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *internal, asCScriptEngine *engine)
{
#ifdef AS_MAX_PORTABILITY
UNUSED_VAR(func);
UNUSED_VAR(internal);
UNUSED_VAR(engine);
// This should never happen, as when AS_MAX_PORTABILITY is on, all functions
// are asCALL_GENERIC, which are prepared by PrepareSystemFunctionGeneric
asASSERT(false);
#endif
#else
// References are always returned as primitive data
if( func->returnType.IsReference() || func->returnType.IsObjectHandle() )
{
@@ -162,7 +240,7 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i
// Only value types can be returned by value
asASSERT( objType & asOBJ_VALUE );
if( !(objType & (asOBJ_APP_CLASS | asOBJ_APP_PRIMITIVE | asOBJ_APP_FLOAT)) )
if( !(objType & (asOBJ_APP_CLASS | asOBJ_APP_PRIMITIVE | asOBJ_APP_FLOAT | asOBJ_APP_ARRAY)) )
{
// If the return is by value then we need to know the true type
engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, func->GetDeclarationStr().AddressOf());
@@ -172,6 +250,13 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i
engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
engine->ConfigError(asINVALID_CONFIGURATION, 0, 0, 0);
}
else if( objType & asOBJ_APP_ARRAY )
{
// Array types are always returned in memory
internal->hostReturnInMemory = true;
internal->hostReturnSize = sizeof(void*)/4;
internal->hostReturnFloat = false;
}
else if( objType & asOBJ_APP_CLASS )
{
internal->hostReturnFloat = false;
@@ -203,7 +288,13 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i
#ifdef THISCALL_RETURN_SIMPLE_IN_MEMORY
if((internal->callConv == ICC_THISCALL ||
#ifdef AS_NO_THISCALL_FUNCTOR_METHOD
internal->callConv == ICC_VIRTUAL_THISCALL) &&
#else
internal->callConv == ICC_VIRTUAL_THISCALL ||
internal->callConv == ICC_THISCALL_OBJFIRST ||
internal->callConv == ICC_THISCALL_OBJLAST) &&
#endif
func->returnType.GetSizeInMemoryDWords() >= THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE)
{
internal->hostReturnInMemory = true;
@@ -242,7 +333,7 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i
engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, func->GetDeclarationStr().AddressOf());
asCString str;
str.Format(TXT_DONT_SUPPORT_RET_TYPE_s_BY_VAL, func->returnType.Format().AddressOf());
str.Format(TXT_DONT_SUPPORT_RET_TYPE_s_BY_VAL, func->returnType.Format(func->nameSpace).AddressOf());
engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
engine->ConfigError(asINVALID_CONFIGURATION, 0, 0, 0);
}
@@ -313,7 +404,7 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i
internal->takesObjByVal = true;
// Can't pass objects by value unless the application type is informed
if( !(func->parameterTypes[n].GetObjectType()->flags & (asOBJ_APP_CLASS | asOBJ_APP_PRIMITIVE | asOBJ_APP_FLOAT)) )
if( !(func->parameterTypes[n].GetObjectType()->flags & (asOBJ_APP_CLASS | asOBJ_APP_PRIMITIVE | asOBJ_APP_FLOAT | asOBJ_APP_ARRAY)) )
{
engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, func->GetDeclarationStr().AddressOf());
@@ -350,29 +441,70 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i
}
}
// Verify if the function has any registered autohandles
internal->hasAutoHandles = false;
for( n = 0; n < internal->paramAutoHandles.GetLength(); n++ )
// Prepare the clean up instructions for the function arguments
internal->cleanArgs.SetLength(0);
int offset = 0;
for( n = 0; n < func->parameterTypes.GetLength(); n++ )
{
if( internal->paramAutoHandles[n] )
{
internal->hasAutoHandles = true;
break;
}
}
asCDataType &dt = func->parameterTypes[n];
#if defined(COMPLEX_OBJS_PASSED_BY_REF) || defined(AS_LARGE_OBJS_PASSED_BY_REF)
bool needFree = false;
#ifdef COMPLEX_OBJS_PASSED_BY_REF
if( dt.GetObjectType() && dt.GetObjectType()->flags & COMPLEX_MASK ) needFree = true;
#endif
#ifdef AS_LARGE_OBJS_PASSED_BY_REF
if( dt.GetSizeInMemoryDWords() >= AS_LARGE_OBJ_MIN_SIZE ) needFree = true;
#endif
if( needFree &&
dt.IsObject() &&
!dt.IsObjectHandle() &&
!dt.IsReference() )
{
asSSystemFunctionInterface::SClean clean;
clean.op = 1; // call free
clean.ot = dt.GetObjectType();
clean.off = short(offset);
#ifndef AS_CALLEE_DESTROY_OBJ_BY_VAL
// If the called function doesn't destroy objects passed by value we must do so here
asSTypeBehaviour *beh = &dt.GetObjectType()->beh;
if( beh->destruct )
clean.op = 2; // call destruct, then free
#endif
internal->cleanArgs.PushLast(clean);
}
#endif
if( n < internal->paramAutoHandles.GetLength() && internal->paramAutoHandles[n] )
{
asSSystemFunctionInterface::SClean clean;
clean.op = 0; // call release
clean.ot = dt.GetObjectType();
clean.off = short(offset);
internal->cleanArgs.PushLast(clean);
}
if( dt.IsObject() && !dt.IsObjectHandle() && !dt.IsReference() )
offset += AS_PTR_SIZE;
else
offset += dt.GetSizeOnStackDWords();
}
#endif // !defined(AS_MAX_PORTABILITY)
return 0;
}
#ifdef AS_MAX_PORTABILITY
int CallSystemFunction(int id, asCContext *context, void *objectPointer)
int CallSystemFunction(int id, asCContext *context)
{
asCScriptEngine *engine = context->m_engine;
asSSystemFunctionInterface *sysFunc = engine->scriptFunctions[id]->sysFuncIntf;
asCScriptFunction *func = engine->scriptFunctions[id];
asSSystemFunctionInterface *sysFunc = func->sysFuncIntf;
int callConv = sysFunc->callConv;
if( callConv == ICC_GENERIC_FUNC || callConv == ICC_GENERIC_METHOD )
return context->CallGeneric(id, objectPointer);
return context->CallGeneric(func);
context->SetInternalException(TXT_INVALID_CALLING_CONVENTION);
@@ -396,15 +528,15 @@ int CallSystemFunction(int id, asCContext *context, void *objectPointer)
// args - This is the function arguments, which are packed as in AngelScript
// retPointer - This points to a the memory buffer where the return object is to be placed, if the function returns the value in memory rather than in registers
// retQW2 - This output parameter should be used if the function returns a value larger than 64bits in registers
// secondObj - This is the object pointer that the proxy method should invoke its method on when the call convention is THISCALL_OBJFIRST/LAST
//
// Return value:
//
// The function should return the value that is returned in registers.
//
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &retQW2);
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &retQW2, void *secondObj);
int CallSystemFunction(int id, asCContext *context, void *objectPointer)
int CallSystemFunction(int id, asCContext *context)
{
asCScriptEngine *engine = context->m_engine;
asCScriptFunction *descr = engine->scriptFunctions[id];
@@ -412,26 +544,24 @@ int CallSystemFunction(int id, asCContext *context, void *objectPointer)
int callConv = sysFunc->callConv;
if( callConv == ICC_GENERIC_FUNC || callConv == ICC_GENERIC_METHOD )
return context->CallGeneric(id, objectPointer);
return context->CallGeneric(descr);
asQWORD retQW = 0;
asQWORD retQW2 = 0;
asDWORD *args = context->m_regs.stackPointer;
void *retPointer = 0;
void *obj = 0;
int popSize = sysFunc->paramSize;
#ifdef AS_NO_THISCALL_FUNCTOR_METHOD
void *obj = 0;
void *secondObj = 0;
if( callConv >= ICC_THISCALL )
{
if( sysFunc->objForThiscall )
{
// This class method is being called as if it is a global function
obj = sysFunc->objForThiscall;
asASSERT( objectPointer == 0 );
}
else if( objectPointer )
{
obj = objectPointer;
}
else
{
@@ -447,7 +577,7 @@ int CallSystemFunction(int id, asCContext *context, void *objectPointer)
}
// Add the base offset for multiple inheritance
#if defined(__GNUC__) && defined(AS_ARM)
#if (defined(__GNUC__) && defined(AS_ARM)) || defined(AS_PSVITA)
// On GNUC + ARM the lsb of the offset is used to indicate a virtual function
// and the whole offset is thus shifted one bit left to keep the original
// offset resolution
@@ -460,7 +590,73 @@ int CallSystemFunction(int id, asCContext *context, void *objectPointer)
args += AS_PTR_SIZE;
}
}
#else
// TODO: clean-up: CallSystemFunctionNative should have two arguments for object pointers
// objForThiscall is the object pointer that should be used for the thiscall
// objForArg is the object pointer that should be passed as argument when using OBJFIRST or OBJLAST
// Used to save two object pointers with THISCALL_OBJLAST or THISCALL_OBJFIRST
void *obj = 0;
void *secondObj = 0;
if( callConv >= ICC_THISCALL )
{
bool continueCheck = true; // True if need check objectPointer or context stack for object
int continueCheckIndex = 0; // Index into objectsPtrs to save the object if continueCheck
if( callConv >= ICC_THISCALL_OBJLAST )
{
asASSERT( sysFunc->objForThiscall != 0 );
// This class method is being called as object method (sysFunc->objForThiscall must be set).
obj = sysFunc->objForThiscall;
continueCheckIndex = 1;
}
else if( sysFunc->objForThiscall )
{
// This class method is being called as if it is a global function
obj = sysFunc->objForThiscall;
continueCheck = false;
}
if( continueCheck )
{
void *tempPtr = 0;
// The object pointer should be popped from the context stack
popSize += AS_PTR_SIZE;
// Check for null pointer
tempPtr = (void*)*(asPWORD*)(args);
if( tempPtr == 0 )
{
context->SetInternalException(TXT_NULL_POINTER_ACCESS);
return 0;
}
// Add the base offset for multiple inheritance
#if (defined(__GNUC__) && defined(AS_ARM)) || defined(AS_PSVITA)
// On GNUC + ARM the lsb of the offset is used to indicate a virtual function
// and the whole offset is thus shifted one bit left to keep the original
// offset resolution
tempPtr = (void*)(asPWORD(tempPtr) + (sysFunc->baseOffset>>1));
#else
tempPtr = (void*)(asPWORD(tempPtr) + sysFunc->baseOffset);
#endif
// Skip the object pointer
args += AS_PTR_SIZE;
if( continueCheckIndex )
secondObj = tempPtr;
else
{
asASSERT( obj == 0 );
obj = tempPtr;
}
}
}
#endif // AS_NO_THISCALL_FUNCTOR_METHOD
if( descr->DoesReturnOnStack() )
{
// Get the address of the location for the return value from the stack
@@ -479,8 +675,9 @@ int CallSystemFunction(int id, asCContext *context, void *objectPointer)
}
context->m_callingSystemFunction = descr;
bool cppException = false;
#ifdef AS_NO_EXCEPTIONS
retQW = CallSystemFunctionNative(context, descr, obj, args, sysFunc->hostReturnInMemory ? retPointer : 0, retQW2);
retQW = CallSystemFunctionNative(context, descr, obj, args, sysFunc->hostReturnInMemory ? retPointer : 0, retQW2, secondObj);
#else
// This try/catch block is to catch potential exception that may
// be thrown by the registered function. The implementation of the
@@ -489,10 +686,12 @@ int CallSystemFunction(int id, asCContext *context, void *objectPointer)
// executed in case of an exception.
try
{
retQW = CallSystemFunctionNative(context, descr, obj, args, sysFunc->hostReturnInMemory ? retPointer : 0, retQW2);
retQW = CallSystemFunctionNative(context, descr, obj, args, sysFunc->hostReturnInMemory ? retPointer : 0, retQW2, secondObj);
}
catch(...)
{
cppException = true;
// Convert the exception to a script exception so the VM can
// properly report the error to the application and then clean up
context->SetException(TXT_EXCEPTION_CAUGHT);
@@ -500,51 +699,6 @@ int CallSystemFunction(int id, asCContext *context, void *objectPointer)
#endif
context->m_callingSystemFunction = 0;
#if defined(COMPLEX_OBJS_PASSED_BY_REF) || defined(AS_LARGE_OBJS_PASSED_BY_REF)
if( sysFunc->takesObjByVal )
{
// Need to free the complex objects passed by value, but that the
// calling convention implicitly passes by reference behind the scene as the
// calling function is the owner of that memory.
// args is pointing to the first real argument as used in CallSystemFunctionNative,
// i.e. hidden arguments such as the object pointer and return address have already
// been skipped.
int spos = 0;
for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ )
{
bool needFree = false;
asCDataType &dt = descr->parameterTypes[n];
#ifdef COMPLEX_OBJS_PASSED_BY_REF
if( dt.GetObjectType() && dt.GetObjectType()->flags & COMPLEX_MASK ) needFree = true;
#endif
#ifdef AS_LARGE_OBJS_PASSED_BY_REF
if( dt.GetSizeInMemoryDWords() >= AS_LARGE_OBJ_MIN_SIZE ) needFree = true;
#endif
if( needFree &&
dt.IsObject() &&
!dt.IsObjectHandle() &&
!dt.IsReference() )
{
void *obj = (void*)*(asPWORD*)&args[spos];
spos += AS_PTR_SIZE;
#ifndef AS_CALLEE_DESTROY_OBJ_BY_VAL
// If the called function doesn't destroy objects passed by value we must do so here
asSTypeBehaviour *beh = &dt.GetObjectType()->beh;
if( beh->destruct )
engine->CallObjectMethod(obj, beh->destruct);
#endif
engine->CallFree(obj);
}
else
spos += dt.GetSizeOnStackDWords();
}
}
#endif
// Store the returned value in our stack
if( descr->returnType.IsObject() && !descr->returnType.IsReference() )
{
@@ -595,7 +749,7 @@ int CallSystemFunction(int id, asCContext *context, void *objectPointer)
}
}
if( context->m_status == asEXECUTION_EXCEPTION )
if( context->m_status == asEXECUTION_EXCEPTION && !cppException )
{
// If the function raised a script exception it really shouldn't have
// initialized the object. However, as it is a soft exception there is
@@ -663,27 +817,36 @@ int CallSystemFunction(int id, asCContext *context, void *objectPointer)
context->m_regs.valueRegister = retQW;
}
// Release autohandles in the arguments
if( sysFunc->hasAutoHandles )
// Clean up arguments
const asUINT cleanCount = sysFunc->cleanArgs.GetLength();
if( cleanCount )
{
args = context->m_regs.stackPointer;
if( callConv >= ICC_THISCALL && !objectPointer )
if( callConv >= ICC_THISCALL )
args += AS_PTR_SIZE;
int spos = 0;
for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ )
asSSystemFunctionInterface::SClean *clean = sysFunc->cleanArgs.AddressOf();
for( asUINT n = 0; n < cleanCount; n++, clean++ )
{
if( sysFunc->paramAutoHandles[n] && *(asPWORD*)&args[spos] != 0 )
void **addr = (void**)&args[clean->off];
if( clean->op == 0 )
{
// Call the release method on the type
engine->CallObjectMethod((void*)*(asPWORD*)&args[spos], descr->parameterTypes[n].GetObjectType()->beh.release);
*(asPWORD*)&args[spos] = 0;
if( *addr != 0 )
{
engine->CallObjectMethod(*addr, clean->ot->beh.release);
*addr = 0;
}
}
else
{
asASSERT( clean->op == 1 || clean->op == 2 );
asASSERT( *addr );
if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() )
spos += AS_PTR_SIZE;
else
spos += descr->parameterTypes[n].GetSizeOnStackDWords();
if( clean->op == 2 )
engine->CallObjectMethod(*addr, clean->ot->beh.destruct);
engine->CallFree(*addr);
}
}
}
+22 -6
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2012 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -46,6 +46,7 @@ BEGIN_AS_NAMESPACE
class asCContext;
class asCScriptEngine;
class asCScriptFunction;
class asCObjectType;
struct asSSystemFunctionInterface;
int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, void *objForThiscall, asSSystemFunctionInterface *internal);
@@ -54,7 +55,7 @@ int PrepareSystemFunctionGeneric(asCScriptFunction *func, asSSystemFunctionInter
int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *internal, asCScriptEngine *engine);
int CallSystemFunction(int id, asCContext *context, void *objectPointer);
int CallSystemFunction(int id, asCContext *context);
inline asPWORD FuncPtrToUInt(asFUNCTION_t func)
{
@@ -83,7 +84,15 @@ enum internalCallConv
ICC_CDECL_OBJFIRST,
ICC_CDECL_OBJFIRST_RETURNINMEM,
ICC_GENERIC_METHOD,
ICC_GENERIC_METHOD_RETURNINMEM // never used
ICC_GENERIC_METHOD_RETURNINMEM, // never used
ICC_THISCALL_OBJLAST,
ICC_THISCALL_OBJLAST_RETURNINMEM,
ICC_VIRTUAL_THISCALL_OBJLAST,
ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM,
ICC_THISCALL_OBJFIRST,
ICC_THISCALL_OBJFIRST_RETURNINMEM,
ICC_VIRTUAL_THISCALL_OBJFIRST,
ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM
};
struct asSSystemFunctionInterface
@@ -97,11 +106,18 @@ struct asSSystemFunctionInterface
int hostReturnSize;
int paramSize;
bool takesObjByVal;
asCArray<bool> paramAutoHandles;
asCArray<bool> paramAutoHandles; // TODO: Should be able to remove this array. Perhaps the flags can be stored together with the inOutFlags in asCScriptFunction?
bool returnAutoHandle;
bool hasAutoHandles;
void *objForThiscall;
struct SClean
{
asCObjectType *ot; // argument type for clean up
short op; // clean up operation: 0 = release, 1 = free, 2 = destruct then free
short off; // argument offset on the stack
};
asCArray<SClean> cleanArgs;
asSSystemFunctionInterface() {}
asSSystemFunctionInterface(const asSSystemFunctionInterface &in)
@@ -122,8 +138,8 @@ struct asSSystemFunctionInterface
takesObjByVal = in.takesObjByVal;
paramAutoHandles = in.paramAutoHandles;
returnAutoHandle = in.returnAutoHandle;
hasAutoHandles = in.hasAutoHandles;
objForThiscall = in.objForThiscall;
cleanArgs = in.cleanArgs;
return *this;
}
};
+109 -29
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -37,6 +37,8 @@
// Written by Fredrik Ehnbom in June 2009, based on as_callfunc_x86.cpp
//
// The code was complemented to support Linux with ARM by Carlos Luna in December, 2012.
//
// Added support for functor methods by Jordi Oliveras Rovira in April, 2014.
// This code has to conform to both AAPCS and the modified ABI for iOS
@@ -71,7 +73,7 @@ extern "C" asQWORD armFuncR0R1 (const asDWORD *, int, asFUNCTION_t, asDWORD
extern "C" asQWORD armFuncObjLast (const asDWORD *, int, asFUNCTION_t, asDWORD obj);
extern "C" asQWORD armFuncR0ObjLast (const asDWORD *, int, asFUNCTION_t, asDWORD r0, asDWORD obj);
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/)
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/, void *secondObject)
{
asCScriptEngine *engine = context->m_engine;
asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
@@ -87,33 +89,45 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
// The return is made in memory
callConv++;
}
bool isThisCallMethod = callConv >= ICC_THISCALL_OBJLAST;
asDWORD paramBuffer[64+2];
// Android & Linux needs to align 64bit types on even registers, but this isn't done on iOS or Windows Phone
// TODO: optimize runtime: There should be a check for this in PrepareSystemFunction() so this
// doesn't have to be done for functions that don't have any 64bit types
#if !defined(AS_ANDROID) && !defined(AS_LINUX)
if( sysFunc->takesObjByVal )
// In cases of thiscall methods, the callstack is configured as a standard thiscall
// adding the secondObject as first or last element in callstack
if( sysFunc->takesObjByVal || isThisCallMethod )
#endif
{
#if defined(AS_ANDROID) || defined(AS_LINUX)
// mask is used as a toggler to skip uneven registers.
int mask = 1;
// Check for object pointer as first argument
switch( callConv )
if( isThisCallMethod )
{
case ICC_THISCALL:
case ICC_CDECL_OBJFIRST:
case ICC_VIRTUAL_THISCALL:
case ICC_THISCALL_RETURNINMEM:
case ICC_CDECL_OBJFIRST_RETURNINMEM:
case ICC_VIRTUAL_THISCALL_RETURNINMEM:
mask = 0;
break;
default:
break;
mask = 0;
}
else
{
// Check for object pointer as first argument
switch( callConv )
{
case ICC_THISCALL:
case ICC_CDECL_OBJFIRST:
case ICC_VIRTUAL_THISCALL:
case ICC_THISCALL_RETURNINMEM:
case ICC_CDECL_OBJFIRST_RETURNINMEM:
case ICC_VIRTUAL_THISCALL_RETURNINMEM:
mask = 0;
break;
default:
break;
}
}
// Check for hidden address in case of return by value
if( sysFunc->hostReturnInMemory )
mask = !mask;
@@ -122,6 +136,14 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
int spos = 0;
int dpos = 2;
if( isThisCallMethod && (callConv >= ICC_THISCALL_OBJFIRST &&
callConv <= ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM) )
{
// Add the object pointer as the first parameter
paramBuffer[dpos++] = (asDWORD)secondObject;
paramSize++;
}
for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ )
{
// TODO: runtime optimize: Declare a reference to descr->parameterTypes[n] so the array doesn't have to be access all the time
@@ -177,6 +199,15 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
paramSize += descr->parameterTypes[n].GetSizeOnStackDWords();
}
}
if( isThisCallMethod && (callConv >= ICC_THISCALL_OBJLAST &&
callConv <= ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM) )
{
// Add the object pointer as the last parameter
paramBuffer[dpos++] = (asDWORD)secondObject;
paramSize++;
}
// Keep a free location at the beginning
args = &paramBuffer[2];
}
@@ -193,9 +224,13 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
break;
case ICC_THISCALL: // fall through
case ICC_CDECL_OBJFIRST:
case ICC_THISCALL_OBJFIRST:
case ICC_THISCALL_OBJLAST:
retQW = armFuncR0(args, paramSize<<2, func, (asDWORD)obj);
break;
case ICC_THISCALL_RETURNINMEM:
case ICC_THISCALL_OBJFIRST_RETURNINMEM:
case ICC_THISCALL_OBJLAST_RETURNINMEM:
#ifdef __GNUC__
// On GNUC the address where the return value will be placed should be put in R0
retQW = armFuncR0R1(args, paramSize<<2, func, (asDWORD)retPointer, (asDWORD)obj);
@@ -208,11 +243,15 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
retQW = armFuncR0R1(args, paramSize<<2, func, (asDWORD)retPointer, (asDWORD)obj);
break;
case ICC_VIRTUAL_THISCALL:
case ICC_VIRTUAL_THISCALL_OBJFIRST:
case ICC_VIRTUAL_THISCALL_OBJLAST:
// Get virtual function table from the object pointer
vftable = *(asFUNCTION_t**)obj;
retQW = armFuncR0(args, paramSize<<2, vftable[FuncPtrToUInt(func)>>2], (asDWORD)obj);
break;
case ICC_VIRTUAL_THISCALL_RETURNINMEM:
case ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM:
case ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM:
// Get virtual function table from the object pointer
vftable = *(asFUNCTION_t**)obj;
#ifdef __GNUC__
@@ -255,7 +294,7 @@ extern "C" asQWORD armFuncR0R1 (const asDWORD *, int, asFUNCTION_t, asDWORD
extern "C" asQWORD armFuncObjLast (const asDWORD *, int, asFUNCTION_t, asDWORD obj);
extern "C" asQWORD armFuncR0ObjLast (const asDWORD *, int, asFUNCTION_t, asDWORD r0, asDWORD obj);
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/)
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/, void *secondObject)
{
asCScriptEngine *engine = context->m_engine;
asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
@@ -307,6 +346,8 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
callConv++;
}
bool isThisCallMethod = callConv >= ICC_THISCALL_OBJLAST;
// Linux needs to align 64bit types on even registers, but this isn't done on iOS or Windows Phone
// TODO: optimize runtime: There should be a check for this in PrepareSystemFunction() so this
// doesn't have to be done for functions that don't have any 64bit types
@@ -314,19 +355,26 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
// mask is used as a toggler to skip uneven registers.
int mask = 1;
// Check for object pointer as first argument
switch( callConv )
if( isThisCallMethod )
{
case ICC_THISCALL:
case ICC_CDECL_OBJFIRST:
case ICC_VIRTUAL_THISCALL:
case ICC_THISCALL_RETURNINMEM:
case ICC_CDECL_OBJFIRST_RETURNINMEM:
case ICC_VIRTUAL_THISCALL_RETURNINMEM:
mask = 0;
break;
default:
break;
mask = 0;
}
else
{
// Check for object pointer as first argument
switch( callConv )
{
case ICC_THISCALL:
case ICC_CDECL_OBJFIRST:
case ICC_VIRTUAL_THISCALL:
case ICC_THISCALL_RETURNINMEM:
case ICC_CDECL_OBJFIRST_RETURNINMEM:
case ICC_VIRTUAL_THISCALL_RETURNINMEM:
mask = 0;
break;
default:
break;
}
}
// Check for hidden address in case of return by value
if( sysFunc->hostReturnInMemory )
@@ -336,10 +384,19 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
int spos = 0;
int dpos = 2;
if( isThisCallMethod && (callConv >= ICC_THISCALL_OBJFIRST &&
callConv <= ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM) )
{
// Add the object pointer as the first parameter
paramBuffer[dpos++] = (asDWORD)secondObject;
paramSize++;
}
for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ )
{
// TODO: runtime optimize: Declare a reference to descr->parameterTypes[n] so the array doesn't have to be access all the time
if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() )
if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() &&
!(descr->parameterTypes[n].GetObjectType()->flags & asOBJ_APP_ARRAY) )
{
#ifdef COMPLEX_OBJS_PASSED_BY_REF
if( descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK )
@@ -501,6 +558,21 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
}// else...
}// Loop
if( isThisCallMethod && (callConv >= ICC_THISCALL_OBJLAST &&
callConv <= ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM) )
{
if (paramSize < 4)
{
paramBuffer[dpos++] = (asDWORD)secondObject;
paramSize++;
}
else
{
paramBuffer[stackPos++] = (asDWORD)secondObject;
stackSize++;
}
}
// Keep a free location at the beginning
args = &paramBuffer[2];
}
@@ -519,9 +591,13 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
break;
case ICC_THISCALL: // fall through
case ICC_CDECL_OBJFIRST:
case ICC_THISCALL_OBJFIRST:
case ICC_THISCALL_OBJLAST:
retQW = armFuncR0(args, paramSize<<2, func, (asDWORD)obj);
break;
case ICC_THISCALL_RETURNINMEM:
case ICC_THISCALL_OBJFIRST_RETURNINMEM:
case ICC_THISCALL_OBJLAST_RETURNINMEM:
// On GNUC the address where the return value will be placed should be put in R0
retQW = armFuncR0R1(args, paramSize<<2, func, (asDWORD)retPointer, (asDWORD)obj);
break;
@@ -529,11 +605,15 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
retQW = armFuncR0R1(args, paramSize<<2, func, (asDWORD)retPointer, (asDWORD)obj);
break;
case ICC_VIRTUAL_THISCALL:
case ICC_VIRTUAL_THISCALL_OBJFIRST:
case ICC_VIRTUAL_THISCALL_OBJLAST:
// Get virtual function table from the object pointer
vftable = *(asFUNCTION_t**)obj;
retQW = armFuncR0(args, paramSize<<2, vftable[FuncPtrToUInt(func)>>2], (asDWORD)obj);
break;
case ICC_VIRTUAL_THISCALL_RETURNINMEM:
case ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM:
case ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM:
// Get virtual function table from the object pointer
vftable = *(asFUNCTION_t**)obj;
// On GNUC the address where the return value will be placed should be put in R0
+9 -2
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -488,6 +488,7 @@ armFuncR0ObjLast:
strge r7, [r6, #8]
str r5, [r6, #12] /* Put objlast in r6 + 12 */
mov r5, #0
movge r5, #4 /* Set r5 with an offset of #4 if there´s one last arg that couldn´t be placed in r registers */
add r5, r5, #4 /* Set r5 with an offset of + #4, so objlast can be loaded into the stack */
@@ -687,6 +688,12 @@ nomoreargsarmFuncR0R1:
pop {r4-r8, r10, r11, pc}
#endif /* hard float abi */
#if defined(__linux__) && defined(__ELF__)
/* ref: http://hardened.gentoo.org/gnu-stack.xml */
.section .note.GNU-stack,"",%progbits
#endif
#endif
#endif /* arm */
@@ -1,6 +1,6 @@
;
; AngelCode Scripting Library
; Copyright (c) 2003-2013 Andreas Jonsson
; Copyright (c) 2003-2014 Andreas Jonsson
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event will the authors be held liable for any
@@ -29,7 +29,7 @@
;
; Assembly routines for the ARM call convention
; Assembly routines for the ARM call convention used for Windows CE
; Written by Fredrik Ehnbom in June 2009
; MSVC currently doesn't support inline assembly for the ARM platform
@@ -0,0 +1,480 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
The original version of this library can be located at:
http://www.angelcode.com/angelscript/
Andreas Jonsson
andreas@angelcode.com
*/
/*
Assembly routines for the Playstation Vita SNC call convention.
This code was adapted from as_callfunc_arm_gcc (ARM, Linux hard float) by Brandon Bare on October 2014.
*/
#ifdef __psp2__
.syntax unified
.cpu cortex-a9
.fpu neon
.section .text.armCallFunc
.balign 2
.thumb
.thumb_func
.align 2
.global armFunc
.global armFuncR0
.global armFuncR0R1
.global armFuncObjLast
.global armFuncR0ObjLast
.type armFunc, %function
.type armFuncR0, %function
.type armFuncR0R1, %function
.type armFuncObjLast, %function
.type armFuncR0ObjLast, %function
/* --------------------------------------------------------------------------------------------*/
armFunc:
.fnstart
push {r4-r8, r10, r11, lr} /* sp must be 8-byte alignment for ABI compliance, so the pushed registers must be even */
mov r6, r0 /* arg table */
movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
mov r4, r2 /* function address */
/* Load float and double args into d0-d7 and s0-s15 */
add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
mov r8, #0
vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
/* If there are no arguments to set into r0-r3 */
/* go check if there are arguments for the stack */
beq stackargs
/* Load the first 4 arguments into r0-r3 */
cmp r7, #4
it ge
ldrge r0, [r6]
cmp r7, #8
it ge
ldrge r1, [r6, #4]
cmp r7, #12
it ge
ldrge r2, [r6, #8]
cmp r7, #16
it ge
ldrge r3, [r6, #12]
stackargs:
ldr r5, [r6, #268] /* Load stack size into r5 */
movs r7, r5 /* Load stack size into r7, checking for 0 args */
/* If there are no args for the stack, branch */
beq nomoreargs
/* Load the rest of the arguments onto the stack */
/* Ensure 8-byte stack alignment */
mov r8, sp
sub sp, sp, r7
add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
sub r12, sp, #8
bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
sub r8, r8, r12
mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
stackargsloop:
ldr r5, [r6], #4
subs r7, r7, #4
str r5, [sp], #4
bne stackargsloop
mov sp, r12
nomoreargs:
blx r4
add sp, sp, r8
vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d7 to the address stored in r10 */
pop {r4-r8, r10, r11, pc}
.fnend
/* --------------------------------------------------------------------------------------------*/
armFuncObjLast:
.fnstart
push {r4-r8, r10, r11, lr} /* We´re storing r11 just to keep the stack aligned to an 8 byte boundary */
mov r6, r0 /* arg table */
movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
mov r4, r2 /* function address */
mov r0, r3 /* objlast. might get overwritten */
mov r5, #0 /* This will hold an offset of #4 only if objlast couldn´t be placed into an "r" register */
/* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
mov r8, #0
vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
/* If there are no arguments to set into r0-r3 */
/* go check if there are arguments for the stack */
beq stackargsFuncObjLast
mov r5, r3 /* store objlast in r5 temporarily */
/* Load the first 4 arguments into r0-r3 */
cmp r7, #4
it ge
ldrge r0, [r6]
cmp r7, #8
it ge
ldrge r1, [r6,#4]
it lt
movlt r1, r5
cmp r7, #12
it ge
ldrge r2, [r6,#8]
it lt
movlt r2, r5
cmp r7, #16
it ge
ldrge r3, [r6,#12]
ittt lt
movlt r3, r5
movlt r5, #0 /* If objlast got placed into a register, r5 = 0 */
blt stackargsFuncObjLast /* If objlast got placed into a register, go to stackargsFuncObjLast */
str r5, [r6, #12] /* Put objlast in r6 + 12 */
mov r5, #4 /* Set r5 with an offset of #4, so objlast can be loaded into the stack */
stackargsFuncObjLast:
ldr r7, [r6, #268] /* Load stack size into r7 */
add r7, r7, r5 /* Add the offset placed in r5 (could be #0 or #4) */
cmp r7, #0 /* Check for 0 args */
/* If there are no args for the stack, branch */
beq nomoreargsarmFuncObjLast
/* Load the rest of the arguments onto the stack */
/* Ensure 8-byte stack alignment */
mov r8, sp
sub sp, sp, r7
add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
sub r12, sp, #8
sub r6, r6, r5 /* r6 = r6 - r5 (r5 can be #0 or #4) */
bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
sub r8, r8, r12
mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
stackargslooparmFuncObjLast:
ldr r5, [r6], #4
subs r7, r7, #4
str r5, [sp], #4
bne stackargslooparmFuncObjLast
mov sp, r12
nomoreargsarmFuncObjLast:
blx r4
add sp, sp, r8
vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
pop {r4-r8, r10,r11, pc}
.fnend
/* --------------------------------------------------------------------------------------------*/
armFuncR0ObjLast:
.fnstart
push {r4-r8, r10, r11, lr}
ldr r5, [sp,#32] /* objlast to temp reg */
mov r6, r0 /* arg table */
movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
mov r4, r2 /* function address */
mov r0, r3 /* r0 explicitly set */
mov r1, r5 /* objlast. might get overwritten */
mov r5, #0 /* This will hold an offset of #4 or #8 if objlast or one arg couldn´t be placed into an "r" register */
/* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
mov r8, #0
vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
/* If there are no arguments to set into r0-r3 */
/* go check if there are arguments for the stack */
beq stackargsFuncR0ObjLast
mov r5, r1 /* store objlast in r5 temporarily */
/* Load the first 3 arguments into r1-r3 */
cmp r7, #4
it ge
ldrge r1, [r6]
cmp r7, #8
it ge
ldrge r2, [r6,#4]
it lt
movlt r2, r5
cmp r7, #12
it ge
ldrge r3, [r6,#8]
ittt lt
movlt r3, r5
movlt r5, #0 /* If objlast got placed into a register, r5 = 0 */
blt stackargsFuncR0ObjLast /* If objlast got placed into a register, go to stackargsFuncR0ObjLast */
cmp r7, #16 /* Else if we have one last arg set the offset accordingly and store the arg in the array */
itt ge
ldrge r7, [r6, #12]
strge r7, [r6, #8]
str r5, [r6, #12] /* Put objlast in r6 + 12 */
mov r5, #0
it ge
movge r5, #4 /* Set r5 with an offset of #4 if there´s one last arg that couldn´t be placed in r registers */
add r5, r5, #4 /* Set r5 with an offset of + #4, so objlast can be loaded into the stack */
stackargsFuncR0ObjLast:
ldr r7, [r6, #268] /* Load stack size into r7 */
add r7, r7, r5 /* Add the offset placed in r5 (could be #0 or #4) */
cmp r7, #0 /* Check for 0 args */
/* If there are no args for the stack, branch */
beq nomoreargsarmFuncR0ObjLast
/* Load the rest of the arguments onto the stack */
/* Ensure 8-byte stack alignment */
mov r8, sp
sub sp, sp, r7
add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
sub r12, sp, #8
sub r6, r6, r5 /* r6 = r6 - r5 (r5 can be #0 or #4) */
bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
sub r8, r8, r12
mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
stackargslooparmFuncR0ObjLast:
ldr r5, [r6], #4
subs r7, r7, #4
str r5, [sp], #4
bne stackargslooparmFuncR0ObjLast
mov sp, r12
nomoreargsarmFuncR0ObjLast:
blx r4
add sp, sp, r8
vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
pop {r4-r8, r10, r11, pc}
.fnend
/* --------------------------------------------------------------------------------------------*/
armFuncR0:
.fnstart
push {r4-r8, r10, r11, lr}
mov r6, r0 /* arg table */
movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
mov r4, r2 /* function address */
mov r11, #0 /* This will hold an offset of #4 only if the last arg that should have been placed into an "r" reg needs to go to the stack */
mov r0, r3 /* r0 explicitly set */
/* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
mov r8, #0
vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
/* If there are no arguments to set into r0-r3 */
/* go check if there are arguments for the stack */
beq stackargsarmFuncR0
/* Load the first 3 arguments into r1-r3 */
cmp r7, #4
it ge
ldrge r1, [r6]
cmp r7, #8
it ge
ldrge r2, [r6, #4]
cmp r7, #12
it ge
ldrge r3, [r6, #8]
cmp r7, #16
it ge
movge r11, #4 /* If there is still one arg to be placed, set the offset in r11 to #4 */
stackargsarmFuncR0:
ldr r5, [r6, #268] /* Load stack size into r5 */
add r5, r11 /* Add the offset placed in r11 (could be #0 or #4) */
movs r7, r5 /* Load stack size into r7, checking for 0 args */
/* If there are no args for the stack, branch */
beq nomoreargsarmFuncR0
/* Load the rest of the arguments onto the stack */
/* Ensure 8-byte stack alignment */
mov r8, sp
sub sp, sp, r7
add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
sub r12, sp, #8
sub r6, r6, r11 /* r6 = r6 - r11 (r11 can be #0 or #4) */
bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
sub r8, r8, r12
mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
stackargslooparmFuncR0:
ldr r5, [r6], #4
subs r7, r7, #4
str r5, [sp], #4
bne stackargslooparmFuncR0
mov sp, r12
nomoreargsarmFuncR0:
blx r4
add sp, sp, r8
vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
pop {r4-r8, r10, r11, pc}
.fnend
/* --------------------------------------------------------------------------------------------*/
armFuncR0R1:
.fnstart
push {r4-r8, r10, r11, lr}
mov r6, r0 /* arg table */
movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
mov r4, r2 /* function address */
mov r11, #0 /* This will hold an offset of #4 or #8 only if the last arg (or last 2 args) that should have been placed into "r" regs need to go to the stack */
mov r0, r3 /* r0 explicitly set */
ldr r1, [sp, #32] /* r1 explicitly set too */
/* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
mov r8, #0
vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
/* If there are no arguments to set into r2-r3 */
/* go check if there are arguments for the stack */
beq stackargsarmFuncR0R1
/* Load the first 2 arguments into r2-r3 */
cmp r7, #4
it ge
ldrge r2, [r6]
cmp r7, #8
it ge
ldrge r3, [r6, #4]
cmp r7, #12
it ge
movge r11, #4 /* If there is a third arg to be placed, set the offset in r11 to #4 */
cmp r7, #16
it ge
movge r11, #8 /* If there is a fourth arg to be placed, set the offset in r11 to #8 */
itt lt
ldrlt r7, [r6, #8] /* Else copy the third arg to the correct place in the array */
strlt r7, [r6, #12]
stackargsarmFuncR0R1:
ldr r5, [r6, #268] /* Load stack size into r5 */
add r5, r11 /* Add the offset placed in r11 (could be #0 or #4 or #8) */
movs r7, r5 /* Load stack size into r7, checking for 0 args */
/* If there are no args for the stack, branch */
beq nomoreargsarmFuncR0R1
/* Load the rest of the arguments onto the stack */
/* Ensure 8-byte stack alignment */
mov r8, sp
sub sp, sp, r7
add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
sub r12, sp, #8
sub r6, r6, r11 /* r6 = r6 - r11 (r11 can be #0 or #4 or #8) */
bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
sub r8, r8, r12
mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
stackargslooparmFuncR0R1:
ldr r5, [r6], #4
subs r7, r7, #4
str r5, [sp], #4
bne stackargslooparmFuncR0R1
mov sp, r12
nomoreargsarmFuncR0R1:
blx r4
add sp, sp, r8
vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
pop {r4-r8, r10, r11, pc}
.fnend
#endif
+4 -2
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -221,12 +221,14 @@ asQWORD GetReturnedDouble()
return d;
}
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/)
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/, void */*secondObject*/)
{
asCScriptEngine *engine = context->m_engine;
asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
int callConv = sysFunc->callConv;
// TODO: Mips does not yet support THISCALL_OBJFIRST/LAST
asQWORD retQW = 0;
void *func = (void*)sysFunc->func;
+4 -2
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -482,8 +482,10 @@ static asQWORD CallThisCallFunction_objLast(const void *obj, const asDWORD* pArg
return ppcFunc( ppcArgs, PPC_STACK_SIZE(numTotalArgs), func );
}
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/)
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/, void */*secondObject*/)
{
// TODO: PPC does not yet support THISCALL_OBJFIRST/LAST
// use a working array of types, we'll configure the final one in stackArgs
asBYTE argsType[2*AS_PPC_MAX_ARGS + 1 + 1 + 1];
memset( argsType, 0, sizeof(argsType));
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -547,8 +547,10 @@ inline bool IsVariableArgument( asCDataType type )
return (type.GetTokenType() == ttQuestion) ? true : false;
}
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/)
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/, void */*secondObject*/)
{
// TODO: PPC 64 does not yet support THISCALL_OBJFIRST/LAST
// use a working array of types, we'll configure the final one in stackArgs
asBYTE argsType[AS_PPC_MAX_ARGS + 1 + 1 + 1];
memset( argsType, 0, sizeof(argsType));
@@ -663,7 +665,8 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ )
{
if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() )
if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() &&
!(descr->parameterTypes[n].GetObjectType()->flags & asOBJ_APP_ARRAY) )
{
#ifdef COMPLEX_OBJS_PASSED_BY_REF
if( descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK )
+4 -2
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -270,8 +270,10 @@ asQWORD GetReturnedDouble()
return d;
}
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/)
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/, void */*secondObject*/)
{
// TODO: SH4 does not yet support THISCALL_OBJFIRST/LAST
asCScriptEngine *engine = context->m_engine;
asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
int callConv = sysFunc->callConv;
+62 -3
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -34,8 +34,14 @@
* Author: Ionut "gargltk" Leonte <ileonte@bitdefender.com>
*
* Initial author: niteice
*
* Added support for functor methods by Jordi Oliveras Rovira in April, 2014.
*/
// Useful references for the System V AMD64 ABI:
// http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/
// http://math-atlas.sourceforge.net/devel/assembly/abi_sysV_amd64.pdf
#include "as_config.h"
#ifndef AS_MAX_PORTABILITY
@@ -73,6 +79,8 @@ static asQWORD __attribute__((noinline)) X64_CallFunction(const asQWORD *args, i
// Backup stack pointer in R15 that is guaranteed to maintain its value over function calls
" movq %%rsp, %%r15 \n"
// Make sure the stack unwind logic knows we've backed up the stack pointer in register r15
" .cfi_def_cfa_register r15 \n"
// Skip the first 128 bytes on the stack frame, called "red zone",
// that might be used by the compiler to store temporary values
@@ -124,6 +132,8 @@ static asQWORD __attribute__((noinline)) X64_CallFunction(const asQWORD *args, i
// Restore stack pointer
" mov %%r15, %%rsp \n"
// Inform the stack unwind logic that the stack pointer has been restored
" .cfi_def_cfa_register rsp \n"
// Put return value in retQW1 and retQW2, using either RAX:RDX or XMM0:XMM1 depending on type of return value
" movl %5, %%ecx \n"
@@ -152,7 +162,7 @@ static inline bool IsVariableArgument( asCDataType type )
return ( type.GetTokenType() == ttQuestion ) ? true : false;
}
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &retQW2)
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &retQW2, void *secondObject)
{
asCScriptEngine *engine = context->m_engine;
asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
@@ -172,8 +182,17 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
callConv++;
}
#ifdef AS_NO_THISCALL_FUNCTOR_METHOD
// Determine the real function pointer in case of virtual method
if ( obj && ( callConv == ICC_VIRTUAL_THISCALL || callConv == ICC_VIRTUAL_THISCALL_RETURNINMEM ) )
#else
if ( obj && ( callConv == ICC_VIRTUAL_THISCALL ||
callConv == ICC_VIRTUAL_THISCALL_RETURNINMEM ||
callConv == ICC_VIRTUAL_THISCALL_OBJFIRST ||
callConv == ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM ||
callConv == ICC_VIRTUAL_THISCALL_OBJLAST ||
callConv == ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM) )
#endif
{
vftable = *((funcptr_t**)obj);
func = vftable[FuncPtrToUInt(asFUNCTION_t(func)) >> 3];
@@ -195,6 +214,11 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
break;
}
#ifndef AS_NO_THISCALL_FUNCTOR_METHOD
case ICC_THISCALL_OBJLAST:
case ICC_VIRTUAL_THISCALL_OBJLAST:
param_post = 2;
#endif
case ICC_THISCALL:
case ICC_VIRTUAL_THISCALL:
case ICC_CDECL_OBJFIRST:
@@ -206,6 +230,11 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
break;
}
#ifndef AS_NO_THISCALL_FUNCTOR_METHOD
case ICC_THISCALL_OBJLAST_RETURNINMEM:
case ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM:
param_post = 2;
#endif
case ICC_THISCALL_RETURNINMEM:
case ICC_VIRTUAL_THISCALL_RETURNINMEM:
case ICC_CDECL_OBJFIRST_RETURNINMEM:
@@ -219,7 +248,33 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
break;
}
case ICC_CDECL_OBJLAST:
#ifndef AS_NO_THISCALL_FUNCTOR_METHOD
case ICC_THISCALL_OBJFIRST:
case ICC_VIRTUAL_THISCALL_OBJFIRST:
{
paramBuffer[0] = (asPWORD)obj;
paramBuffer[1] = (asPWORD)secondObject;
argsType[0] = x64INTARG;
argsType[1] = x64INTARG;
argIndex = 2;
break;
}
case ICC_THISCALL_OBJFIRST_RETURNINMEM:
case ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM:
{
paramBuffer[0] = (asPWORD)retPointer;
paramBuffer[1] = (asPWORD)obj;
paramBuffer[2] = (asPWORD)secondObject;
argsType[0] = x64INTARG;
argsType[1] = x64INTARG;
argsType[2] = x64INTARG;
argIndex = 3;
break;
}
#endif
case ICC_CDECL_OBJLAST:
param_post = 1;
break;
case ICC_CDECL_OBJLAST_RETURNINMEM:
@@ -337,7 +392,11 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
// For the CDECL_OBJ_LAST calling convention we need to add the object pointer as the last argument
if( param_post )
{
#ifdef AS_NO_THISCALL_FUNCTOR_METHOD
paramBuffer[argIndex] = (asPWORD)obj;
#else
paramBuffer[argIndex] = (asPWORD)(param_post > 1 ? secondObject : obj);
#endif
argsType[argIndex] = x64INTARG;
argIndex++;
}
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -31,6 +31,8 @@
//
// This code was adapted from as_callfunc_x64_msvc by _Vicious_ on August 20th, 2011.
//
// Added support for functor methods by Jordi Oliveras Rovira in April, 2014.
//
#include <stdio.h>
@@ -165,7 +167,7 @@ static asQWORD GetReturnedDouble()
return ret;
}
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/)
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/, void *secondObject)
{
asCScriptEngine *engine = context->m_engine;
asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
@@ -189,10 +191,16 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
allArgBuffer[paramSize++] = (asQWORD)retPointer;
}
#ifdef AS_NO_THISCALL_FUNCTOR_METHOD
if( callConv == ICC_THISCALL ||
callConv == ICC_THISCALL_RETURNINMEM ||
callConv == ICC_VIRTUAL_THISCALL ||
callConv == ICC_VIRTUAL_THISCALL_RETURNINMEM )
#else
// Optimization to avoid check 12 values (all ICC_ that contains THISCALL)
if( (callConv >= ICC_THISCALL && callConv <= ICC_VIRTUAL_THISCALL_RETURNINMEM) ||
(callConv >= ICC_THISCALL_OBJLAST && callConv <= ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM) )
#endif
{
// Add the object pointer as the first parameter
allArgBuffer[paramSize++] = (asQWORD)obj;
@@ -204,8 +212,28 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
// Add the object pointer as the first parameter
allArgBuffer[paramSize++] = (asQWORD)obj;
}
#ifndef AS_NO_THISCALL_FUNCTOR_METHOD
else if( callConv == ICC_THISCALL_OBJFIRST ||
callConv == ICC_THISCALL_OBJFIRST_RETURNINMEM ||
callConv == ICC_VIRTUAL_THISCALL_OBJFIRST ||
callConv == ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM )
{
// Add the object pointer as the first parameter
allArgBuffer[paramSize++] = (asQWORD)secondObject;
}
#endif
#ifdef AS_NO_THISCALL_FUNCTOR_METHOD
if( callConv == ICC_VIRTUAL_THISCALL ||
callConv == ICC_VIRTUAL_THISCALL_RETURNINMEM )
#else
if( callConv == ICC_VIRTUAL_THISCALL ||
callConv == ICC_VIRTUAL_THISCALL_RETURNINMEM ||
callConv == ICC_VIRTUAL_THISCALL_OBJFIRST ||
callConv == ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM ||
callConv == ICC_VIRTUAL_THISCALL_OBJLAST ||
callConv == ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM )
#endif
{
// Get the true function pointer from the virtual function table
vftable = *(void***)obj;
@@ -287,6 +315,16 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
// Add the object pointer as the last parameter
allArgBuffer[paramSize++] = (asQWORD)obj;
}
#ifndef AS_NO_THISCALL_FUNCTOR_METHOD
else if( callConv == ICC_THISCALL_OBJLAST ||
callConv == ICC_THISCALL_OBJLAST_RETURNINMEM ||
callConv == ICC_VIRTUAL_THISCALL_OBJLAST ||
callConv == ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM )
{
// Add the object pointer as the last parameter
allArgBuffer[paramSize++] = (asQWORD)secondObject;
}
#endif
retQW = CallX64(allArgBuffer, floatArgBuffer, paramSize*8, (asPWORD)func);
+40 -16
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -28,6 +28,9 @@
andreas@angelcode.com
*/
//
// Added support for thiscall methods by Jordi Oliveras Rovira in April, 2014.
//
#include <stdio.h>
@@ -48,7 +51,7 @@ extern "C" asQWORD CallX64(const asQWORD *args, const asQWORD *floatArgs, int pa
extern "C" asDWORD GetReturnedFloat();
extern "C" asQWORD GetReturnedDouble();
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/)
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/, void *secondObject)
{
asCScriptEngine *engine = context->m_engine;
asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
@@ -62,10 +65,10 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
asQWORD floatArgBuffer[4];
int callConv = sysFunc->callConv;
if( callConv == ICC_THISCALL ||
callConv == ICC_THISCALL_RETURNINMEM ||
callConv == ICC_VIRTUAL_THISCALL ||
callConv == ICC_VIRTUAL_THISCALL_RETURNINMEM )
// Optimization to avoid check 12 values (all ICC_ that contains THISCALL)
if( (callConv >= ICC_THISCALL && callConv <= ICC_VIRTUAL_THISCALL_RETURNINMEM) ||
(callConv >= ICC_THISCALL_OBJLAST && callConv <= ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM) )
{
// Add the object pointer as the first parameter
allArgBuffer[paramSize++] = (asQWORD)obj;
@@ -86,9 +89,21 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
// Add the object pointer as the first parameter
allArgBuffer[paramSize++] = (asQWORD)obj;
}
else if( callConv == ICC_THISCALL_OBJFIRST ||
callConv == ICC_THISCALL_OBJFIRST_RETURNINMEM ||
callConv == ICC_VIRTUAL_THISCALL_OBJFIRST ||
callConv == ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM )
{
// Add the object pointer as the first parameter
allArgBuffer[paramSize++] = (asQWORD)secondObject;
}
if( callConv == ICC_VIRTUAL_THISCALL ||
callConv == ICC_VIRTUAL_THISCALL_RETURNINMEM )
callConv == ICC_VIRTUAL_THISCALL_RETURNINMEM ||
callConv == ICC_VIRTUAL_THISCALL_OBJFIRST ||
callConv == ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM ||
callConv == ICC_VIRTUAL_THISCALL_OBJLAST ||
callConv == ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM )
{
// Get the true function pointer from the virtual function table
vftable = *(void***)obj;
@@ -100,10 +115,11 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
asUINT spos = 0;
for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ )
{
if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() )
asCDataType &dt = descr->parameterTypes[n];
if( dt.IsObject() && !dt.IsObjectHandle() && !dt.IsReference() )
{
if( descr->parameterTypes[n].GetSizeInMemoryDWords() >= AS_LARGE_OBJ_MIN_SIZE ||
(descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK) )
if( dt.GetSizeInMemoryDWords() >= AS_LARGE_OBJ_MIN_SIZE ||
(dt.GetObjectType()->flags & COMPLEX_MASK) )
{
allArgBuffer[dpos++] = *(asQWORD*)&args[spos];
spos += AS_PTR_SIZE;
@@ -112,18 +128,18 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
else
{
// Copy the object's memory to the buffer
memcpy(&allArgBuffer[dpos], *(void**)(args+spos), descr->parameterTypes[n].GetSizeInMemoryBytes());
memcpy(&allArgBuffer[dpos], *(void**)(args+spos), dt.GetSizeInMemoryBytes());
// Delete the original memory
engine->CallFree(*(char**)(args+spos));
spos += AS_PTR_SIZE;
asUINT dwords = descr->parameterTypes[n].GetSizeInMemoryDWords();
asUINT dwords = dt.GetSizeInMemoryDWords();
asUINT qwords = (dwords >> 1) + (dwords & 1);
dpos += qwords;
paramSize += qwords;
}
}
else if( descr->parameterTypes[n].GetTokenType() == ttQuestion )
else if( dt.GetTokenType() == ttQuestion )
{
// Copy the reference and the type id
allArgBuffer[dpos++] = *(asQWORD*)&args[spos];
@@ -134,14 +150,14 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
else
{
// Copy the value directly
asUINT dwords = descr->parameterTypes[n].GetSizeOnStackDWords();
asUINT dwords = dt.GetSizeOnStackDWords();
if( dwords > 1 )
{
allArgBuffer[dpos] = *(asQWORD*)&args[spos];
// Double arguments are moved to a separate buffer in order to be placed in the XMM registers,
// though this is only done for first 4 arguments, the rest are placed on the stack
if( paramSize < 4 && descr->parameterTypes[n].IsDoubleType() )
if( paramSize < 4 && dt.IsDoubleType() )
floatArgBuffer[dpos] = *(asQWORD*)&args[spos];
dpos++;
@@ -153,7 +169,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
// Float arguments are moved to a separate buffer in order to be placed in the XMM registers,
// though this is only done for first 4 arguments, the rest are placed on the stack
if( paramSize < 4 && descr->parameterTypes[n].IsFloatType() )
if( paramSize < 4 && dt.IsFloatType() )
floatArgBuffer[dpos] = args[spos];
dpos++;
@@ -170,6 +186,14 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
// Add the object pointer as the last parameter
allArgBuffer[paramSize++] = (asQWORD)obj;
}
else if( callConv == ICC_THISCALL_OBJLAST ||
callConv == ICC_THISCALL_OBJLAST_RETURNINMEM ||
callConv == ICC_VIRTUAL_THISCALL_OBJLAST ||
callConv == ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM )
{
// Add the object pointer as the last parameter
allArgBuffer[paramSize++] = (asQWORD)secondObject;
}
retQW = CallX64(allArgBuffer, floatArgBuffer, paramSize*8, (asPWORD)func);
+42 -7
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -34,6 +34,8 @@
//
// These functions handle the actual calling of system functions
//
// Added support for functor methods by Jordi Oliveras Rovira in April, 2014.
//
@@ -87,7 +89,7 @@ asQWORD CallThisCallFunctionRetByRef(const void *, const asDWORD *, int, asFUNCT
asDWORD GetReturnedFloat();
asQWORD GetReturnedDouble();
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/)
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/, void *secondObject)
{
asCScriptEngine *engine = context->m_engine;
asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
@@ -95,13 +97,30 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
asQWORD retQW = 0;
// Prepare the parameters
int paramSize = sysFunc->paramSize;
asDWORD paramBuffer[64];
if( sysFunc->takesObjByVal )
int callConv = sysFunc->callConv;
// Changed because need check for ICC_THISCALL_OBJFIRST or
// ICC_THISCALL_OBJLAST if sysFunc->takesObjByVal (avoid copy code)
// Check if is THISCALL_OBJ* calling convention (in this case needs to add secondObject pointer into stack).
bool isThisCallMethod = callConv >= ICC_THISCALL_OBJLAST;
int paramSize = isThisCallMethod || sysFunc->takesObjByVal ? 0 : sysFunc->paramSize;
int dpos = 1;
if( isThisCallMethod &&
(callConv >= ICC_THISCALL_OBJFIRST &&
callConv <= ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM) )
{
// Add the object pointer as the first parameter
paramBuffer[dpos++] = (asDWORD)secondObject;
paramSize++;
}
if( sysFunc->takesObjByVal || isThisCallMethod )
{
paramSize = 0;
int spos = 0;
int dpos = 1;
for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ )
{
if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() )
@@ -146,9 +165,17 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
args = &paramBuffer[1];
}
if( isThisCallMethod &&
(callConv >= ICC_THISCALL_OBJLAST &&
callConv <= ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM) )
{
// Add the object pointer as the last parameter
paramBuffer[dpos++] = (asDWORD)secondObject;
paramSize++;
}
// Make the actual call
asFUNCTION_t func = sysFunc->func;
int callConv = sysFunc->callConv;
if( sysFunc->hostReturnInMemory )
callConv++;
@@ -176,14 +203,20 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
break;
case ICC_THISCALL:
case ICC_THISCALL_OBJFIRST:
case ICC_THISCALL_OBJLAST:
retQW = CallThisCallFunction(obj, args, paramSize<<2, func);
break;
case ICC_THISCALL_RETURNINMEM:
case ICC_THISCALL_OBJFIRST_RETURNINMEM:
case ICC_THISCALL_OBJLAST_RETURNINMEM:
retQW = CallThisCallFunctionRetByRef(obj, args, paramSize<<2, func, retPointer);
break;
case ICC_VIRTUAL_THISCALL:
case ICC_VIRTUAL_THISCALL_OBJFIRST:
case ICC_VIRTUAL_THISCALL_OBJLAST:
{
// Get virtual function table from the object pointer
asFUNCTION_t *vftable = *(asFUNCTION_t**)obj;
@@ -192,6 +225,8 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
break;
case ICC_VIRTUAL_THISCALL_RETURNINMEM:
case ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM:
case ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM:
{
// Get virtual function table from the object pointer
asFUNCTION_t *vftable = *(asFUNCTION_t**)obj;
+4 -2
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -498,8 +498,10 @@ inline bool IsVariableArgument( asCDataType type )
return (type.GetTokenType() == ttQuestion) ? true : false;
}
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/)
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/, void */*secondObject*/)
{
// TODO: Xenon does not yet support THISCALL_OBJFIRST/LAST
asCScriptEngine *engine = context->m_engine;
asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
int callConv = sysFunc->callConv;
File diff suppressed because it is too large Load Diff
+30 -17
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -103,6 +103,7 @@ struct asSExprContext
property_handle = false;
property_ref = false;
methodName = "";
enumValue = "";
}
bool IsClassMethod()
{
@@ -143,6 +144,13 @@ struct asSOverloadCandidate
asUINT cost;
};
struct asSNamedArgument
{
asCString name;
asSExprContext *ctx;
asUINT match;
};
enum EImplicitConv
{
asIC_IMPLICIT_CONV,
@@ -206,31 +214,34 @@ protected:
int CompileFunctionCall(asCScriptNode *node, asSExprContext *out, asCObjectType *objectType, bool objIsConst, const asCString &scope = "");
void CompileConstructCall(asCScriptNode *node, asSExprContext *out);
void CompileConversion(asCScriptNode *node, asSExprContext *out);
int CompileOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out);
void CompileOperatorOnHandles(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out);
void CompileMathOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out);
void CompileBitwiseOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out);
void CompileComparisonOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out);
void CompileBooleanOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out);
bool CompileOverloadedDualOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out);
int CompileOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
void CompileOperatorOnHandles(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
void CompileMathOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
void CompileBitwiseOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
void CompileComparisonOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
void CompileBooleanOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
bool CompileOverloadedDualOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, bool isHandle = false, eTokenType opToken = ttUnrecognizedToken);
int CompileOverloadedDualOperator2(asCScriptNode *node, const char *methodName, asSExprContext *l, asSExprContext *r, asSExprContext *out, bool specificReturn = false, const asCDataType &returnType = asCDataType::CreatePrimitive(ttVoid, false));
void CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByteCode *bc, int isVarGlobOrMem);
int CompileInitListElement(asSListPatternNode *&patternNode, asCScriptNode *&valueNode, int bufferTypeId, short bufferVar, asUINT &bufferSize, asCByteCode &byteCode);
int CompileInitListElement(asSListPatternNode *&patternNode, asCScriptNode *&valueNode, int bufferTypeId, short bufferVar, asUINT &bufferSize, asCByteCode &byteCode, int &elementsInSubList);
int CallDefaultConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asCScriptNode *node, int isVarGlobOrMem = 0, bool derefDest = false);
int CallDefaultConstructor(const asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asCScriptNode *node, int isVarGlobOrMem = 0, bool derefDest = false);
int CallCopyConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asSExprContext *arg, asCScriptNode *node, bool isGlobalVar = false, bool derefDestination = false);
void CallDestructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc);
int CompileArgumentList(asCScriptNode *node, asCArray<asSExprContext *> &args);
int CompileDefaultArgs(asCScriptNode *node, asCArray<asSExprContext*> &args, asCScriptFunction *func);
asUINT MatchFunctions(asCArray<int> &funcs, asCArray<asSExprContext*> &args, asCScriptNode *node, const char *name, asCObjectType *objectType = NULL, bool isConstMethod = false, bool silent = false, bool allowObjectConstruct = true, const asCString &scope = "");
int CompileArgumentList(asCScriptNode *node, asCArray<asSExprContext *> &args, asCArray<asSNamedArgument> &namedArgs);
int CompileDefaultAndNamedArgs(asCScriptNode *node, asCArray<asSExprContext*> &args, int funcId, asCObjectType *type, asCArray<asSNamedArgument> *namedArgs = 0);
asUINT MatchFunctions(asCArray<int> &funcs, asCArray<asSExprContext*> &args, asCScriptNode *node, const char *name, asCArray<asSNamedArgument> *namedArgs = NULL, asCObjectType *objectType = NULL, bool isConstMethod = false, bool silent = false, bool allowObjectConstruct = true, const asCString &scope = "");
int CompileVariableAccess(const asCString &name, const asCString &scope, asSExprContext *ctx, asCScriptNode *errNode, bool isOptional = false, bool noFunction = false, bool noGlobal = false, asCObjectType *objType = 0);
void CompileMemberInitialization(asCByteCode *bc, bool onlyDefaults);
bool CompileInitialization(asCScriptNode *node, asCByteCode *bc, asCDataType &type, asCScriptNode *errNode, int offset, asQWORD *constantValue, int isVarGlobOrMem);
bool CompileAutoType(asCDataType &autoType, asSExprContext &compiledCtx, asCScriptNode *exprNode, asCScriptNode *errNode);
bool CompileInitialization(asCScriptNode *node, asCByteCode *bc, asCDataType &type, asCScriptNode *errNode, int offset, asQWORD *constantValue, int isVarGlobOrMem, asSExprContext *preCompiled = 0);
void CompileInitAsCopy(asCDataType &type, int offset, asCByteCode *bc, asSExprContext *arg, asCScriptNode *node, bool derefDestination);
// Helper functions
void ProcessPropertyGetAccessor(asSExprContext *ctx, asCScriptNode *node);
int ProcessPropertySetAccessor(asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node);
int ProcessPropertyGetSetAccessor(asSExprContext *ctx, asSExprContext *lctx, asSExprContext *rctx, eTokenType op, asCScriptNode *errNode);
int FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asCScriptNode *node, asSNameSpace *ns, bool isThisAccess = false);
int FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node, asSNameSpace *ns, bool isThisAccess = false);
void PrepareTemporaryObject(asCScriptNode *node, asSExprContext *ctx, bool forceOnHeap = false);
@@ -241,16 +252,17 @@ protected:
void Dereference(asSExprContext *ctx, bool generateCode);
bool CompileRefCast(asSExprContext *ctx, const asCDataType &to, bool isExplicit, asCScriptNode *node, bool generateCode = true);
asUINT MatchArgument(asCArray<int> &funcs, asCArray<asSOverloadCandidate> &matches, const asSExprContext *argExpr, int paramNum, bool allowObjectConstruct = true);
int MatchArgument(asCScriptFunction *desc, const asSExprContext *argExpr, int paramNum, bool allowObjectConstruct = true);
void PerformFunctionCall(int funcId, asSExprContext *out, bool isConstructor = false, asCArray<asSExprContext*> *args = 0, asCObjectType *objTypeForConstruct = 0, bool useVariable = false, int varOffset = 0, int funcPtrVar = 0);
void MoveArgsToStack(int funcId, asCByteCode *bc, asCArray<asSExprContext *> &args, bool addOneToOffset);
void MakeFunctionCall(asSExprContext *ctx, int funcId, asCObjectType *objectType, asCArray<asSExprContext*> &args, asCScriptNode *node, bool useVariable = false, int stackOffset = 0, int funcPtrVar = 0);
void PrepareFunctionCall(int funcId, asCByteCode *bc, asCArray<asSExprContext *> &args);
void AfterFunctionCall(int funcId, asCArray<asSExprContext*> &args, asSExprContext *ctx, bool deferAll);
void ProcessDeferredParams(asSExprContext *ctx);
void PrepareArgument(asCDataType *paramType, asSExprContext *ctx, asCScriptNode *node, bool isFunction = false, int refType = 0, bool isMakingCopy = false);
int PrepareArgument(asCDataType *paramType, asSExprContext *ctx, asCScriptNode *node, bool isFunction = false, int refType = 0, bool isMakingCopy = false);
void PrepareArgument2(asSExprContext *ctx, asSExprContext *arg, asCDataType *paramType, bool isFunction = false, int refType = 0, bool isMakingCopy = false);
bool IsLValue(asCTypeInfo &type);
int DoAssignment(asSExprContext *out, asSExprContext *lctx, asSExprContext *rctx, asCScriptNode *lexpr, asCScriptNode *rexpr, int op, asCScriptNode *opNode);
int DoAssignment(asSExprContext *out, asSExprContext *lctx, asSExprContext *rctx, asCScriptNode *lexpr, asCScriptNode *rexpr, eTokenType op, asCScriptNode *opNode);
void MergeExprBytecode(asSExprContext *before, asSExprContext *after);
void MergeExprBytecodeAndType(asSExprContext *before, asSExprContext *after);
void FilterConst(asCArray<int> &funcs, bool removeConst = true);
@@ -275,6 +287,7 @@ protected:
asUINT ImplicitConvObjectRef(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode);
asUINT ImplicitConvObjectValue(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode);
void ImplicitConversionConstant(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType);
void ImplicitConvObjectToBestMathType(asSExprContext *ctx, asCScriptNode *node);
void LineInstr(asCByteCode *bc, size_t pos);
@@ -284,7 +297,7 @@ protected:
void Error(const asCString &msg, asCScriptNode *node);
void Warning(const asCString &msg, asCScriptNode *node);
void Information(const asCString &msg, asCScriptNode *node);
void PrintMatchingFuncs(asCArray<int> &funcs, asCScriptNode *node);
void PrintMatchingFuncs(asCArray<int> &funcs, asCScriptNode *node, asCObjectType *inType = 0);
void AddVariableScope(bool isBreakScope = false, bool isContinueScope = false);
void RemoveVariableScope();
void FinalizeFunction();
+159 -58
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2014 Andreas Jonsson
Copyright (c) 2003-2015 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -101,6 +101,10 @@
// if the new order of the member initialization caused null pointer exceptions in older
// scripts (e.g. if a base class accessed members of a derived class through a virtual method).
// AS_USE_NAMESPACE
// Adds the AngelScript namespace on the declarations.
//
// Library usage
@@ -140,12 +144,12 @@
// STDCALL
// This is used to declare a function to use the stdcall calling convention.
// AS_USE_NAMESPACE
// Adds the AngelScript namespace on the declarations.
// AS_NO_MEMORY_H
// Some compilers don't come with the memory.h header file.
// AS_NO_THISCALL_FUNCTOR_METHOD
// Defined if the support for functor methods hasn't been implemented on the platform.
//
@@ -166,6 +170,9 @@
// Embarcadero C++Builder
// __BORLANDC__ is defined
// Sun CC compiler
// __SUNPRO_CC is defined
//
@@ -213,6 +220,9 @@
// AS_BIG_ENDIAN
// Define this for CPUs that use big endian memory layout, e.g. PPC
// AS_SPARC
// Define this for SPARC CPU family
//
@@ -230,6 +240,7 @@
// AS_XBOX - Microsoft XBox
// AS_XBOX360 - Microsoft XBox 360
// AS_PSP - Sony Playstation Portable
// AS_PSVITA - Sony Playstation Vita
// AS_PS2 - Sony Playstation 2
// AS_PS3 - Sony Playstation 3
// AS_DC - Sega Dreamcast
@@ -241,6 +252,7 @@
// AS_HAIKU - Haiku
// AS_ILLUMOS - Illumos like (OpenSolaris, OpenIndiana, NCP, etc)
// AS_MARMALADE - Marmalade cross platform SDK (a layer on top of the OS)
// AS_SUN - Sun UNIX
@@ -339,6 +351,9 @@
#define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 0
#define THISCALL_CALLEE_POPS_HIDDEN_RETURN_POINTER
// Not implemented by default. Undefined with tested platforms.
#define AS_NO_THISCALL_FUNCTOR_METHOD
// Embarcadero C++Builder
#if defined(__BORLANDC__)
@@ -437,6 +452,7 @@
#define THISCALL_CALLEE_POPS_ARGUMENTS
#define STDCALL __stdcall
#define AS_SIZEOF_BOOL 1
#define COMPLEX_OBJS_PASSED_BY_REF
#define ASM_INTEL // Intel style for inline assembly on microsoft compilers
@@ -452,14 +468,18 @@
#else
#if defined(_XBOX) || (defined(_M_IX86) && !defined(__LP64__))
#define AS_X86
#ifndef _XBOX
// Not tested with xbox (only enabled if is Windows)
#undef AS_NO_THISCALL_FUNCTOR_METHOD
#endif
#elif defined(_M_X64)
#define AS_X64_MSVC
#undef AS_NO_THISCALL_FUNCTOR_METHOD
#define AS_CALLEE_DESTROY_OBJ_BY_VAL
#define AS_LARGE_OBJS_PASSED_BY_REF
#define AS_LARGE_OBJ_MIN_SIZE 3
#define COMPLEX_OBJS_PASSED_BY_REF
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_MASK (asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#define COMPLEX_MASK (asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#endif
#endif
@@ -468,18 +488,22 @@
#define AS_CALLEE_DESTROY_OBJ_BY_VAL
#define CDECL_RETURN_SIMPLE_IN_MEMORY
#define STDCALL_RETURN_SIMPLE_IN_MEMORY
#define COMPLEX_OBJS_PASSED_BY_REF
#define COMPLEX_MASK asOBJ_APP_CLASS_ASSIGNMENT
#define COMPLEX_RETURN_MASK asOBJ_APP_CLASS_ASSIGNMENT
#define AS_SOFTFP
#define COMPLEX_MASK (asOBJ_APP_CLASS_ASSIGNMENT | asOBJ_APP_ARRAY)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_ASSIGNMENT | asOBJ_APP_ARRAY)
// Windows CE uses softfp calling convention, while Windows RT uses hardfp calling convention
// ref: http://stackoverflow.com/questions/16375355/what-is-the-windows-rt-on-arm-native-code-calling-convention
#if defined(_WIN32_WCE)
#define AS_SOFTFP
#endif
#endif
#ifndef COMPLEX_MASK
#define COMPLEX_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT)
#define COMPLEX_MASK (asOBJ_APP_ARRAY)
#endif
#ifndef COMPLEX_RETURN_MASK
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT | asOBJ_APP_ARRAY)
#endif
#define UNREACHABLE_RETURN
@@ -511,13 +535,26 @@
// SN Systems ProDG
#if defined(__SNC__) || defined(SNSYS)
#define GNU_STYLE_VIRTUAL_METHOD
#define MULTI_BASE_OFFSET(x) (*((asDWORD*)(&x)+1))
#define CALLEE_POPS_HIDDEN_RETURN_POINTER
#define COMPLEX_OBJS_PASSED_BY_REF
#define ASM_AT_N_T // AT&T style inline assembly
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR)
#ifdef __psp2__
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define THISCALL_RETURN_SIMPLE_IN_MEMORY
#define CDECL_RETURN_SIMPLE_IN_MEMORY
#define STDCALL_RETURN_SIMPLE_IN_MEMORY
#define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
#define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
#define STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
#else
#define GNU_STYLE_VIRTUAL_METHOD
#define ASM_AT_N_T // AT&T style inline assembly
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR)
#endif
#define AS_SIZEOF_BOOL 1
#define asVSNPRINTF(a, b, c, d) vsnprintf(a, b, c, d)
@@ -541,11 +578,22 @@
// Support native calling conventions on PS3
#define AS_PS3
#define AS_PPC_64
#define AS_NO_MEMORY_H
#define AS_NO_EXCEPTIONS
#include <stdlib.h>
// PSP
#elif defined(__psp__)
#define AS_NO_MEMORY_H
#define AS_MIPS
#define AS_PSP
// PSVita
#elif defined(__psp2__)
#define AS_PSVITA
#define AS_ARM
#define AS_NO_MEMORY_H
#define AS_NO_EXCEPTIONS
#define AS_CALLEE_DESTROY_OBJ_BY_VAL
#undef AS_NO_THISCALL_FUNCTOR_METHOD
#endif
#define UNREACHABLE_RETURN
@@ -555,16 +603,12 @@
// Use the following command to determine predefined macros: echo . | g++ -dM -E -
#if (defined(__GNUC__) && !defined(__SNC__)) || defined(EPPC) || defined(__CYGWIN__) // JWC -- use this instead for Wii
#define GNU_STYLE_VIRTUAL_METHOD
#if !defined( __amd64__ )
#define MULTI_BASE_OFFSET(x) (*((asDWORD*)(&x)+1))
#else
#define MULTI_BASE_OFFSET(x) (*((asQWORD*)(&x)+1))
#endif
#define MULTI_BASE_OFFSET(x) (*((asPWORD*)(&x)+1))
#define asVSNPRINTF(a, b, c, d) vsnprintf(a, b, c, d)
#define CALLEE_POPS_HIDDEN_RETURN_POINTER
#define COMPLEX_OBJS_PASSED_BY_REF
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR)
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_ARRAY)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_ARRAY)
#define AS_NO_MEMORY_H
#define AS_SIZEOF_BOOL 1
#define STDCALL __attribute__((stdcall))
@@ -618,9 +662,9 @@
#undef GNU_STYLE_VIRTUAL_METHOD
#undef COMPLEX_MASK
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#undef COMPLEX_RETURN_MASK
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#define AS_CALLEE_DESTROY_OBJ_BY_VAL
#endif
@@ -651,6 +695,7 @@
#if (defined(_ARM_) || defined(__arm__))
// iOS use ARM processor
#define AS_ARM
#undef AS_NO_THISCALL_FUNCTOR_METHOD
#define CDECL_RETURN_SIMPLE_IN_MEMORY
#define STDCALL_RETURN_SIMPLE_IN_MEMORY
#define THISCALL_RETURN_SIMPLE_IN_MEMORY
@@ -666,9 +711,9 @@
#define STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
#define COMPLEX_OBJS_PASSED_BY_REF
#undef COMPLEX_MASK
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#undef COMPLEX_RETURN_MASK
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
// iOS uses soft-float ABI
#define AS_SOFTFP
@@ -679,8 +724,8 @@
#elif (defined(__arm64__))
// The IPhone 5S+ uses an ARM64 processor
// AngelScript currently doesn't support native calling
// AngelScript currently doesn't support native calling
// for 64bit ARM processors so it's necessary to turn on
// portability mode
#define AS_MAX_PORTABILITY
@@ -692,21 +737,23 @@
#elif (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__)
// Support native calling conventions on Mac OS X + Intel 32bit CPU
#define AS_X86
#undef AS_NO_THISCALL_FUNCTOR_METHOD
#define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK
#undef COMPLEX_MASK
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#undef COMPLEX_RETURN_MASK
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#elif defined(__LP64__) && !defined(__ppc__) && !defined(__PPC__) && !defined(__arm64__)
// http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/LowLevelABI/140-x86-64_Function_Calling_Conventions/x86_64.html#//apple_ref/doc/uid/TP40005035-SW1
#define AS_X64_GCC
#undef AS_NO_THISCALL_FUNCTOR_METHOD
#define HAS_128_BIT_PRIMITIVES
#define SPLIT_OBJS_BY_MEMBER_TYPES
#undef COMPLEX_MASK
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#undef COMPLEX_RETURN_MASK
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#define AS_LARGE_OBJS_PASSED_BY_REF
#define AS_LARGE_OBJ_MIN_SIZE 5
// STDCALL is not available on 64bit Mac
@@ -720,9 +767,9 @@
#define CDECL_RETURN_SIMPLE_IN_MEMORY
#define STDCALL_RETURN_SIMPLE_IN_MEMORY
#undef COMPLEX_MASK
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#undef COMPLEX_RETURN_MASK
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#elif (defined(__ppc__) || defined(__PPC__)) && defined(__LP64__)
#define AS_PPC_64
@@ -740,13 +787,14 @@
//#define STDCALL_RETURN_SIMPLE_IN_MEMORY
#undef COMPLEX_MASK
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#undef COMPLEX_RETURN_MASK
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#if (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__)
// Support native calling conventions on Intel 32bit CPU
#define AS_X86
#undef AS_NO_THISCALL_FUNCTOR_METHOD
// As of version 4.7 MinGW changed the ABI, presumably
// to be better aligned with how MSVC works
@@ -760,6 +808,7 @@
#elif defined(__x86_64__)
#define AS_X64_MINGW
#undef AS_NO_THISCALL_FUNCTOR_METHOD
#define AS_LARGE_OBJS_PASSED_BY_REF
#define AS_LARGE_OBJ_MIN_SIZE 3
#define COMPLEX_OBJS_PASSED_BY_REF
@@ -773,9 +822,9 @@
#elif defined(__linux__) && !defined(ANDROID) && !defined(__ANDROID__)
#undef COMPLEX_MASK
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#undef COMPLEX_RETURN_MASK
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#if (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__)
#define THISCALL_RETURN_SIMPLE_IN_MEMORY
@@ -785,8 +834,10 @@
// Support native calling conventions on Intel 32bit CPU
#define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK
#define AS_X86
#undef AS_NO_THISCALL_FUNCTOR_METHOD
#elif defined(__LP64__) && !defined(__arm64__)
#define AS_X64_GCC
#undef AS_NO_THISCALL_FUNCTOR_METHOD
#define HAS_128_BIT_PRIMITIVES
#define SPLIT_OBJS_BY_MEMBER_TYPES
#define AS_LARGE_OBJS_PASSED_BY_REF
@@ -797,6 +848,9 @@
#elif defined(__ARMEL__) || defined(__arm__)
#define AS_ARM
// TODO: The stack unwind on exceptions currently fails due to the assembler code in as_callfunc_arm_gcc.S
#define AS_NO_EXCEPTIONS
#undef STDCALL
#define STDCALL
@@ -822,9 +876,12 @@
// Verify if soft-float or hard-float ABI is used
#if defined(__SOFTFP__) && __SOFTFP__ == 1
// -ffloat-abi=softfp or -ffloat-abi=soft
#define AS_SOFTFP
#define AS_SOFTFP
#endif
// Tested with both hard float and soft float abi
#undef AS_NO_THISCALL_FUNCTOR_METHOD
#elif defined(__mips__)
#define AS_MIPS
#define AS_BIG_ENDIAN
@@ -848,9 +905,9 @@
#define AS_BSD
#if (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__)
#undef COMPLEX_MASK
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#undef COMPLEX_RETURN_MASK
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK
#define AS_X86
#elif defined(__LP64__)
@@ -858,9 +915,9 @@
#define HAS_128_BIT_PRIMITIVES
#define SPLIT_OBJS_BY_MEMBER_TYPES
#undef COMPLEX_MASK
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#undef COMPLEX_RETURN_MASK
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#define AS_LARGE_OBJS_PASSED_BY_REF
#define AS_LARGE_OBJ_MIN_SIZE 5
#undef STDCALL
@@ -915,36 +972,47 @@
#elif defined(ANDROID) || defined(__ANDROID__)
#define AS_ANDROID
// Android NDK 9+ supports posix threads
// Android 2.3+ supports posix threads
#define AS_POSIX_THREADS
// Common configuration with Android arm and x86
#define CDECL_RETURN_SIMPLE_IN_MEMORY
#define STDCALL_RETURN_SIMPLE_IN_MEMORY
#define THISCALL_RETURN_SIMPLE_IN_MEMORY
#undef THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
#undef CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
#undef STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
#define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
#define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
#define STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
#undef COMPLEX_MASK
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#undef COMPLEX_RETURN_MASK
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#if (defined(_ARM_) || defined(__arm__))
// Android ARM
#undef THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
#undef CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
#undef STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
#define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
#define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
#define STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2
// The stdcall calling convention is not used on the arm cpu
#undef STDCALL
#define STDCALL
#undef GNU_STYLE_VIRTUAL_METHOD
#undef COMPLEX_MASK
#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#undef COMPLEX_RETURN_MASK
#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
#define AS_ARM
#undef AS_NO_THISCALL_FUNCTOR_METHOD
#define AS_SOFTFP
#define AS_CALLEE_DESTROY_OBJ_BY_VAL
#elif (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__)
// Android Intel x86 (same config as Linux x86). Tested with Intel x86 Atom System Image.
// Support native calling conventions on Intel 32bit CPU
#define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK
#define AS_X86
#undef AS_NO_THISCALL_FUNCTOR_METHOD
#endif
// Haiku OS
@@ -1001,6 +1069,39 @@
#define UNREACHABLE_RETURN
#endif
// Sun CC
// Initial information provided by Andrey Bergman
#if defined(__SUNPRO_CC)
#if defined(__sparc)
#define AS_SPARC
#endif
#if defined(__sun)
#define AS_SUN
#endif
// Native calling conventions is not yet supported for Sun CC
#if !defined(AS_MAX_PORTABILITY)
#define AS_MAX_PORTABILITY
#endif
// I presume Sun CC uses a similar structure of method pointers as gnuc
#define MULTI_BASE_OFFSET(x) (*((asPWORD*)(&x)+1))
#if !defined(AS_SIZEOF_BOOL)
#define AS_SIZEOF_BOOL 1 // sizeof(bool) == 1
#endif
#if !defined(UNREACHABLE_RETURN)
#define UNREACHABLE_RETURN
#endif
#if !defined(STDCALL)
#define STDCALL // There is no stdcall on Solaris/SunPro/SPARC
#endif
#if !defined(asVSNPRINTF)
#define asVSNPRINTF(a, b, c, d) vsnprintf(a, b, c, d)
#endif
#endif
//
// Detect target hardware
+31 -72
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -88,10 +88,29 @@ void asCConfigGroup::RefConfigGroup(asCConfigGroup *group)
group->AddRef();
}
void asCConfigGroup::AddReferencesForFunc(asCScriptEngine *engine, asCScriptFunction *func)
{
AddReferencesForType(engine, func->returnType.GetObjectType());
for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
AddReferencesForType(engine, func->parameterTypes[n].GetObjectType());
}
void asCConfigGroup::AddReferencesForType(asCScriptEngine *engine, asCObjectType *type)
{
if( type == 0 ) return;
// Keep reference to other groups
RefConfigGroup(engine->FindConfigGroupForObjectType(type));
// Keep track of which generated template instances the config group uses
if( type->flags & asOBJ_TEMPLATE && engine->generatedTemplateTypes.Exists(type) && !generatedTemplateInstances.Exists(type) )
generatedTemplateInstances.PushLast(type);
}
bool asCConfigGroup::HasLiveObjects()
{
for( asUINT n = 0; n < objTypes.GetLength(); n++ )
if( objTypes[n]->GetRefCount() != 0 )
if( objTypes[n]->externalRefCount.get() != 0 )
return true;
return false;
@@ -123,7 +142,7 @@ void asCConfigGroup::RemoveConfiguration(asCScriptEngine *engine, bool notUsed)
int index = engine->registeredGlobalFuncs.GetIndex(scriptFunctions[n]);
if( index >= 0 )
engine->registeredGlobalFuncs.Erase(index);
scriptFunctions[n]->Release();
scriptFunctions[n]->ReleaseInternal();
if( engine->stringFactory == scriptFunctions[n] )
engine->stringFactory = 0;
}
@@ -141,27 +160,24 @@ void asCConfigGroup::RemoveConfiguration(asCScriptEngine *engine, bool notUsed)
for( n = 0; n < funcDefs.GetLength(); n++ )
{
engine->registeredFuncDefs.RemoveValue(funcDefs[n]);
funcDefs[n]->Release();
funcDefs[n]->ReleaseInternal();
engine->RemoveFuncdef(funcDefs[n]);
funcDefs[n]->ReleaseInternal();
}
funcDefs.SetLength(0);
engine->ClearUnusedTypes();
// Remove object types (skip this if it is possible other groups are still using the types)
if( !notUsed )
{
for( n = 0; n < objTypes.GetLength(); n++ )
for( n = asUINT(objTypes.GetLength()); n-- > 0; )
{
asCObjectType *t = objTypes[n];
asSMapNode<asSNameSpaceNamePair, asCObjectType*> *cursor;
if( engine->allRegisteredTypes.MoveTo(&cursor, asSNameSpaceNamePair(t->nameSpace, t->name)) &&
cursor->value == t )
{
#ifdef AS_DEBUG
ValidateNoUsage(engine, t);
#endif
engine->allRegisteredTypes.Erase(cursor);
if( engine->defaultArrayObjectType == t )
engine->defaultArrayObjectType = 0;
@@ -174,21 +190,17 @@ void asCConfigGroup::RemoveConfiguration(asCScriptEngine *engine, bool notUsed)
else
engine->registeredObjTypes.RemoveValue(t);
asDELETE(t, asCObjectType);
t->DestroyInternal();
t->ReleaseInternal();
}
else
{
int idx = engine->templateInstanceTypes.IndexOf(t);
if( idx >= 0 )
{
#ifdef AS_DEBUG
ValidateNoUsage(engine, t);
#endif
engine->templateInstanceTypes.RemoveIndexUnordered(idx);
t->templateSubTypes.SetLength(0);
asDELETE(t, asCObjectType);
t->DestroyInternal();
t->ReleaseInternal();
}
}
}
@@ -201,57 +213,4 @@ void asCConfigGroup::RemoveConfiguration(asCScriptEngine *engine, bool notUsed)
referencedConfigGroups.SetLength(0);
}
#ifdef AS_DEBUG
void asCConfigGroup::ValidateNoUsage(asCScriptEngine *engine, asCObjectType *type)
{
for( asUINT n = 0; n < engine->scriptFunctions.GetLength(); n++ )
{
asCScriptFunction *func = engine->scriptFunctions[n];
if( func == 0 ) continue;
// Ignore factory, list factory, and members
if( func->name == "_beh_3_" || func->name == "_beh_4_" || func->objectType == type )
continue;
// Ignore function definitions too, as they aren't released until the engine is destroyed
if( func->funcType == asFUNC_FUNCDEF )
continue;
// Ignore functions whose object type has already reached refCount 0 as they are to be removed
if( func->objectType && func->objectType->GetRefCount() == 0 )
continue;
if( func->returnType.GetObjectType() == type )
{
asCString msg;
// We can only use the function name here, because the types used by the function may have been deleted already
msg.Format(TXT_TYPE_s_IS_STILL_USED_BY_FUNC_s, type->name.AddressOf(), func->GetDeclaration());
engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, msg.AddressOf());
}
else
{
for( asUINT p = 0; p < func->parameterTypes.GetLength(); p++ )
{
if( func->parameterTypes[p].GetObjectType() == type )
{
asCString msg;
// We can only use the function name here, because the types used by the function may have been deleted already
msg.Format(TXT_TYPE_s_IS_STILL_USED_BY_FUNC_s, type->name.AddressOf(), func->GetDeclaration());
engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, msg.AddressOf());
break;
}
}
}
}
// TODO: Check also usage of the type in global variables
// TODO: Check also usage of the type in local variables in script functions
// TODO: Check also usage of the type as members of classes
// TODO: Check also usage of the type as sub types in other types
}
#endif
END_AS_NAMESPACE
+7 -4
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2012 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -63,9 +63,8 @@ public:
bool HasLiveObjects();
void RemoveConfiguration(asCScriptEngine *engine, bool notUsed = false);
#ifdef AS_DEBUG
void ValidateNoUsage(asCScriptEngine *engine, asCObjectType *type);
#endif
void AddReferencesForFunc(asCScriptEngine *engine, asCScriptFunction *func);
void AddReferencesForType(asCScriptEngine *engine, asCObjectType *type);
asCString groupName;
int refCount;
@@ -75,6 +74,10 @@ public:
asCArray<asCGlobalProperty*> globalProps;
asCArray<asCConfigGroup*> referencedConfigGroups;
asCArray<asCScriptFunction*> funcDefs;
// This array holds the generated template instances that are used
// by the config group as part of function signature or property
asCArray<asCObjectType*> generatedTemplateInstances;
};
END_AS_NAMESPACE
+295 -110
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2014 Andreas Jonsson
Copyright (c) 2003-2015 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -61,7 +61,6 @@ const int RESERVE_STACK = 2*AS_PTR_SIZE;
// For each script function call we push 9 PTRs on the call stack
const int CALLSTACK_FRAME_SIZE = 9;
#if defined(AS_DEBUG)
class asCDebugStats
@@ -254,15 +253,27 @@ void asCContext::DetachEngine()
{
if( m_stackBlocks[n] )
{
#ifndef WIP_16BYTE_ALIGN
asDELETEARRAY(m_stackBlocks[n]);
#else
asDELETEARRAYALIGNED(m_stackBlocks[n]);
#endif
}
}
m_stackBlocks.SetLength(0);
m_stackBlockSize = 0;
// Clean the user data
if( m_userData && m_engine->cleanContextFunc )
m_engine->cleanContextFunc(this);
for( asUINT n = 0; n < m_userData.GetLength(); n += 2 )
{
if( m_userData[n+1] )
{
for( asUINT c = 0; c < m_engine->cleanContextFuncs.GetLength(); c++ )
if( m_engine->cleanContextFuncs[c].type == m_userData[n] )
m_engine->cleanContextFuncs[c].cleanFunc(this);
}
}
m_userData.SetLength(0);
// Clear engine pointer
if( m_holdEngineRef )
@@ -277,17 +288,55 @@ asIScriptEngine *asCContext::GetEngine() const
}
// interface
void *asCContext::SetUserData(void *data)
void *asCContext::SetUserData(void *data, asPWORD type)
{
void *oldData = m_userData;
m_userData = data;
return oldData;
// As a thread might add a new new user data at the same time as another
// it is necessary to protect both read and write access to the userData member
ACQUIREEXCLUSIVE(m_engine->engineRWLock);
// It is not intended to store a lot of different types of userdata,
// so a more complex structure like a associative map would just have
// more overhead than a simple array.
for( asUINT n = 0; n < m_userData.GetLength(); n += 2 )
{
if( m_userData[n] == type )
{
void *oldData = reinterpret_cast<void*>(m_userData[n+1]);
m_userData[n+1] = reinterpret_cast<asPWORD>(data);
RELEASEEXCLUSIVE(m_engine->engineRWLock);
return oldData;
}
}
m_userData.PushLast(type);
m_userData.PushLast(reinterpret_cast<asPWORD>(data));
RELEASEEXCLUSIVE(m_engine->engineRWLock);
return 0;
}
// interface
void *asCContext::GetUserData() const
void *asCContext::GetUserData(asPWORD type) const
{
return m_userData;
// There may be multiple threads reading, but when
// setting the user data nobody must be reading.
ACQUIRESHARED(m_engine->engineRWLock);
for( asUINT n = 0; n < m_userData.GetLength(); n += 2 )
{
if( m_userData[n] == type )
{
RELEASESHARED(m_engine->engineRWLock);
return reinterpret_cast<void*>(m_userData[n+1]);
}
}
RELEASESHARED(m_engine->engineRWLock);
return 0;
}
// interface
@@ -322,6 +371,16 @@ int asCContext::Prepare(asIScriptFunction *func)
// Release the returned object (if any)
CleanReturnObject();
// Release the object if it is a script object
if( m_initialFunction && m_initialFunction->objectType && (m_initialFunction->objectType->flags & asOBJ_SCRIPT_OBJECT) )
{
asCScriptObject *obj = *(asCScriptObject**)&m_regs.stackFramePointer[0];
if( obj )
obj->Release();
*(asPWORD*)&m_regs.stackFramePointer[0] = 0;
}
if( m_initialFunction && m_initialFunction == func )
{
// If the same function is executed again, we can skip a lot of the setup
@@ -437,6 +496,14 @@ int asCContext::Unprepare()
// Release the returned object (if any)
CleanReturnObject();
// Release the object if it is a script object
if( m_initialFunction && m_initialFunction->objectType && (m_initialFunction->objectType->flags & asOBJ_SCRIPT_OBJECT) )
{
asCScriptObject *obj = *(asCScriptObject**)&m_regs.stackFramePointer[0];
if( obj )
obj->Release();
}
// Release the initial function
if( m_initialFunction )
{
@@ -624,8 +691,15 @@ int asCContext::SetObject(void *obj)
return asERROR;
}
asASSERT( *(asPWORD*)&m_regs.stackFramePointer[0] == 0 );
*(asPWORD*)&m_regs.stackFramePointer[0] = (asPWORD)obj;
// TODO: This should be optional by having a flag where the application can chose whether it should be done or not
// The flag could be named something like takeOwnership and have default value of true
if( obj && (m_initialFunction->objectType->flags & asOBJ_SCRIPT_OBJECT) )
reinterpret_cast<asCScriptObject*>(obj)->AddRef();
return 0;
}
@@ -977,6 +1051,44 @@ int asCContext::SetArgObject(asUINT arg, void *obj)
return 0;
}
int asCContext::SetArgVarType(asUINT arg, void *ptr, int typeId)
{
if( m_status != asEXECUTION_PREPARED )
return asCONTEXT_NOT_PREPARED;
if( arg >= (unsigned)m_initialFunction->parameterTypes.GetLength() )
{
m_status = asEXECUTION_ERROR;
return asINVALID_ARG;
}
// Verify the type of the argument
asCDataType *dt = &m_initialFunction->parameterTypes[arg];
if( dt->GetTokenType() != ttQuestion )
{
m_status = asEXECUTION_ERROR;
return asINVALID_TYPE;
}
// Determine the position of the argument
int offset = 0;
if( m_initialFunction->objectType )
offset += AS_PTR_SIZE;
// If function returns object by value an extra pointer is pushed on the stack
if( m_returnValueSize )
offset += AS_PTR_SIZE;
for( asUINT n = 0; n < arg; n++ )
offset += m_initialFunction->parameterTypes[n].GetSizeOnStackDWords();
// Set the typeId and pointer
*(asPWORD*)(&m_regs.stackFramePointer[offset]) = (asPWORD)ptr;
offset += AS_PTR_SIZE;
*(int*)(&m_regs.stackFramePointer[offset]) = typeId;
return 0;
}
// TODO: Instead of GetAddressOfArg, maybe we need a SetArgValue(int arg, void *value, bool takeOwnership) instead.
@@ -1119,6 +1231,14 @@ int asCContext::Execute()
SetInternalException(TXT_NULL_POINTER_ACCESS);
}
}
else if( m_currentFunction->funcType == asFUNC_IMPORTED )
{
int funcId = m_engine->importedFunctions[m_currentFunction->id & ~FUNC_IMPORTED]->boundFunctionId;
if( funcId > 0 )
m_currentFunction = m_engine->scriptFunctions[funcId];
else
SetInternalException(TXT_UNBOUND_FUNCTION);
}
if( m_currentFunction->funcType == asFUNC_SCRIPT )
{
@@ -1132,7 +1252,7 @@ int asCContext::Execute()
// The current function is an application registered function
// Call the function directly
CallSystemFunction(m_currentFunction->id, this, 0);
CallSystemFunction(m_currentFunction->id, this);
// Was the call successful?
if( m_status == asEXECUTION_ACTIVE )
@@ -1174,13 +1294,12 @@ int asCContext::Execute()
if( gcPosObjects > gcPreObjects )
{
// Execute as many steps as there were new objects created
while( gcPosObjects-- > gcPreObjects )
m_engine->GarbageCollect(asGC_ONE_STEP | asGC_DESTROY_GARBAGE | asGC_DETECT_GARBAGE);
m_engine->GarbageCollect(asGC_ONE_STEP | asGC_DESTROY_GARBAGE | asGC_DETECT_GARBAGE, gcPosObjects - gcPreObjects);
}
else if( gcPosObjects > 0 )
{
// Execute at least one step, even if no new objects were created
m_engine->GarbageCollect(asGC_ONE_STEP | asGC_DESTROY_GARBAGE | asGC_DETECT_GARBAGE);
m_engine->GarbageCollect(asGC_ONE_STEP | asGC_DESTROY_GARBAGE | asGC_DETECT_GARBAGE, 1);
}
}
@@ -1430,22 +1549,46 @@ int asCContext::GetLineNumber(asUINT stackLevel, int *column, const char **secti
// internal
bool asCContext::ReserveStackSpace(asUINT size)
{
#ifdef WIP_16BYTE_ALIGN
// Pad size to a multiple of MAX_TYPE_ALIGNMENT.
const asUINT remainder = size % MAX_TYPE_ALIGNMENT;
if(remainder != 0)
{
size = size + (MAX_TYPE_ALIGNMENT - (size % MAX_TYPE_ALIGNMENT));
}
#endif
// Make sure the first stack block is allocated
if( m_stackBlocks.GetLength() == 0 )
{
m_stackBlockSize = m_engine->initialContextStackSize;
asASSERT( m_stackBlockSize > 0 );
#ifndef WIP_16BYTE_ALIGN
asDWORD *stack = asNEWARRAY(asDWORD,m_stackBlockSize);
#else
asDWORD *stack = asNEWARRAYALIGNED(asDWORD, m_stackBlockSize, MAX_TYPE_ALIGNMENT);
#endif
if( stack == 0 )
{
// Out of memory
return false;
}
#ifdef WIP_16BYTE_ALIGN
asASSERT( isAligned(stack, MAX_TYPE_ALIGNMENT) );
#endif
m_stackBlocks.PushLast(stack);
m_stackIndex = 0;
m_regs.stackPointer = m_stackBlocks[0] + m_stackBlockSize;
#ifdef WIP_16BYTE_ALIGN
// Align the stack pointer. This is necessary as the m_stackBlockSize is not necessarily evenly divisable with the max alignment
((asPWORD&)m_regs.stackPointer) &= ~(MAX_TYPE_ALIGNMENT-1);
asASSERT( isAligned(m_regs.stackPointer, MAX_TYPE_ALIGNMENT) );
#endif
}
// Check if there is enough space on the current stack block, otherwise move
@@ -1472,7 +1615,11 @@ bool asCContext::ReserveStackSpace(asUINT size)
if( m_stackBlocks.GetLength() == m_stackIndex )
{
// Allocate the new stack block, with twice the size of the previous
asDWORD *stack = asNEWARRAY(asDWORD,(m_stackBlockSize << m_stackIndex));
#ifndef WIP_16BYTE_ALIGN
asDWORD *stack = asNEWARRAY(asDWORD, (m_stackBlockSize << m_stackIndex));
#else
asDWORD *stack = asNEWARRAYALIGNED(asDWORD, (m_stackBlockSize << m_stackIndex), MAX_TYPE_ALIGNMENT);
#endif
if( stack == 0 )
{
// Out of memory
@@ -1484,6 +1631,11 @@ bool asCContext::ReserveStackSpace(asUINT size)
SetInternalException(TXT_STACK_OVERFLOW);
return false;
}
#ifdef WIP_16BYTE_ALIGN
asASSERT( isAligned(stack, MAX_TYPE_ALIGNMENT) );
#endif
m_stackBlocks.PushLast(stack);
}
@@ -1494,6 +1646,13 @@ bool asCContext::ReserveStackSpace(asUINT size)
m_currentFunction->GetSpaceNeededForArguments() -
(m_currentFunction->objectType ? AS_PTR_SIZE : 0) -
(m_currentFunction->DoesReturnOnStack() ? AS_PTR_SIZE : 0);
#ifdef WIP_16BYTE_ALIGN
// Align the stack pointer
(asPWORD&)m_regs.stackPointer &= ~(MAX_TYPE_ALIGNMENT-1);
asASSERT( isAligned(m_regs.stackPointer, MAX_TYPE_ALIGNMENT) );
#endif
}
return true;
@@ -1512,19 +1671,6 @@ void asCContext::CallScriptFunction(asCScriptFunction *func)
m_currentFunction = func;
m_regs.programPointer = m_currentFunction->scriptData->byteCode.AddressOf();
// Make sure there is space on the stack to execute the function
asDWORD *oldStackPointer = m_regs.stackPointer;
if( !ReserveStackSpace(func->scriptData->stackNeeded) )
return;
// If a new stack block was allocated then we'll need to move
// over the function arguments to the new block
if( m_regs.stackPointer != oldStackPointer )
{
int numDwords = func->GetSpaceNeededForArguments() + (func->objectType ? AS_PTR_SIZE : 0) + (func->DoesReturnOnStack() ? AS_PTR_SIZE : 0);
memcpy(m_regs.stackPointer, oldStackPointer, sizeof(asDWORD)*numDwords);
}
PrepareScriptFunction();
}
@@ -1532,6 +1678,21 @@ void asCContext::PrepareScriptFunction()
{
asASSERT( m_currentFunction->scriptData );
// Make sure there is space on the stack to execute the function
asDWORD *oldStackPointer = m_regs.stackPointer;
if( !ReserveStackSpace(m_currentFunction->scriptData->stackNeeded) )
return;
// If a new stack block was allocated then we'll need to move
// over the function arguments to the new block.
if( m_regs.stackPointer != oldStackPointer )
{
int numDwords = m_currentFunction->GetSpaceNeededForArguments() +
(m_currentFunction->objectType ? AS_PTR_SIZE : 0) +
(m_currentFunction->DoesReturnOnStack() ? AS_PTR_SIZE : 0);
memcpy(m_regs.stackPointer, oldStackPointer, sizeof(asDWORD)*numDwords);
}
// Update framepointer
m_regs.stackFramePointer = m_regs.stackPointer;
@@ -2329,7 +2490,7 @@ void asCContext::ExecuteNext()
m_regs.stackPointer = l_sp;
m_regs.stackFramePointer = l_fp;
l_sp += CallSystemFunction(i, this, 0);
l_sp += CallSystemFunction(i, this);
// Update the program position after the call so that line number is correct
l_bc += 2;
@@ -2361,9 +2522,9 @@ void asCContext::ExecuteNext()
case asBC_CALLBND:
{
// TODO: Clean-up: This code is very similar to asBC_CallPtr. Create a shared method for them
// Get the function ID from the stack
int i = asBC_INTARG(l_bc);
l_bc += 2;
asASSERT( i >= 0 );
asASSERT( i & FUNC_IMPORTED );
@@ -2376,6 +2537,9 @@ void asCContext::ExecuteNext()
int funcId = m_engine->importedFunctions[i & ~FUNC_IMPORTED]->boundFunctionId;
if( funcId == -1 )
{
// Need to update the program pointer for the exception handler
m_regs.programPointer += 2;
// Tell the exception handler to clean up the arguments to this function
m_needToCleanupArgs = true;
SetInternalException(TXT_UNBOUND_FUNCTION);
@@ -2384,8 +2548,46 @@ void asCContext::ExecuteNext()
else
{
asCScriptFunction *func = m_engine->GetScriptFunction(funcId);
if( func->funcType == asFUNC_SCRIPT )
{
m_regs.programPointer += 2;
CallScriptFunction(func);
}
else if( func->funcType == asFUNC_DELEGATE )
{
// Push the object pointer on the stack. There is always a reserved space for this so
// we don't don't need to worry about overflowing the allocated memory buffer
asASSERT( m_regs.stackPointer - AS_PTR_SIZE >= m_stackBlocks[m_stackIndex] );
m_regs.stackPointer -= AS_PTR_SIZE;
*(asPWORD*)m_regs.stackPointer = asPWORD(func->objForDelegate);
CallScriptFunction(func);
// Call the delegated method
if( func->funcForDelegate->funcType == asFUNC_SYSTEM )
{
m_regs.stackPointer += CallSystemFunction(func->funcForDelegate->id, this);
// Update program position after the call so the line number
// is correct in case the system function queries it
m_regs.programPointer += 2;
}
else
{
m_regs.programPointer += 2;
// TODO: run-time optimize: The true method could be figured out when creating the delegate
CallInterfaceMethod(func->funcForDelegate);
}
}
else
{
asASSERT( func->funcType == asFUNC_SYSTEM );
m_regs.stackPointer += CallSystemFunction(func->id, this);
// Update program position after the call so the line number
// is correct in case the system function queries it
m_regs.programPointer += 2;
}
}
// Extract the values from the context again
@@ -2476,13 +2678,17 @@ void asCContext::ExecuteNext()
if( func )
{
// Push the object pointer on the stack (it will be popped by the function)
l_sp -= AS_PTR_SIZE;
*(asPWORD*)l_sp = (asPWORD)mem;
// Need to move the values back to the context as the called functions
// may use the debug interface to inspect the registers
m_regs.programPointer = l_bc;
m_regs.stackPointer = l_sp;
m_regs.stackFramePointer = l_fp;
l_sp += CallSystemFunction(func, this, mem);
l_sp += CallSystemFunction(func, this);
}
// Pop the variable address from the stack
@@ -3352,7 +3558,7 @@ void asCContext::ExecuteNext()
break;
case asBC_u64TOf:
#if _MSC_VER <= 1200 // MSVC6
#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC6
{
// MSVC6 doesn't permit UINT64 to double
asINT64 v = *(asINT64*)(l_fp - asBC_SWORDARG1(l_bc));
@@ -3373,7 +3579,7 @@ void asCContext::ExecuteNext()
break;
case asBC_u64TOd:
#if _MSC_VER <= 1200 // MSVC6
#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC6
{
// MSVC6 doesn't permit UINT64 to double
asINT64 v = *(asINT64*)(l_fp - asBC_SWORDARG0(l_bc));
@@ -3655,7 +3861,7 @@ void asCContext::ExecuteNext()
// Call the delegated method
if( func->funcForDelegate->funcType == asFUNC_SYSTEM )
{
m_regs.stackPointer += CallSystemFunction(func->funcForDelegate->id, this, 0);
m_regs.stackPointer += CallSystemFunction(func->funcForDelegate->id, this);
// Update program position after the call so the line number
// is correct in case the system function queries it
@@ -3673,7 +3879,7 @@ void asCContext::ExecuteNext()
{
asASSERT( func->funcType == asFUNC_SYSTEM );
m_regs.stackPointer += CallSystemFunction(func->id, this, 0);
m_regs.stackPointer += CallSystemFunction(func->id, this);
// Update program position after the call so the line number
// is correct in case the system function queries it
@@ -3906,7 +4112,11 @@ void asCContext::ExecuteNext()
asUINT size = asBC_DWORDARG(l_bc);
asBYTE **var = (asBYTE**)(l_fp - asBC_SWORDARG0(l_bc));
#ifndef WIP_16BYTE_ALIGN
*var = asNEWARRAY(asBYTE, size);
#else
*var = asNEWARRAYALIGNED(asBYTE, size, MAX_TYPE_ALIGNMENT);
#endif
// Clear the buffer for the pointers that will be placed in it
memset(*var, 0, size);
@@ -4622,23 +4832,6 @@ void asCContext::CleanStackFrame()
}
}
}
// If the object is a script declared object, then we must release it
// as the compiler adds a reference at the entry of the function. Make sure
// the function has actually been entered
if( m_currentFunction->objectType && m_regs.programPointer != m_currentFunction->scriptData->byteCode.AddressOf() )
{
// Methods returning a reference or constructors don't add a reference
if( !m_currentFunction->returnType.IsReference() && m_currentFunction->name != m_currentFunction->objectType->name )
{
asSTypeBehaviour *beh = &m_currentFunction->objectType->beh;
if( beh->release && *(asPWORD*)&m_regs.stackFramePointer[0] != 0 )
{
m_engine->CallObjectMethod((void*)*(asPWORD*)&m_regs.stackFramePointer[0], beh->release);
*(asPWORD*)&m_regs.stackFramePointer[0] = 0;
}
}
}
}
else
m_isStackMemoryNotAllocated = false;
@@ -4729,13 +4922,14 @@ asEContextState asCContext::GetState() const
// interface
int asCContext::SetLineCallback(asSFuncPtr callback, void *obj, int callConv)
{
m_lineCallback = true;
m_regs.doProcessSuspend = true;
// First turn off the line callback to avoid a second thread
// attempting to call it while the new one is still being set
m_lineCallback = false;
m_lineCallbackObj = obj;
bool isObj = false;
if( (unsigned)callConv == asCALL_GENERIC )
if( (unsigned)callConv == asCALL_GENERIC || (unsigned)callConv == asCALL_THISCALL_OBJFIRST || (unsigned)callConv == asCALL_THISCALL_OBJLAST )
{
m_lineCallback = false;
m_regs.doProcessSuspend = m_doSuspend;
return asNOT_SUPPORTED;
}
@@ -4744,15 +4938,18 @@ int asCContext::SetLineCallback(asSFuncPtr callback, void *obj, int callConv)
isObj = true;
if( obj == 0 )
{
m_lineCallback = false;
m_regs.doProcessSuspend = m_doSuspend;
return asINVALID_ARG;
}
}
int r = DetectCallingConvention(isObj, callback, callConv, 0, &m_lineCallbackFunc);
if( r < 0 ) m_lineCallback = false;
// Turn on the line callback after setting both the function pointer and object pointer
if( r >= 0 ) m_lineCallback = true;
// The BC_SUSPEND instruction should be processed if either line
// callback is set or if the application has requested a suspension
m_regs.doProcessSuspend = m_doSuspend || m_lineCallback;
return r;
@@ -4772,7 +4969,7 @@ int asCContext::SetExceptionCallback(asSFuncPtr callback, void *obj, int callCon
m_exceptionCallback = true;
m_exceptionCallbackObj = obj;
bool isObj = false;
if( (unsigned)callConv == asCALL_GENERIC )
if( (unsigned)callConv == asCALL_GENERIC || (unsigned)callConv == asCALL_THISCALL_OBJFIRST || (unsigned)callConv == asCALL_THISCALL_OBJLAST )
return asNOT_SUPPORTED;
if( (unsigned)callConv >= asCALL_THISCALL )
{
@@ -4809,91 +5006,79 @@ void asCContext::ClearExceptionCallback()
m_exceptionCallback = false;
}
int asCContext::CallGeneric(int id, void *objectPointer)
int asCContext::CallGeneric(asCScriptFunction *descr)
{
asCScriptFunction *sysFunction = m_engine->scriptFunctions[id];
asSSystemFunctionInterface *sysFunc = sysFunction->sysFuncIntf;
asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
void (*func)(asIScriptGeneric*) = (void (*)(asIScriptGeneric*))sysFunc->func;
int popSize = sysFunc->paramSize;
asDWORD *args = m_regs.stackPointer;
// Verify the object pointer if it is a class method
void *currentObject = 0;
asASSERT( sysFunc->callConv == ICC_GENERIC_FUNC || sysFunc->callConv == ICC_GENERIC_METHOD );
if( sysFunc->callConv == ICC_GENERIC_METHOD )
{
if( objectPointer )
// The object pointer should be popped from the context stack
popSize += AS_PTR_SIZE;
// Check for null pointer
currentObject = (void*)*(asPWORD*)(args);
if( currentObject == 0 )
{
currentObject = objectPointer;
// Don't increase the reference of this pointer
// since it will not have been constructed yet
SetInternalException(TXT_NULL_POINTER_ACCESS);
return 0;
}
else
{
// The object pointer should be popped from the context stack
popSize += AS_PTR_SIZE;
// Check for null pointer
currentObject = (void*)*(asPWORD*)(args);
if( currentObject == 0 )
{
SetInternalException(TXT_NULL_POINTER_ACCESS);
return 0;
}
asASSERT( sysFunc->baseOffset == 0 );
// Add the base offset for multiple inheritance
currentObject = (void*)(asPWORD(currentObject) + sysFunc->baseOffset);
// Skip object pointer
args += AS_PTR_SIZE;
}
// Skip object pointer
args += AS_PTR_SIZE;
}
if( sysFunction->DoesReturnOnStack() )
if( descr->DoesReturnOnStack() )
{
// Skip the address where the return value will be stored
args += AS_PTR_SIZE;
popSize += AS_PTR_SIZE;
}
asCGeneric gen(m_engine, sysFunction, currentObject, args);
asCGeneric gen(m_engine, descr, currentObject, args);
m_callingSystemFunction = sysFunction;
m_callingSystemFunction = descr;
func(&gen);
m_callingSystemFunction = 0;
m_regs.valueRegister = gen.returnVal;
m_regs.objectRegister = gen.objectRegister;
m_regs.objectType = sysFunction->returnType.GetObjectType();
m_regs.objectType = descr->returnType.GetObjectType();
// Clean up function parameters
int offset = 0;
for( asUINT n = 0; n < sysFunction->parameterTypes.GetLength(); n++ )
// Clean up arguments
const asUINT cleanCount = sysFunc->cleanArgs.GetLength();
if( cleanCount )
{
if( sysFunction->parameterTypes[n].IsObject() && !sysFunction->parameterTypes[n].IsReference() )
asSSystemFunctionInterface::SClean *clean = sysFunc->cleanArgs.AddressOf();
for( asUINT n = 0; n < cleanCount; n++, clean++ )
{
void *obj = *(void**)&args[offset];
if( obj )
void **addr = (void**)&args[clean->off];
if( clean->op == 0 )
{
// Release the object
asSTypeBehaviour *beh = &sysFunction->parameterTypes[n].GetObjectType()->beh;
if( sysFunction->parameterTypes[n].GetObjectType()->flags & asOBJ_REF )
if( *addr != 0 )
{
asASSERT( (sysFunction->parameterTypes[n].GetObjectType()->flags & asOBJ_NOCOUNT) || beh->release );
if( beh->release )
m_engine->CallObjectMethod(obj, beh->release);
}
else
{
// Call the destructor then free the memory
if( beh->destruct )
m_engine->CallObjectMethod(obj, beh->destruct);
m_engine->CallFree(obj);
m_engine->CallObjectMethod(*addr, clean->ot->beh.release);
*addr = 0;
}
}
else
{
asASSERT( clean->op == 1 || clean->op == 2 );
asASSERT( *addr );
if( clean->op == 2 )
m_engine->CallObjectMethod(*addr, clean->ot->beh.destruct);
m_engine->CallFree(*addr);
}
}
offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
}
// Return how much should be popped from the stack
+13 -12
View File
@@ -76,14 +76,15 @@ public:
int SetObject(void *obj);
// Arguments
int SetArgByte(asUINT arg, asBYTE value);
int SetArgWord(asUINT arg, asWORD value);
int SetArgDWord(asUINT arg, asDWORD value);
int SetArgQWord(asUINT arg, asQWORD value);
int SetArgFloat(asUINT arg, float value);
int SetArgDouble(asUINT arg, double value);
int SetArgAddress(asUINT arg, void *addr);
int SetArgObject(asUINT arg, void *obj);
int SetArgByte(asUINT arg, asBYTE value);
int SetArgWord(asUINT arg, asWORD value);
int SetArgDWord(asUINT arg, asDWORD value);
int SetArgQWord(asUINT arg, asQWORD value);
int SetArgFloat(asUINT arg, float value);
int SetArgDouble(asUINT arg, double value);
int SetArgAddress(asUINT arg, void *addr);
int SetArgObject(asUINT arg, void *obj);
int SetArgVarType(asUINT arg, void *ptr, int typeId);
void *GetAddressOfArg(asUINT arg);
// Return value
@@ -122,8 +123,8 @@ public:
asIScriptFunction *GetSystemFunction();
// User data
void *SetUserData(void *data);
void *GetUserData() const;
void *SetUserData(void *data, asPWORD type);
void *GetUserData(asPWORD type) const;
public:
// Internal public functions
@@ -136,7 +137,7 @@ public:
void CallLineCallback();
void CallExceptionCallback();
int CallGeneric(int funcID, void *objectPointer);
int CallGeneric(asCScriptFunction *func);
void DetachEngine();
@@ -204,7 +205,7 @@ public:
asSSystemFunctionInterface m_exceptionCallbackFunc;
void * m_exceptionCallbackObj;
void *m_userData;
asCArray<asPWORD> m_userData;
// Registers available to JIT compiler functions
asSVMRegisters m_regs;
+155 -63
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2015 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -46,24 +46,28 @@ BEGIN_AS_NAMESPACE
asCDataType::asCDataType()
{
tokenType = ttUnrecognizedToken;
objectType = 0;
isReference = false;
isReadOnly = false;
isObjectHandle = false;
isConstHandle = false;
funcDef = 0;
tokenType = ttUnrecognizedToken;
objectType = 0;
isReference = false;
isReadOnly = false;
isAuto = false;
isObjectHandle = false;
isConstHandle = false;
funcDef = 0;
isHandleToAsHandleType = false;
}
asCDataType::asCDataType(const asCDataType &dt)
{
tokenType = dt.tokenType;
objectType = dt.objectType;
isReference = dt.isReference;
isReadOnly = dt.isReadOnly;
isObjectHandle = dt.isObjectHandle;
isConstHandle = dt.isConstHandle;
funcDef = dt.funcDef;
tokenType = dt.tokenType;
objectType = dt.objectType;
isReference = dt.isReference;
isReadOnly = dt.isReadOnly;
isAuto = dt.isAuto;
isObjectHandle = dt.isObjectHandle;
isConstHandle = dt.isConstHandle;
funcDef = dt.funcDef;
isHandleToAsHandleType = dt.isHandleToAsHandleType;
}
asCDataType::~asCDataType()
@@ -90,6 +94,17 @@ asCDataType asCDataType::CreateObject(asCObjectType *ot, bool isConst)
return dt;
}
asCDataType asCDataType::CreateAuto(bool isConst)
{
asCDataType dt;
dt.tokenType = ttIdentifier;
dt.isReadOnly = isConst;
dt.isAuto = true;
return dt;
}
asCDataType asCDataType::CreateObjectHandle(asCObjectType *ot, bool isConst)
{
asCDataType dt;
@@ -144,7 +159,7 @@ bool asCDataType::IsNullHandle() const
return false;
}
asCString asCDataType::Format(bool includeNamespace) const
asCString asCDataType::Format(asSNameSpace *currNs, bool includeNamespace) const
{
if( IsNullHandle() )
return "<null handle>";
@@ -154,11 +169,13 @@ asCString asCDataType::Format(bool includeNamespace) const
if( isReadOnly )
str = "const ";
if( includeNamespace )
// If the type is not declared in the current namespace, then the namespace
// must always be informed to guarantee that the correct type is informed
if( includeNamespace || (objectType && objectType->nameSpace != currNs) || (funcDef && funcDef->nameSpace != currNs) )
{
if( objectType )
if( objectType && objectType->nameSpace->name != "" )
str += objectType->nameSpace->name + "::";
else if( funcDef )
else if( funcDef && funcDef->nameSpace->name != "" )
str += funcDef->nameSpace->name + "::";
}
@@ -169,7 +186,7 @@ asCString asCDataType::Format(bool includeNamespace) const
else if( IsArrayType() && objectType && !objectType->engine->ep.expandDefaultArrayToTemplate )
{
asASSERT( objectType->templateSubTypes.GetLength() == 1 );
str += objectType->templateSubTypes[0].Format(includeNamespace);
str += objectType->templateSubTypes[0].Format(currNs, includeNamespace);
str += "[]";
}
else if( funcDef )
@@ -184,13 +201,20 @@ asCString asCDataType::Format(bool includeNamespace) const
str += "<";
for( asUINT subtypeIndex = 0; subtypeIndex < objectType->templateSubTypes.GetLength(); subtypeIndex++ )
{
str += objectType->templateSubTypes[subtypeIndex].Format(includeNamespace);
str += objectType->templateSubTypes[subtypeIndex].Format(currNs, includeNamespace);
if( subtypeIndex != objectType->templateSubTypes.GetLength()-1 )
str += ",";
}
str += ">";
}
}
else if( isAuto )
{
if( isObjectHandle )
str += "<auto@>";
else
str += "<auto>";
}
else
{
str = "<unknown>";
@@ -211,13 +235,15 @@ asCString asCDataType::Format(bool includeNamespace) const
asCDataType &asCDataType::operator =(const asCDataType &dt)
{
tokenType = dt.tokenType;
isReference = dt.isReference;
objectType = dt.objectType;
isReadOnly = dt.isReadOnly;
isObjectHandle = dt.isObjectHandle;
isConstHandle = dt.isConstHandle;
funcDef = dt.funcDef;
tokenType = dt.tokenType;
isReference = dt.isReference;
objectType = dt.objectType;
isReadOnly = dt.isReadOnly;
isObjectHandle = dt.isObjectHandle;
isConstHandle = dt.isConstHandle;
isAuto = dt.isAuto;
funcDef = dt.funcDef;
isHandleToAsHandleType = dt.isHandleToAsHandleType;
return (asCDataType &)*this;
}
@@ -226,35 +252,46 @@ int asCDataType::MakeHandle(bool b, bool acceptHandleForScope)
{
if( !b )
{
isObjectHandle = b;
isObjectHandle = false;
isConstHandle = false;
isHandleToAsHandleType = false;
}
else if( b && !isObjectHandle )
else
{
// Only reference types are allowed to be handles,
// but not nohandle reference types, and not scoped references
// (except when returned from registered function)
// funcdefs are special reference types and support handles
// value types with asOBJ_ASHANDLE are treated as a handle
if( !funcDef &&
(!objectType ||
!((objectType->flags & asOBJ_REF) || (objectType->flags & asOBJ_TEMPLATE_SUBTYPE) || (objectType->flags & asOBJ_ASHANDLE)) ||
(objectType->flags & asOBJ_NOHANDLE) ||
((objectType->flags & asOBJ_SCOPED) && !acceptHandleForScope)) )
return -1;
if( isAuto )
{
isObjectHandle = true;
}
else if( !isObjectHandle )
{
// Only reference types are allowed to be handles,
// but not nohandle reference types, and not scoped references
// (except when returned from registered function)
// funcdefs are special reference types and support handles
// value types with asOBJ_ASHANDLE are treated as a handle
if( !funcDef &&
(!objectType ||
!((objectType->flags & asOBJ_REF) || (objectType->flags & asOBJ_TEMPLATE_SUBTYPE) || (objectType->flags & asOBJ_ASHANDLE)) ||
(objectType->flags & asOBJ_NOHANDLE) ||
((objectType->flags & asOBJ_SCOPED) && !acceptHandleForScope)) )
return -1;
isObjectHandle = b;
isConstHandle = false;
isObjectHandle = b;
isConstHandle = false;
// ASHANDLE supports being handle, but as it really is a value type it will not be marked as a handle
if( (objectType->flags & asOBJ_ASHANDLE) )
isObjectHandle = false;
// ASHANDLE supports being handle, but as it really is a value type it will not be marked as a handle
if( (objectType->flags & asOBJ_ASHANDLE) )
{
isObjectHandle = false;
isHandleToAsHandleType = true;
}
}
}
return 0;
}
int asCDataType::MakeArray(asCScriptEngine *engine)
int asCDataType::MakeArray(asCScriptEngine *engine, asCModule *module)
{
if( engine->defaultArrayObjectType == 0 )
return asINVALID_TYPE;
@@ -263,7 +300,7 @@ int asCDataType::MakeArray(asCScriptEngine *engine)
isReadOnly = false;
asCArray<asCDataType> subTypes;
subTypes.PushLast(*this);
asCObjectType *at = engine->GetTemplateInstanceType(engine->defaultArrayObjectType, subTypes);
asCObjectType *at = engine->GetTemplateInstanceType(engine->defaultArrayObjectType, subTypes, module);
isReadOnly = tmpIsReadOnly;
isObjectHandle = false;
@@ -305,7 +342,7 @@ int asCDataType::MakeHandleToConst(bool b)
bool asCDataType::SupportHandles() const
{
if( objectType &&
(objectType->flags & asOBJ_REF) &&
(objectType->flags & (asOBJ_REF | asOBJ_ASHANDLE)) &&
!(objectType->flags & asOBJ_NOHANDLE) &&
!isObjectHandle )
return true;
@@ -313,19 +350,39 @@ bool asCDataType::SupportHandles() const
return false;
}
bool asCDataType::CanBeInstanciated() const
bool asCDataType::CanBeInstantiated() const
{
if( GetSizeOnStackDWords() == 0 ||
(IsObject() &&
(objectType->flags & asOBJ_REF) && // It's a ref type and
((objectType->flags & asOBJ_NOHANDLE) || // the ref type doesn't support handles or
(!IsObjectHandle() && // it's not a handle and
objectType->beh.factories.GetLength() == 0))) ) // the ref type cannot be instanciated
if( GetSizeOnStackDWords() == 0 ) // Void
return false;
if( !IsObject() ) // Primitives
return true;
if( IsObjectHandle() && !(objectType->flags & asOBJ_NOHANDLE) ) // Handles
return true;
if( funcDef ) // Funcdefs can be instantiated as delegates
return true;
if( (objectType->flags & asOBJ_REF) && objectType->beh.factories.GetLength() == 0 ) // ref types without factories
return false;
if( (objectType->flags & asOBJ_ABSTRACT) && !IsObjectHandle() ) // Can't instantiate abstract classes
return false;
return true;
}
bool asCDataType::IsAbstractClass() const
{
return objectType && (objectType->flags & asOBJ_ABSTRACT) ? true : false;
}
bool asCDataType::IsInterface() const
{
return objectType && objectType->IsInterface();
}
bool asCDataType::CanBeCopied() const
{
// All primitives can be copied
@@ -334,8 +391,8 @@ bool asCDataType::CanBeCopied() const
// Plain-old-data structures can always be copied
if( objectType->flags & asOBJ_POD ) return true;
// It must be possible to instanciate the type
if( !CanBeInstanciated() ) return false;
// It must be possible to instantiate the type
if( !CanBeInstantiated() ) return false;
// It must have a default constructor or factory
if( objectType->beh.construct == 0 &&
@@ -361,6 +418,14 @@ bool asCDataType::IsHandleToConst() const
return isReadOnly;
}
bool asCDataType::IsObjectConst() const
{
if( IsObjectHandle() )
return IsHandleToConst();
return IsReadOnly();
}
// TODO: 3.0.0: This should be removed
bool asCDataType::IsArrayType() const
{
@@ -441,7 +506,7 @@ bool asCDataType::IsEqualExceptConst(const asCDataType &dt) const
bool asCDataType::IsPrimitive() const
{
// Enumerations are primitives
// Enumerations are primitives
if( IsEnumType() )
return true;
@@ -456,6 +521,16 @@ bool asCDataType::IsPrimitive() const
return true;
}
bool asCDataType::IsMathType() const
{
if( tokenType == ttInt || tokenType == ttInt8 || tokenType == ttInt16 || tokenType == ttInt64 ||
tokenType == ttUInt || tokenType == ttUInt8 || tokenType == ttUInt16 || tokenType == ttUInt64 ||
tokenType == ttFloat || tokenType == ttDouble )
return true;
return false;
}
bool asCDataType::IsIntegerType() const
{
if( tokenType == ttInt ||
@@ -505,13 +580,14 @@ bool asCDataType::IsBooleanType() const
bool asCDataType::IsObject() const
{
// Enumerations are not objects, even though they are described with an objectType.
if( IsEnumType() )
if( IsPrimitive() )
return false;
if( objectType ) return true;
// Null handle doesn't have an object type but should still be considered an object
if( objectType == 0 )
return IsNullHandle();
return false;
return true;
}
int asCDataType::GetSizeInMemoryBytes() const
@@ -569,6 +645,19 @@ int asCDataType::GetSizeOnStackDWords() const
return GetSizeInMemoryDWords() + size;
}
#ifdef WIP_16BYTE_ALIGN
int asCDataType::GetAlignment() const
{
if( objectType == NULL )
{
// TODO: Small primitives should not be aligned to 4 byte boundaries
return 4; //Default alignment
}
return objectType->alignment;
}
#endif
asSTypeBehaviour *asCDataType::GetBehaviour() const
{
return objectType ? &objectType->beh : 0;
@@ -576,6 +665,9 @@ asSTypeBehaviour *asCDataType::GetBehaviour() const
bool asCDataType::IsEnumType() const
{
// Do a sanity check on the objectType, to verify that we aren't trying to access memory after it has been released
asASSERT( objectType == 0 || objectType->name.GetLength() < 100 );
if( objectType && (objectType->flags & asOBJ_ENUM) )
return true;
+37 -21
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2015 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -49,6 +49,8 @@ struct asSTypeBehaviour;
class asCScriptEngine;
class asCObjectType;
class asCScriptFunction;
class asCModule;
struct asSNameSpace;
// TODO: refactor: Reference should not be part of the datatype. This should be stored separately, e.g. in asCTypeInfo
// MakeReference, MakeReadOnly, IsReference, IsReadOnly should be removed
@@ -62,36 +64,45 @@ public:
bool IsValid() const;
asCString Format(bool includeNamespace = false) const;
asCString Format(asSNameSpace *currNs, bool includeNamespace = false) const;
static asCDataType CreatePrimitive(eTokenType tt, bool isConst);
static asCDataType CreateObject(asCObjectType *ot, bool isConst);
static asCDataType CreateAuto(bool isConst);
static asCDataType CreateObjectHandle(asCObjectType *ot, bool isConst);
static asCDataType CreateFuncDef(asCScriptFunction *ot);
static asCDataType CreateNullHandle();
int MakeHandle(bool b, bool acceptHandleForScope = false);
int MakeArray(asCScriptEngine *engine);
int MakeArray(asCScriptEngine *engine, asCModule *requestingModule);
int MakeReference(bool b);
int MakeReadOnly(bool b);
int MakeHandleToConst(bool b);
bool IsTemplate() const;
bool IsScriptObject() const;
bool IsPrimitive() const;
bool IsObject() const;
bool IsReference() const {return isReference;}
bool IsReadOnly() const;
bool IsIntegerType() const;
bool IsUnsignedType() const;
bool IsFloatType() const;
bool IsDoubleType() const;
bool IsBooleanType() const;
bool IsObjectHandle() const {return isObjectHandle;}
bool IsHandleToConst() const;
bool IsArrayType() const;
bool IsEnumType() const;
bool IsAnyType() const {return tokenType == ttQuestion;}
bool IsTemplate() const;
bool IsScriptObject() const;
bool IsPrimitive() const;
bool IsMathType() const;
bool IsObject() const;
bool IsReference() const {return isReference;}
bool IsAuto() const {return isAuto;}
bool IsReadOnly() const;
bool IsIntegerType() const;
bool IsUnsignedType() const;
bool IsFloatType() const;
bool IsDoubleType() const;
bool IsBooleanType() const;
bool IsObjectHandle() const {return isObjectHandle;}
bool IsHandleToAuto() const {return isAuto && isObjectHandle;}
bool IsHandleToConst() const;
bool IsArrayType() const;
bool IsEnumType() const;
bool IsAnyType() const {return tokenType == ttQuestion;}
bool IsHandleToAsHandleType() const {return isHandleToAsHandleType;}
bool IsAbstractClass() const;
bool IsInterface() const;
bool IsObjectConst() const;
bool IsEqualExceptRef(const asCDataType &) const;
bool IsEqualExceptRefAndConst(const asCDataType &) const;
@@ -99,7 +110,7 @@ public:
bool IsNullHandle() const;
bool SupportHandles() const;
bool CanBeInstanciated() const;
bool CanBeInstantiated() const;
bool CanBeCopied() const;
bool operator ==(const asCDataType &) const;
@@ -113,6 +124,9 @@ public:
int GetSizeOnStackDWords() const;
int GetSizeInMemoryBytes() const;
int GetSizeInMemoryDWords() const;
#ifdef WIP_16BYTE_ALIGN
int GetAlignment() const;
#endif
void SetTokenType(eTokenType tt) {tokenType = tt;}
void SetObjectType(asCObjectType *obj) {objectType = obj;}
@@ -135,7 +149,9 @@ protected:
bool isReadOnly:1;
bool isObjectHandle:1;
bool isConstHandle:1;
char dummy:4;
bool isAuto:1;
bool isHandleToAsHandleType:1; // Used by the compiler to know how to initialize the object
char dummy:2;
};
END_AS_NAMESPACE
+13 -2
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2012 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -38,12 +38,16 @@
#include "as_config.h"
#if defined(AS_DEBUG)
#ifndef AS_WII
// The Wii SDK doesn't have these, we'll survive without AS_DEBUG
#ifndef _WIN32_WCE
// Neither does WinCE
#ifndef AS_PSVITA
// Possible on PSVita, but requires SDK access
#if defined(__GNUC__) || defined( AS_MARMALADE )
@@ -256,10 +260,17 @@ END_AS_NAMESPACE
#endif // AS_PSVITA
#endif // _WIN32_WCE
#endif // AS_WII
#else // !defined(AS_DEBUG)
// Define it so nothing is done
#define TimeIt(x)
#endif // !defined(AS_DEBUG)
#endif
+68 -34
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -156,7 +156,14 @@ int asCGarbageCollector::GetObjectInGC(asUINT idx, asUINT *seqNbr, void **obj, a
return asSUCCESS;
}
int asCGarbageCollector::GarbageCollect(asDWORD flags)
// TODO: Should have a flag to tell the garbage collector to automatically determine how many iterations are needed
// It should then gather statistics such as how many objects has been created since last run, and how many objects
// are destroyed per iteration, and how many objects are detected as cyclic garbage per iteration.
// It should try to reach a stable number of objects, i.e. so that on average the number of objects added to
// the garbage collector is the same as the number of objects destroyed. And it should try to minimize the number
// of iterations of detections that must be executed per cycle while still identifying the cyclic garbage
// These variables should also be available for inspection through the gcstatistics.
int asCGarbageCollector::GarbageCollect(asDWORD flags, asUINT iterations)
{
// If the GC is already processing in another thread, then don't enter here again
if( TRYENTERCRITICALSECTION(gcCollecting) )
@@ -178,9 +185,8 @@ int asCGarbageCollector::GarbageCollect(asDWORD flags)
// Reset the state
if( doDetect )
{
// Move all objects to the old list, so we guarantee that all is detected
for( asUINT n = (asUINT)gcNewObjects.GetLength(); n-- > 0; )
MoveObjectToOldList(n);
// Move all new objects to the old list, so we guarantee that all is detected
MoveAllObjectsToOldList();
detectState = clearCounters_init;
}
if( doDestroy )
@@ -189,7 +195,10 @@ int asCGarbageCollector::GarbageCollect(asDWORD flags)
destroyOldState = destroyGarbage_init;
}
unsigned int count = (unsigned int)(gcNewObjects.GetLength() + gcOldObjects.GetLength());
// The full cycle only works with the objects in the old list so that the
// set of objects scanned for garbage is fixed even if new objects are added
// by other threads in parallel.
unsigned int count = (unsigned int)(gcOldObjects.GetLength());
for(;;)
{
// Detect all garbage with cyclic references
@@ -199,25 +208,16 @@ int asCGarbageCollector::GarbageCollect(asDWORD flags)
// Now destroy all known garbage
if( doDestroy )
{
while( DestroyNewGarbage() == 1 ) {}
if( !doDetect )
while( DestroyNewGarbage() == 1 ) {}
while( DestroyOldGarbage() == 1 ) {}
}
// Run another iteration if any garbage was destroyed
if( count != (unsigned int)(gcNewObjects.GetLength() + gcOldObjects.GetLength()) )
count = (unsigned int)(gcNewObjects.GetLength() + gcOldObjects.GetLength());
if( count != (unsigned int)(gcOldObjects.GetLength()) )
count = (unsigned int)(gcOldObjects.GetLength());
else
{
// Let the engine destroy the types that reached refCount 0
// If none were destroyed, then leave the GC
// TODO: The asCObjectType should destroy its content when refCount reaches 0
// since no-one is using them. The registered types should have their
// refcount increased by the config groups. Doing it like that will allow
// me to remove this call to ClearUnusedTypes() that the GC really
// shouldn't be calling.
if( engine->ClearUnusedTypes() == 0 )
break;
}
break;
}
isProcessing = false;
@@ -226,16 +226,19 @@ int asCGarbageCollector::GarbageCollect(asDWORD flags)
}
else
{
// Destroy the garbage that we know of
if( doDestroy )
while( iterations-- > 0 )
{
DestroyNewGarbage();
DestroyOldGarbage();
}
// Destroy the garbage that we know of
if( doDestroy )
{
DestroyNewGarbage();
DestroyOldGarbage();
}
// Run another incremental step of the identification of cyclic references
if( doDetect )
IdentifyGarbageWithCyclicRefs();
// Run another incremental step of the identification of cyclic references
if( doDetect && gcOldObjects.GetLength() > 0 )
IdentifyGarbageWithCyclicRefs();
}
}
isProcessing = false;
@@ -246,19 +249,33 @@ int asCGarbageCollector::GarbageCollect(asDWORD flags)
return 1;
}
// TODO: Additional statistics to gather
//
// - How many objects are added on average between each destroyed object
// - How many objects are added on average between each detected object
// - how many iterations are needed for each destroyed object
// - how many iterations are needed for each detected object
//
// The average must have a decay so that long running applications will not suffer
// from objects being created early on in the application and then never destroyed.
//
// This ought to be possible to accomplish by holding two buckets.
// Numbers will be accumulated in one bucket while the other is held fixed.
// When returning the average it should use a weighted average between the two buckets using the size as weight.
// When a bucket is filled up, the buckets are switched, and then new bucket is emptied to gather new statistics.
void asCGarbageCollector::GetStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected, asUINT *newObjects, asUINT *totalNewDestroyed) const
{
// It's not necessary to protect this access, as
// it doesn't matter if another thread is currently
// appending a new object.
// It is not necessary to protect this with critical sections, however
// as it is not protected the variables can be filled in slightly different
// moments and might not match perfectly when inspected by the application
// afterwards.
if( currentSize )
*currentSize = (asUINT)(gcNewObjects.GetLength() + gcOldObjects.GetLength());
if( totalDestroyed )
*totalDestroyed = numDestroyed;
asASSERT( numAdded == gcNewObjects.GetLength() + gcOldObjects.GetLength() + numDestroyed );
if( totalDetected )
*totalDetected = numDetected;
@@ -328,6 +345,16 @@ void asCGarbageCollector::MoveObjectToOldList(int idx)
LEAVECRITICALSECTION(gcCritical);
}
void asCGarbageCollector::MoveAllObjectsToOldList()
{
// We need to protect this update with a critical section as
// another thread might be appending an object at the same time
ENTERCRITICALSECTION(gcCritical);
if( gcOldObjects.Concatenate(gcNewObjects) )
gcNewObjects.SetLength(0);
LEAVECRITICALSECTION(gcCritical);
}
int asCGarbageCollector::DestroyNewGarbage()
{
// This function will only be called within the critical section gcCollecting
@@ -900,8 +927,15 @@ asCGarbageCollector::asSMapNode_t *asCGarbageCollector::GetNode(void *obj, asSIn
if( freeNodes.GetLength() )
node = freeNodes.PopLast();
else
{
node = asNEW(asSMapNode_t);
if( !node )
{
// Out of memory
return 0;
}
}
node->Init(obj, it);
return node;
}
+3 -2
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -56,7 +56,7 @@ public:
asCGarbageCollector();
~asCGarbageCollector();
int GarbageCollect(asDWORD flags);
int GarbageCollect(asDWORD flags, asUINT iterations);
void GetStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected, asUINT *newObjects, asUINT *totalNewDestroyed) const;
void GCEnumCallback(void *reference);
int AddScriptObjectToGC(void *obj, asCObjectType *objType);
@@ -104,6 +104,7 @@ protected:
void RemoveNewObjectAtIdx(int idx);
void RemoveOldObjectAtIdx(int idx);
void MoveObjectToOldList(int idx);
void MoveAllObjectsToOldList();
// Holds all the objects known by the garbage collector
asCArray<asSObjTypePair> gcNewObjects;
+21 -139
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2012 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -50,31 +50,32 @@ asCGlobalProperty::asCGlobalProperty()
asCGlobalProperty::~asCGlobalProperty()
{
#ifndef WIP_16BYTE_ALIGNED
if( memoryAllocated ) { asDELETEARRAY(memory); }
#else
if( memoryAllocated ) { asDELETEARRAYALIGNED(memory); }
#endif
if( initFunc )
initFunc->Release();
initFunc->ReleaseInternal();
}
void asCGlobalProperty::AddRef()
{
gcFlag = false;
refCount.atomicInc();
}
void asCGlobalProperty::Release()
{
gcFlag = false;
if( refCount.atomicDec() == 0 )
asDELETE(this, asCGlobalProperty);
}
// The property doesn't delete itself. The
// engine will do that at a later time
if( refCount.atomicDec() == 2 && initFunc )
void asCGlobalProperty::DestroyInternal()
{
if( initFunc )
{
// Since the initFunc holds references to the property,
// we'll release it when we reach refCount 2. This will
// break the circle and allow the engine to free the property
// without the need for the GC to attempt finding circular
// references.
initFunc->Release();
initFunc->ReleaseInternal();
initFunc = 0;
}
}
@@ -92,14 +93,19 @@ void asCGlobalProperty::AllocateMemory()
{
if( type.GetSizeOnStackDWords() > 2 )
{
#ifndef WIP_16BYTE_ALIGNED
memory = asNEWARRAY(asDWORD, type.GetSizeOnStackDWords());
#else
// TODO: Avoid aligned allocation if not needed to reduce the waste of memory for the alignment
memory = asNEWARRAYALIGNED(asDWORD, type.GetSizeOnStackDWords(), type.GetAlignment());
#endif
memoryAllocated = true;
}
}
void asCGlobalProperty::SetRegisteredAddress(void *p)
{
realAddress = p;
realAddress = p;
if( type.IsObject() && !type.IsReference() && !type.IsObjectHandle() )
{
// The global property is a pointer to a pointer
@@ -114,60 +120,13 @@ void *asCGlobalProperty::GetRegisteredAddress() const
return realAddress;
}
int asCGlobalProperty::GetRefCount()
{
return refCount.get();
}
void asCGlobalProperty::SetGCFlag()
{
gcFlag = true;
}
bool asCGlobalProperty::GetGCFlag()
{
return gcFlag;
}
void asCGlobalProperty::EnumReferences(asIScriptEngine *engine)
{
engine->GCEnumCallback(initFunc);
}
void asCGlobalProperty::ReleaseAllHandles(asIScriptEngine *)
{
if( initFunc )
{
initFunc->Release();
initFunc = 0;
}
}
void asCGlobalProperty::Orphan(asCModule *module)
{
if( initFunc && initFunc->module == module )
{
// The owning module is releasing the property, so we need to notify
// the GC in order to resolve any circular references that may exists
// This will add the property
initFunc->engine->gc.AddScriptObjectToGC(this, &initFunc->engine->globalPropertyBehaviours);
// This will add the function
initFunc->AddRef();
initFunc->Orphan(module);
}
Release();
}
void asCGlobalProperty::SetInitFunc(asCScriptFunction *initFunc)
{
// This should only be done once
asASSERT( this->initFunc == 0 );
this->initFunc = initFunc;
this->initFunc->AddRef();
this->initFunc->AddRefInternal();
}
asCScriptFunction *asCGlobalProperty::GetInitFunc()
@@ -175,81 +134,4 @@ asCScriptFunction *asCGlobalProperty::GetInitFunc()
return initFunc;
}
#ifdef AS_MAX_PORTABILITY
static void GlobalProperty_AddRef_Generic(asIScriptGeneric *gen)
{
asCGlobalProperty *self = (asCGlobalProperty*)gen->GetObject();
self->AddRef();
}
static void GlobalProperty_Release_Generic(asIScriptGeneric *gen)
{
asCGlobalProperty *self = (asCGlobalProperty*)gen->GetObject();
self->Release();
}
static void GlobalProperty_GetRefCount_Generic(asIScriptGeneric *gen)
{
asCGlobalProperty *self = (asCGlobalProperty*)gen->GetObject();
*(int*)gen->GetAddressOfReturnLocation() = self->GetRefCount();
}
static void GlobalProperty_SetGCFlag_Generic(asIScriptGeneric *gen)
{
asCGlobalProperty *self = (asCGlobalProperty*)gen->GetObject();
self->SetGCFlag();
}
static void GlobalProperty_GetGCFlag_Generic(asIScriptGeneric *gen)
{
asCGlobalProperty *self = (asCGlobalProperty*)gen->GetObject();
*(bool*)gen->GetAddressOfReturnLocation() = self->GetGCFlag();
}
static void GlobalProperty_EnumReferences_Generic(asIScriptGeneric *gen)
{
asCGlobalProperty *self = (asCGlobalProperty*)gen->GetObject();
asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
self->EnumReferences(engine);
}
static void GlobalProperty_ReleaseAllHandles_Generic(asIScriptGeneric *gen)
{
asCGlobalProperty *self = (asCGlobalProperty*)gen->GetObject();
asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
self->ReleaseAllHandles(engine);
}
#endif
void asCGlobalProperty::RegisterGCBehaviours(asCScriptEngine *engine)
{
// Register the gc behaviours for the global properties
int r = 0;
UNUSED_VAR(r); // It is only used in debug mode
engine->globalPropertyBehaviours.engine = engine;
engine->globalPropertyBehaviours.flags = asOBJ_REF | asOBJ_GC;
engine->globalPropertyBehaviours.name = "_builtin_globalprop_";
#ifndef AS_MAX_PORTABILITY
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCGlobalProperty,AddRef), asCALL_THISCALL, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_RELEASE, "void f()", asMETHOD(asCGlobalProperty,Release), asCALL_THISCALL, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(asCGlobalProperty,GetRefCount), asCALL_THISCALL, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_SETGCFLAG, "void f()", asMETHOD(asCGlobalProperty,SetGCFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(asCGlobalProperty,GetGCFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(asCGlobalProperty,EnumReferences), asCALL_THISCALL, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(asCGlobalProperty,ReleaseAllHandles), asCALL_THISCALL, 0); asASSERT( r >= 0 );
#else
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_ADDREF, "void f()", asFUNCTION(GlobalProperty_AddRef_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_RELEASE, "void f()", asFUNCTION(GlobalProperty_Release_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(GlobalProperty_GetRefCount_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(GlobalProperty_SetGCFlag_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(GlobalProperty_GetGCFlag_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(GlobalProperty_EnumReferences_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(GlobalProperty_ReleaseAllHandles_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
#endif
}
END_AS_NAMESPACE
+92 -1
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2012 Andreas Jonsson
Copyright (c) 2003-2015 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -49,6 +49,63 @@
BEGIN_AS_NAMESPACE
#ifdef WIP_16BYTE_ALIGN
// TODO: Add support for 16byte aligned application types (e.g. __m128). The following is a list of things that needs to be implemented:
//
// ok - The script context must make sure to always allocate the local stack memory buffer on 16byte aligned boundaries (asCContext::ReserveStackSpace)
// ok - The engine must make sure to always allocate the memory for the script objects on 16byte aligned boundaries (asCScriptEngine::CallAlloc)
// ok - The application needs to inform a new flag when registering types that require 16byte alignment, e.g. asOBJ_APP_ALIGN16 (asCScriptEngine::RegisterObjectType)
// ok - The script object type must make sure to align member properties of these types correctly (asCObjectType::AddPropertyToClass)
// ok - Script global properties must allocate memory on 16byte boundaries if holding these types (asCGlobalProperty::AllocateMemory)
// TODO - The script compiler must make sure to allocate the local variables on 16byte boundaries (asCCompiler::AllocateVariable)
// TODO - The script compiler must add pad bytes on the stack for all function calls to guarantee that the stack position is 16byte aligned on entry in the called function (asCCompiler)
// TODO - The bytecode serializer must be capable of adjusting these pad bytes to guarantee platform independent saved bytecode. Remember that the registered type may not be 16byte aligned on all platforms (asCWriter & asCReader)
// TODO - The bytecode serializer must also be prepared to adjust the position of the local variables according to the need fro 16byte alignment (asCWriter & asCReader)
// TODO - The code for the native calling conventions must be adjusted for all platforms that should support 16byte aligned types (as_callfunc...)
// ok - When the context needs to grow the local stack memory it must copy the function arguments so that the stack entry position is 16byte aligned (asCContext::CallScriptFunction)
// TODO - When the context is prepared for a new call, it must set the initial stack position so the stack entry position is 16byte aligned (asCContext::Prepare)
//
// http://www.gamedev.net/topic/650555-alignment-requirements/
// TODO: Allow user to register its own aligned memory routines
// Wrappers for aligned allocations
void *debugAlignedMalloc(size_t size, size_t align, const char *file, int line)
{
void *mem = ((asALLOCFUNCDEBUG_t)userAlloc)(size + (align-1) + sizeof(void*), file, line);
char *amem = ((char*)mem) + sizeof(void*);
if( (uintptr_t)amem & (align - 1) )
amem += align - ((uintptr_t)amem & (align - 1));
((void**)amem)[-1] = mem;
return amem;
}
void *alignedMalloc(size_t size, size_t align)
{
void *mem = userAlloc(size + (align-1) + sizeof(void*));
char *amem = ((char*)mem) + sizeof(void*);
if( (uintptr_t)amem & (align - 1) )
amem += align - ((uintptr_t)amem & (align - 1));
((void**)amem)[-1] = mem;
return amem;
}
void alignedFree(void *mem)
{
userFree( ((void**)mem)[-1] );
}
bool isAligned(const void* const pointer, asUINT alignment)
{
return (uintptr_t(pointer) % alignment) == 0;
}
#endif
// By default we'll use the standard memory management functions
// Make sure these globals are initialized first. Otherwise the
@@ -61,25 +118,47 @@ BEGIN_AS_NAMESPACE
#pragma init_seg(lib)
asALLOCFUNC_t userAlloc = malloc;
asFREEFUNC_t userFree = free;
#ifdef WIP_16BYTE_ALIGN
#ifdef AS_DEBUG
asALLOCALIGNEDFUNC_t userAllocAligned = (asALLOCALIGNEDFUNC_t)debugAlignedMalloc;
#else
asALLOCALIGNEDFUNC_t userAllocAligned = alignedMalloc;
#endif
asFREEALIGNEDFUNC_t userFreeAligned = alignedFree;
#endif
#else
// Other compilers will just have to rely on luck.
asALLOCFUNC_t userAlloc = malloc;
asFREEFUNC_t userFree = free;
#ifdef WIP_16BYTE_ALIGN
asALLOCALIGNEDFUNC_t userAllocAligned = alignedMalloc;
asFREEALIGNEDFUNC_t userFreeAligned = alignedFree;
#endif
#endif
extern "C"
{
// interface
int asSetGlobalMemoryFunctions(asALLOCFUNC_t allocFunc, asFREEFUNC_t freeFunc)
{
// Clean-up thread local memory before changing the allocation routines to avoid
// potential problem with trying to free memory using a different allocation
// routine than used when allocating it.
asThreadCleanup();
userAlloc = allocFunc;
userFree = freeFunc;
return 0;
}
// interface
int asResetGlobalMemoryFunctions()
{
// Clean-up thread local memory before changing the allocation routines to avoid
// potential problem with trying to free memory using a different allocation
// routine than used when allocating it.
asThreadCleanup();
userAlloc = malloc;
@@ -88,6 +167,18 @@ int asResetGlobalMemoryFunctions()
return 0;
}
// interface
void *asAllocMem(size_t size)
{
return asNEWARRAY(asBYTE, size);
}
// interface
void asFreeMem(void *mem)
{
asDELETEARRAY(mem);
}
} // extern "C"
asCMemoryMgr::asCMemoryMgr()
+31 -1
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2012 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -48,6 +48,25 @@ BEGIN_AS_NAMESPACE
extern asALLOCFUNC_t userAlloc;
extern asFREEFUNC_t userFree;
#ifdef WIP_16BYTE_ALIGN
// TODO: This declaration should be in angelscript.h
// when the application can register it's own
// aligned memory routines
typedef void *(*asALLOCALIGNEDFUNC_t)(size_t, size_t);
typedef void (*asFREEALIGNEDFUNC_t)(void *);
extern asALLOCALIGNEDFUNC_t userAllocAligned;
extern asFREEALIGNEDFUNC_t userFreeAligned;
typedef void *(*asALLOCALIGNEDFUNCDEBUG_t)(size_t, size_t, const char *, unsigned int);
// The maximum type alignment supported.
const int MAX_TYPE_ALIGNMENT = 16;
// Utility function used for assertions.
bool isAligned(const void* const pointer, asUINT alignment);
#endif // WIP_16BYTE_ALIGN
// We don't overload the new operator as that would affect the application as well
#ifndef AS_DEBUG
@@ -58,6 +77,11 @@ extern asFREEFUNC_t userFree;
#define asNEWARRAY(x,cnt) (x*)userAlloc(sizeof(x)*cnt)
#define asDELETEARRAY(ptr) userFree(ptr)
#ifdef WIP_16BYTE_ALIGN
#define asNEWARRAYALIGNED(x,cnt, alignment) (x*)userAllocAligned(sizeof(x)*cnt, alignment)
#define asDELETEARRAYALIGNED(ptr) userFreeAligned(ptr)
#endif
#else
typedef void *(*asALLOCFUNCDEBUG_t)(size_t, const char *, unsigned int);
@@ -68,6 +92,12 @@ extern asFREEFUNC_t userFree;
#define asNEWARRAY(x,cnt) (x*)((asALLOCFUNCDEBUG_t)(userAlloc))(sizeof(x)*cnt, __FILE__, __LINE__)
#define asDELETEARRAY(ptr) userFree(ptr)
#ifdef WIP_16BYTE_ALIGN
//TODO: Equivalent of debug allocation function with alignment?
#define asNEWARRAYALIGNED(x,cnt, alignment) (x*)userAllocAligned(sizeof(x)*cnt, alignment)
#define asDELETEARRAYALIGNED(ptr) userFreeAligned(ptr)
#endif
#endif
END_AS_NAMESPACE
+495 -104
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2014 Andreas Jonsson
Copyright (c) 2003-2015 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -46,6 +46,33 @@
BEGIN_AS_NAMESPACE
// TODO: 2.30.0: redesign: Improved method for discarding modules (faster clean-up, less abuse of garbage collector)
//
// I need to separate the reference counter for internal references and outside references:
//
// - Internal references are for example, when the module refers to a function or object since it is declared in the module, or when
// a function refers to another function since it is being called in the code.
// - Outside references are for example object instances holding a reference to the object type, or a context currently
// executing a function.
//
// If no object instances are alive or no contexts are alive it is known that functions from a discarded module
// can be called, so they can be destroyed without any need to execute the complex garbage collection routines.
//
// If there are live objects, the entire module should be kept for safe keeping, though no longer visible.
//
// TODO: It may not be necessary to keep track of internal references. Without keeping track of internal references, can I still
// handle RemoveFunction and RemoveGlobalVariable correctly?
//
// TODO: How to avoid global variables keeping code alive? For example a script object, or a funcdef?
// Can I do a quick check of the object types and functions to count number of outside references, and then do another
// check over the global variables to subtract the outside references coming from these? What if the outside reference
// is added by an application type in a global variable that the engine doesn't know about? Example, a global dictionary
// holding object instances. Should discarding a module immediately destroy the content of the global variables? What if
// a live object tries to access the global variable after it has been discarded? Throwing a script exception is acceptable?
// Perhaps I need to allow the user to provide a clean-up routine that will be executed before destroying the objects.
// Or I might just put that responsibility on the application.
// internal
asCModule::asCModule(const char *name, asCScriptEngine *engine)
{
@@ -66,6 +93,8 @@ asCModule::~asCModule()
{
InternalReset();
// The builder is not removed by InternalReset because it holds the script
// sections that will be built, so we need to explictly remove it now if it exists
if( builder )
{
asDELETE(builder,asCBuilder);
@@ -75,34 +104,114 @@ asCModule::~asCModule()
if( engine )
{
// Clean the user data
if( userData && engine->cleanModuleFunc )
engine->cleanModuleFunc(this);
for( asUINT n = 0; n < userData.GetLength(); n += 2 )
{
if( userData[n+1] )
{
for( asUINT c = 0; c < engine->cleanModuleFuncs.GetLength(); c++ )
if( engine->cleanModuleFuncs[c].type == userData[n] )
engine->cleanModuleFuncs[c].cleanFunc(this);
}
}
// Remove the module from the engine
if( engine->lastModule == this )
engine->lastModule = 0;
engine->scriptModules.RemoveValue(this);
ACQUIREEXCLUSIVE(engine->engineRWLock);
// The module must have been discarded before it is deleted
asASSERT( !engine->scriptModules.Exists(this) );
engine->discardedModules.RemoveValue(this);
RELEASEEXCLUSIVE(engine->engineRWLock);
}
}
// interface
void asCModule::Discard()
{
asDELETE(this,asCModule);
// Reset the global variables already so that no object in the global variables keep the module alive forever.
// If any live object tries to access the global variables during clean up they will fail with a script exception,
// so the application must keep that in mind before discarding a module.
CallExit();
// Keep a local copy of the engine pointer, because once the module is moved do the discarded
// pile, it is possible that another thread might discard it while we are still in here. So no
// further access to members may be done after that
asCScriptEngine *lEngine = engine;
// Instead of deleting the module immediately, move it to the discarded pile
// This will turn it invisible to the application, yet keep it alive until all
// external references to its entities have been released.
ACQUIREEXCLUSIVE(engine->engineRWLock);
if( lEngine->lastModule == this )
lEngine->lastModule = 0;
lEngine->scriptModules.RemoveValue(this);
lEngine->discardedModules.PushLast(this);
RELEASEEXCLUSIVE(lEngine->engineRWLock);
// Allow the engine to go over the list of discarded modules to see what can be cleaned up at this moment.
// Don't do this if the engine is already shutting down, as it will be done explicitly by the engine itself with error reporting
if( !lEngine->shuttingDown )
{
if( lEngine->ep.autoGarbageCollect )
lEngine->GarbageCollect();
else
{
// GarbageCollect calls DeleteDiscardedModules, so no need
// to call it again if we already called GarbageCollect
lEngine->DeleteDiscardedModules();
}
}
}
// interface
void *asCModule::SetUserData(void *data)
void *asCModule::SetUserData(void *data, asPWORD type)
{
void *oldData = userData;
userData = data;
return oldData;
// As a thread might add a new new user data at the same time as another
// it is necessary to protect both read and write access to the userData member
ACQUIREEXCLUSIVE(engine->engineRWLock);
// It is not intended to store a lot of different types of userdata,
// so a more complex structure like a associative map would just have
// more overhead than a simple array.
for( asUINT n = 0; n < userData.GetLength(); n += 2 )
{
if( userData[n] == type )
{
void *oldData = reinterpret_cast<void*>(userData[n+1]);
userData[n+1] = reinterpret_cast<asPWORD>(data);
RELEASEEXCLUSIVE(engine->engineRWLock);
return oldData;
}
}
userData.PushLast(type);
userData.PushLast(reinterpret_cast<asPWORD>(data));
RELEASEEXCLUSIVE(engine->engineRWLock);
return 0;
}
// interface
void *asCModule::GetUserData() const
void *asCModule::GetUserData(asPWORD type) const
{
return userData;
// There may be multiple threads reading, but when
// setting the user data nobody must be reading.
ACQUIRESHARED(engine->engineRWLock);
for( asUINT n = 0; n < userData.GetLength(); n += 2 )
{
if( userData[n] == type )
{
void *ud = reinterpret_cast<void*>(userData[n+1]);
RELEASESHARED(engine->engineRWLock);
return ud;
}
}
RELEASESHARED(engine->engineRWLock);
return 0;
}
// interface
@@ -204,6 +313,15 @@ int asCModule::Build()
#else
TimeIt("asCModule::Build");
// Don't allow the module to be rebuilt if there are still
// external references that will need the previous code
// TODO: 2.30.0: interface: The asIScriptModule must have a method for querying if the module is used
if( HasExternalReferences(false) )
{
engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_MODULE_IS_IN_USE);
return asMODULE_IS_IN_USE;
}
// Only one thread may build at one time
// TODO: It should be possible to have multiple threads perform compilations
int r = engine->RequestBuild();
@@ -218,7 +336,7 @@ int asCModule::Build()
return asINVALID_CONFIGURATION;
}
InternalReset();
InternalReset();
if( !builder )
{
@@ -306,8 +424,8 @@ int asCModule::CallInit(asIScriptContext *myCtx)
{
if( ctx == 0 )
{
r = engine->CreateContext(&ctx, true);
if( r < 0 )
ctx = engine->RequestContext();
if( ctx == 0 )
break;
}
@@ -346,7 +464,7 @@ int asCModule::CallInit(asIScriptContext *myCtx)
if( ctx && !myCtx )
{
ctx->Release();
engine->ReturnContext(ctx);
ctx = 0;
}
@@ -401,33 +519,98 @@ void asCModule::CallExit()
isGlobalVarInitialized = false;
}
// internal
bool asCModule::HasExternalReferences(bool shuttingDown)
{
// Check all entiteis in the module for any external references.
// If there are any external references the module cannot be deleted yet.
for( asUINT n = 0; n < scriptFunctions.GetLength(); n++ )
if( scriptFunctions[n] && scriptFunctions[n]->externalRefCount.get() )
{
if( !shuttingDown )
return true;
else
{
asCString msg;
msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf());
engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, scriptFunctions[n]->GetName(), scriptFunctions[n]->GetFuncType());
engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
}
}
for( asUINT n = 0; n < classTypes.GetLength(); n++ )
if( classTypes[n] && classTypes[n]->externalRefCount.get() )
{
if( !shuttingDown )
return true;
else
{
asCString msg;
msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf());
engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
msg.Format(TXT_PREV_TYPE_IS_NAMED_s, classTypes[n]->GetName());
engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
}
}
for( asUINT n = 0; n < funcDefs.GetLength(); n++ )
if( funcDefs[n] && funcDefs[n]->externalRefCount.get() )
{
if( !shuttingDown )
return true;
else
{
asCString msg;
msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf());
engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, funcDefs[n]->GetName(), funcDefs[n]->GetFuncType());
engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
}
}
for( asUINT n = 0; n < templateInstances.GetLength(); n++ )
if( templateInstances[n] && templateInstances[n]->externalRefCount.get() )
{
if( !shuttingDown )
return true;
else
{
asCString msg;
msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf());
engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
msg.Format(TXT_PREV_TYPE_IS_NAMED_s, templateInstances[n]->GetName());
engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
}
}
return false;
}
// internal
void asCModule::InternalReset()
{
CallExit();
size_t n;
asUINT n;
// Release all global functions
asCSymbolTable<asCScriptFunction>::iterator funcIt = globalFunctions.List();
for( ; funcIt; funcIt++ )
(*funcIt)->Release();
// Remove all global functions
globalFunctions.Clear();
// First release all compiled functions
for( n = 0; n < scriptFunctions.GetLength(); n++ )
if( scriptFunctions[n] )
scriptFunctions[n]->Orphan(this);
scriptFunctions.SetLength(0);
// Release the global properties declared in the module
// Destroy the internals of the global properties here, but do not yet remove them from the
// engine, because functions need the engine's varAddressMap to get to the property. If the
// property is removed already, it may leak as the refCount doesn't reach 0.
asCSymbolTableIterator<asCGlobalProperty> globIt = scriptGlobals.List();
while( globIt )
{
(*globIt)->Orphan(this);
(*globIt)->DestroyInternal();
globIt++;
}
scriptGlobals.Clear();
UnbindAllImportedFunctions();
@@ -436,39 +619,156 @@ void asCModule::InternalReset()
{
if( bindInformations[n] )
{
asUINT id = bindInformations[n]->importedFunctionSignature->id & ~FUNC_IMPORTED;
engine->importedFunctions[id] = 0;
engine->freeImportedFunctionIdxs.PushLast(id);
bindInformations[n]->importedFunctionSignature->ReleaseInternal();
asDELETE(bindInformations[n]->importedFunctionSignature, asCScriptFunction);
asDELETE(bindInformations[n], sBindInfo);
}
}
bindInformations.SetLength(0);
// Free declared types, including classes, typedefs, and enums
// TODO: optimize: Check if it is possible to destroy the object directly without notifying the GC
for( n = 0; n < templateInstances.GetLength(); n++ )
{
asCObjectType *type = templateInstances[n];
if( engine->FindNewOwnerForSharedType(type, this) != this )
{
// The type is owned by another module, just release our reference
type->ReleaseInternal();
continue;
}
// Orphan the template instance
type->module = 0;
// No other module is holding the template type
engine->RemoveTemplateInstanceType(type);
type->ReleaseInternal();
}
templateInstances.SetLength(0);
for( n = 0; n < classTypes.GetLength(); n++ )
classTypes[n]->Orphan(this);
{
asCObjectType *type = classTypes[n];
if( type->IsShared() )
{
// The type is shared, so transfer ownership to another module that also uses it
if( engine->FindNewOwnerForSharedType(type, this) != this )
{
// The type is owned by another module, just release our reference
type->ReleaseInternal();
continue;
}
}
// The type should be destroyed now
type->DestroyInternal();
// Remove the type from the engine
if( type->IsShared() )
{
engine->sharedScriptTypes.RemoveValue(type);
type->ReleaseInternal();
}
// Release it from the module
type->module = 0;
type->ReleaseInternal();
}
classTypes.SetLength(0);
for( n = 0; n < enumTypes.GetLength(); n++ )
enumTypes[n]->Release();
{
asCObjectType *type = enumTypes[n];
if( type->IsShared() )
{
// The type is shared, so transfer ownership to another module that also uses it
if( engine->FindNewOwnerForSharedType(type, this) != this )
{
// The type is owned by another module, just release our reference
type->ReleaseInternal();
continue;
}
}
// The type should be destroyed now
type->DestroyInternal();
// Remove the type from the engine
if( type->IsShared() )
{
engine->sharedScriptTypes.RemoveValue(type);
type->ReleaseInternal();
}
// Release it from the module
type->module = 0;
type->ReleaseInternal();
}
enumTypes.SetLength(0);
for( n = 0; n < typeDefs.GetLength(); n++ )
typeDefs[n]->Release();
{
asCObjectType *type = typeDefs[n];
// The type should be destroyed now
type->DestroyInternal();
// Release it from the module
type->module = 0;
type->ReleaseInternal();
}
typeDefs.SetLength(0);
// Free funcdefs
for( n = 0; n < funcDefs.GetLength(); n++ )
{
// The funcdefs are not removed from the engine at this moment as they may still be referred
// to by other types. The engine's ClearUnusedTypes will take care of the clean up.
funcDefs[n]->Release();
asCScriptFunction *func = funcDefs[n];
if( func->IsShared() )
{
// The func is shared, so transfer ownership to another module that also uses it
if( engine->FindNewOwnerForSharedFunc(func, this) != this )
{
// The func is owned by another module, just release our reference
func->ReleaseInternal();
continue;
}
}
func->DestroyInternal();
engine->RemoveFuncdef(func);
func->module = 0;
func->ReleaseInternal();
}
funcDefs.SetLength(0);
// Allow the engine to clean up what is not used
engine->CleanupAfterDiscardModule();
// Then release the functions
for( n = 0; n < scriptFunctions.GetLength(); n++ )
{
asCScriptFunction *func = scriptFunctions[n];
if( func->IsShared() )
{
// The func is shared, so transfer ownership to another module that also uses it
if( engine->FindNewOwnerForSharedFunc(func, this) != this )
{
// The func is owned by another module, just release our reference
func->ReleaseInternal();
continue;
}
}
func->DestroyInternal();
func->module = 0;
func->ReleaseInternal();
}
scriptFunctions.SetLength(0);
// Now remove and release the global properties as there are no more references to them
globIt = scriptGlobals.List();
while( globIt )
{
engine->RemoveGlobalProperty(*globIt);
asASSERT( (*globIt)->refCount.get() == 1 );
(*globIt)->Release();
globIt++;
}
scriptGlobals.Clear();
asASSERT( IsEmpty() );
}
@@ -476,12 +776,22 @@ void asCModule::InternalReset()
// interface
asIScriptFunction *asCModule::GetFunctionByName(const char *name) const
{
const asCArray<unsigned int> &idxs = globalFunctions.GetIndexes(defaultNamespace, name);
if( idxs.GetLength() != 1 )
return 0;
asSNameSpace *ns = defaultNamespace;
while( ns )
{
const asCArray<unsigned int> &idxs = globalFunctions.GetIndexes(ns, name);
if( idxs.GetLength() != 1 )
return 0;
const asIScriptFunction *func = globalFunctions.Get(idxs[0]);
return const_cast<asIScriptFunction*>(func);
const asIScriptFunction *func = globalFunctions.Get(idxs[0]);
if( func )
return const_cast<asIScriptFunction*>(func);
// Recursively search parent namespaces
ns = engine->GetParentNameSpace(ns);
}
return 0;
}
// interface
@@ -562,38 +872,49 @@ asIScriptFunction *asCModule::GetFunctionByDecl(const char *decl) const
asSNameSpace *ns = func.nameSpace == engine->nameSpaces[0] ? defaultNamespace : func.nameSpace;
// Search script functions for matching interface
asIScriptFunction *f = 0;
const asCArray<unsigned int> &idxs = globalFunctions.GetIndexes(ns, func.name);
for( unsigned int n = 0; n < idxs.GetLength(); n++ )
while( ns )
{
const asCScriptFunction *funcPtr = globalFunctions.Get(idxs[n]);
if( funcPtr->objectType == 0 &&
func.returnType == funcPtr->returnType &&
func.parameterTypes.GetLength() == funcPtr->parameterTypes.GetLength()
)
asIScriptFunction *f = 0;
const asCArray<unsigned int> &idxs = globalFunctions.GetIndexes(ns, func.name);
for( unsigned int n = 0; n < idxs.GetLength(); n++ )
{
bool match = true;
for( size_t p = 0; p < func.parameterTypes.GetLength(); ++p )
const asCScriptFunction *funcPtr = globalFunctions.Get(idxs[n]);
if( funcPtr->objectType == 0 &&
func.returnType == funcPtr->returnType &&
func.parameterTypes.GetLength() == funcPtr->parameterTypes.GetLength()
)
{
if( func.parameterTypes[p] != funcPtr->parameterTypes[p] )
bool match = true;
for( asUINT p = 0; p < func.parameterTypes.GetLength(); ++p )
{
match = false;
break;
if( func.parameterTypes[p] != funcPtr->parameterTypes[p] )
{
match = false;
break;
}
}
if( match )
{
if( f == 0 )
f = const_cast<asCScriptFunction*>(funcPtr);
else
// Multiple functions
return 0;
}
}
}
if( match )
{
if( f == 0 )
f = const_cast<asCScriptFunction*>(funcPtr);
else
// Multiple functions
return 0;
}
if( f )
return f;
else
{
// Search for matching functions in the parent namespace
ns = engine->GetParentNameSpace(ns);
}
}
return f;
return 0;
}
// interface
@@ -605,21 +926,41 @@ asUINT asCModule::GetGlobalVarCount() const
// interface
int asCModule::GetGlobalVarIndexByName(const char *name) const
{
asSNameSpace *ns = defaultNamespace;
// Find the global var id
int id = scriptGlobals.GetFirstIndex(defaultNamespace, name);
while( ns )
{
int id = scriptGlobals.GetFirstIndex(ns, name);
if( id >= 0 ) return id;
if( id == -1 ) return asNO_GLOBAL_VAR;
// Recursively search parent namespaces
ns = engine->GetParentNameSpace(ns);
}
return id;
return asNO_GLOBAL_VAR;
}
// interface
int asCModule::RemoveGlobalVar(asUINT index)
{
// TODO: 2.30.0: redesign: Before removing the variable, clear it to free the object
// The property shouldn't be orphaned.
asCGlobalProperty *prop = scriptGlobals.Get(index);
if( !prop )
return asINVALID_ARG;
prop->Orphan(this);
// Destroy the internal of the global variable (removes the initialization function)
prop->DestroyInternal();
// Check if the module is the only one referring to the module, if so remove it from the engine too
// If the property is not removed now, it will be removed later when the module is discarded
if( prop->refCount.get() == 2 )
engine->RemoveGlobalProperty(prop);
// Remove the global variable from the module
prop->Release();
scriptGlobals.Erase(index);
return 0;
@@ -641,9 +982,15 @@ int asCModule::GetGlobalVarIndexByDecl(const char *decl) const
return r;
// Search global variables for a match
int id = scriptGlobals.GetFirstIndex(nameSpace, name, asCCompGlobPropType(dt));
if( id != -1 )
return id;
while( nameSpace )
{
int id = scriptGlobals.GetFirstIndex(nameSpace, name, asCCompGlobPropType(dt));
if( id != -1 )
return id;
// Recursively search parent namespace
nameSpace = engine->GetParentNameSpace(nameSpace);
}
return asNO_GLOBAL_VAR;
}
@@ -670,9 +1017,9 @@ const char *asCModule::GetGlobalVarDeclaration(asUINT index, bool includeNamespa
if (!prop) return 0;
asCString *tempString = &asCThreadManager::GetLocalData()->string;
*tempString = prop->type.Format();
*tempString = prop->type.Format(defaultNamespace);
*tempString += " ";
if( includeNamespace )
if( includeNamespace && prop->nameSpace->name != "" )
*tempString += prop->nameSpace->name + "::";
*tempString += prop->name;
@@ -715,12 +1062,19 @@ asIObjectType *asCModule::GetObjectTypeByIndex(asUINT index) const
// interface
asIObjectType *asCModule::GetObjectTypeByName(const char *name) const
{
for( asUINT n = 0; n < classTypes.GetLength(); n++ )
asSNameSpace *ns = defaultNamespace;
while( ns )
{
if( classTypes[n] &&
classTypes[n]->name == name &&
classTypes[n]->nameSpace == defaultNamespace )
return classTypes[n];
for( asUINT n = 0; n < classTypes.GetLength(); n++ )
{
if( classTypes[n] &&
classTypes[n]->name == name &&
classTypes[n]->nameSpace == ns )
return classTypes[n];
}
// Recursively search parent namespace
ns = engine->GetParentNameSpace(ns);
}
return 0;
@@ -744,6 +1098,24 @@ int asCModule::GetTypeIdByDecl(const char *decl) const
return engine->GetTypeIdFromDataType(dt);
}
// interface
asIObjectType *asCModule::GetObjectTypeByDecl(const char *decl) const
{
asCDataType dt;
// This const cast is safe since we know the engine won't be modified
asCBuilder bld(engine, const_cast<asCModule*>(this));
// Don't write parser errors to the message callback
bld.silent = true;
int r = bld.ParseDataType(decl, &dt, defaultNamespace);
if( r < 0 )
return 0;
return dt.GetObjectType();
}
// interface
asUINT asCModule::GetEnumCount() const
{
@@ -827,7 +1199,7 @@ int asCModule::GetNextImportedFunctionId()
#ifndef AS_NO_COMPILER
// internal
int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &name, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, bool isInterface, asCObjectType *objType, bool isConstMethod, bool isGlobalFunction, bool isPrivate, bool isFinal, bool isOverride, bool isShared, asSNameSpace *ns)
int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &name, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asCString> &paramNames, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, bool isInterface, asCObjectType *objType, bool isConstMethod, bool isGlobalFunction, bool isPrivate, bool isProtected, bool isFinal, bool isOverride, bool isShared, asSNameSpace *ns)
{
asASSERT(id >= 0);
@@ -860,11 +1232,15 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a
func->scriptData->declaredAt = declaredAt;
}
func->parameterTypes = params;
func->parameterNames = paramNames;
func->inOutFlags = inOutFlags;
func->defaultArgs = defaultArgs;
func->objectType = objType;
if( objType )
objType->AddRefInternal();
func->isReadOnly = isConstMethod;
func->isPrivate = isPrivate;
func->isProtected = isProtected;
func->isFinal = isFinal;
func->isOverride = isOverride;
func->isShared = isShared;
@@ -875,9 +1251,9 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a
asASSERT( !(!objType && isFinal) );
asASSERT( !(!objType && isOverride) );
// The script function's refCount was initialized to 1
// The internal ref count was already set by the constructor
scriptFunctions.PushLast(func);
engine->SetScriptFunction(func);
engine->AddScriptFunction(func);
// Compute the signature id
if( objType )
@@ -885,10 +1261,7 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a
// Add reference
if( isGlobalFunction )
{
globalFunctions.Put(func);
func->AddRef();
}
return 0;
}
@@ -897,8 +1270,8 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a
int asCModule::AddScriptFunction(asCScriptFunction *func)
{
scriptFunctions.PushLast(func);
func->AddRef();
engine->SetScriptFunction(func);
func->AddRefInternal();
engine->AddScriptFunction(func);
return 0;
}
@@ -982,14 +1355,14 @@ int asCModule::BindImportedFunction(asUINT index, asIScriptFunction *func)
if( dst->parameterTypes.GetLength() != src->parameterTypes.GetLength() )
return asINVALID_INTERFACE;
for( size_t n = 0; n < dst->parameterTypes.GetLength(); ++n )
for( asUINT n = 0; n < dst->parameterTypes.GetLength(); ++n )
{
if( dst->parameterTypes[n] != src->parameterTypes[n] )
return asINVALID_INTERFACE;
}
bindInformations[index]->boundFunctionId = src->GetId();
src->AddRef();
src->AddRefInternal();
return asSUCCESS;
}
@@ -1007,7 +1380,7 @@ int asCModule::UnbindImportedFunction(asUINT index)
if( oldFuncID != -1 )
{
bindInformations[index]->boundFunctionId = -1;
engine->scriptFunctions[oldFuncID]->Release();
engine->scriptFunctions[oldFuncID]->ReleaseInternal();
}
}
@@ -1047,7 +1420,7 @@ int asCModule::BindAllImportedFunctions()
asCScriptFunction *importFunc = GetImportedFunction(n);
if( importFunc == 0 ) return asERROR;
asCString str = importFunc->GetDeclarationStr();
asCString str = importFunc->GetDeclarationStr(false, true);
// Get module name from where the function should be imported
const char *moduleName = GetImportedFunctionSourceModule(n);
@@ -1086,7 +1459,7 @@ int asCModule::UnbindAllImportedFunctions()
// internal
asCObjectType *asCModule::GetObjectType(const char *type, asSNameSpace *ns)
{
size_t n;
asUINT n;
// TODO: optimize: Improve linear search
for( n = 0; n < classTypes.GetLength(); n++ )
@@ -1121,8 +1494,9 @@ asCGlobalProperty *asCModule::AllocateGlobalProperty(const char *name, const asC
// Make an entry in the address to variable map
engine->varAddressMap.Insert(prop->GetAddressOfValue(), prop);
// Store the variable in the module scope (the reference count is already set to 1)
// Store the variable in the module scope
scriptGlobals.Put(prop);
prop->AddRef();
return prop;
}
@@ -1166,6 +1540,14 @@ int asCModule::LoadByteCode(asIBinaryStream *in, bool *wasDebugInfoStripped)
{
if( in == 0 ) return asINVALID_ARG;
// Don't allow the module to be rebuilt if there are still
// external references that will need the previous code
if( HasExternalReferences(false) )
{
engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_MODULE_IS_IN_USE);
return asMODULE_IS_IN_USE;
}
// Only permit loading bytecode if no other thread is currently compiling
// TODO: It should be possible to have multiple threads perform compilations
int r = engine->RequestBuild();
@@ -1302,14 +1684,14 @@ int asCModule::CompileFunction(const char *sectionName, const char *code, int li
if( r >= 0 && outFunc && func )
{
// Return the function to the caller
// Return the function to the caller and add an external reference
*outFunc = func;
func->AddRef();
}
// Release our reference to the function
if( func )
func->Release();
func->ReleaseInternal();
return r;
#endif
@@ -1318,15 +1700,24 @@ int asCModule::CompileFunction(const char *sectionName, const char *code, int li
// interface
int asCModule::RemoveFunction(asIScriptFunction *func)
{
// TODO: 2.30.0: redesign: Check if there are any references before removing the function
// if there are, just hide it from the visible but do not destroy or
// remove it from the module.
//
// Only if the function has no live references, nor internal references
// can it be immediately removed, and its internal references released.
//
// Check if any previously hidden functions are without references,
// if so they should removed too.
// Find the global function
asCScriptFunction *f = static_cast<asCScriptFunction*>(func);
int idx = globalFunctions.GetIndex(f);
if( idx >= 0 )
{
globalFunctions.Erase(idx);
f->Release();
scriptFunctions.RemoveValue(f);
f->Orphan(this);
f->ReleaseInternal();
return 0;
}
@@ -1348,7 +1739,7 @@ int asCModule::AddFuncDef(const asCString &name, asSNameSpace *ns)
engine->funcDefs.PushLast(func);
func->id = engine->GetNextScriptFunctionId();
engine->SetScriptFunction(func);
engine->AddScriptFunction(func);
return (int)funcDefs.GetLength()-1;
}
+26 -20
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -132,6 +132,7 @@ public:
virtual asUINT GetObjectTypeCount() const;
virtual asIObjectType *GetObjectTypeByIndex(asUINT index) const;
virtual asIObjectType *GetObjectTypeByName(const char *name) const;
virtual asIObjectType *GetObjectTypeByDecl(const char *decl) const;
virtual int GetTypeIdByDecl(const char *decl) const;
// Enums
@@ -159,8 +160,8 @@ public:
virtual int LoadByteCode(asIBinaryStream *in, bool *wasDebugInfoStripped);
// User data
virtual void *SetUserData(void *data);
virtual void *GetUserData() const;
virtual void *SetUserData(void *data, asPWORD type);
virtual void *GetUserData(asPWORD type) const;
//-----------------------------------------------
// Internal
@@ -177,6 +178,7 @@ public:
void InternalReset();
bool IsEmpty() const;
bool HasExternalReferences(bool shuttingDown);
int CallInit(asIScriptContext *ctx);
void CallExit();
@@ -184,7 +186,7 @@ public:
void JITCompile();
#ifndef AS_NO_COMPILER
int AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &name, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, bool isInterface, asCObjectType *objType = 0, bool isConstMethod = false, bool isGlobalFunction = false, bool isPrivate = false, bool isFinal = false, bool isOverride = false, bool isShared = false, asSNameSpace *ns = 0);
int AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &name, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asCString> &paramNames, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, bool isInterface, asCObjectType *objType = 0, bool isConstMethod = false, bool isGlobalFunction = false, bool isPrivate = false, bool isProtected = false, bool isFinal = false, bool isOverride = false, bool isShared = false, asSNameSpace *ns = 0);
int AddScriptFunction(asCScriptFunction *func);
int AddImportedFunction(int id, const asCString &name, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, asSNameSpace *ns, const asCString &moduleName);
int AddFuncDef(const asCString &name, asSNameSpace *ns);
@@ -197,31 +199,35 @@ public:
asCString name;
asCScriptEngine *engine;
asCBuilder *builder;
void *userData;
asDWORD accessMask;
asSNameSpace *defaultNamespace;
asCScriptEngine *engine;
asCBuilder *builder;
asCArray<asPWORD> userData;
asDWORD accessMask;
asSNameSpace *defaultNamespace;
// This array holds all functions, class members, factories, etc that were compiled with the module
asCArray<asCScriptFunction *> scriptFunctions;
// This array holds global functions declared in the module
asCSymbolTable<asCScriptFunction> globalFunctions;
// This array holds imported functions in the module
asCArray<sBindInfo *> bindInformations;
// This array holds all functions, class members, factories, etc that were compiled with the module.
// These references hold an internal reference to the function object.
asCArray<asCScriptFunction *> scriptFunctions; // increases ref count
// This array holds global functions declared in the module. These references are not counted,
// as the same pointer is always present in the scriptFunctions array too.
asCSymbolTable<asCScriptFunction> globalFunctions; // doesn't increase ref count
// This array holds imported functions in the module.
asCArray<sBindInfo *> bindInformations; // increases ref count
// This array holds template instance types created for the module's object types
asCArray<asCObjectType*> templateInstances; // increases ref count
// This array holds the global variables declared in the script
asCSymbolTable<asCGlobalProperty> scriptGlobals;
asCSymbolTable<asCGlobalProperty> scriptGlobals; // increases ref count
bool isGlobalVarInitialized;
// This array holds class and interface types
asCArray<asCObjectType*> classTypes;
asCArray<asCObjectType*> classTypes; // increases ref count
// This array holds enum types
asCArray<asCObjectType*> enumTypes;
asCArray<asCObjectType*> enumTypes; // increases ref count
// This array holds typedefs
asCArray<asCObjectType*> typeDefs;
asCArray<asCObjectType*> typeDefs; // increases ref count
// This array holds the funcdefs declared in the module
asCArray<asCScriptFunction*> funcDefs;
asCArray<asCScriptFunction*> funcDefs; // increases ref count
};
END_AS_NAMESPACE
+3 -2
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2013 Andreas Jonsson
Copyright (c) 2013-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -73,4 +73,5 @@ struct asSNameSpaceNamePair
END_AS_NAMESPACE
#endif
#endif
+151 -266
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2015 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -45,140 +45,95 @@
BEGIN_AS_NAMESPACE
#ifdef AS_MAX_PORTABILITY
static void ObjectType_AddRef_Generic(asIScriptGeneric *gen)
{
asCObjectType *self = (asCObjectType*)gen->GetObject();
self->AddRef();
}
static void ObjectType_Release_Generic(asIScriptGeneric *gen)
{
asCObjectType *self = (asCObjectType*)gen->GetObject();
self->Release();
}
static void ObjectType_GetRefCount_Generic(asIScriptGeneric *gen)
{
asCObjectType *self = (asCObjectType*)gen->GetObject();
*(int*)gen->GetAddressOfReturnLocation() = self->GetRefCount();
}
static void ObjectType_SetGCFlag_Generic(asIScriptGeneric *gen)
{
asCObjectType *self = (asCObjectType*)gen->GetObject();
self->SetGCFlag();
}
static void ObjectType_GetGCFlag_Generic(asIScriptGeneric *gen)
{
asCObjectType *self = (asCObjectType*)gen->GetObject();
*(bool*)gen->GetAddressOfReturnLocation() = self->GetGCFlag();
}
static void ObjectType_EnumReferences_Generic(asIScriptGeneric *gen)
{
asCObjectType *self = (asCObjectType*)gen->GetObject();
asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
self->EnumReferences(engine);
}
static void ObjectType_ReleaseAllHandles_Generic(asIScriptGeneric *gen)
{
asCObjectType *self = (asCObjectType*)gen->GetObject();
asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
self->ReleaseAllHandles(engine);
}
#endif
void RegisterObjectTypeGCBehaviours(asCScriptEngine *engine)
{
// Register the gc behaviours for the object types
int r = 0;
UNUSED_VAR(r); // It is only used in debug mode
engine->objectTypeBehaviours.engine = engine;
engine->objectTypeBehaviours.flags = asOBJ_REF | asOBJ_GC;
engine->objectTypeBehaviours.name = "_builtin_objecttype_";
#ifndef AS_MAX_PORTABILITY
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCObjectType,AddRef), asCALL_THISCALL, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_RELEASE, "void f()", asMETHOD(asCObjectType,Release), asCALL_THISCALL, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(asCObjectType,GetRefCount), asCALL_THISCALL, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_SETGCFLAG, "void f()", asMETHOD(asCObjectType,SetGCFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(asCObjectType,GetGCFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(asCObjectType,EnumReferences), asCALL_THISCALL, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(asCObjectType,ReleaseAllHandles), asCALL_THISCALL, 0); asASSERT( r >= 0 );
#else
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_ADDREF, "void f()", asFUNCTION(ObjectType_AddRef_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_RELEASE, "void f()", asFUNCTION(ObjectType_Release_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ObjectType_GetRefCount_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ObjectType_SetGCFlag_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ObjectType_GetGCFlag_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ObjectType_EnumReferences_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ObjectType_ReleaseAllHandles_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
#endif
}
asCObjectType::asCObjectType()
{
engine = 0;
module = 0;
refCount.set(0);
externalRefCount.set(0);
internalRefCount.set(1); // start with one internal ref-count
engine = 0;
module = 0;
derivedFrom = 0;
size = 0;
acceptValueSubType = true;
acceptRefSubType = true;
acceptRefSubType = true;
scriptSectionIdx = -1;
declaredAt = 0;
accessMask = 0xFFFFFFFF;
nameSpace = 0;
nameSpace = 0;
#ifdef WIP_16BYTE_ALIGN
alignment = 4;
#endif
}
asCObjectType::asCObjectType(asCScriptEngine *engine)
{
externalRefCount.set(0);
internalRefCount.set(1); // start with one internal ref count
this->engine = engine;
module = 0;
refCount.set(0);
module = 0;
derivedFrom = 0;
acceptValueSubType = true;
acceptRefSubType = true;
acceptRefSubType = true;
scriptSectionIdx = -1;
declaredAt = 0;
accessMask = 0xFFFFFFFF;
nameSpace = engine->nameSpaces[0];
nameSpace = engine->nameSpaces[0];
#ifdef WIP_16BYTE_ALIGN
alignment = 4;
#endif
}
int asCObjectType::AddRef() const
{
gcFlag = false;
return refCount.atomicInc();
return externalRefCount.atomicInc();
}
int asCObjectType::Release() const
{
gcFlag = false;
return refCount.atomicDec();
}
int r = externalRefCount.atomicDec();
void asCObjectType::Orphan(asCModule *mod)
{
if( mod && mod == module )
if( r == 0 )
{
module = 0;
if( flags & asOBJ_SCRIPT_OBJECT )
// There are no more external references, if there are also no
// internal references then it is time to delete the object type
if( internalRefCount.get() == 0 )
{
// Tell the GC that this type exists so it can resolve potential circular references
engine->gc.AddScriptObjectToGC(this, &engine->objectTypeBehaviours);
// It's necessary to orphan the template instance types that refer to this object type,
// otherwise the garbage collector cannot identify the circular references that involve
// the type and the template type
engine->OrphanTemplateInstances(this);
// If the engine is no longer set, then it has already been
// released and we must take care of the deletion ourselves
asDELETE(const_cast<asCObjectType*>(this), asCObjectType);
}
}
Release();
return r;
}
int asCObjectType::AddRefInternal()
{
return internalRefCount.atomicInc();
}
int asCObjectType::ReleaseInternal()
{
int r = internalRefCount.atomicDec();
if( r == 0 )
{
// There are no more internal references, if there are also no
// external references then it is time to delete the object type
if( externalRefCount.get() == 0 )
{
// If the engine is no longer set, then it has already been
// released and we must take care of the deletion ourselves
asDELETE(const_cast<asCObjectType*>(this), asCObjectType);
}
}
return r;
}
// interface
@@ -237,36 +192,29 @@ void *asCObjectType::GetUserData(asPWORD type) const
return 0;
}
int asCObjectType::GetRefCount()
void asCObjectType::DestroyInternal()
{
return refCount.get();
}
if( engine == 0 ) return;
bool asCObjectType::GetGCFlag()
{
return gcFlag;
}
void asCObjectType::SetGCFlag()
{
gcFlag = true;
}
asCObjectType::~asCObjectType()
{
// Skip this for list patterns as they do not increase the references
if( flags & asOBJ_LIST_PATTERN )
{
// Clear the engine pointer to mark the object type as invalid
engine = 0;
return;
}
// Release the object types held by the templateSubTypes
for( asUINT subtypeIndex = 0; subtypeIndex < templateSubTypes.GetLength(); subtypeIndex++ )
{
if( templateSubTypes[subtypeIndex].GetObjectType() )
templateSubTypes[subtypeIndex].GetObjectType()->Release();
templateSubTypes[subtypeIndex].GetObjectType()->ReleaseInternal();
}
templateSubTypes.SetLength(0);
if( derivedFrom )
derivedFrom->Release();
derivedFrom->ReleaseInternal();
derivedFrom = 0;
ReleaseAllProperties();
@@ -290,6 +238,22 @@ asCObjectType::~asCObjectType()
engine->cleanObjectTypeFuncs[c].cleanFunc(this);
}
}
userData.SetLength(0);
// Remove the type from the engine
engine->RemoveFromTypeIdMap(this);
// Clear the engine pointer to mark the object type as invalid
engine = 0;
}
asCObjectType::~asCObjectType()
{
if( engine == 0 )
return;
// TODO: 2.30.0: redesign: Shouldn't this have been done already?
DestroyInternal();
}
// interface
@@ -369,30 +333,23 @@ int asCObjectType::GetTypeId() const
// interface
int asCObjectType::GetSubTypeId(asUINT subtypeIndex) const
{
if( flags & asOBJ_TEMPLATE )
{
if( subtypeIndex >= templateSubTypes.GetLength() )
return asINVALID_ARG;
// This method is only supported for templates and template specializations
if( templateSubTypes.GetLength() == 0 )
return asERROR;
return engine->GetTypeIdFromDataType(templateSubTypes[subtypeIndex]);
}
if( subtypeIndex >= templateSubTypes.GetLength() )
return asINVALID_ARG;
// Only template types have sub types
return asERROR;
return engine->GetTypeIdFromDataType(templateSubTypes[subtypeIndex]);
}
// interface
asIObjectType *asCObjectType::GetSubType(asUINT subtypeIndex) const
{
if( flags & asOBJ_TEMPLATE )
{
if( subtypeIndex >= templateSubTypes.GetLength() )
return 0;
if( subtypeIndex >= templateSubTypes.GetLength() )
return 0;
return templateSubTypes[subtypeIndex].GetObjectType();
}
return 0;
return templateSubTypes[subtypeIndex].GetObjectType();
}
asUINT asCObjectType::GetSubTypeCount() const
@@ -475,7 +432,7 @@ asIScriptFunction *asCObjectType::GetMethodByIndex(asUINT index, bool getVirtual
asIScriptFunction *asCObjectType::GetMethodByName(const char *name, bool getVirtual) const
{
int id = -1;
for( size_t n = 0; n < methods.GetLength(); n++ )
for( asUINT n = 0; n < methods.GetLength(); n++ )
{
if( engine->scriptFunctions[methods[n]]->name == name )
{
@@ -532,23 +489,26 @@ asUINT asCObjectType::GetPropertyCount() const
}
// interface
int asCObjectType::GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, int *offset, bool *isReference, asDWORD *accessMask) const
int asCObjectType::GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, bool *isProtected, int *offset, bool *isReference, asDWORD *accessMask) const
{
if( index >= properties.GetLength() )
return asINVALID_ARG;
asCObjectProperty *prop = properties[index];
if( name )
*name = properties[index]->name.AddressOf();
*name = prop->name.AddressOf();
if( typeId )
*typeId = engine->GetTypeIdFromDataType(properties[index]->type);
*typeId = engine->GetTypeIdFromDataType(prop->type);
if( isPrivate )
*isPrivate = properties[index]->isPrivate;
*isPrivate = prop->isPrivate;
if( isProtected )
*isProtected = prop->isProtected;
if( offset )
*offset = properties[index]->byteOffset;
*offset = prop->byteOffset;
if( isReference )
*isReference = properties[index]->type.IsReference();
*isReference = prop->type.IsReference();
if( accessMask )
*accessMask = properties[index]->accessMask;
*accessMask = prop->accessMask;
return 0;
}
@@ -562,9 +522,11 @@ const char *asCObjectType::GetPropertyDeclaration(asUINT index, bool includeName
asCString *tempString = &asCThreadManager::GetLocalData()->string;
if( properties[index]->isPrivate )
*tempString = "private ";
else if( properties[index]->isProtected )
*tempString = "protected ";
else
*tempString = "";
*tempString += properties[index]->type.Format(includeNamespace);
*tempString += properties[index]->type.Format(nameSpace, includeNamespace);
*tempString += " ";
*tempString += properties[index]->name;
@@ -596,7 +558,6 @@ asUINT asCObjectType::GetBehaviourCount() const
// For reference types, the factories are also stored in the constructor
// list, so it is sufficient to enumerate only those
count += (asUINT)beh.constructors.GetLength();
count += (asUINT)beh.operators.GetLength() / 2;
return count;
}
@@ -689,14 +650,6 @@ asIScriptFunction *asCObjectType::GetBehaviourByIndex(asUINT index, asEBehaviour
else
count += (asUINT)beh.constructors.GetLength();
if( index - count < beh.operators.GetLength() / 2 )
{
index = 2*(index - count);
if( outBehaviour ) *outBehaviour = static_cast<asEBehaviours>(beh.operators[index]);
return engine->scriptFunctions[beh.operators[index + 1]];
}
return 0;
}
@@ -717,10 +670,10 @@ asDWORD asCObjectType::GetAccessMask() const
}
// internal
asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &name, const asCDataType &dt, bool isPrivate)
asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &name, const asCDataType &dt, bool isPrivate, bool isProtected, bool isInherited)
{
asASSERT( flags & asOBJ_SCRIPT_OBJECT );
asASSERT( dt.CanBeInstanciated() );
asASSERT( dt.CanBeInstantiated() );
asASSERT( !IsInterface() );
// Store the properties in the object type descriptor
@@ -731,9 +684,11 @@ asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &name, cons
return 0;
}
prop->name = name;
prop->type = dt;
prop->isPrivate = isPrivate;
prop->name = name;
prop->type = dt;
prop->isPrivate = isPrivate;
prop->isProtected = isProtected;
prop->isInherited = isInherited;
int propSize;
if( dt.IsObject() )
@@ -755,8 +710,19 @@ asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &name, cons
propSize = dt.GetSizeInMemoryBytes();
// Add extra bytes so that the property will be properly aligned
#ifndef WIP_16BYTE_ALIGN
if( propSize == 2 && (size & 1) ) size += 1;
if( propSize > 2 && (size & 3) ) size += 4 - (size & 3);
#else
asUINT alignment = dt.GetAlignment();
const asUINT propSizeAlignmentDifference = size & (alignment-1);
if( propSizeAlignmentDifference != 0 )
{
size += (alignment - propSizeAlignmentDifference);
}
asASSERT((size % alignment) == 0);
#endif
prop->byteOffset = size;
size += propSize;
@@ -770,7 +736,7 @@ asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &name, cons
// Add reference to object types
asCObjectType *type = prop->type.GetObjectType();
if( type )
type->AddRef();
type->AddRefInternal();
return prop;
}
@@ -791,7 +757,14 @@ void asCObjectType::ReleaseAllProperties()
// Release references to objects types
asCObjectType *type = properties[n]->type.GetObjectType();
if( type )
type->Release();
type->ReleaseInternal();
}
else
{
// Release template instance types (ref increased by RegisterObjectProperty)
asCObjectType *type = properties[n]->type.GetObjectType();
if( type )
type->ReleaseInternal();
}
asDELETE(properties[n],asCObjectProperty);
@@ -801,13 +774,6 @@ void asCObjectType::ReleaseAllProperties()
properties.SetLength(0);
}
// internal
void asCObjectType::ReleaseAllHandles(asIScriptEngine *)
{
ReleaseAllFunctions();
ReleaseAllProperties();
}
// internal
void asCObjectType::ReleaseAllFunctions()
{
@@ -816,7 +782,7 @@ void asCObjectType::ReleaseAllFunctions()
for( asUINT a = 0; a < beh.factories.GetLength(); a++ )
{
if( engine->scriptFunctions[beh.factories[a]] )
engine->scriptFunctions[beh.factories[a]]->Release();
engine->scriptFunctions[beh.factories[a]]->ReleaseInternal();
}
beh.factories.SetLength(0);
@@ -825,155 +791,74 @@ void asCObjectType::ReleaseAllFunctions()
for( asUINT b = 0; b < beh.constructors.GetLength(); b++ )
{
if( engine->scriptFunctions[beh.constructors[b]] )
engine->scriptFunctions[beh.constructors[b]]->Release();
engine->scriptFunctions[beh.constructors[b]]->ReleaseInternal();
}
beh.constructors.SetLength(0);
if( beh.templateCallback )
engine->scriptFunctions[beh.templateCallback]->Release();
engine->scriptFunctions[beh.templateCallback]->ReleaseInternal();
beh.templateCallback = 0;
if( beh.listFactory )
engine->scriptFunctions[beh.listFactory]->Release();
engine->scriptFunctions[beh.listFactory]->ReleaseInternal();
beh.listFactory = 0;
if( beh.destruct )
engine->scriptFunctions[beh.destruct]->Release();
engine->scriptFunctions[beh.destruct]->ReleaseInternal();
beh.destruct = 0;
if( beh.copy )
engine->scriptFunctions[beh.copy]->Release();
engine->scriptFunctions[beh.copy]->ReleaseInternal();
beh.copy = 0;
for( asUINT e = 1; e < beh.operators.GetLength(); e += 2 )
{
if( engine->scriptFunctions[beh.operators[e]] )
engine->scriptFunctions[beh.operators[e]]->Release();
}
beh.operators.SetLength(0);
for( asUINT c = 0; c < methods.GetLength(); c++ )
{
if( engine->scriptFunctions[methods[c]] )
engine->scriptFunctions[methods[c]]->Release();
engine->scriptFunctions[methods[c]]->ReleaseInternal();
}
methods.SetLength(0);
for( asUINT d = 0; d < virtualFunctionTable.GetLength(); d++ )
{
if( virtualFunctionTable[d] )
virtualFunctionTable[d]->Release();
virtualFunctionTable[d]->ReleaseInternal();
}
virtualFunctionTable.SetLength(0);
// GC behaviours
if( beh.addref )
engine->scriptFunctions[beh.addref]->Release();
engine->scriptFunctions[beh.addref]->ReleaseInternal();
beh.addref = 0;
if( beh.release )
engine->scriptFunctions[beh.release]->Release();
engine->scriptFunctions[beh.release]->ReleaseInternal();
beh.release = 0;
if( beh.gcEnumReferences )
engine->scriptFunctions[beh.gcEnumReferences]->Release();
engine->scriptFunctions[beh.gcEnumReferences]->ReleaseInternal();
beh.gcEnumReferences = 0;
if( beh.gcGetFlag )
engine->scriptFunctions[beh.gcGetFlag]->Release();
engine->scriptFunctions[beh.gcGetFlag]->ReleaseInternal();
beh.gcGetFlag = 0;
if( beh.gcGetRefCount )
engine->scriptFunctions[beh.gcGetRefCount]->Release();
engine->scriptFunctions[beh.gcGetRefCount]->ReleaseInternal();
beh.gcGetRefCount = 0;
if( beh.gcReleaseAllReferences )
engine->scriptFunctions[beh.gcReleaseAllReferences]->Release();
engine->scriptFunctions[beh.gcReleaseAllReferences]->ReleaseInternal();
beh.gcReleaseAllReferences = 0;
if( beh.gcSetFlag )
engine->scriptFunctions[beh.gcSetFlag]->Release();
engine->scriptFunctions[beh.gcSetFlag]->ReleaseInternal();
beh.gcSetFlag = 0;
if ( beh.getWeakRefFlag )
engine->scriptFunctions[beh.getWeakRefFlag]->Release();
engine->scriptFunctions[beh.getWeakRefFlag]->ReleaseInternal();
beh.getWeakRefFlag = 0;
}
// internal
void asCObjectType::EnumReferences(asIScriptEngine *)
{
for( asUINT a = 0; a < beh.factories.GetLength(); a++ )
if( engine->scriptFunctions[beh.factories[a]] )
engine->GCEnumCallback(engine->scriptFunctions[beh.factories[a]]);
for( asUINT b = 0; b < beh.constructors.GetLength(); b++ )
if( engine->scriptFunctions[beh.constructors[b]] )
engine->GCEnumCallback(engine->scriptFunctions[beh.constructors[b]]);
if( beh.templateCallback )
engine->GCEnumCallback(engine->scriptFunctions[beh.templateCallback]);
if( beh.listFactory )
engine->GCEnumCallback(engine->scriptFunctions[beh.listFactory]);
if( beh.destruct )
engine->GCEnumCallback(engine->scriptFunctions[beh.destruct]);
if( beh.addref )
engine->GCEnumCallback(engine->scriptFunctions[beh.addref]);
if( beh.release )
engine->GCEnumCallback(engine->scriptFunctions[beh.release]);
if( beh.copy )
engine->GCEnumCallback(engine->scriptFunctions[beh.copy]);
if( beh.gcEnumReferences )
engine->GCEnumCallback(engine->scriptFunctions[beh.gcEnumReferences]);
if( beh.gcGetFlag )
engine->GCEnumCallback(engine->scriptFunctions[beh.gcGetFlag]);
if( beh.gcGetRefCount )
engine->GCEnumCallback(engine->scriptFunctions[beh.gcGetRefCount]);
if( beh.gcReleaseAllReferences )
engine->GCEnumCallback(engine->scriptFunctions[beh.gcReleaseAllReferences]);
if( beh.gcSetFlag )
engine->GCEnumCallback(engine->scriptFunctions[beh.gcSetFlag]);
for( asUINT e = 1; e < beh.operators.GetLength(); e += 2 )
if( engine->scriptFunctions[beh.operators[e]] )
engine->GCEnumCallback(engine->scriptFunctions[beh.operators[e]]);
for( asUINT c = 0; c < methods.GetLength(); c++ )
if( engine->scriptFunctions[methods[c]] )
engine->GCEnumCallback(engine->scriptFunctions[methods[c]]);
for( asUINT d = 0; d < virtualFunctionTable.GetLength(); d++ )
if( virtualFunctionTable[d] )
engine->GCEnumCallback(virtualFunctionTable[d]);
for( asUINT p = 0; p < properties.GetLength(); p++ )
{
asCObjectType *type = properties[p]->type.GetObjectType();
if( type )
engine->GCEnumCallback(type);
}
for( asUINT t = 0; t < templateSubTypes.GetLength(); t++ )
if( templateSubTypes[t].GetObjectType() )
engine->GCEnumCallback(templateSubTypes[t].GetObjectType());
if( beh.getWeakRefFlag )
engine->GCEnumCallback(engine->scriptFunctions[beh.getWeakRefFlag]);
if( derivedFrom )
engine->GCEnumCallback(derivedFrom);
}
END_AS_NAMESPACE
+20 -36
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -51,28 +51,6 @@ BEGIN_AS_NAMESPACE
// TODO: memory: Need to minimize used memory here, because not all types use all properties of the class
// TODO: The type id should have flags for differenciating between value types and reference types. It should also have a flag for differenciating interface types.
// Additional flag to the class object type
const asDWORD asOBJ_IMPLICIT_HANDLE = 0x00400000;
const asDWORD asOBJ_LIST_PATTERN = 0x08000000;
const asDWORD asOBJ_ENUM = 0x10000000;
const asDWORD asOBJ_TEMPLATE_SUBTYPE = 0x20000000;
const asDWORD asOBJ_TYPEDEF = 0x40000000;
// asOBJ_GC is used to indicate that the type can potentially
// form circular references, thus is garbage collected.
// The fact that an object is garbage collected doesn't imply that an other object
// that can reference it also must be garbage collected, only if the garbage collected
// object can reference the other object as well.
// For registered types however, we set the flag asOBJ_GC if the GC
// behaviours are registered. For script types that contain any such type we
// automatically make garbage collected as well, because we cannot know what type
// of references that object can contain, and must assume the worst.
struct asSTypeBehaviour
{
@@ -119,7 +97,6 @@ struct asSTypeBehaviour
asCArray<int> factories;
asCArray<int> constructors;
asCArray<int> operators;
};
struct asSEnumValue
@@ -131,8 +108,6 @@ struct asSEnumValue
class asCScriptEngine;
struct asSNameSpace;
void RegisterObjectTypeGCBehaviours(asCScriptEngine *engine);
class asCObjectType : public asIObjectType
{
public:
@@ -178,7 +153,7 @@ public:
// Properties
asUINT GetPropertyCount() const;
int GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, int *offset, bool *isReference, asDWORD *accessMask) const;
int GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, bool *isProtected, int *offset, bool *isReference, asDWORD *accessMask) const;
const char *GetPropertyDeclaration(asUINT index, bool includeNamespace = false) const;
// Behaviours
@@ -195,25 +170,27 @@ public:
public:
asCObjectType(asCScriptEngine *engine);
~asCObjectType();
void DestroyInternal();
void Orphan(asCModule *module);
int GetRefCount();
void SetGCFlag();
bool GetGCFlag();
void EnumReferences(asIScriptEngine *);
void ReleaseAllHandles(asIScriptEngine *);
// Keep an internal reference counter to separate references coming from
// application or script objects and references coming from the script code
int AddRefInternal();
int ReleaseInternal();
void ReleaseAllFunctions();
bool IsInterface() const;
bool IsShared() const;
asCObjectProperty *AddPropertyToClass(const asCString &name, const asCDataType &dt, bool isPrivate);
asCObjectProperty *AddPropertyToClass(const asCString &name, const asCDataType &dt, bool isPrivate, bool isProtected, bool isInherited);
void ReleaseAllProperties();
asCString name;
asSNameSpace *nameSpace;
int size;
#ifdef WIP_16BYTE_ALIGN
int alignment;
#endif
asCArray<asCObjectProperty*> properties;
asCArray<int> methods;
asCArray<asCObjectType*> interfaces;
@@ -232,16 +209,23 @@ public:
bool acceptValueSubType;
bool acceptRefSubType;
// Store the script section where the code was declared
int scriptSectionIdx;
// Store the location where the function was declared (row in the lower 20 bits, and column in the upper 12)
int declaredAt;
asCScriptEngine *engine;
asCModule *module;
asCArray<asPWORD> userData;
protected:
friend class asCScriptEngine;
friend class asCConfigGroup;
friend class asCModule;
asCObjectType();
mutable asCAtomic refCount;
mutable bool gcFlag;
mutable asCAtomic externalRefCount;
asCAtomic internalRefCount;
};
END_AS_NAMESPACE
File diff suppressed because it is too large Load Diff
+6 -4
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2013 Andreas Jonsson
Copyright (c) 2003-2014 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -76,6 +76,7 @@ protected:
void RewindTo(const sToken *token);
void SetPos(size_t pos);
void Error(const asCString &text, sToken *token);
void Warning(const asCString &text, sToken *token);
void Info(const asCString &text, sToken *token);
asCScriptNode *CreateNode(eScriptNode type);
@@ -83,11 +84,11 @@ protected:
asCScriptNode *ParseFunctionDefinition();
asCScriptNode *ParseParameterList();
asCScriptNode *SuperficiallyParseExpression();
asCScriptNode *ParseType(bool allowConst, bool allowVariableType = false);
asCScriptNode *ParseType(bool allowConst, bool allowVariableType = false, bool allowAuto = false);
asCScriptNode *ParseTypeMod(bool isParam);
void ParseOptionalScope(asCScriptNode *node);
asCScriptNode *ParseRealType();
asCScriptNode *ParseDataType(bool allowVariableType = false);
asCScriptNode *ParseDataType(bool allowVariableType = false, bool allowAuto = false);
asCScriptNode *ParseIdentifier();
asCScriptNode *ParseListPattern();
@@ -143,7 +144,7 @@ protected:
asCScriptNode *ParseExprPreOp();
asCScriptNode *ParseExprPostOp();
asCScriptNode *ParseExprValue();
asCScriptNode *ParseArgList();
asCScriptNode *ParseArgList(bool withParenthesis = true);
asCScriptNode *ParseFunctionCall();
asCScriptNode *ParseVariableAccess();
asCScriptNode *ParseConstructCall();
@@ -168,6 +169,7 @@ protected:
asCString ExpectedTokens(const char *token1, const char *token2);
asCString ExpectedOneOf(int *tokens, int count);
asCString ExpectedOneOf(const char **tokens, int count);
asCString InsteadFound(sToken &t);
bool errorWhileParsing;
bool isSyntaxError;
+6 -13
View File
@@ -1,6 +1,6 @@
/*
AngelCode Scripting Library
Copyright (c) 2003-2012 Andreas Jonsson
Copyright (c) 2003-2015 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@@ -54,11 +54,14 @@ class asCObjectProperty
{
public:
asCObjectProperty() {accessMask = 0xFFFFFFFF;}
asCObjectProperty(const asCObjectProperty &o) : name(o.name), type(o.type), byteOffset(o.byteOffset), accessMask(o.accessMask), isPrivate(o.isPrivate), isProtected(o.isProtected), isInherited(o.isInherited) {}
asCString name;
asCDataType type;
int byteOffset;
bool isPrivate;
asDWORD accessMask;
bool isPrivate;
bool isProtected;
bool isInherited;
};
class asCGlobalProperty
@@ -69,7 +72,7 @@ public:
void AddRef();
void Release();
int GetRefCount();
void DestroyInternal();
void *GetAddressOfValue();
void AllocateMemory();
@@ -84,16 +87,7 @@ public:
void SetInitFunc(asCScriptFunction *initFunc);
asCScriptFunction *GetInitFunc();
static void RegisterGCBehaviours(asCScriptEngine *engine);
//protected:
void SetGCFlag();
bool GetGCFlag();
void EnumReferences(asIScriptEngine *);
void ReleaseAllHandles(asIScriptEngine *);
void Orphan(asCModule *module);
// This is only stored for registered properties, and keeps the pointer given by the application
void *realAddress;
@@ -108,7 +102,6 @@ public:
// The global property structure is reference counted, so that the
// engine can keep track of how many references to the property there are.
asCAtomic refCount;
bool gcFlag;
};
class asCCompGlobPropType : public asIFilter
File diff suppressed because it is too large Load Diff
+6 -3
View File
@@ -124,9 +124,9 @@ protected:
// Helper class for adjusting offsets within initialization list buffers
struct SListAdjuster
{
SListAdjuster(asDWORD *bc, asCObjectType *ot);
SListAdjuster(asCReader *rd, asDWORD *bc, asCObjectType *ot);
void AdjustAllocMem();
int AdjustOffset(int offset, asCObjectType *listPatternType);
int AdjustOffset(int offset);
void SetRepeatCount(asUINT rc);
void SetNextType(int typeId);
@@ -137,11 +137,13 @@ protected:
};
asCArray<SInfo> stack;
asCReader *reader;
asDWORD *allocMemBC;
asUINT maxOffset;
asCObjectType *patternType;
asUINT repeatCount;
int lastOffset;
int nextOffset;
asUINT lastAdjustedOffset;
asSListPatternNode *patternNode;
int nextTypeId;
@@ -239,7 +241,8 @@ protected:
asUINT repeatCount;
asSListPatternNode *patternNode;
asUINT entries;
int lastOffset;
int lastOffset; // Last offset adjusted
int nextOffset; // next expected offset to be adjusted
int nextTypeId;
};
asCArray<SListAdjuster*> listAdjusters;

Some files were not shown because too many files have changed in this diff Show More