... + prefix-in + relative-path module. All of those ingredients
(or some similar alternatives) are necessary to trigger a slow
way of saving module context for interaction evaluation where
a module-path index shift was getting lost.
Previously the relevant predicates where disjoint, and until this commit
the only predicate that recognizes #f was `not`. So it's necessary to fix
two reductions to allow other predicates that recognize #f, like `boolean?`.
Add a hidden `true-object?` primitive that recognizes only #t, that is also
useful to calculate unions and complements with `boolean?` and `not`.
Also, extend a special case for expressions like
(or (symbol? x) (something))
where the optimizer is confused by the temporal variable that saves the
result of `(symbol? x)`, and the final expression is equivalent to
(let ([temp (symbol? x)])
(if temp #t (something)))
This extension detects that the temporal variable is a `boolean?` and
reduces the expression to
(if (symbol? x) #t (something))
It's worth noting that this hasn't caused me an issue, I came across it as I wanted to see what sys-type actually did. I couldn't say what the affect of this change would be and don't have a use case for it, it just looks wrong!
Provide `--enable-ubsan` to simplify `-fsanitize=undefined` builds,
where alignment and floating-point divide-by-zero need to be
disabled to get useful results.
Also, repair undefined behavior exposed by the test suite. Most of the
repairs are avoiding `memset(..., NULL, 0)` --- which is an unhelpful
requirement, IMO. The other two repairs are worthwhile but unlikely to
have caused trouble.
The optimizer assumed a fixnum result if either argument to
`bitwise-and` implies a fixnum result. That's not correct if the
fixnum agument is negative.
Thanks to Peter Samarin for a bug report.
Merge to v6.7
In case a write barrier happens between the set and use
of `errno`, make sure the barrier doesn't cause the
`errno` value to change in the process of making other
system calls.
When calling a procedure that is attached as a
`prop:rename-transformer` property value, make sure that
any available expansion context is accessible as reflected by
`(syntax-transforming?)`.
Syntax parameters as rename transformers particularly rely on that
information for local expansion.
Thanks to Jay for the "stxparam.rktl" test.
Closes#1479
In a pattern like
a*b
a naive attempt to match will take quadratic time on an input that
contains all "a"s an no "b". To improve that case, the regexp compiler
detects that a match will require a "b" and checks the input for a "b"
to enable linear-time failure.
That optimization mishandled `(?!...)` and `(?<!...)` patterns,
treating the must-not-match subpatterns as things that must match.
So,
(regexp-match "a*(?!b)" "aaaxy")
returned false, because the input doesn't contain "b".
Thie commit repairs the optimization.
Closes#1468
Fix a regression relative to v6.4 caused by a refactoring of the
compiler between v6.4 and v6.5. The refactoring lost information about
letrecs that are converted internally to let* when a mutable variable
is involved, and it ends up allocating a closure before the box of a
mutable variable that is referenced by the closure. Something like
`with-continuation-mark` is needed around the closure's `lambda` to
prevent other optimizations from hiding the bug.
Closes#1462
lookup-errno now returns #f when given an unknown symbol instead
of raising a contract error. It should not return #f for any
symbol that it previously accepted.
The `if` case of the compiler's space-safety pass abused its "last
non-tail call relative to the closest enclosing binding" state as
"last non-tail call relative to the enclosing run time", which could
cause it to not clear a stack position as needed to maintain space
safety.
* add lang-reader-module-paths to syntax/module-reader
to be used as the third argument to make-meta-reader in lang-extensions
like at-exp
* document lang-reader-module-paths
* use lang-reader-module-paths in at-exp
This makes two changes to the forms in racket/splicing to adjust how
syntax properties are propagated through expansion:
1. Uses of make-syntax-introducer are passed #t as the first argument,
which causes the introduced scope to be consider a use-site rather
than macro-introduction scope. This prevents syntax objects from
being unnecessarily marked as unoriginal, in the syntax-original?
sense.
2. Uses of syntax/loc have been adjusted to copy syntax properties
from original syntax objects, which were previously discared. Forms
that were spliced into the surrounding context, such as begin,
define-values, and define-syntaxes, recreated the top-level syntax
objects, which did not preserve syntax properties from the
originals.
This is not a perfect solution, mostly because it potentially elides
properties that may be associated with captured literals (that is,
properties attached directly to begin, define-values, or define-syntaxes
identifiers themselves). However, it seems to accommodate most of the
common use-cases: propagation of syntax-original?-ness and forms like
`struct`, which attach properties like 'sub-range-binders.
fixes#1410
A `struct-copy` form can generates a call for a constructor that
includes a sequence of `unsafe-struct-ref` arguments. Each
`unsafe-struct-ref` must still check for a chaperone. Make the JIT
recognize that pattern an turn it into a single test instead of
one test per `unsafe-struct-ref`.
http-proxy/ contains a suite of almost useful (but mostly useless) servers.
These can be used to test http-client, and url.rkt
git proxy is not tested yet -- I really wouldn’t know how
This patch adds https and git proxying through HTTP’s `CONNECT` method.
**Sanity Checks Needed:**
1. Is the git protocol proxying necessary?
It might be overkill, and I haven’t overly tested it since `raco pkg
install` uses https as its transport anyway
2. If anyone is better clued up on HTTP `CONNECT` best practice, then
please check the headers that I pass (in `http-client.rkt`)
3. Is HTTP `CONNECT` the only/best way to proxy HTTPS? It is what *curl*
uses (which might be a good indicator)
4. Will the ports be closed properly? (does anyone see a fid leak?)
- how do I test for that? Open (and allegedly close) 1024 tunnels?
5. The `abandon-p` definitions in `http-conn-CONNECT-tunnel` could
probably be reduced, but they’re defined as they are to allow me to
put debugging hooks in
6. No tests or documentation yet
7. I edited this with *vim*, and therefore the indentation is a la vim.
I looked at doing a global reindent (of git-checkout) and so much
changed that I abandoned that as an idea. It indentation is too
“off-style” then feel free to change it :-)
**git-checkout.rkt:**
- `initial-connect` now tries to use a git proxy (see `url.rkt`, below)
when *transport*=`git`
- (if *transport*=`https`, then `url.rkt`’s standard proxying will be
used)
**http-client.rkt:**
- `http-conn-open!` can now be passed a
`(list/c base-ssl?/c input-port? output-port? (-> port? void?))` to
describe:
- maybe a negotiated ssl context
- two tunnel (or other arbitrary) ports to use instead of newly
`...-connect`ed ports
- an abandon function for those ports
- `http-conn-send!` has a function `print-to` which curries
`(fprintf to)`, but allows a hook for an `eprintf` for debugging
- **added `http-conn-CONNECT-tunnel`:** this opens an new `http-conn`
and arranges for CONNECT tunneling to `target-host` and `target-port`
- factored contracts into `base-ssl?/c` and `base-ssl?-tnl/c`
- added contract for `http-conn-CONNECT-tunnel`
**url.rkt:**
- `proxiable-url-schemes`: now includes `https` and `git`
- `env->c-p-s-entries`: the environment variable “parser” now takes a
rest-list of lists of environment variables, and the scheme that these
variables proxy is garnered from the variables’ names. As before
there are:
- `plt_http_proxy` and `http_proxy`
- `plt_https_proxy` and `https_proxy`
- `plt_git_proxy` and `git_proxy`
during the previous iteration of obtaining the proxy variables at
startup, we discussed the appropriate naming conventions for these
variables. This doesn’t seem to deviate from that
- `env->c-p-s-entries`: having a proxy url that isn’t strictly:
`http://hostname:portno` (e.g. having a training slash) generates a
log warning, not an error. It was beginning to bug me
- `proxy-servers-guard`: accepts any one of the `proxiable-url-schemes`
(not just `http`)
- no proxy is agnostic to the URL scheme
- `proxy-tunneled?`: returns false for `http`, which is proxied using an
HTTP proxy. Returns true for other URL schemes -- which go through a
tunnel
- **`make-ports`:** tests whether a tunnel proxy is necessary. If so, it
creates a tunnel and plumbs the connections
- elsewhere, anywhere that tests for proxy, now tests for
`(and proxy (not proxy-tunneled? url))`, because tunneled HTTPS
connections are direct (once they’re through the tunnel, IYSWIM)
Make the optimizer recognize and track `make-struct-property-type`
values, and use that information to recognize `make-struct-type`
calls that will defnitely succeed because a property that hs no
guard is given a value in the list of properties.
Combined with the change to require-keyword expansion, this
change allows the optimizer to inline `f` in
(define (g y)
(f #:x y))
(define (f #:x x)
(list x))
because the `make-struct-type` that appears between `g` and `f`
is determined to have no side-effect that would prevent `f` from
having its expected value.
Make the definition of a function with a required keyword expand in a
way that allows the optimizer to recognize it as a form that has no
errors or externally visible side effects.
The old expansion of
(define (f #:x x) ...)
included
(define lifted-constructor (make-required ....))
(define f (lifted-constructor (lambda ....) ....))
where `make-required` calls `make-struct-type` and returns just the
constructor.
The new expansion instead has
(define-values (_ lifted-constructor _ _ _)
(make-struct-type ....))
(define f (lifted-constructor (lambda ....) ....))
In other words, `make-required` is inlined by macro expansion,
so that the optimizer will be able to see it and eventually
conclude that no side effects have taken place.
When a module defines and exports an identifier at two phases,
and when another module imports both of them at the same phase,
an error was not reported as it should have been.
With this option, FFI calls always block until scheme_check_foreign_work
is called by the program embedding Racket.
This is needed for embedding Racket into contexts where you do not
control the event loop, need Racket to make FFI calls, and those FFI
calls must occur on a thread within the event loop. A good example of
this is with OpenGL FFI calls that require the current thread to hold
the OpenGL/EGL context.
An important point about this is that scheme_check_foreign_work will
only execute a single FFI call. So if this is used for OpenGL rendering,
you'll want to run it a lot.
Some expressions are omittable only when the arguments have certain types.
In this case the application is marked with APPN_FLAG_OMITTABLE instead of relaying on the flags of the primitive.
The optimizer can't use this flag to move the expression inside a lamba or across a potential continuation capture, unlike other omittable expressions. They can be moved
only in more restricted conditions.
For example, in this program
#lang racket/base
(define n 10000)
(define m 10000)
(time
(define xs (build-list n (lambda (x) 0)))
(length xs)
(define ws (list->vector xs)) ; <-- omittable
(for ([i (in-range m)])
(vector-ref ws 0))) ; <-- ws is used once
If the optimizer moves the expression in the definition of ws inside the recursive
lambda that is created by the for, then the code is equivalent to:
#lang racket/base
(define n 10000)
(define m 10000)
(time
(define xs (build-list n (lambda (x) 0)))
(length xs)
(for ([i (in-range m)])
(vector-ref (list->vector xs) 0))) ; <-- moved here
And the new code is O(n*m) instead of O(n+m). This example is a minimized version
of the function kde from the plot package, where n=m and the bug changed the run
time from linear to quadratic.
The application of some procedures are omittables when the arguments have
certain properties. Check the arity of the procedure before marking the application as omittable.
The only case that appears to be relevant is the expression (-).
The relevant predicates are almost disjoint. The superposition
is solved with predicate_implies and predicate_implies_not.
This is also valid considering the equivalence classes modulo
eqv? and equal?. So if the optimizer knows that two expressions
X and Y have different relevant types, then it can reduce
(equal? X Y) ==> (begin X Y #f).
Changes signatures in `syntax/modcode` to accept `path-string?` arguments
instead of `path?`.
Before, the docs listed `path-string?` but the contracts used `path?`.
Now they agree.
The optimizer now makes more choices based on imported structure-type
info that thet validator needs to reconstruct, so pass that
information all the way through.
Allow a `struct` form to be recognized when it provides
a number as the 8th argument to `make-struct-type`. In
particular, that change allows the construction of
optional-keyword functions to be recognized as a
purely functional operation.
Also, allow the optimizer to use information about imports
when deciding whether a module-level form is functional.
It's ok to use that information, because the validator has
it, too.
This combination of changes allows something like
(define (f #:optional [x #f])
(later))
(define (later) ....)
to compile to a reference to `later` wihout a check.
Fixing dead-code cleanup in the letrec-check pass exposed
a bug in a part of the letrec check interpretation that is
analogous to copy propagation. The copy's representation
now refers to the original variable, instead of copying
the current set of deferrals (which is wrong if the original
is a `letrec`-bound variable that hasn't yet accumulated
its closures).
Due to an obvious problem in the setup, the letrec-check pass wasn't
running an intended dead-code pruning pass. Correcting the problem
cuases one test in "optimize.rktl" to change, because the letrec-check
pass can see more in one case than thanother.
(Problem discovered by accidentally fixing the setup in a Racket
branch based on "linklets".)
Along with the `PLT_COMPILED_FILE_CHECK` environment variable, allows
the timestamp check to be disabled when deciding whether to use a
compiled bytecode file.
In accomodating this change, `raco make` and `raco setup` in all modes
check whether the SHA1 hash of a module source matches the one
recorded in its ".dep" file, even if the timestamp on the bytecode
file is newer. (If the compile-file check mode is 'exists, the
timestamp is completely ignored.)
1. Changed the API documentation for scheme_make_hash_tree, adding primitives for:
* SCHEME_hashtr_eq
* SCHEME_hashtr_equal
* SCHEME_hashtr_eqv
2. Changed direct uses of scheme_make_hash_tree to use these enumed values.
3. Fixed bugs in documentation
4. Defaults to racket/interactive (and racket/gui/interactive) if there is nothing in the config file
Now accepts any whitespace, not just spaces, ignores both leading and
trailing whitespace, and accepts multiple whitespace characters
separating subterms.
After refactoring the test for the inferred types of some procedures that
use vector?/bytes?/string?/list? it was easier to spot the missing information.
Note that in the documentation, some arguments like the position in
(vector-ref <vector> <position>)
are documented as exact-nonnegative-integer? but due to the implementation
details they are actually in a subset of fixnum?s.
When `read` parses a literal hash table, it inserts an placeholder
just in case it's needed for cycles. The `unsafe-immutable-hash-...`
operations in some cases did not detect and remove the placeholder.
Closes#1376
Merge to v6.6
The namespace returned by `variable-reference->namespace` (or
`namespace-anchor->namespace`) may be used via `eval` to define new
bindings, so enable top-level binding support for the namespace.
for example, make the optimizer convert something like
(struct a (x))
(lambda (v) (if (a? v) (a-x v) #f))
to
(struct a (x))
(lambda (v) (if (a? v) (unsafe-struct-ref v 0) #f))
The optimizer change in e887fa56d1 recognized struct declarations that
involved only whitelisted properties to guarantee that constructor
properties are preserved --- while `prop:chaperone-unsafe-undefined`
can affect the constructor, and other properties might imply that one.
But the optimizer's transformer aren't actually invalidated by
`prop:chaperone-unsafe-undefined`; the JIT's assumptions are affected,
but that's handled in a different way. So, remove the whitelist and
allow any property list.
Faster hasing of booleans, correct potential loss of distinction
for a compound structure that ends in a symbol or keyword, and
shortcuiting lookup in an empty immutable hash table.
This change permits EH patterns like (~once <nullable>), because the
match will happen at most once, so there is no danger of divergence.
Thanks to Alex Knauth for pointing out this special case.
Merge to release branch.
The optimizer tries to reduce the `if` assuming that the result will be used.
In case it later detects that the result will be ignored, it can try to
apply some additional reductions to the branches and to the whole expression.
The SSL_library_init() function has been removed. (There's a new
SSL_init_ssl() function, but calling it is optional.) The
SSL_load_error_strings() function is similarly gone.
The SSLv23_client_method() and SSLv23_server_method() functions
are also gone. The new TLS_client_method() and TLS_server_method()
functions are better names for what SSLv23_client_method() and
SSLv23_server_method() evolved to do.
Finally, the dance for server-triggered renogotiation needs to
change, since the old dance involved manipulating the structure
directly.
Merge to v6.6
When creating a collision node, make sure the "has a value" bit
is set, since the "has a hash code" bit should imply it.
This bug was made easier to trigger by 3fbb384604, but it was
potentially a problem for scope sets before.
Closes#1366
Merge to v6.6
This function exposes the fast subset operation that is built in for
immutable hash tables (and used by the set-of-scopes implementation).
Also, make the space optimization implicit for `eq?`-based hash tables
that contain only #t values (instead of explicit and only available
internally). It turns out to be easy and efficient to make the
representation automatic, because the HAMT implementation can support
a mixture of nodes with some containing explicit values and some
containing implicit #t values.
Now with-disappeared-uses surrounds its body with let, so it can contain
multiple body expressions. The record-disappeared-use function is like
record-disappeared-uses but for a single identifier.
The `#%linklet` module is intended to eventually provide
a simplified compiler for the core Racket language. For
now, it provides minimal hooks for bootstrapping an
expander implementation.
When the properties argument for `make-struct-type` is non-empty,
then we cant; guarantee that `make-struct-type` succeeds, but
if it does, then we can still know that the result is a structure
type and (as long as `prop:chaperone-unsafe-undefined` is not
involved) the properties don't affect the constructor, predicate,
selector, or mutators.
The `eq?` hash code of a symbol, unreadable symbol, or keyword depends
only on the character content, but all in exactly the same way, so
that the same string would produce the same hash code for all. That's
not a big deal for hashing, but it doesn't seem like a good idea, and
it can be confusing.
The resolve-module-path-* functions effectively already had a default argument,
which is #f, this allows you to just directly call it with one argument.
When walking up the cycle chain to find the mutable item,
intermediate items need to be marked as potentially
shared, and a mutable item should not be added more
than once.
This fixes an immediate problem, but the macro expander should have
complained about an unbound `maybe` at phase 2. (A new implementation
of the macro expander detected the unbound `maybe`.)
The transformation also has the effect of making ellipsis patterns
with nullable heads, such as ((~seq x:sc ...) ...), terminate
rather than looping forever.
To do: add null eh match check and error.
Inserting keys with sequential hash codes --- as in 0, 1, 2, 3, etc.
--- performed badly compared to random keys, because it triggered the
worst case of allocation: allocate a node of size 1, then 2, then 3,
then 32, then 32 plus a subtree of size 1, then 32 plus a subtree of
size 2, and so on. By rearranging the bits in a hash code, arrange
for nodes that are more like 4-wide instead of 32-wide. In other
words, the tree become wider with thinner branches, instead of growning
just as a thick branch to the left.
Of course, there's now a different sequence of inserts that used
to perform well and now perform badly (the inverse of the new
reordering), but that case seems much more likely than the cae
of sequential inserts.
In (~and p1 p2), a failure in p2 now always dominates a failure in p1.
Consequently, if a pattern succeeds, its failures don't matter.
Add {pat,hpat,action}:ord wrappers, ord prframes. Apply ordering to
main pattern and side clauses. Add better progress analysis to
eliminate order wrapping.
Although the JIT would not try to use a block of shared code for more
than a certain number of arguments, it could in rare cases (related to
self tail calls, for example) generate the code and attempt to install
it in the array of shared-code pointers.
When an array value is provided, make sure that it's an array
with at least the expected length (or longer) and same element
layout. That's weaker than checking that the array elements have
the right type, because an `eq?` check at the ctype layer seems
too strong, and the ctype API doesn't provide enough information
for a more flexible equality.
This push makes the exn:misc:match exception transparent. This
matches other racket-raised user exceptions.
The motivation for this change was breakage in the handin-server;
specifically, the discussion in
https://groups.google.com/forum/#!topic/racket-users/nEos3-osoWE
...in which the handin-server was not behaving the same on exn:misc:match
because it was not transparent. This caused the handin server to
refuse to rewrite these exceptions, resulting in less helpful
messages for users.
The previous fix (1acaf011) caused a performance regression
(compilation time?), reported by stchang. Reverting to quote.
Apparently, the problem with gensym and deterministic compilation
isn't the uninterned-ness; it's the global counter used for the
name. So use a compilation-local counter instead.
Avoid creating a result that is intended as a module path but
has elements that are not syntactically allowed, such as a "."
in a collection-path element.
A phase shift was mising on `begin-for-syntax`es introduced by
`syntax-local-lift-module-end-declaration`, which is in turn
used to implement` module+`, so `module+` didn't work under
two or more `begin-for-syntaxes`.
Closes#1312
Syntax objects generally make sense as properties in other syntax
objects, but they require special care when marshaling to bytecode
(as syntax objects do in general). To make that special handling
possible and reliable, constrain the shape of allowed values.
The name `path-extension` created a conflict for an existing
registered package, so it should not have been added to
`racket/path`.
Also, `path-get-extension` was intended to work on a path
that is syntactically a directory, so fix and test that.
Change the one expansion mode as far as I can tell) that disables
lifts so that lifts are now allowed, which means that
`(syntax-transforming?)` implies `(syntax-transforming--with-lifts?)`.
The old documentation incorrectly characterized when lifts
were allowed. Ryan noticed the documentation problem, and that
observation led to this simplication.
Although excessive fragmentation is already detected at the end
of a major GC, it can get out of hand already during a long
incremental phase. So, check for excessive fragmentation and
bail out to a major GC when it happens.
Related to PR 15287
Fixes a failure in the web server tests caused by d23b296627.
Formerly, `(string->url "http://racket-lang.org")`, with no trailing
slash, would produce a `url` structure with `path-absolute?` as #f.
That doesn't exactly make sense, because a URL with a host must always
have an absolute path component. Claiming a relative path component
interacts badly with extending a URL with a path later. (Although
`combine-url/relative` compenstate, a similar function in the web
server doesn't.) The revised `url->string` always sets `path-absolute?`
to #t when a host is present, and whether the path is empty or contains
an empty string still records whether a trailing "/" was present.
The `url->string` function, meanwhile, now needs to use whether the
path is empty to determine whether a "/" should be added after
the host name, not whether `path-absolute?` is true.
This is a partial solution to the ~and problem, only for side clauses.
In (~and p1 p2 p3), one often wants errors in p2 to take precedence over
errors in p1, and likewise for p3 over p2. One solution is ~commit, but
that prevents backtracking. Another is ~post, but then two ~post wrappers
are needed around p3. Also, it doesn't make sense to compare progress of
the third #:with clause from stxclass A to the second #:with clause of
stxclass B and say third beats second.
So, generalize 'post to (post group index); post frames are comparable to
each other only if group is the same, then compared by index. (Post still
beats CAR and CDR.) Each set of side clauses shares a group.
For simplicity of code generation for now, use gensyms to identify groups.
Since an IPv6 literal address includes ":"s, it must be written
between "[" and "]" as a host name.
Based on a patch by @Phlosioneer and comments by @Blaisorblade,
with additional changes to make `url->string` work.
Closes#980Closes#1243
A `#:name` identifier picks the name that is bound to static
information about a structure type. An `#:extra-name` identifier
specifies an additional name to be bound to the information.
This pair of options is analogous to `#:constructor-name`
and `#:extra-constructor-name`.
Based on Jen Axel's suggestion and implementation.
Closes#1309
Provide a cleaned-up set up path-extension functions. In contrast
to `path-{add,replace}-suffix` and `filename-extension`, a dot
at the beginning of a path element is not treated as an extension
separator. Also, `path-extension` returns an extension including
its separator, which is more consistent with other extension
functions.
The new `path-has-extension?` function replaces many uses of
regexp matching in the base collections.
Closes#1307
restricted through `get-info`, which prunes the environment
variable set before it loads the "info.rkt" file. All
environment variables are pruned except those listed in
`PLT_INFO_ALLOW_VARS` (separated by semicolons).
Related to emina/rosette#17.
Add a hook to `raco setup` to make copies of installed executables,
where the copies start with the configuration or addon directory
of creation time, instead of the default installation or user-specific
path.
Although the same effect can be achived by setting environment
variables such as PLTADDONDIR, tethered executables can be easier
to work with and compose better with other programs.
See also #1206 for some discussion, although this change does
not exactly address the original idea there.
Reduce (unbox (box x)) => x
Extend the reductions for cXr to the unsafe versions, for
example reduce (unsafe-car (cons x y)) => x
Check and save types in unsafe operations
Pass a string to the handler to describe the problem.
Also, fix minor issues (GC registration, contracts and `history`
in docs) and make `pregexp`, etc., report compilation errors as
`pregexp`, etc.
* Add 6.4 version, as this is now the default one to download on the website.
* raco doc <<name>> should use raco docs <<name>>
* raco is now on the PATH, remove warning
* Change `raco setup --check-deps <<name>>` to `raco setup --check-pkg-deps --pkgs <<name>>` (the former seems obsolete).
* Move `raco pkg install --deps search-auto` to the `install:` section, so that it is done before running the tests
* Move `raco pkg install --deps search-auto cover`, to the `after_success section`, since `raco cover` is run there.
* Fixed .travis.yml syntax (wrong indentation for fields under "matrix:")
* Clone https://github.com/greghendershott/travis-racket.git to a separate directory, not a subdirectory of the current package, as this can cause problems (see https://travis-ci.org/jsmaniac/type-expander/jobs/121099218#L824)
POSIX and ANSI specify that char is always 1 byte, and I'm almost
certain that no systems violate this. Regardless, the SIZEOF_CHAR macro
is never used.
Allow `system-type` on non-Windows platforms to run `uname` to get
machine information, even in a sandbox or other contexts with a
limiting secutiry guard.
Check that it works to apply a continuation that shares with
an enclosing continuation, where a runstack overflow happens
between the continuations.
Closes PR 15281
While expanding a module, the root of module-relative references is a
fresh notion of "this module".
After expansion, "this module" is shifted to "an expanded module",
which is a global constant (for top-level modules). When an expanded
module is re-expanded, "an expanded module" is shifted to a fresh
"this module" during re-expansion, and so on.
One problem with this approach is that the shift from "this module" to
"an expanded module" isn't applied to syntax properties --- but
there's some extra trickery to make it work out by mutating "this
module" to make it look like "an expanded module".
Submodule expansion introduces an intermediate "parent of this module"
that wasn't currently covered by the extra trickery, so fix that.
`->i` already supports method contracts (for use wihin `object-contract`,
whose `->i` support is tested, but undocumented), which would make `->im`
possible.
Unfortunately, that support is very incomplete, missing support for using
`this` in contracts, making this `->im` (or the undocumented `->i` +
`object-contract` combo) basically useless.
Once/if that is added, then this commit would enable `->im`. Until then,
it's mostly useful for future reference (hence will be reverted).
In the meantime, it's possible to use `->i` within class/object contracts
with an explicit `this` argument, so nothing critical is lost, just a tiny
shortcut.
Support creating executables when the base executable has
sections after ".rsrc", as long as there's room to add
a section to the section table. The new resource data is
written to the end of the file and vitrual space, but the
old space needs to be recorded as a section to keep them
contiguous.
MSVC 2015 puts a ".reloc" section after ".rsrc".
because right now they are too noisy to be useful to anyone other
than contract system maintainers. Once the problems inside the contract
library itself is fixed, consider moving these back to warning
Collect common types of frame (eg message, literal, etc) and
report together. For literals, symbols, and other atoms, compress
multiple entries to list. For example:
before: "expected the identifier `X' or expected the identifier `Y'"
now: "expected one of these identifiers: `X' or `Y'"
Previously, syntax-parse would only report errors for one maximal
progress equivalence class (and generate a useless "and other errors
occurred" message). But approach to linearizing the tree of failures
behaved badly if there was too much branching even for a single progress
equiv class. So now it dumps all of the maximal failures into one pile
and tries to find shared "sync points" (frames and terms) to linearize
the failure tree.
In particular, this eliminates the "and other errors" message.
Also updated and improved comments.
use trace-printf for all of the printing (which logs to info@compiler/cm
already) and make all of the indentation printing use the nicer:
| | | | |
style, and avoid creating the indentation strings unless they are actually used
Repair a mismatch between `syntax-local-lift-expression` and the
way that `compile` tries to avoid creating bindings while
compiling a top-level `define` form.
Closes#1284 and #1282
The meaning of SI_KERNEL signals is not clear, but ignoring
them seems to let the process continue ok. (These signals show
up when running `typed-racket-test/main --int`.)
In some cases, complex variants of (if (not <expr>) tb fb) are not reduced.
Extract the type information of the tests in <expr> to use it in tb and fb.
This wouldn't matter if the dependencies recorded in the dep file were
exactly the same as the files that are actually loaded when a file is
required. But in the case of lazy-require (or, more accurately, when
the cm-accomplice library is used), the dependencies in the dep files
can include things that are, in some cases, not actually
required. This is no problem for raco setup, since it looks at all of
the files anyway, but it can cause a particularly bad interaction with
DrRacket's online compilation facility.
For example say there is some file, e.g., mzscheme/main that is
required lazily. So when you edit a file in DrRacket, it will traverse
the requires and lets say it sees that the of mzscheme/main's
dependencies need to be compiled. So it will compile that dependency,
and then the ormap in this commit will be shortcircuited, which will
cause CM to stop looking at dependencies and decide to compile
mzscheme/main. So DrRacket will compile mzscheme/main, and then
whatever other pending compiles were going on and DrRacket's online
check syntax will complete, but because the lazy require doesn't
triggered, mzscheme/main isn't actually loaded during compilation.
Now you make another edit to the buffer and the same thing happens
except this time it gets past that first dependency of mzscheme/main
because there is now a .zo file for it from the last go 'round. But
say there isn't one for the second dependency. So it compiles that
file and compiles mzscheme/main now for a second time, but still
doesn't look at the third and fourth (etc) dependencies of
mzscheme/main.
Overall, this means that the second time you edit you file in
DrRacket, it should have been quick for the expansion portion to
finish because, after all, everything has been compiled and should
have been cached in .zo files. But because of the short circuiting, it
the .zo files weren't actually created and so your second edit is also
slow to come back.
After this commit, because of the ormap, the second edit will be
faster.
One worry with this commit is that it might change something that
could cause raco setup to go slower. To test that, I applied only this
change to a fresh checkout and did a full build. I then deleted all zo
files in racket/share/pkgs and timed 'raco setup -D' twice (four times
total). Here are the timings I get. The version of the code that uses
ormap:
% ... delete .zo files ...
% time raco setup -D
real 9m2.354s
user 37m5.176s
sys 4m14.963s
% ... delete .zo files ...
% time raco setup -D
real 9m2.421s
user 37m43.793s
sys 4m23.111s
The version of the code that uses the change in this commit:
% ... delete .zo files ...
% time raco setup -D
real 8m58.852s
user 36m51.369s
sys 4m13.633s
% ... delete .zo files ...
% time raco setup -D
real 8m53.980s
user 37m40.262s
sys 4m23.692s
Some functions were passing when they shouldn't have, only to fail when
the function is called.
Technically not backwards compatible, but should only affect functions
that were never called.
For example,
raco pkg update --lookup gui-doc
should suggest uncloning "gui-lib", too, assuming they were
cloned in the usual way. Due to too-early normalization of
GitHub URLs, though, shared-clone detection was broken.
A syntax property is added as preserved or not. For backward
compatibility, the default for a 'paren-shape key is preserved, and
any other key's default is non-preserved.
Cross-module inlining that pulls a variable reference across a
module boundary imposes a more struct requirement that run-time
"constant" detection is consistent with the optimizer's view of
"constant" within a module. So, make sure they're the same.
Sometimes the optimizer removes all the references to a variable but it
doesn't detect that the variable is unused, so it keeps the definition.
Later, the sfs detects the unused variable so it marks it, but it doesn't
remove the let form.
Formerly, cross-module inlining would not work for a function like
(define (f x)
(if .... .... (slow x)))
unless `slow` was also inlined into `f`. This commit changes
cross-module inlining so that it allows a call to `f` to be replaced
with an expression that references other module-level bindings (that
are not primitives), such as `slow`.
Adjusting the inlining rules can always make some program worse. In
this case, a hueristic about whether to export an optimized or
unoptimized variant of a fnuciton for inlining tends to collide with
the adjusted inlining rule, so this commit tweaks that heuristic, too.
Compiler changes allow the body of a `with-continuation-mark`
form to produce an unboxed value, but the validator and JIT
were not updated for that change.
Enable the optimizer to figure to figure out that a loop
argument is always a real number, for example, in much the
same way that it can detect fixnums and flonums for unboxing.
Unboxing information was only needed at the resolve level,
but `real?` information is useful only to the optimizer, so
the generalization enables the optimizer to reach
approximations of type information earlier (e.g., among
a subset of a function's arguments).
For simple enough M, `(let ([x M]) x)` is already converted
to just M, but add a conversion for other forms that gets rid
of the binding while preserving non-tailness.
Simplify `(wcm <k1> <v1> (wcm <k1> <v2> <e>))` to
`(begin <v1> (wcm <k1> <v2> <e>))` for a simple enough <k1>.
A variable simple enough, so this is useful for improving
errortrace output.
Use the structure-type name, in addition to the structure
content. Including the name is espeically useful for
distinguishing prefabs structs that differ in the prefab
name.
Compute an `equal?` hash code for `read`able values that
is a constant, at least for a given version of Racket. Only
(interned) symbols failed to have that property before.
An `XFORM_NONGCING_NONALIASING` function doesn't trigger a GC, and
when it is given an argument that is an address of a local variable,
it fills in that address and doesn't leak it. This annotation allows
the xform transformation (to support precise GC) avoid some work for
some hash-iteration functions.
Restore exports available to embedding, extending, and FFI
applications, and shift boundary back between hash-table
implementation details (in "hash.c") and Racket interface
(in "list.c").
With the old representation of local variables, optimize_info_lookup
had to search the stack for the frame with the information about the
variable. This was complicated so it has many flags to be used in
different situations and extract different kind of information.
With the new representation this process is easier, so it's possible
to split the function into a few smaller functions with an easier
control flow.
In particular, this is useful to avoid marking a variable as used
inside a lambda when the reference in immediately reduced to a
constant using the type information.
The iterator saves the return points in a list. For small immutable hashes,
encode the values in the list in the bits of a fixnum to avoid allocations.
Expose tagged allocation and a function that interprets a description
of tagged shapes. As a furst cut, the description can only specify
constant offsets for pointers within the object, but future extensions
are possible.
When a chaperone-wrapped function leads to a slow-path tail
call, the continuation-mark depth can be made too deep when
resolving the slow tail call.
Closes#1265
Mostly just fill in some corners, but also fix a bug with lifted
functions that accepted a boxed argument and have less than three
arguments total.
The `tests/racket/test` test suite now passes with
`PLT_RECOMPILE_COMPILE` set --- except for the "optimize.rktl" test
suite, wher emore work is needed to ensure that optimizations
don't get lost.
Reduce
(eq? v v) ==> #t
(if t v v) ==> (begin t v)
(if v v #f) ==> v
when v is a local or a top level variable.
Previously, the last two reductions were used only
with local variables.
Also, move the (if x #t #f) ==> (not x) reduction
after branch optimization.
When a key is removed at a level that other only has a collision
table, the HAMT representation was not adjusted properly by
eliminating the layer. As aresult, table comparison via
`equal?` could fail. The problem could show up with hash tables
used to represent scope sets, where an internal "subset?" test
could fail and produce an incorrect binding resolution.
The transformation from
(begin (let <bindings> (begin <e1> ...)) <e2> ...)
to
(let <bindings> (begin <e1> ... <e2> ...))
makes things look simpler and might help the optimizer a little. But
it also tends to make the run-time stack deeper, and that slows some
programs a small but measurable amount.
A better solution would be to keep the transformation but add another
pass that moves expressions out of a `let`.
Since this operation only moves the code and doesn't make the final
bytecode bigger, it's not necessary to decrease the fuel and then it
is available for further inlining.
The calculation of used variables in a possibly unused function did
not work right when the function is referenced by a more deeply
nested function that itself is unused. The extra uses triggered by
more nested uses need to be registered as tentative in the more nested
frame, not in the outer frame.
Closes#1247
On Unix and OS X, the check to avoid replacing an existing
file or directory is made by Racket, rather than the OS,
so don't claim a system error if the operation fails for
that reason.
Also, update the docs to clarify that the check is not
atomic with the move.
Closes issue #1158
Correct the second-biggest design flaw in the bytecode optimizer:
instead of using a de Bruijn-like representation of variable
references in the optimizer pass, use variable objects.
This change is intended to address limitations on programs like the
one in
http://bugs.racket-lang.org/query/?cmd=view&pr=15244
where the optimizer could not perform a straightforward-seeming
transformation due to the constraints of its representation.
Besides handling the bug-report example better, there are other minor
optimization improvements as a side effect of refactoring the code. To
simplify the optimizer's implementation (e.g., eliminate code that I
didn't want to convert) and also preserve success for optimizer tests,
the optimizer ended up getting a little better at flattening and
eliminating `let` forms and `begin`--`let` combinations.
Overall, the optimizer tests in "optimize.rktl" pass, which helps
ensure that no optimizations were lost. I had to modify just a few
tests:
* The test at line 2139 didn't actually check against reordering as
intended, but was instead checking that the bug-report limitation
was intact (and now it's not).
* The tests around 3095 got extra `p` references, because the
optimizer is now able to eliminate an unused `let` around the
second case, but it still doesn't discover the unusedness of `p` in
the first case soon enough to eliminate the `let`. The extra
references prevent eliminating the `let` in both case, since that's
not the point of the tests.
Thanks to Gustavo for taking a close look at the changes.
LocalWords: pkgs rkt