ECMA-357 botch where * or @b or (given valid namespace reference n) n::id
results in undefined, instead of a TypeError.
- Lazily bootstrap AnyName and AttributeName classes, instead of leaving the
former uninitialized, and initializing the latter only if QName is init'ed.
These classes, representing ECMA-357 internal types, must be initialized
in order to string conversion and default value on them to return useful
results. So this change also requires the shared qname_toString to cope
with these classes, which ape QName in having a JSXMLQName as private data.
- Revise Filtering Predicate Expressions bytecode schema to avoid bogo-script
creating in js_FilterXMLObject. With a new JSOP_ENDFILTER bytecode acting
in lieu of JSOP_POPV, but also exiting the nested js_Interpret() call, the
runtime can avoid trying to fake a JSScript for the subsequence of script
bytecode in parens in x.(e), that contains the bytecode for e plus the pop
or endfilter op.
This requires a historic reparameterization of js_Interpret to take the
starting pc! I cleaned up order of declaration, use, and useless init nits
for a few variables while messing with it.
- Based on the above change, fix the decompiler to handle filtered predicate
expressions -- that code was stubbed out till now, and I forgot to go back.
All better now, especially thanks to JSOP_ENDFILTER.
- Also while fixing filtered predicates, eliminate the useless TOK_RP parse
node above the parenthesized expression, to avoid a JSOP_GROUP bytecode.
- Fix js_GetAttributeNameObject so it doesn't take over its QName parameter's
object and rebind it to an object of class AttributeName -- instead, clone
the qn if necessary. This is important to cope with the errata, noticed a
while ago but finally recorded:
9.2.1.2 Step 2(e)(i, ii),
9.2.1.2 Step 7(e)(i),
9.2.1.3 Step 2(b)(ii)(1)(a)
All uses of a.[[Name]] for an attribute a in these sections that pass
that QName object to [[Delete]] must pass an AttributeName cloned from
a.[[Name]]. The [[Name]] internal property is always a QName instance
and never an AttributeName or AnyName instance. But [[Delete]] will
not operate on x.[[Attributes]] when given a QName by these sections,
so a child could be wrongly deleted instead of the attribute of the
same name.
This rework exposed a bug in the XML.prototype.name() impl, where it was
returning an AttributeName, not a QName, for attribute-class XML objects.
Clearly wrong -- the E4X spec makes plain early on that [[Name]] is always
a QName -- but the spec and e4x testsuite seemed to require it due to the
above-noted errata.
git-svn-id: svn://10.0.0.236/trunk@166845 18797224-902f-48f8-a5cc-f745e15eee43
locals (169559, r=shaver).
- Also fix longstanding bug where global regexps in precompiled scripts were
wrongly shared among threads/contexts (165201, r=shaver).
- Also fix strict-aliasing gcc warning causes (206599, r=bryner).
git-svn-id: svn://10.0.0.236/trunk@154749 18797224-902f-48f8-a5cc-f745e15eee43
errors, etc.''):
We now ReportStatementTooLarge only if
- a jump offset overflows 32 bits, signed;
- there are 2**32 or more span dependencies in a script;
- a backpatch chain link is more than (2**30 - 1) bytecodes long;
- a source note's distance from the last note, or from script main entry
point, is > 0x7fffff bytes.
Narrative of the patch, by file:
- js.c
The js_SrcNoteName array of const char * is now a js_SrcNoteSpec array of
"specifiers", structs that include a const char *name member. Also, due to
span-dependent jumps at the ends of basic blocks where the decompiler knows
the basic block length, but not the jump format, we need an offset operand
for SRC_COND, SRC_IF_ELSE, and SRC_WHILE (to tell the distance from the
branch bytecode after the condition expression to the span-dependent jump).
- jsarena.[ch]
JS arenas are used mainly for last-in-first-out allocation with _en masse_
release to the malloc pool (or, optionally, to a private freelist). But
the code generator needs to allocate and grow (by doubling, to avoid O(n^2)
growth) allocations that hold bytecode, source notes, and span-dependency
records. This exception to LIFO allocation works by claiming an entire
arena from the pool and realloc'ing it, as soon as the allocation size
reaches the pool's default arena size. Call such an allocation a "large
single allocation".
This patch adds a new arena API, JS_ArenaFreeAllocation, which can be used
to free a large single allocation. If called with an allocation that's not
a large single allocation, it will nevertheless attempt to retract the arena
containing that allocation, if the allocation is last within its arena.
Thus JS_ArenaFreeAllocation adds a non-LIFO "free" special case to match the
non-LIFO "grow" special case already implemented under JS_ARENA_GROW for
large single allocations.
The code generator still benefits via this extension to arenas, over purely
manual malloc/realloc/free, by virtue of _en masse_ free (JS_ARENA_RELEASE
after code generation has completed, successfully or not).
To avoid searching for the previous arena, in order to update its next
member upon reallocation of the arena containing a large single allocation,
the oversized arena has a back-pointer to that next member stored (but not
as allocable space within the arena) in a (JSArena **) footer at its end.
- jscntxt.c
I've observed for many scripts that the bytes of source notes and bytecode
are of comparable lengths, but only now am I fixing the default arena size
for cx->notePool to match the size for cx->codePool (1024 instead of 256).
- jsemit.c
Span-dependent instructions in JS bytecode consist of the jump (JOF_JUMP)
and switch (JOF_LOOKUPSWITCH, JOF_TABLESWITCH) format opcodes, subdivided
into unconditional (gotos and gosubs), and conditional jumps or branches
(which pop a value, test it, and jump depending on its value). Most jumps
have just one immediate operand, a signed offset from the jump opcode's pc
to the target bytecode. The lookup and table switch opcodes may contain
many jump offsets.
This patch adds "X" counterparts to the opcodes/formats (X is suffixed, btw,
to prefer JSOP_ORX and thereby to avoid colliding on the JSOP_XOR name for
the extended form of the JSOP_OR branch opcode). The unextended or short
formats have 16-bit signed immediate offset operands, the extended or long
formats have 32-bit signed immediates. The span-dependency problem consists
of selecting as few long instructions as possible, or about as few -- since
jumps can span other jumps, extending one jump may cause another to need to
be extended.
Most JS scripts are short, so need no extended jumps. We optimize for this
case by generating short jumps until we know a long jump is needed. After
that point, we keep generating short jumps, but each jump's 16-bit immediate
offset operand is actually an unsigned index into cg->spanDeps, an array of
JSSpanDep structs. Each struct tells the top offset in the script of the
opcode, the "before" offset of the jump (which will be the same as top for
simplex jumps, but which will index further into the bytecode array for a
non-initial jump offset in a lookup or table switch), the after "offset"
adjusted during span-dependent instruction selection (initially the same
value as the "before" offset), and the jump target (more below).
Since we generate cg->spanDeps lazily, from within js_SetJumpOffset, we must
ensure that all bytecode generated so far can be inspected to discover where
the jump offset immediate operands lie within CG_CODE(cg). But the bonus is
that we generate span-dependency records sorted by their offsets, so we can
binary-search when trying to find a JSSpanDep for a given bytecode offset,
or the nearest JSSpanDep at or above a given pc.
To avoid limiting scripts to 64K jumps, if the cg->spanDeps index overflows
65534, we store SPANDEP_INDEX_HUGE in the jump's immediate operand. This
tells us that we need to binary-search for the cg->spanDeps entry by the
jump opcode's bytecode offset (sd->before).
Jump targets need to be maintained in a data structure that lets us look
up an already-known target by its address (jumps may have a common target),
and that also lets us update the addresses (script-relative, a.k.a. absolute
offsets) of targets that come after a jump target (for when a jump below
that target needs to be extended). We use an AVL tree, implemented using
recursion, but with some tricky optimizations to its height-balancing code
(see http://www.enteract.com/~bradapp/ftp/src/libs/C++/AvlTrees.html).
A final wrinkle: backpatch chains are linked by jump-to-jump offsets with
positive sign, even though they link "backward" (i.e., toward lower bytecode
address). We don't want to waste space and search time in the AVL tree for
such temporary backpatch deltas, so we use a single-bit wildcard scheme to
tag true JSJumpTarget pointers and encode untagged, signed (positive) deltas
in JSSpanDep.target pointers, depending on whether the JSSpanDep has a known
target, or is still awaiting backpatching.
Note that backpatch chains would present a problem for BuildSpanDepTable,
which inspects bytecode to build cg->spanDeps on demand, when the first
short jump offset overflows. To solve this temporary problem, we emit a
proxy bytecode (JSOP_BACKPATCH; JSOP_BACKPATCH_PUSH for jumps that push a
result on the interpreter's stack, namely JSOP_GOSUB; or JSOP_BACKPATCH_POP
for branch ops) whose nuses/ndefs counts help keep the stack balanced, but
whose opcode format distinguishes its backpatch delta immediate operand from
a normal jump offset.
The cg->spanDeps array and JSJumpTarget structs are allocated from the
cx->tempPool arena-pool. This created a LIFO vs. non-LIFO conflict: there
were two places under the TOK_SWITCH case in js_EmitTree that used tempPool
to allocate and release a chunk of memory, during whose lifetime JSSpanDep
and/or JSJumpTarget structs might also be allocated from tempPool -- the
ensuing release would prove disastrous. These bitmap and table temporaries
are now allocated from the malloc heap.
- jsinterp.c
Straightforward cloning and JUMP => JUMPX mutating of the jump and switch
format bytecode cases.
- jsobj.c
Silence warnings about %p used without (void *) casts.
- jsopcode.c
Massive and scary decompiler whackage to cope with extended jumps, using
source note offsets to help find jumps whose format (short or long) can't
be discovered from properties of prior instructions in the script.
One cute hack here: long || and && expressions are broken up to wrap before
the 80th column, with the operator at the end of each non-terminal line.
- jsopcode.h, jsopcode.tbl
The new extended jump opcodes, formats, and fundamental parameterization
macros. Also, more comments.
- jsparse.c
Random and probably only aesthetic fix to avoid decorating a foo[i]++ or
--foo[i] parse tree node with JSOP_SETCALL, wrongly (only foo(i)++ or
--foo(i), or the other post- or prefix form operator, should have such an
opcode decoration on its parse tree).
- jsscript.h
Random macro naming sanity: use trailing _ rather than leading _ for macro
local variables in order to avoid invading the standard C global namespace.
git-svn-id: svn://10.0.0.236/trunk@105588 18797224-902f-48f8-a5cc-f745e15eee43
with JSRESOLVE_ASSIGNING, wrongly), plus a few miscellaneous bugfixes.
- Combine the JSStackFrame members constructing, special, overrides, and
reserved into a uint32 flags member.
- Separate JOF_ASSIGNING from the JOF_SET bytecode format flag, and impute
JSRESOLVE_ASSIGNING from the presence of JOF_ASSIGNING among the current
opcode's format flags. To handle the for-in loop opcodes, which do more
than simply assign -- in particular, they do property lookups whose resolve
hook outcalls should not be flagged with JSRESOLVE_ASSIGNING -- a new frame
flag, JSFRAME_ASSIGNING, has been added.
- Fix interpreter version selection to respect JS_SetVersion, whose effect on
cx->version is "sticky".
- Fix js_DecompileValueGenerator to deal with JSOP_ENUMELEM -- it never had,
as this testcase shows (it crashes without this patch):
version(120);
eval("function fe(s) { for (it[s] in this); }");
try { fe('rdonly'); } catch (e) { print(e); }
git-svn-id: svn://10.0.0.236/trunk@104525 18797224-902f-48f8-a5cc-f745e15eee43
- Fix scope chain for nested functions at top-level (JSOP_DEFFUN), in a part of another statement (JSOP_CLOSURE), and unnamed in an expression (JSOP_ANONFUNOBJ) to match ECMA-262 13.2. My bad: fp->varobj was used up till now, instead of fp->scopeChain; we still *bind* the name of a statement-level (top or not) nested function in fp->varobj. This fixes bug 69559. (r=rogerl, sr=jband)
- Add an Intern command to the shell, for GC vs. intern'ed atom testing.
git-svn-id: svn://10.0.0.236/trunk@87871 18797224-902f-48f8-a5cc-f745e15eee43
- Optimize integer ++ and -- to avoid double-to-int, which is quite costly for
some compilers (ftol on Windows with MSVC).
- Optimized arguments[i] and arguments.length references to use bytecodes that
avoid creating an arguments object for the current frame. This entailed
simplifying the compiler to avoid flagging functions and scripts that set
arguments, since we have code in jsfun.c to catch such sets at runtime.
- The code generator now eliminates useless expression statements, giving a
strict warning about them.
- Rationalized jsemit.c's LookupArgOrVar to have well-defined results in *pn.
Eliminate bytecode specializations for argument and local variable gets and
sets from jsparse.c -- these precede jsemit.c's LookupArgOrVar and frustrate
it, by setting pn_slot non-negative too early.
- Code generation errors set report->filename and report->lineno, rather than
hacking "{0}, line {1}: " into the localized message.
- Bogus JSFRAME_VAROBJBUG removed, JSOPTION_VAROBJFIX is sufficient.
- Spruce up jsinterp.c macros to use JS_BEGIN/END_MACRO brackets if possible.
- Avoid calling JS_PropertyStub. The call is too costly compared to a branch
in the caller.
git-svn-id: svn://10.0.0.236/trunk@85537 18797224-902f-48f8-a5cc-f745e15eee43
- Optimize integer ++ and -- to avoid double-to-int, which is quite costly for
some compilers (ftol on Windows with MSVC).
- Optimized arguments[i] and arguments.length references to use bytecodes that
avoid creating an arguments object for the current frame. This entailed
simplifying the compiler to avoid flagging functions and scripts that set
arguments, since we have code in jsfun.c to catch such sets at runtime.
- The code generator now eliminates useless expression statements, giving a
strict warning about them.
- Rationalized jsemit.c's LookupArgOrVar to have well-defined results in *pn.
- Code generation errors set report->filename and report->lineno, rather than
hacking "{0}, line {1}: " into the localized message.
- Bogus JSFRAME_VAROBJBUG removed, JSOPTION_VAROBJFIX is sufficient.
- Spruce up jsinterp.c macros to use JS_BEGIN/END_MACRO brackets if possible.
- Avoid calling JS_PropertyStub. The call is too costly compared to a branch
in the caller.
git-svn-id: svn://10.0.0.236/trunk@85488 18797224-902f-48f8-a5cc-f745e15eee43
Make try { ... } catch(exn) { return exn } work by ensuring that the return value (exn) is maintained on the stack as we pop off scopes to return from the try/catch/finally. The newly added JSOP_SWAP opcode helps us bubble.
This fixes a regression uncovered by the fix to 56716.
(I've noticed that this causes *depend* builds of the standalone JS shell to crash on this construct, but I've tested in the Mozilla build, and the dependencies seem to solve the problem there.)
r=brendan.mozilla.org
sr=jband@netscape.com
git-svn-id: svn://10.0.0.236/trunk@82433 18797224-902f-48f8-a5cc-f745e15eee43
- #if JS_HAS_LVALUE_RETURN around cx->rval2/rval2set defs and uses.
- Instrument different kinds of invocations, #ifdef DEBUG only.
- Clean up basis case of empty switch statement to use high = -1, low = 0,
requiring care when optimizing in-range tests using unsigned casts, but
freeing the interpreter and decompiler from having to do an extra test
before looping from low to high.
- Clean up all codegen to use JUMP_OFFSET_LEN, ATOM_INDEX_LEN, etc. instead of
magic 2 or 4.
- Add JSOP_TRY and JSOP_FINALLY no-ops to save a srcnote per JSOP_NOP, and to
make decompilation and jit'ing easier.
- Minimize number of source notes to maximize SRC_XDELTA span.
- Use JSSCRIPT_FIND_CATCH_START in throw code.
- Indentation and bracing nits picked.
git-svn-id: svn://10.0.0.236/trunk@77900 18797224-902f-48f8-a5cc-f745e15eee43
- Tabs expanded as much as I could stand, without taking too much cvsblame.
git-svn-id: svn://10.0.0.236/trunk@59716 18797224-902f-48f8-a5cc-f745e15eee43
- Add JS1.5 getter/setter support in all its glory:
* getter function SN() {return ++x} at top-level or as a closure binds an SN
property getter than returns the incremented value of x. Likewise for
setter function SN(y) {return y = x}.
* getters and setters may be defined in an object literal:
o = {p getter:function() {return ++this.x},
p setter:function(y){return this.x = y},
x:42};
* getter= and setter= operators (compound tokens) may be used to bind getter
and setter properties dynamically:
o = new Object;
o.p getter= function() {return ++this.x};
o.p setter= function(y){return this.x = y};
o.x = 42;
Waldemar is concerned that this form will collide semantically with JS2, so
I am not committing to keeping it in JS1.5. I'd like to check my code in
ASAP so shaver can use it, and I'd also like to see this form get used (or
not) during Mozilla betas. Caveat emptor, and if you find this "dynamic"
or "imperative" form necessary and hard to substitute, please let me know.
If this proves important to users, then I think JS1.5 should keep it.
- Cleaned up property flags (in a binary-incompatible fashion -- who cares?) by
eliminating JSPROP_ASSIGNHACK and JSPROP_TINYIDHACK.
- Added JS_DONT_PRETTY_PRINT flag to be ORed with the indent argument to the
several JS_Decompile*() API calls. This avoids any newlines or identation in
the decompiled string.
- Improved and extended (for getter/setter non-reservation) scanner lookahead
by using a circular (power-of-2 sized) token buffer.
- Fix ECMA Edition 3 deviation where function f(){function g(){}} bound f.g by
mistake (it should arrange to make a closure named g in activations of f, but
it should not bind a property of function f).
git-svn-id: svn://10.0.0.236/trunk@48436 18797224-902f-48f8-a5cc-f745e15eee43
to define an unbound global variable used to enumerate an empty object, when
the standard says no variable should be defined.
- Clean up minor nits, make comment style match prevailing, tighten up for..in
element-indexing special case comments.
- Fix js_Invoke to take CONSTRUCT and INTERNAL flags arg instead of a construct
boolean arg and the JSStackFrame internalCall mis-located boolean non-arg.
Use these flags correctly in all calls (previous version failed to set the
bogus frame.internalCall around js_Invoke calls from jsfun.c and jsstr.c).
git-svn-id: svn://10.0.0.236/trunk@39473 18797224-902f-48f8-a5cc-f745e15eee43
+ merging of js/src and js/ref
+ elimination of most dependencies on NSPR
+ JS1.4 feature additions and accumulated bug fixes
More details are in last week's mozilla status report.
git-svn-id: svn://10.0.0.236/trunk@12797 18797224-902f-48f8-a5cc-f745e15eee43