Age | Commit message (Collapse) | Author | Files | Lines |
|
This issue was caused by the fix in 24b234543c7322d2dd20339b45367fa3f4c53495
Because we used closed hashing for the dict hash table, it is important
that the table doesn't get too full, as it gets very inefficient due to
hash collisions. When allowing for space, also consider dummy entries that
consume slots. If there are too many dummy slots, the hash table is expanded,
clearing out the dummy slots.
Without this fix it is possible to get unlucky when filling a dictionary
and emptying it again (twice) will result all slots become dummy slots
and thus no more entries can be added.
See REGTEST 54
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Fixes #191
Signed-off-by: Steve Bennett <steveb@workware.net.au>
Reported-by: D. Bohdan <dbohdan@dbohdan.com>
|
|
jim.h now includes JIM_ABI_VERSION that should be incremented whenever
the ABI changes. Then all loadable modules should call Jim_CheckAbiVersion()
to make sure they are loaded against the correct version.
Add Jim_PackageProvideCheck() that does both Jim_CheckAbiVersion()
and Jim_PackageProvide() to simplify the implementation of loadable extensions.
Also rename the "big" sqlite3 extension to just sqlite to avoid a naming conflict with
the smaller jim-sqlite3 extension.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Allows a debugger or tracing facility to be implemented
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
This means that $variable references and [commands] are not expanded.
This should mitigate security concerns when using the 'integer expression' feature.
It means that you must do:
string repeat a $i*4
Not:
string repeat a {$i*4}
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
For convenience, many commands now accept integer expressions
rather than only simple integers.
These are:
loop, range, incr, string repeat, lrepeat, pack, unpack, rand
This simplifies many cases where previously expr {} or $() was required.
e.g.
foreach i [range 4+1 2*$b] { ... }
string repeat 2**$n a
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Although the documentation has always stated that, like Tcl,
insertion order of dictionaries was preserved, this has never
been the case. Instead, dictionaries were implemented as simple
hash tables that did not preserve order.
Now, a new implementation of dictionaries preserves insertion
order and has a number of other benefits.
Instead of hashing keys and storing keys and values in the hash table,
the keys and values are not stored in a separate table, exactly as
lists are stored, with alternating key, value pairs. Iterating over the
dictionary is exactly like iterating over a list, where the order is consistent.
The hash table uses closed hashing rather than open hashing to avoid
allocatation of hash entry structures. Instead a fixed (but expandable)
hash table maps the key hash to the offset in the key/value table.
This use of offsets means that if the key/value table grows, the offsets
remain valid. Likewise, if the hash table needs to grow, the key, value table
remains unchanged.
In addition to the offset (which indexes to the value, and 0 means the hash table entry is unused),
the original hash is stored in the hash table. This reduces the need for object
comparisons on hash entry collisions.
The collision resolution algorithm is the same as that used by Python:
peturb >>= 5;
idx = (5 * idx + 1 + peturb) & dict->sizemask;
In order to reduce collisions, the hash table is expanded once it reaches
half full. This is more conservative that Python where the table is expanded
when it is two thirds full.
Note that if a hash collision occurs and then the original entry
that cased the hash collision is removed, we still need to continue
iterating when searching for the new key. Don't stop at the now-empty
slot. So these entries are marked with offset=-1 to indicate that
they need to be skipped.
In addition, the new faster hashing algorithm from Tcl 8.7 is used.
This the hash for integers to be calculated efficiently without requiring
them to be converted to string form first.
This implementation is modelled largely on the Python dict implementation.
Overall the performance should be an improvement over the current implementation,
whilst preserving order. Dictionary creating and insertion should be faster
as hash entries do not need to be allocated and resizing should be slightly faster.
Entry lookup should be about the same, except may be faster for pure integer keys.
Below are some indicative benchmarks.
OLD NEW
dict-create-1.1 Create empty dict 97.2ns .
dict-create-1.2 Create small dict 440ns -27%
dict-create-1.3 Create medium dict 1.54us -57%
dict-create-1.4 Create large dict (int keys) 130us -80%
dict-create-1.5 Create large dict (string keys) 143us -75%
dict-set-1.1 Replace existing item 258ns -34%
dict-set-1.2 Replace nonexistent item 365ns -49%
dict-exists-1.1 Find existing item 55.7ns -5%
dict-exists-1.2 Find nonexistent item 55.0ns -5%
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Instead of incrementing the proc epoch on every command removal
and some command creation, cache previous deleted commands
(empty structure only). Periodically increment the proc epoch
and invalide all cached commands.
This is especially a win when creating short lived commands.
e.g.
proc a {} {
local proc b {} {
# do something
}
# now b is removed
}
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
The hash table used to store commands now uses Jim_Obj keys rather
than allocated char *, so embedded nulls are supported.
This means that some API function such as Jim_RenameCommand()
now take Jim_Obj * rather than const char *, however Jim_CreateCommand()
is retained with const char * for convenience and the new Jim_CreateCommandObj()
is added.
This is generally a performance win as the existing Jim_Obj can be used
as the key.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Hash tables used to store variables are now use Jim_Obj keys rather
than allocated char *, so embedded nulls are supported.
This is generally a performance win as the existing Jim_Obj can be used
as the key.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
If the pattern begins with -, the internal invocation of regexp
will treat the pattern as an option. Fix this by adding -- to the
internal invocation of regexp.
Fixes #154
Reported-by: Barry Arthur <barry.arthur@gmail.com>
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Previously we stored lastCollectTime as time_t, but to support
more easily enabling 64 bit vs 32 bit time_t, convert this
to be JimClock() compatible (64 bit milliseconds).
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Reported-by: dbohdan <dbohdan@dbohdan.com>
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
- fix popen [open "|pipeline ..."] to return meaningful status in close
(but note that stderr is not captured)
- popen pipelines can now be used as the target of exec redirection
- overally improvements to exec on windows. Now crt file descriptors
are used throughout
- add support for [pid], [wait] and popen on windows
- os.wait is now wait, and integrates with [exec ... &] to be able
to wait for running background tasks
- [socket pipe] is now also [pipe] and is supported on windows
- [file tempfile] is supported on windows
- move duplicated code between jim-aio.c and jim-exec.c to jimiocompat.c
- Fix [exec] on windows to match unix semantics wrt sharing the parent stream
unless redirected rather than using /dev/null
- On windows redirect to or from /dev/null is automatically converted to NUL:
- If signal support is disabled, implement a minimal Jim_SignalId() for exec and wait
- aio now supports getfd, to return the underlying file descriptor.
This is used by exec to support redirection, and allows popen channels
to support exec redirection.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
To avoid an explosion of different internal rep structures,
simply use the existing ptrIntValue for jim-regexp
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
When Jim_GetEnum() succeeds, cache the result in the object
to speed up subsequent identical calls to Jim_GetEnum()
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
With 'history completion <cmd>'
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Rework the expression engine to use recursive descent evaluation rather than
a shunting yard algorithm. Among other things, it is easier to make lazy operators
and the ternary operator work correctly.
In particular, the following expression no longer crashes: $(99?9,99?9:*9:999)?9)
And the code is now smaller.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
The script implementation of dict values was not correctly handling the case
where a dictionary had duplicate values.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Compiling for C++ (as is needed for Metakit extension) generates an
error due to the use of the reserved word 'template' as an argument
name.
Renaming this argument
|
|
This option returns a list of support subcommands and is
useful for command line completion.
Support added to: socket, namespace, tcl::prefix, string, dict, info
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
* named boolean values in `expr` are internally converted to int
* named constants are lower-case only
|
|
"*" for some arguments
|
|
Rather than taking a string and a length, it is simpler and more efficient
to take a Jim_Obj
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
As identified by frgm
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
referneces => references
|
|
There is no need to protect against merging tailcalls across
uplevel since any tailcalls should already be fully resolved.
This fixes a problem with the following only running one loop:
foreach a {b c d} {
command-with-tailcall $a
}
In particular:
dict for {a b} {1 2 3 4} { puts $a,$b }
Reported-by: Jon Povey <jon.povey@emsolutions.com.au>
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
This applies to [exec] and [file tempfile]
Reported-by: Jakub Wilk
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Sweep through and clean up all (most) of the comments in the code.
While there, adjust some variable and function names to be more consistent,
and make a few small code changes - again, mostly for consistency.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Resolve the tailcall command immediately in [tailcall] and stash it.
If a tailcall is currently being evaluated, new tailcalls in the same
frame are merged/deferred to evaluate in the same C stack frame.
Can't merge tailcall evaluations across uplevel.
Add some tests for these cases
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
dict for, values, incr, append, lappend, update, replace and info
Also implement array stat (the same as dict info)
Note that [dict info] and [array stat] are for useful for checking
the behaviour of the hash randomiser
Add Jim_EvalEnsemble()
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
To avoid hash table collision attacks (n.runs-SA-2011.004)
Note that this options is *off* by default, but it is reasonable
to consider reversing this.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Currently tailcall resolves the command in the parent
namespace.
This also fixes the deletion of [local] commands
such that they are always correctly deleted.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
aio [open], as well as similar commands return the name of the
created command. If this is done in the non-global namespace, the
returned name is implicitly scoped to the current namespace while
the actual command is created in the global namespace. Thus [close]
does not work when invoked in that namespace.
The solution is to return a fully qualified name, such as ::aio.handle3
Note that this may also be a problem for similar command such as
[proc] and [alias] that return command names.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
|
|
And remove declarations of some obsolete functions
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
For performance reasons
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
The following should break when a handled signal is caught.
catch -signal { vwait forever }
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
The API function definition for Jim_InitStringRep() has been removed
by the commit:
commit 2e8b9ddb92ed1cea3054ed8180d363c9dcc72dd9
Author: Steve Bennett <steveb@workware.net.au>
Date: Sat Feb 18 14:47:11 2012 +1000
Small cleanup/optimisation in object create/dup
Remove the declaration from the headers as well.
Signed-off-by: Ezequiel Garcia <elezegarcia@gmail.com>
|
|
No perf difference measured using bench.tcl.
Signed-off-by: Lauri Kasanen <cand@gmx.com>
|
|
Ensure that the internal rep of interp->emptyObj is never
changed to a script, since scripts use emptyObj as the source
filename when no source info is available. Instead use a special
nullScriptObj for this purpose.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
See README.namespaces
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|