1 |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
2 |
* vim: set ts=8 sw=4 et tw=99: |
* vim: set ts=8 sw=4 et tw=99: |
3 |
* |
* |
4 |
* ***** BEGIN LICENSE BLOCK ***** |
* ***** BEGIN LICENSE BLOCK ***** |
41 |
/* |
/* |
42 |
* JS bytecode generation. |
* JS bytecode generation. |
43 |
*/ |
*/ |
|
#include "jsstddef.h" |
|
44 |
#ifdef HAVE_MEMORY_H |
#ifdef HAVE_MEMORY_H |
45 |
#include <memory.h> |
#include <memory.h> |
46 |
#endif |
#endif |
47 |
#include <new> |
#include <new> |
48 |
#include <string.h> |
#include <string.h> |
49 |
#include "jstypes.h" |
#include "jstypes.h" |
50 |
|
#include "jsstdint.h" |
51 |
#include "jsarena.h" /* Added by JSIFY */ |
#include "jsarena.h" /* Added by JSIFY */ |
52 |
#include "jsutil.h" /* Added by JSIFY */ |
#include "jsutil.h" /* Added by JSIFY */ |
53 |
#include "jsbit.h" |
#include "jsbit.h" |
112 |
|
|
113 |
/* NB: non-null only after OOM. */ |
/* NB: non-null only after OOM. */ |
114 |
if (spanDeps) |
if (spanDeps) |
115 |
JS_free(compiler->context, spanDeps); |
compiler->context->free(spanDeps); |
116 |
|
|
117 |
if (upvarMap.vector) |
if (upvarMap.vector) |
118 |
JS_free(compiler->context, upvarMap.vector); |
compiler->context->free(upvarMap.vector); |
119 |
} |
} |
120 |
|
|
121 |
static ptrdiff_t |
static ptrdiff_t |
128 |
base = CG_BASE(cg); |
base = CG_BASE(cg); |
129 |
next = CG_NEXT(cg); |
next = CG_NEXT(cg); |
130 |
limit = CG_LIMIT(cg); |
limit = CG_LIMIT(cg); |
131 |
offset = PTRDIFF(next, base, jsbytecode); |
offset = next - base; |
132 |
if (next + delta > limit) { |
if (next + delta > limit) { |
133 |
length = offset + delta; |
length = offset + delta; |
134 |
length = (length <= BYTECODE_CHUNK) |
length = (length <= BYTECODE_CHUNK) |
138 |
if (!base) { |
if (!base) { |
139 |
JS_ARENA_ALLOCATE_CAST(base, jsbytecode *, cg->codePool, incr); |
JS_ARENA_ALLOCATE_CAST(base, jsbytecode *, cg->codePool, incr); |
140 |
} else { |
} else { |
141 |
size = BYTECODE_SIZE(PTRDIFF(limit, base, jsbytecode)); |
size = BYTECODE_SIZE(limit - base); |
142 |
incr -= size; |
incr -= size; |
143 |
JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr); |
JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr); |
144 |
} |
} |
549 |
if ((index & (index - 1)) == 0 && |
if ((index & (index - 1)) == 0 && |
550 |
(!(sdbase = cg->spanDeps) || index >= SPANDEPS_MIN)) { |
(!(sdbase = cg->spanDeps) || index >= SPANDEPS_MIN)) { |
551 |
size = sdbase ? SPANDEPS_SIZE(index) : SPANDEPS_SIZE_MIN / 2; |
size = sdbase ? SPANDEPS_SIZE(index) : SPANDEPS_SIZE_MIN / 2; |
552 |
sdbase = (JSSpanDep *) JS_realloc(cx, sdbase, size + size); |
sdbase = (JSSpanDep *) cx->realloc(sdbase, size + size); |
553 |
if (!sdbase) |
if (!sdbase) |
554 |
return JS_FALSE; |
return JS_FALSE; |
555 |
cg->spanDeps = sdbase; |
cg->spanDeps = sdbase; |
557 |
|
|
558 |
cg->numSpanDeps = index + 1; |
cg->numSpanDeps = index + 1; |
559 |
sd = cg->spanDeps + index; |
sd = cg->spanDeps + index; |
560 |
sd->top = PTRDIFF(pc, CG_BASE(cg), jsbytecode); |
sd->top = pc - CG_BASE(cg); |
561 |
sd->offset = sd->before = PTRDIFF(pc2, CG_BASE(cg), jsbytecode); |
sd->offset = sd->before = pc2 - CG_BASE(cg); |
562 |
|
|
563 |
if (js_CodeSpec[*pc].format & JOF_BACKPATCH) { |
if (js_CodeSpec[*pc].format & JOF_BACKPATCH) { |
564 |
/* Jump offset will be backpatched if off is a non-zero "bpdelta". */ |
/* Jump offset will be backpatched if off is a non-zero "bpdelta". */ |
673 |
if (index != SPANDEP_INDEX_HUGE) |
if (index != SPANDEP_INDEX_HUGE) |
674 |
return cg->spanDeps + index; |
return cg->spanDeps + index; |
675 |
|
|
676 |
offset = PTRDIFF(pc, CG_BASE(cg), jsbytecode); |
offset = pc - CG_BASE(cg); |
677 |
lo = 0; |
lo = 0; |
678 |
hi = cg->numSpanDeps - 1; |
hi = cg->numSpanDeps - 1; |
679 |
while (lo <= hi) { |
while (lo <= hi) { |
910 |
next = base + length; |
next = base + length; |
911 |
if (next > limit) { |
if (next > limit) { |
912 |
JS_ASSERT(length > BYTECODE_CHUNK); |
JS_ASSERT(length > BYTECODE_CHUNK); |
913 |
size = BYTECODE_SIZE(PTRDIFF(limit, base, jsbytecode)); |
size = BYTECODE_SIZE(limit - base); |
914 |
incr = BYTECODE_SIZE(length) - size; |
incr = BYTECODE_SIZE(length) - size; |
915 |
JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr); |
JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr); |
916 |
if (!base) { |
if (!base) { |
1165 |
* can span top-level statements, because JS lacks goto. |
* can span top-level statements, because JS lacks goto. |
1166 |
*/ |
*/ |
1167 |
size = SPANDEPS_SIZE(JS_BIT(JS_CeilingLog2(cg->numSpanDeps))); |
size = SPANDEPS_SIZE(JS_BIT(JS_CeilingLog2(cg->numSpanDeps))); |
1168 |
JS_free(cx, cg->spanDeps); |
cx->free(cg->spanDeps); |
1169 |
cg->spanDeps = NULL; |
cg->spanDeps = NULL; |
1170 |
FreeJumpTargets(cg, cg->jumpTargets); |
FreeJumpTargets(cg, cg->jumpTargets); |
1171 |
cg->jumpTargets = NULL; |
cg->jumpTargets = NULL; |
1427 |
stop = CG_CODE(cg, -1); |
stop = CG_CODE(cg, -1); |
1428 |
while (pc != stop) { |
while (pc != stop) { |
1429 |
delta = GetJumpOffset(cg, pc); |
delta = GetJumpOffset(cg, pc); |
1430 |
span = PTRDIFF(target, pc, jsbytecode); |
span = target - pc; |
1431 |
CHECK_AND_SET_JUMP_OFFSET(cx, cg, pc, span); |
CHECK_AND_SET_JUMP_OFFSET(cx, cg, pc, span); |
1432 |
|
|
1433 |
/* |
/* |
1525 |
continue; |
continue; |
1526 |
|
|
1527 |
obj = stmt->blockObj; |
obj = stmt->blockObj; |
1528 |
JS_ASSERT(LOCKED_OBJ_GET_CLASS(obj) == &js_BlockClass); |
JS_ASSERT(obj->getClass() == &js_BlockClass); |
1529 |
scope = OBJ_SCOPE(obj); |
scope = OBJ_SCOPE(obj); |
1530 |
sprop = SCOPE_GET_PROPERTY(scope, ATOM_TO_JSID(atom)); |
sprop = scope->lookup(ATOM_TO_JSID(atom)); |
1531 |
if (sprop) { |
if (sprop) { |
1532 |
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); |
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); |
1533 |
|
|
1601 |
} else { |
} else { |
1602 |
JS_ASSERT(cg->flags & TCF_COMPILE_N_GO); |
JS_ASSERT(cg->flags & TCF_COMPILE_N_GO); |
1603 |
obj = cg->scopeChain; |
obj = cg->scopeChain; |
1604 |
ok = OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &objbox, |
ok = obj->lookupProperty(cx, ATOM_TO_JSID(atom), &objbox, &prop); |
|
&prop); |
|
1605 |
if (!ok) |
if (!ok) |
1606 |
return JS_FALSE; |
return JS_FALSE; |
1607 |
if (objbox == obj) { |
if (objbox == obj) { |
1611 |
* variable object. Therefore we can get constant values |
* variable object. Therefore we can get constant values |
1612 |
* from our variable object here. |
* from our variable object here. |
1613 |
*/ |
*/ |
1614 |
ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, |
ok = obj->getAttributes(cx, ATOM_TO_JSID(atom), prop, &attrs); |
|
&attrs); |
|
1615 |
if (ok && IS_CONSTANT_PROPERTY(attrs)) { |
if (ok && IS_CONSTANT_PROPERTY(attrs)) { |
1616 |
ok = OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp); |
ok = obj->getProperty(cx, ATOM_TO_JSID(atom), vp); |
1617 |
JS_ASSERT_IF(ok, *vp != JSVAL_HOLE); |
JS_ASSERT_IF(ok, *vp != JSVAL_HOLE); |
1618 |
} |
} |
1619 |
} |
} |
1620 |
if (prop) |
if (prop) |
1621 |
OBJ_DROP_PROPERTY(cx, objbox, prop); |
objbox->dropProperty(cx, prop); |
1622 |
if (!ok) |
if (!ok) |
1623 |
return JS_FALSE; |
return JS_FALSE; |
1624 |
if (prop) |
if (prop) |
1820 |
} |
} |
1821 |
|
|
1822 |
OBJ_SCOPE(blockObj)->freeslot = JSSLOT_FREE(&js_BlockClass); |
OBJ_SCOPE(blockObj)->freeslot = JSSLOT_FREE(&js_BlockClass); |
1823 |
js_ReallocSlots(cx, blockObj, JSSLOT_FREE(&js_BlockClass), JS_TRUE); |
return js_GrowSlots(cx, blockObj, JSSLOT_FREE(&js_BlockClass)); |
|
return true; |
|
1824 |
} |
} |
1825 |
|
|
1826 |
/* |
/* |
1897 |
JS_ASSERT(ALE_INDEX(ale) <= length); |
JS_ASSERT(ALE_INDEX(ale) <= length); |
1898 |
if (ALE_INDEX(ale) == length) { |
if (ALE_INDEX(ale) == length) { |
1899 |
length = 2 * JS_MAX(2, length); |
length = 2 * JS_MAX(2, length); |
1900 |
vector = (uint32 *) JS_realloc(cx, vector, length * sizeof *vector); |
vector = (uint32 *) cx->realloc(vector, length * sizeof *vector); |
1901 |
if (!vector) |
if (!vector) |
1902 |
return false; |
return false; |
1903 |
cg->upvarMap.vector = vector; |
cg->upvarMap.vector = vector; |
2109 |
if (op != JSOP_NAME) |
if (op != JSOP_NAME) |
2110 |
return JS_TRUE; |
return JS_TRUE; |
2111 |
|
|
|
#ifdef DEBUG |
|
2112 |
JSStackFrame *caller = cg->compiler->callerFrame; |
JSStackFrame *caller = cg->compiler->callerFrame; |
2113 |
JS_ASSERT(caller); |
JS_ASSERT(caller); |
2114 |
|
JS_ASSERT(caller->script); |
2115 |
|
|
2116 |
JSTreeContext *tc = cg; |
JSTreeContext *tc = cg; |
2117 |
while (tc->staticLevel != level) |
while (tc->staticLevel != level) |
2120 |
|
|
2121 |
JSCodeGenerator *evalcg = (JSCodeGenerator *) tc; |
JSCodeGenerator *evalcg = (JSCodeGenerator *) tc; |
2122 |
JS_ASSERT(evalcg->flags & TCF_COMPILE_N_GO); |
JS_ASSERT(evalcg->flags & TCF_COMPILE_N_GO); |
|
JS_ASSERT(!(evalcg->flags & TCF_IN_FOR_INIT)); |
|
|
JS_ASSERT(caller->script); |
|
2123 |
JS_ASSERT(caller->fun && caller->varobj == evalcg->scopeChain); |
JS_ASSERT(caller->fun && caller->varobj == evalcg->scopeChain); |
2124 |
#endif |
|
2125 |
|
/* |
2126 |
|
* Don't generate upvars on the left side of a for loop. See |
2127 |
|
* bug 470758 and bug 520513. |
2128 |
|
*/ |
2129 |
|
if (evalcg->flags & TCF_IN_FOR_INIT) |
2130 |
|
return JS_TRUE; |
2131 |
|
|
2132 |
if (cg->staticLevel == level) { |
if (cg->staticLevel == level) { |
2133 |
pn->pn_op = JSOP_GETUPVAR; |
pn->pn_op = JSOP_GETUPVAR; |
2142 |
uintN skip = cg->staticLevel - level; |
uintN skip = cg->staticLevel - level; |
2143 |
if (skip != 0) { |
if (skip != 0) { |
2144 |
JS_ASSERT(cg->flags & TCF_IN_FUNCTION); |
JS_ASSERT(cg->flags & TCF_IN_FUNCTION); |
2145 |
JS_ASSERT(cg->lexdeps.lookup(atom)); |
JS_ASSERT_IF(UPVAR_FRAME_SLOT(cookie) != CALLEE_UPVAR_SLOT, |
2146 |
|
cg->lexdeps.lookup(atom)); |
2147 |
JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM); |
JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM); |
2148 |
JS_ASSERT(cg->fun->u.i.skipmin <= skip); |
JS_ASSERT(cg->fun->u.i.skipmin <= skip); |
2149 |
|
|
2200 |
if (!vector) { |
if (!vector) { |
2201 |
uint32 length = cg->lexdeps.count; |
uint32 length = cg->lexdeps.count; |
2202 |
|
|
2203 |
vector = (uint32 *) calloc(length, sizeof *vector); |
vector = (uint32 *) js_calloc(length * sizeof *vector); |
2204 |
if (!vector) { |
if (!vector) { |
2205 |
JS_ReportOutOfMemory(cx); |
JS_ReportOutOfMemory(cx); |
2206 |
return JS_FALSE; |
return JS_FALSE; |
2210 |
} |
} |
2211 |
|
|
2212 |
uintN slot = UPVAR_FRAME_SLOT(cookie); |
uintN slot = UPVAR_FRAME_SLOT(cookie); |
2213 |
if (dn_kind != JSDefinition::ARG) { |
if (slot != CALLEE_UPVAR_SLOT && dn_kind != JSDefinition::ARG) { |
2214 |
JSTreeContext *tc = cg; |
JSTreeContext *tc = cg; |
2215 |
do { |
do { |
2216 |
tc = tc->parent; |
tc = tc->parent; |
2436 |
|
|
2437 |
case PN_UNARY: |
case PN_UNARY: |
2438 |
switch (pn->pn_type) { |
switch (pn->pn_type) { |
|
case TOK_RP: |
|
|
ok = CheckSideEffects(cx, cg, pn->pn_kid, answer); |
|
|
break; |
|
|
|
|
2439 |
case TOK_DELETE: |
case TOK_DELETE: |
2440 |
pn2 = pn->pn_kid; |
pn2 = pn->pn_kid; |
2441 |
switch (pn2->pn_type) { |
switch (pn2->pn_type) { |
3143 |
/* Just grab 8K for the worst-case bitmap. */ |
/* Just grab 8K for the worst-case bitmap. */ |
3144 |
intmap_bitlen = JS_BIT(16); |
intmap_bitlen = JS_BIT(16); |
3145 |
intmap = (jsbitmap *) |
intmap = (jsbitmap *) |
3146 |
JS_malloc(cx, |
cx->malloc((JS_BIT(16) >> JS_BITS_PER_WORD_LOG2) |
3147 |
(JS_BIT(16) >> JS_BITS_PER_WORD_LOG2) |
* sizeof(jsbitmap)); |
|
* sizeof(jsbitmap)); |
|
3148 |
if (!intmap) { |
if (!intmap) { |
3149 |
JS_ReportOutOfMemory(cx); |
JS_ReportOutOfMemory(cx); |
3150 |
return JS_FALSE; |
return JS_FALSE; |
3161 |
|
|
3162 |
release: |
release: |
3163 |
if (intmap && intmap != intmap_space) |
if (intmap && intmap != intmap_space) |
3164 |
JS_free(cx, intmap); |
cx->free(intmap); |
3165 |
if (!ok) |
if (!ok) |
3166 |
return JS_FALSE; |
return JS_FALSE; |
3167 |
|
|
3305 |
*/ |
*/ |
3306 |
if (tableLength != 0) { |
if (tableLength != 0) { |
3307 |
tableSize = (size_t)tableLength * sizeof *table; |
tableSize = (size_t)tableLength * sizeof *table; |
3308 |
table = (JSParseNode **) JS_malloc(cx, tableSize); |
table = (JSParseNode **) cx->malloc(tableSize); |
3309 |
if (!table) |
if (!table) |
3310 |
return JS_FALSE; |
return JS_FALSE; |
3311 |
memset(table, 0, tableSize); |
memset(table, 0, tableSize); |
3473 |
|
|
3474 |
out: |
out: |
3475 |
if (table) |
if (table) |
3476 |
JS_free(cx, table); |
cx->free(table); |
3477 |
if (ok) { |
if (ok) { |
3478 |
ok = js_PopStatementCG(cx, cg); |
ok = js_PopStatementCG(cx, cg); |
3479 |
|
|
3499 |
if (js_Emit1(cx, cg, JSOP_GENERATOR) < 0) |
if (js_Emit1(cx, cg, JSOP_GENERATOR) < 0) |
3500 |
return JS_FALSE; |
return JS_FALSE; |
3501 |
CG_SWITCH_TO_MAIN(cg); |
CG_SWITCH_TO_MAIN(cg); |
3502 |
|
} else { |
3503 |
|
/* |
3504 |
|
* Emit a trace hint opcode only if not in a generator, since generators |
3505 |
|
* are not yet traced and both want to be the first instruction. |
3506 |
|
*/ |
3507 |
|
if (js_Emit1(cx, cg, JSOP_TRACE) < 0) |
3508 |
|
return JS_FALSE; |
3509 |
} |
} |
3510 |
|
|
3511 |
return js_EmitTree(cx, cg, body) && |
return js_EmitTree(cx, cg, body) && |
3638 |
{ |
{ |
3639 |
jsuint slot; |
jsuint slot; |
3640 |
|
|
|
/* Skip any parenthesization. */ |
|
|
while (pn->pn_type == TOK_RP) |
|
|
pn = pn->pn_kid; |
|
|
|
|
3641 |
/* |
/* |
3642 |
* Now emit the lvalue opcode sequence. If the lvalue is a nested |
* Now emit the lvalue opcode sequence. If the lvalue is a nested |
3643 |
* destructuring initialiser-form, call ourselves to handle it, then |
* destructuring initialiser-form, call ourselves to handle it, then |
3862 |
} |
} |
3863 |
|
|
3864 |
/* MaybeEmitGroupAssignment won't call us if rhs is holey. */ |
/* MaybeEmitGroupAssignment won't call us if rhs is holey. */ |
3865 |
JS_ASSERT(pn->pn_type != TOK_COMMA); |
JS_ASSERT(!(pn->pn_type == TOK_COMMA && pn->pn_arity == PN_NULLARY)); |
3866 |
if (!js_EmitTree(cx, cg, pn)) |
if (!js_EmitTree(cx, cg, pn)) |
3867 |
return JS_FALSE; |
return JS_FALSE; |
3868 |
++limit; |
++limit; |
4490 |
jmp = EmitJump(cx, cg, JSOP_GOTO, 0); |
jmp = EmitJump(cx, cg, JSOP_GOTO, 0); |
4491 |
if (jmp < 0) |
if (jmp < 0) |
4492 |
return JS_FALSE; |
return JS_FALSE; |
4493 |
top = CG_OFFSET(cg); |
top = js_Emit1(cx, cg, JSOP_TRACE); |
4494 |
if (!js_Emit1(cx, cg, JSOP_LOOP)) |
if (top < 0) |
4495 |
return JS_FALSE; |
return JS_FALSE; |
4496 |
if (!js_EmitTree(cx, cg, pn->pn_right)) |
if (!js_EmitTree(cx, cg, pn->pn_right)) |
4497 |
return JS_FALSE; |
return JS_FALSE; |
4513 |
return JS_FALSE; |
return JS_FALSE; |
4514 |
|
|
4515 |
/* Compile the loop body. */ |
/* Compile the loop body. */ |
4516 |
top = CG_OFFSET(cg); |
top = js_Emit1(cx, cg, JSOP_TRACE); |
4517 |
if (!js_Emit1(cx, cg, JSOP_LOOP)) |
if (top < 0) |
4518 |
return JS_FALSE; |
return JS_FALSE; |
4519 |
js_PushStatement(cg, &stmtInfo, STMT_DO_LOOP, top); |
js_PushStatement(cg, &stmtInfo, STMT_DO_LOOP, top); |
4520 |
if (!js_EmitTree(cx, cg, pn->pn_left)) |
if (!js_EmitTree(cx, cg, pn->pn_left)) |
4613 |
|
|
4614 |
top = CG_OFFSET(cg); |
top = CG_OFFSET(cg); |
4615 |
SET_STATEMENT_TOP(&stmtInfo, top); |
SET_STATEMENT_TOP(&stmtInfo, top); |
4616 |
if (!js_Emit1(cx, cg, JSOP_LOOP)) |
if (js_Emit1(cx, cg, JSOP_TRACE) < 0) |
4617 |
return JS_FALSE; |
return JS_FALSE; |
4618 |
|
|
4619 |
#ifdef DEBUG |
#ifdef DEBUG |
4842 |
SET_STATEMENT_TOP(&stmtInfo, top); |
SET_STATEMENT_TOP(&stmtInfo, top); |
4843 |
|
|
4844 |
/* Emit code for the loop body. */ |
/* Emit code for the loop body. */ |
4845 |
if (!js_Emit1(cx, cg, JSOP_LOOP)) |
if (js_Emit1(cx, cg, JSOP_TRACE) < 0) |
4846 |
return JS_FALSE; |
return JS_FALSE; |
4847 |
if (!js_EmitTree(cx, cg, pn->pn_right)) |
if (!js_EmitTree(cx, cg, pn->pn_right)) |
4848 |
return JS_FALSE; |
return JS_FALSE; |
5608 |
* stack, which impose pervasive runtime "GetValue" costs. |
* stack, which impose pervasive runtime "GetValue" costs. |
5609 |
*/ |
*/ |
5610 |
pn2 = pn->pn_left; |
pn2 = pn->pn_left; |
|
JS_ASSERT(pn2->pn_type != TOK_RP); |
|
5611 |
atomIndex = (jsatomid) -1; /* quell GCC overwarning */ |
atomIndex = (jsatomid) -1; /* quell GCC overwarning */ |
5612 |
switch (pn2->pn_type) { |
switch (pn2->pn_type) { |
5613 |
case TOK_NAME: |
case TOK_NAME: |
5906 |
} |
} |
5907 |
break; |
break; |
5908 |
|
|
5909 |
|
case TOK_PLUS: |
5910 |
|
/* For TCF_IN_FUNCTION test, see TOK_RB concerning JSOP_NEWARRAY. */ |
5911 |
|
if (pn->pn_arity == PN_LIST && pn->pn_count < JS_BIT(16) && |
5912 |
|
(cg->flags & TCF_IN_FUNCTION)) { |
5913 |
|
/* Emit up to the first string literal conventionally. */ |
5914 |
|
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { |
5915 |
|
if (pn2->pn_type == TOK_STRING) |
5916 |
|
break; |
5917 |
|
if (!js_EmitTree(cx, cg, pn2)) |
5918 |
|
return JS_FALSE; |
5919 |
|
if (pn2 != pn->pn_head && js_Emit1(cx, cg, JSOP_ADD) < 0) |
5920 |
|
return JS_FALSE; |
5921 |
|
} |
5922 |
|
|
5923 |
|
/* Emit remainder as a single JSOP_CONCATN. */ |
5924 |
|
for (index = 0; pn2; pn2 = pn2->pn_next, index++) { |
5925 |
|
if (!js_EmitTree(cx, cg, pn2)) |
5926 |
|
return JS_FALSE; |
5927 |
|
} |
5928 |
|
|
5929 |
|
if (index != 0) { |
5930 |
|
EMIT_UINT16_IMM_OP(JSOP_CONCATN, index); |
5931 |
|
|
5932 |
|
/* If we had a prefix, we need to be added to it now. */ |
5933 |
|
if (pn->pn_head->pn_type != TOK_STRING && |
5934 |
|
js_Emit1(cx, cg, JSOP_ADD) < 0) { |
5935 |
|
return JS_FALSE; |
5936 |
|
} |
5937 |
|
} |
5938 |
|
break; |
5939 |
|
} |
5940 |
case TOK_BITOR: |
case TOK_BITOR: |
5941 |
case TOK_BITXOR: |
case TOK_BITXOR: |
5942 |
case TOK_BITAND: |
case TOK_BITAND: |
5945 |
case TOK_IN: |
case TOK_IN: |
5946 |
case TOK_INSTANCEOF: |
case TOK_INSTANCEOF: |
5947 |
case TOK_SHOP: |
case TOK_SHOP: |
|
case TOK_PLUS: |
|
5948 |
case TOK_MINUS: |
case TOK_MINUS: |
5949 |
case TOK_STAR: |
case TOK_STAR: |
5950 |
case TOK_DIVOP: |
case TOK_DIVOP: |
6016 |
} |
} |
6017 |
#endif |
#endif |
6018 |
pn2 = pn->pn_kid; |
pn2 = pn->pn_kid; |
6019 |
if (op == JSOP_TYPEOF) { |
|
6020 |
for (pn3 = pn2; pn3->pn_type == TOK_RP; pn3 = pn3->pn_kid) |
/* See js_FoldConstants for why this assertion holds true. */ |
6021 |
continue; |
JS_ASSERT_IF(op == JSOP_TYPEOF, pn2->pn_type == TOK_NAME); |
6022 |
if (pn3->pn_type != TOK_NAME) |
|
|
op = JSOP_TYPEOFEXPR; |
|
|
} |
|
6023 |
oldflags = cg->flags; |
oldflags = cg->flags; |
6024 |
cg->flags &= ~TCF_IN_FOR_INIT; |
cg->flags &= ~TCF_IN_FOR_INIT; |
6025 |
if (!js_EmitTree(cx, cg, pn2)) |
if (!js_EmitTree(cx, cg, pn2)) |
6181 |
jmp = js_Emit3(cx, cg, JSOP_FILTER, 0, 0); |
jmp = js_Emit3(cx, cg, JSOP_FILTER, 0, 0); |
6182 |
if (jmp < 0) |
if (jmp < 0) |
6183 |
return JS_FALSE; |
return JS_FALSE; |
6184 |
top = CG_OFFSET(cg); |
top = js_Emit1(cx, cg, JSOP_TRACE); |
6185 |
if (!js_Emit1(cx, cg, JSOP_LOOP)) |
if (top < 0) |
6186 |
return JS_FALSE; |
return JS_FALSE; |
6187 |
if (!js_EmitTree(cx, cg, pn->pn_right)) |
if (!js_EmitTree(cx, cg, pn->pn_right)) |
6188 |
return JS_FALSE; |
return JS_FALSE; |
6467 |
for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) { |
for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) { |
6468 |
if (op == JSOP_NEWINIT && !EmitNumberOp(cx, atomIndex, cg)) |
if (op == JSOP_NEWINIT && !EmitNumberOp(cx, atomIndex, cg)) |
6469 |
return JS_FALSE; |
return JS_FALSE; |
6470 |
if (pn2->pn_type == TOK_COMMA) { |
if (pn2->pn_type == TOK_COMMA && pn2->pn_arity == PN_NULLARY) { |
6471 |
if (js_Emit1(cx, cg, JSOP_HOLE) < 0) |
if (js_Emit1(cx, cg, JSOP_HOLE) < 0) |
6472 |
return JS_FALSE; |
return JS_FALSE; |
6473 |
} else { |
} else { |
6592 |
break; |
break; |
6593 |
#endif /* JS_HAS_SHARP_VARS */ |
#endif /* JS_HAS_SHARP_VARS */ |
6594 |
|
|
|
case TOK_RP: |
|
|
{ |
|
|
uintN oldflags; |
|
|
|
|
|
/* |
|
|
* The node for (e) has e as its kid, enabling users who want to nest |
|
|
* assignment expressions in conditions to avoid the error correction |
|
|
* done by Condition (from x = y to x == y) by double-parenthesizing. |
|
|
*/ |
|
|
oldflags = cg->flags; |
|
|
cg->flags &= ~TCF_IN_FOR_INIT; |
|
|
if (!js_EmitTree(cx, cg, pn->pn_kid)) |
|
|
return JS_FALSE; |
|
|
cg->flags |= oldflags & TCF_IN_FOR_INIT; |
|
|
break; |
|
|
} |
|
|
|
|
6595 |
case TOK_NAME: |
case TOK_NAME: |
6596 |
/* |
/* |
6597 |
* Cope with a left-over function definition that was replaced by a use |
* Cope with a left-over function definition that was replaced by a use |
7063 |
/* Maybe this offset was already set to a three-byte value. */ |
/* Maybe this offset was already set to a three-byte value. */ |
7064 |
if (!(*sn & SN_3BYTE_OFFSET_FLAG)) { |
if (!(*sn & SN_3BYTE_OFFSET_FLAG)) { |
7065 |
/* Losing, need to insert another two bytes for this offset. */ |
/* Losing, need to insert another two bytes for this offset. */ |
7066 |
index = PTRDIFF(sn, CG_NOTES(cg), jssrcnote); |
index = sn - CG_NOTES(cg); |
7067 |
|
|
7068 |
/* |
/* |
7069 |
* Simultaneously test to see if the source note array must grow to |
* Simultaneously test to see if the source note array must grow to |
7249 |
* If the code being compiled is function code, allocate a reserved slot in |
* If the code being compiled is function code, allocate a reserved slot in |
7250 |
* the cloned function object that shares its precompiled script with other |
* the cloned function object that shares its precompiled script with other |
7251 |
* cloned function objects and with the compiler-created clone-parent. There |
* cloned function objects and with the compiler-created clone-parent. There |
7252 |
* are nregexps = JS_SCRIPT_REGEXPS(script)->length such reserved slots in each |
* are nregexps = script->regexps()->length such reserved slots in each |
7253 |
* function object cloned from fun->object. NB: during compilation, a funobj |
* function object cloned from fun->object. NB: during compilation, a funobj |
7254 |
* slots element must never be allocated, because js_AllocSlot could hand out |
* slots element must never be allocated, because js_AllocSlot could hand out |
7255 |
* one of the slots that should be given to a regexp clone. |
* one of the slots that should be given to a regexp clone. |