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