зеркало из https://github.com/mozilla/gecko-dev.git
Merge.
This commit is contained in:
Коммит
50aec18ba5
|
@ -537,8 +537,8 @@ static struct {
|
|||
},
|
||||
};
|
||||
static struct {
|
||||
jsbytecode for_in[10];
|
||||
jsbytecode for_each[10];
|
||||
jsbytecode for_in[13];
|
||||
jsbytecode for_each[13];
|
||||
jsbytecode for_in_native[10];
|
||||
jsbytecode for_each_native[10];
|
||||
} iter_imacros = {
|
||||
|
@ -546,15 +546,17 @@ static struct {
|
|||
/* 0*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(iterator),
|
||||
/* 3*/ JSOP_INT8, (JSITER_ENUMERATE),
|
||||
/* 5*/ JSOP_CALL, 0, 1,
|
||||
/* 8*/ JSOP_PUSH,
|
||||
/* 9*/ JSOP_STOP,
|
||||
/* 8*/ JSOP_OBJTOP, ((JSMSG_BAD_ITERATOR_RETURN) & 0xff00) >> 8, ((JSMSG_BAD_ITERATOR_RETURN) & 0xff),
|
||||
/*11*/ JSOP_PUSH,
|
||||
/*12*/ JSOP_STOP,
|
||||
},
|
||||
{
|
||||
/* 0*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(iterator),
|
||||
/* 3*/ JSOP_INT8, (JSITER_ENUMERATE|JSITER_FOREACH),
|
||||
/* 5*/ JSOP_CALL, 0, 1,
|
||||
/* 8*/ JSOP_PUSH,
|
||||
/* 9*/ JSOP_STOP,
|
||||
/* 8*/ JSOP_OBJTOP, ((JSMSG_BAD_ITERATOR_RETURN) & 0xff00) >> 8, ((JSMSG_BAD_ITERATOR_RETURN) & 0xff),
|
||||
/*11*/ JSOP_PUSH,
|
||||
/*12*/ JSOP_STOP,
|
||||
},
|
||||
{
|
||||
/* 0*/ JSOP_CALLBUILTIN, ((JSBUILTIN_ObjectToIterator) & 0xff00) >> 8, ((JSBUILTIN_ObjectToIterator) & 0xff),
|
||||
|
@ -788,7 +790,7 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
|
|||
0, /* JSOP_SETCALL */
|
||||
0, /* JSOP_TRY */
|
||||
0, /* JSOP_FINALLY */
|
||||
0, /* JSOP_UNUSED135 */
|
||||
0, /* JSOP_OBJTOP */
|
||||
0, /* JSOP_ARGSUB */
|
||||
0, /* JSOP_ARGCNT */
|
||||
0, /* JSOP_DEFLOCALFUN */
|
||||
|
|
|
@ -583,6 +583,7 @@
|
|||
callprop iterator # fun obj
|
||||
int8 (JSITER_ENUMERATE) # fun obj flags
|
||||
call 1 # iterobj
|
||||
objtop (JSMSG_BAD_ITERATOR_RETURN) # iterobj
|
||||
push # iterobj undef
|
||||
stop
|
||||
.end
|
||||
|
@ -591,6 +592,7 @@
|
|||
callprop iterator # fun obj
|
||||
int8 (JSITER_ENUMERATE|JSITER_FOREACH) # fun obj flags
|
||||
call 1 # iterobj
|
||||
objtop (JSMSG_BAD_ITERATOR_RETURN) # iterobj
|
||||
push # iterobj undef
|
||||
stop
|
||||
.end
|
||||
|
|
|
@ -291,7 +291,7 @@ MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 208, 1, JSEXN_TYPEERR, "generator function
|
|||
MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 209, 0, JSEXN_TYPEERR, "anonymous generator function returns a value")
|
||||
MSG_DEF(JSMSG_NAME_AFTER_FOR_PAREN, 210, 0, JSEXN_SYNTAXERR, "missing name after for (")
|
||||
MSG_DEF(JSMSG_IN_AFTER_FOR_NAME, 211, 0, JSEXN_SYNTAXERR, "missing in after for")
|
||||
MSG_DEF(JSMSG_BAD_ITERATOR_RETURN, 212, 2, JSEXN_TYPEERR, "{0}.{1} returned a primitive value")
|
||||
MSG_DEF(JSMSG_BAD_ITERATOR_RETURN, 212, 1, JSEXN_TYPEERR, "{0}.__iterator__ returned a primitive value")
|
||||
MSG_DEF(JSMSG_KEYWORD_NOT_NS, 213, 0, JSEXN_SYNTAXERR, "keyword is used as namespace")
|
||||
MSG_DEF(JSMSG_BAD_GENERATOR_YIELD, 214, 1, JSEXN_TYPEERR, "yield from closing generator {0}")
|
||||
MSG_DEF(JSMSG_BAD_GENERATOR_SYNTAX, 215, 1, JSEXN_SYNTAXERR, "{0} expression must be parenthesized")
|
||||
|
|
|
@ -1191,24 +1191,12 @@ JS_GetOptions(JSContext *cx)
|
|||
return cx->options;
|
||||
}
|
||||
|
||||
#define SYNC_OPTIONS_TO_VERSION(cx) \
|
||||
JS_BEGIN_MACRO \
|
||||
if ((cx)->options & JSOPTION_XML) \
|
||||
(cx)->version |= JSVERSION_HAS_XML; \
|
||||
else \
|
||||
(cx)->version &= ~JSVERSION_HAS_XML; \
|
||||
if ((cx)->options & JSOPTION_ANONFUNFIX) \
|
||||
(cx)->version |= JSVERSION_ANONFUNFIX; \
|
||||
else \
|
||||
(cx)->version &= ~JSVERSION_ANONFUNFIX; \
|
||||
JS_END_MACRO
|
||||
|
||||
JS_PUBLIC_API(uint32)
|
||||
JS_SetOptions(JSContext *cx, uint32 options)
|
||||
{
|
||||
uint32 oldopts = cx->options;
|
||||
cx->options = options;
|
||||
SYNC_OPTIONS_TO_VERSION(cx);
|
||||
js_SyncOptionsToVersion(cx);
|
||||
return oldopts;
|
||||
}
|
||||
|
||||
|
@ -1217,7 +1205,7 @@ JS_ToggleOptions(JSContext *cx, uint32 options)
|
|||
{
|
||||
uint32 oldopts = cx->options;
|
||||
cx->options ^= options;
|
||||
SYNC_OPTIONS_TO_VERSION(cx);
|
||||
js_SyncOptionsToVersion(cx);
|
||||
return oldopts;
|
||||
}
|
||||
|
||||
|
|
|
@ -2164,7 +2164,7 @@ js_ArrayCompPush(JSContext *cx, JSObject *obj, jsval v)
|
|||
static jsval FASTCALL
|
||||
Array_p_push1(JSContext* cx, JSObject* obj, jsval v)
|
||||
{
|
||||
if (OBJ_IS_DENSE_ARRAY(cx, obj)
|
||||
if (OBJ_IS_DENSE_ARRAY(cx, obj)
|
||||
? array_push1_dense(cx, obj, v, &v)
|
||||
: array_push_slowly(cx, obj, 1, &v, &v)) {
|
||||
return v;
|
||||
|
@ -2229,7 +2229,6 @@ array_pop_dense(JSContext *cx, JSObject* obj, jsval *vp)
|
|||
return JS_FALSE;
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = index;
|
||||
return JS_TRUE;
|
||||
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
@ -2255,7 +2254,7 @@ array_pop(JSContext *cx, uintN argc, jsval *vp)
|
|||
obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
if (OBJ_IS_DENSE_ARRAY(cx, obj))
|
||||
if (OBJ_IS_DENSE_ARRAY(cx, obj))
|
||||
return array_pop_dense(cx, obj, vp);
|
||||
return array_pop_slowly(cx, obj, vp);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=80:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
|
@ -61,6 +61,7 @@
|
|||
#include "jsnum.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsscan.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsscript.h"
|
||||
|
@ -207,6 +208,38 @@ js_InitContextThread(JSContext *cx, JSThread *thread)
|
|||
|
||||
#endif /* JS_THREADSAFE */
|
||||
|
||||
/*
|
||||
* JSOPTION_XML and JSOPTION_ANONFUNFIX must be part of the JS version
|
||||
* associated with scripts, so in addition to storing them in cx->options we
|
||||
* duplicate them in cx->version (script->version, etc.) and ensure each bit
|
||||
* remains synchronized between the two through these two functions.
|
||||
*/
|
||||
void
|
||||
js_SyncOptionsToVersion(JSContext* cx)
|
||||
{
|
||||
if (cx->options & JSOPTION_XML)
|
||||
cx->version |= JSVERSION_HAS_XML;
|
||||
else
|
||||
cx->version &= ~JSVERSION_HAS_XML;
|
||||
if (cx->options & JSOPTION_ANONFUNFIX)
|
||||
cx->version |= JSVERSION_ANONFUNFIX;
|
||||
else
|
||||
cx->version &= ~JSVERSION_ANONFUNFIX;
|
||||
}
|
||||
|
||||
inline void
|
||||
js_SyncVersionToOptions(JSContext* cx)
|
||||
{
|
||||
if (cx->version & JSVERSION_HAS_XML)
|
||||
cx->options |= JSOPTION_XML;
|
||||
else
|
||||
cx->options &= ~JSOPTION_XML;
|
||||
if (cx->version & JSVERSION_ANONFUNFIX)
|
||||
cx->options |= JSOPTION_ANONFUNFIX;
|
||||
else
|
||||
cx->options &= ~JSOPTION_ANONFUNFIX;
|
||||
}
|
||||
|
||||
void
|
||||
js_OnVersionChange(JSContext *cx)
|
||||
{
|
||||
|
@ -221,6 +254,7 @@ void
|
|||
js_SetVersion(JSContext *cx, JSVersion version)
|
||||
{
|
||||
cx->version = version;
|
||||
js_SyncVersionToOptions(cx);
|
||||
js_OnVersionChange(cx);
|
||||
}
|
||||
|
||||
|
@ -237,33 +271,47 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
|||
return NULL;
|
||||
#endif
|
||||
|
||||
cx = (JSContext *) malloc(sizeof *cx);
|
||||
/*
|
||||
* We need to initialize the new context fully before adding it to the
|
||||
* runtime list. After that it can be accessed from another thread via
|
||||
* js_ContextIterator.
|
||||
*/
|
||||
cx = (JSContext *) calloc(1, sizeof *cx);
|
||||
if (!cx)
|
||||
return NULL;
|
||||
memset(cx, 0, sizeof *cx);
|
||||
|
||||
cx->runtime = rt;
|
||||
js_InitOperationLimit(cx);
|
||||
cx->debugHooks = &rt->globalDebugHooks;
|
||||
#if JS_STACK_GROWTH_DIRECTION > 0
|
||||
cx->stackLimit = (jsuword)-1;
|
||||
cx->stackLimit = (jsuword) -1;
|
||||
#endif
|
||||
cx->scriptStackQuota = JS_DEFAULT_SCRIPT_STACK_QUOTA;
|
||||
#ifdef JS_THREADSAFE
|
||||
cx->gcLocalFreeLists = (JSGCFreeListSet *) &js_GCEmptyFreeListSet;
|
||||
|
||||
/*
|
||||
* At this point cx is not on rt->contextList. Thus we do not need to
|
||||
* prevent a race against the GC when adding cx to JSThread.contextList.
|
||||
*/
|
||||
js_InitContextThread(cx, thread);
|
||||
#endif
|
||||
JS_STATIC_ASSERT(JSVERSION_DEFAULT == 0);
|
||||
JS_ASSERT(cx->version == JSVERSION_DEFAULT);
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
JS_INIT_ARENA_POOL(&cx->stackPool, "stack", stackChunkSize, sizeof(jsval),
|
||||
&cx->scriptStackQuota);
|
||||
|
||||
JS_INIT_ARENA_POOL(&cx->tempPool, "temp",
|
||||
1024, /* FIXME: bug 421435 */
|
||||
sizeof(jsdouble), &cx->scriptStackQuota);
|
||||
|
||||
js_InitRegExpStatics(cx);
|
||||
JS_ASSERT(cx->resolveFlags == 0);
|
||||
|
||||
JS_LOCK_GC(rt);
|
||||
for (;;) {
|
||||
first = (rt->contextList.next == &rt->contextList);
|
||||
if (rt->state == JSRTS_UP) {
|
||||
JS_ASSERT(!first);
|
||||
|
||||
/* Ensure that it is safe to update rt->contextList below. */
|
||||
js_WaitForGC(rt);
|
||||
break;
|
||||
}
|
||||
if (rt->state == JSRTS_DOWN) {
|
||||
|
@ -276,26 +324,6 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
|||
JS_APPEND_LINK(&cx->link, &rt->contextList);
|
||||
JS_UNLOCK_GC(rt);
|
||||
|
||||
/*
|
||||
* First we do the infallible, every-time per-context initializations.
|
||||
* Should a later, fallible initialization (js_InitRegExpStatics, e.g.,
|
||||
* or the stuff under 'if (first)' below) fail, at least the version
|
||||
* and arena-pools will be valid and safe to use (say, from the last GC
|
||||
* done by js_DestroyContext).
|
||||
*/
|
||||
cx->version = JSVERSION_DEFAULT;
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
JS_INIT_ARENA_POOL(&cx->stackPool, "stack", stackChunkSize, sizeof(jsval),
|
||||
&cx->scriptStackQuota);
|
||||
|
||||
JS_INIT_ARENA_POOL(&cx->tempPool, "temp",
|
||||
1024, /* FIXME: bug 421435 */
|
||||
sizeof(jsdouble), &cx->scriptStackQuota);
|
||||
|
||||
js_InitRegExpStatics(cx);
|
||||
|
||||
cx->resolveFlags = 0;
|
||||
|
||||
/*
|
||||
* If cx is the first context on this runtime, initialize well-known atoms,
|
||||
* keywords, numbers, and strings. If one of these steps should fail, the
|
||||
|
@ -437,16 +465,21 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
|||
}
|
||||
}
|
||||
|
||||
/* Remove cx from context list first. */
|
||||
JS_LOCK_GC(rt);
|
||||
JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING);
|
||||
#ifdef JS_THREADSAFE
|
||||
/*
|
||||
* Typically we are called outside a request, so ensure that the GC is not
|
||||
* running before removing the context from rt->contextList, see bug 477021.
|
||||
*/
|
||||
if (cx->requestDepth == 0)
|
||||
js_WaitForGC(rt);
|
||||
js_RevokeGCLocalFreeLists(cx);
|
||||
#endif
|
||||
JS_REMOVE_LINK(&cx->link);
|
||||
last = (rt->contextList.next == &rt->contextList);
|
||||
if (last)
|
||||
rt->state = JSRTS_LANDING;
|
||||
#ifdef JS_THREADSAFE
|
||||
js_RevokeGCLocalFreeLists(cx);
|
||||
#endif
|
||||
JS_UNLOCK_GC(rt);
|
||||
|
||||
if (last) {
|
||||
|
|
|
@ -1157,6 +1157,14 @@ js_InitThreadPrivateIndex(void (*ptr)(void *));
|
|||
extern JSBool
|
||||
js_CleanupThreadPrivateData();
|
||||
|
||||
/*
|
||||
* Ensures the JSOPTION_XML and JSOPTION_ANONFUNFIX bits of cx->options are
|
||||
* reflected in cx->version, since each bit must travel with a script that has
|
||||
* it set.
|
||||
*/
|
||||
extern void
|
||||
js_SyncOptionsToVersion(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Common subroutine of JS_SetVersion and js_SetVersion, to update per-context
|
||||
* data that depends on version.
|
||||
|
|
|
@ -6435,6 +6435,14 @@ js_Interpret(JSContext *cx)
|
|||
}
|
||||
END_CASE(JSOP_PRIMTOP)
|
||||
|
||||
BEGIN_CASE(JSOP_OBJTOP)
|
||||
lval = FETCH_OPND(-1);
|
||||
if (JSVAL_IS_PRIMITIVE(lval)) {
|
||||
js_ReportValueError(cx, GET_UINT16(regs.pc), -1, lval, NULL);
|
||||
goto error;
|
||||
}
|
||||
END_CASE(JSOP_OBJTOP)
|
||||
|
||||
BEGIN_CASE(JSOP_INSTANCEOF)
|
||||
rval = FETCH_OPND(-1);
|
||||
if (JSVAL_IS_PRIMITIVE(rval) ||
|
||||
|
@ -6884,7 +6892,6 @@ js_Interpret(JSContext *cx)
|
|||
L_JSOP_DEFXMLNS:
|
||||
# endif
|
||||
|
||||
L_JSOP_UNUSED135:
|
||||
L_JSOP_UNUSED203:
|
||||
L_JSOP_UNUSED204:
|
||||
L_JSOP_UNUSED205:
|
||||
|
|
|
@ -416,12 +416,8 @@ js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp)
|
|||
goto bad;
|
||||
}
|
||||
if (JSVAL_IS_PRIMITIVE(*vp)) {
|
||||
const char *printable = js_AtomToPrintableString(cx, atom);
|
||||
if (printable) {
|
||||
js_ReportValueError2(cx, JSMSG_BAD_ITERATOR_RETURN,
|
||||
JSDVG_SEARCH_STACK, *vp, NULL,
|
||||
printable);
|
||||
}
|
||||
js_ReportValueError(cx, JSMSG_BAD_ITERATOR_RETURN,
|
||||
JSDVG_SEARCH_STACK, *vp, NULL);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
@ -982,8 +978,6 @@ generator_op(JSContext *cx, JSGeneratorOp op, jsval *vp, uintN argc)
|
|||
}
|
||||
}
|
||||
|
||||
js_LeaveTrace(cx);
|
||||
|
||||
arg = ((op == JSGENOP_SEND || op == JSGENOP_THROW) && argc != 0)
|
||||
? vp[2]
|
||||
: JSVAL_VOID;
|
||||
|
|
|
@ -303,7 +303,7 @@ js_FinishLock(JSThinLock *tl)
|
|||
#include <stdio.h>
|
||||
#include "jsdhash.h"
|
||||
|
||||
static FILE *logfp;
|
||||
static FILE *logfp = NULL;
|
||||
static JSDHashTable logtbl;
|
||||
|
||||
typedef struct logentry {
|
||||
|
@ -314,7 +314,7 @@ typedef struct logentry {
|
|||
} logentry;
|
||||
|
||||
static void
|
||||
logit(JSScope *scope, char op, const char *file, int line)
|
||||
logit(JSTitle *title, char op, const char *file, int line)
|
||||
{
|
||||
logentry *entry;
|
||||
|
||||
|
@ -324,35 +324,35 @@ logit(JSScope *scope, char op, const char *file, int line)
|
|||
return;
|
||||
setvbuf(logfp, NULL, _IONBF, 0);
|
||||
}
|
||||
fprintf(logfp, "%p %c %s %d\n", scope, op, file, line);
|
||||
fprintf(logfp, "%p %d %c %s %d\n", title, title->u.count, op, file, line);
|
||||
|
||||
if (!logtbl.entryStore &&
|
||||
!JS_DHashTableInit(&logtbl, JS_DHashGetStubOps(), NULL,
|
||||
sizeof(logentry), 100)) {
|
||||
return;
|
||||
}
|
||||
entry = (logentry *) JS_DHashTableOperate(&logtbl, scope, JS_DHASH_ADD);
|
||||
entry = (logentry *) JS_DHashTableOperate(&logtbl, title, JS_DHASH_ADD);
|
||||
if (!entry)
|
||||
return;
|
||||
entry->stub.key = scope;
|
||||
entry->stub.key = title;
|
||||
entry->op = op;
|
||||
entry->file = file;
|
||||
entry->line = line;
|
||||
}
|
||||
|
||||
void
|
||||
js_unlog_scope(JSScope *scope)
|
||||
js_unlog_title(JSTitle *title)
|
||||
{
|
||||
if (!logtbl.entryStore)
|
||||
return;
|
||||
(void) JS_DHashTableOperate(&logtbl, scope, JS_DHASH_REMOVE);
|
||||
(void) JS_DHashTableOperate(&logtbl, title, JS_DHASH_REMOVE);
|
||||
}
|
||||
|
||||
# define LOGIT(scope,op) logit(scope, op, __FILE__, __LINE__)
|
||||
# define LOGIT(title,op) logit(title, op, __FILE__, __LINE__)
|
||||
|
||||
#else
|
||||
|
||||
# define LOGIT(scope,op) /* nothing */
|
||||
# define LOGIT(title, op) /* nothing */
|
||||
|
||||
#endif /* DEBUG_SCOPE_COUNT */
|
||||
|
||||
|
@ -665,7 +665,7 @@ js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot)
|
|||
if (!NativeCompareAndSwap(&tl->owner, me, 0)) {
|
||||
/* Assert that scope locks never revert to flyweight. */
|
||||
JS_ASSERT(title->ownercx != cx);
|
||||
LOGIT(scope, '1');
|
||||
LOGIT(title, '1');
|
||||
title->u.count = 1;
|
||||
js_UnlockObj(cx, obj);
|
||||
}
|
||||
|
@ -755,7 +755,7 @@ js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
|
|||
if (!NativeCompareAndSwap(&tl->owner, me, 0)) {
|
||||
/* Assert that scope locks never revert to flyweight. */
|
||||
JS_ASSERT(title->ownercx != cx);
|
||||
LOGIT(scope, '1');
|
||||
LOGIT(title, '1');
|
||||
title->u.count = 1;
|
||||
js_UnlockObj(cx, obj);
|
||||
}
|
||||
|
@ -1211,7 +1211,7 @@ js_UnlockTitle(JSContext *cx, JSTitle *title)
|
|||
JS_ASSERT(0); /* unbalanced unlock */
|
||||
return;
|
||||
}
|
||||
LOGIT(scope, '-');
|
||||
LOGIT(title, '-');
|
||||
if (--title->u.count == 0)
|
||||
ThinUnlock(&title->lock, me);
|
||||
}
|
||||
|
@ -1279,7 +1279,7 @@ js_TransferTitle(JSContext *cx, JSTitle *oldtitle, JSTitle *newtitle)
|
|||
/*
|
||||
* Reset oldtitle's lock state so that it is completely unlocked.
|
||||
*/
|
||||
LOGIT(oldscope, '0');
|
||||
LOGIT(oldtitle, '0');
|
||||
oldtitle->u.count = 0;
|
||||
ThinUnlock(&oldtitle->lock, CX_THINLOCK_ID(cx));
|
||||
}
|
||||
|
@ -1350,6 +1350,10 @@ js_InitTitle(JSContext *cx, JSTitle *title)
|
|||
void
|
||||
js_FinishTitle(JSContext *cx, JSTitle *title)
|
||||
{
|
||||
#ifdef DEBUG_SCOPE_COUNT
|
||||
js_unlog_title(title);
|
||||
#endif
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Title must be single-threaded at this point, so set ownercx. */
|
||||
JS_ASSERT(title->u.count == 0);
|
||||
|
|
|
@ -353,7 +353,12 @@ OPDEF(JSOP_SETCALL, 132, "setcall", NULL, 3, -1, 2, 18, JOF_UINT16
|
|||
OPDEF(JSOP_TRY, 133,"try", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_FINALLY, 134,"finally", NULL, 1, 0, 2, 0, JOF_BYTE)
|
||||
|
||||
OPDEF(JSOP_UNUSED135, 135,"unused135", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
/*
|
||||
* Ensure that the value on the top of the stack is an object. The one
|
||||
* argument is an error message, defined in js.msg, that takes one parameter
|
||||
* (the decompilation of the primitive value).
|
||||
*/
|
||||
OPDEF(JSOP_OBJTOP, 135,"objtop", NULL, 3, 0, 0, 0, JOF_UINT16)
|
||||
|
||||
/*
|
||||
* Bytecodes that avoid making an arguments object in most cases:
|
||||
|
|
|
@ -174,11 +174,6 @@ js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp,
|
|||
return scope;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SCOPE_COUNT
|
||||
extern void
|
||||
js_unlog_scope(JSScope *scope);
|
||||
#endif
|
||||
|
||||
#if defined DEBUG || defined JS_DUMP_PROPTREE_STATS
|
||||
# include "jsprf.h"
|
||||
# define LIVE_SCOPE_METER(cx,expr) JS_LOCK_RUNTIME_VOID(cx->runtime,expr)
|
||||
|
@ -189,10 +184,6 @@ js_unlog_scope(JSScope *scope);
|
|||
void
|
||||
js_DestroyScope(JSContext *cx, JSScope *scope)
|
||||
{
|
||||
#ifdef DEBUG_SCOPE_COUNT
|
||||
js_unlog_scope(scope);
|
||||
#endif
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
js_FinishTitle(cx, &scope->title);
|
||||
#endif
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "jsparse.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsscript.h"
|
||||
#include "jstracer.h"
|
||||
#if JS_HAS_XDR
|
||||
#include "jsxdrapi.h"
|
||||
#endif
|
||||
|
@ -1607,6 +1608,9 @@ js_DestroyScript(JSContext *cx, JSScript *script)
|
|||
JS_ASSERT(script->owner == cx->thread);
|
||||
#endif
|
||||
js_FlushPropertyCacheForScript(cx, script);
|
||||
#ifdef JS_TRACER
|
||||
js_FlushScriptFragments(cx, script);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -546,14 +546,33 @@ getLoop(JSTraceMonitor* tm, const void *ip, uint32 globalShape)
|
|||
return getVMFragment(tm, ip, globalShape);
|
||||
}
|
||||
|
||||
static inline void*
|
||||
placementNewInLirBuffer(size_t size, nanojit::LirBuffer *buf)
|
||||
{
|
||||
LirBufWriter writer(buf);
|
||||
char *mem = (char*) writer.skip(size)->payload();
|
||||
if (!mem)
|
||||
return NULL;
|
||||
memset (mem, 0, size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void*
|
||||
avmplus::GCObject::operator new(size_t size, nanojit::LirBuffer *buf)
|
||||
{
|
||||
return placementNewInLirBuffer(size, buf);
|
||||
}
|
||||
|
||||
void*
|
||||
operator new(size_t size, nanojit::LirBuffer *buf)
|
||||
{
|
||||
return placementNewInLirBuffer(size, buf);
|
||||
}
|
||||
|
||||
static Fragment*
|
||||
getAnchor(JSTraceMonitor* tm, const void *ip, uint32 globalShape)
|
||||
{
|
||||
LirBufWriter writer(tm->lirbuf);
|
||||
char *fragmem = (char*) writer.skip(sizeof(VMFragment))->payload();
|
||||
if (!fragmem)
|
||||
return NULL;
|
||||
VMFragment *f = new (fragmem) VMFragment(ip, globalShape);
|
||||
VMFragment *f = new (tm->lirbuf) VMFragment(ip, globalShape);
|
||||
JS_ASSERT(f);
|
||||
|
||||
Fragment *p = getVMFragment(tm, ip, globalShape);
|
||||
|
@ -1256,16 +1275,6 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* _anchor, Fragment* _frag
|
|||
}
|
||||
}
|
||||
|
||||
TreeInfo::~TreeInfo()
|
||||
{
|
||||
UnstableExit* temp;
|
||||
|
||||
while (unstableExits) {
|
||||
temp = unstableExits->next;
|
||||
delete unstableExits;
|
||||
unstableExits = temp;
|
||||
}
|
||||
}
|
||||
|
||||
TraceRecorder::~TraceRecorder()
|
||||
{
|
||||
|
@ -1282,7 +1291,6 @@ TraceRecorder::~TraceRecorder()
|
|||
if (fragment) {
|
||||
if (wasRootFragment && !fragment->root->code()) {
|
||||
JS_ASSERT(!fragment->root->vmprivate);
|
||||
delete treeInfo;
|
||||
}
|
||||
|
||||
if (trashSelf)
|
||||
|
@ -1290,8 +1298,6 @@ TraceRecorder::~TraceRecorder()
|
|||
|
||||
for (unsigned int i = 0; i < whichTreesToTrash.length(); i++)
|
||||
js_TrashTree(cx, whichTreesToTrash.get(i));
|
||||
} else if (wasRootFragment) {
|
||||
delete treeInfo;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
delete verbose_filter;
|
||||
|
@ -2603,7 +2609,7 @@ TraceRecorder::closeLoop(JSTraceMonitor* tm, bool& demote)
|
|||
*/
|
||||
debug_only_v(printf("Trace has unstable loop variable with no stable peer, "
|
||||
"compiling anyway.\n");)
|
||||
UnstableExit* uexit = new UnstableExit;
|
||||
UnstableExit* uexit = new (tm->lirbuf) UnstableExit;
|
||||
uexit->fragment = fragment;
|
||||
uexit->exit = exit;
|
||||
uexit->next = treeInfo->unstableExits;
|
||||
|
@ -2708,7 +2714,6 @@ TraceRecorder::joinEdgesToEntry(Fragmento* fragmento, Fragment* peer_root)
|
|||
}
|
||||
if (remove) {
|
||||
*unext = uexit->next;
|
||||
delete uexit;
|
||||
uexit = *unext;
|
||||
} else {
|
||||
unext = &uexit->next;
|
||||
|
@ -2952,12 +2957,6 @@ nanojit::LirNameMap::formatGuard(LIns *i, char *out)
|
|||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
nanojit::Fragment::onDestroy()
|
||||
{
|
||||
delete (TreeInfo *)vmprivate;
|
||||
}
|
||||
|
||||
static JS_REQUIRES_STACK bool
|
||||
js_DeleteRecorder(JSContext* cx)
|
||||
{
|
||||
|
@ -3076,7 +3075,6 @@ js_TrashTree(JSContext* cx, Fragment* f)
|
|||
unsigned length = ti->dependentTrees.length();
|
||||
for (unsigned n = 0; n < length; ++n)
|
||||
js_TrashTree(cx, data[n]);
|
||||
delete ti;
|
||||
JS_ASSERT(!f->code() && !f->vmprivate);
|
||||
}
|
||||
|
||||
|
@ -3320,7 +3318,7 @@ js_RecordTree(JSContext* cx, JSTraceMonitor* tm, Fragment* f, Fragment* outer,
|
|||
JS_ASSERT(!f->code() && !f->vmprivate);
|
||||
|
||||
/* setup the VM-private treeInfo structure for this fragment */
|
||||
TreeInfo* ti = new (&gc) TreeInfo(f, globalShape, globalSlots);
|
||||
TreeInfo* ti = new (tm->lirbuf) TreeInfo(f, globalShape, globalSlots);
|
||||
|
||||
/* capture the coerced type of each active slot in the type map */
|
||||
ti->typeMap.captureTypes(cx, *globalSlots, 0/*callDepth*/);
|
||||
|
@ -3443,7 +3441,6 @@ js_AttemptToStabilizeTree(JSContext* cx, VMSideExit* exit, Fragment* outer)
|
|||
for (UnstableExit* uexit = from_ti->unstableExits; uexit != NULL; uexit = uexit->next) {
|
||||
if (uexit->exit == exit) {
|
||||
*tail = uexit->next;
|
||||
delete uexit;
|
||||
bound = true;
|
||||
break;
|
||||
}
|
||||
|
@ -4591,6 +4588,20 @@ js_FlushJITOracle(JSContext* cx)
|
|||
oracle.clear();
|
||||
}
|
||||
|
||||
extern JS_REQUIRES_STACK void
|
||||
js_FlushScriptFragments(JSContext* cx, JSScript* script)
|
||||
{
|
||||
if (!TRACING_ENABLED(cx))
|
||||
return;
|
||||
debug_only_v(printf("Flushing fragments for script %p.\n", script);)
|
||||
JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
|
||||
for (size_t i = 0; i < FRAGMENT_TABLE_SIZE; ++i) {
|
||||
VMFragment *f = tm->vmfragments[i];
|
||||
if (f && JS_UPTRDIFF(f->ip, script->code) < script->length)
|
||||
tm->vmfragments[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern JS_REQUIRES_STACK void
|
||||
js_FlushJITCache(JSContext* cx)
|
||||
{
|
||||
|
@ -5530,7 +5541,10 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2
|
|||
JSAtom* atom;
|
||||
JSPropCacheEntry* entry;
|
||||
PROPERTY_CACHE_TEST(cx, pc, aobj, obj2, entry, atom);
|
||||
if (atom) {
|
||||
if (!atom) {
|
||||
// Null atom means that obj2 is locked and must now be unlocked.
|
||||
JS_UNLOCK_OBJ(cx, obj2);
|
||||
} else {
|
||||
// Miss: pre-fill the cache for the interpreter, as well as for our needs.
|
||||
// FIXME: 452357 - correctly propagate exceptions into the interpreter from
|
||||
// js_FindPropertyHelper, js_LookupPropertyWithFlags, and elsewhere.
|
||||
|
@ -6432,6 +6446,13 @@ TraceRecorder::record_JSOP_PRIMTOP()
|
|||
return true;
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK bool
|
||||
TraceRecorder::record_JSOP_OBJTOP()
|
||||
{
|
||||
// See the comment in record_JSOP_PRIMTOP.
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_Array(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
|
||||
|
||||
|
@ -9098,10 +9119,6 @@ ObjectToIterator_tn(JSContext* cx, jsbytecode* pc, JSObject *obj, int32 flags)
|
|||
cx->builtinStatus |= JSBUILTIN_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
if (OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_GeneratorClass) {
|
||||
js_LeaveTrace(cx);
|
||||
return NULL;
|
||||
}
|
||||
return JSVAL_TO_OBJECT(v);
|
||||
}
|
||||
|
||||
|
@ -9376,7 +9393,6 @@ InitIMacroCode()
|
|||
return false; \
|
||||
}
|
||||
|
||||
UNUSED(135)
|
||||
UNUSED(203)
|
||||
UNUSED(204)
|
||||
UNUSED(205)
|
||||
|
|
|
@ -296,7 +296,6 @@ public:
|
|||
branchCount(0),
|
||||
unstableExits(NULL)
|
||||
{}
|
||||
~TreeInfo();
|
||||
|
||||
inline unsigned nGlobalTypes() {
|
||||
return typeMap.length() - nStackTypes;
|
||||
|
@ -602,6 +601,9 @@ js_InitJIT(JSTraceMonitor *tm);
|
|||
extern void
|
||||
js_FinishJIT(JSTraceMonitor *tm);
|
||||
|
||||
extern void
|
||||
js_FlushScriptFragments(JSContext* cx, JSScript* script);
|
||||
|
||||
extern void
|
||||
js_FlushJITCache(JSContext* cx);
|
||||
|
||||
|
|
|
@ -210,7 +210,7 @@ JS_DumpHistogram(JSBasicStats *bs, FILE *fp)
|
|||
|
||||
#endif /* JS_BASIC_STATS */
|
||||
|
||||
#if defined DEBUG_notme && defined XP_UNIX
|
||||
#if defined(DEBUG_notme) && defined(XP_UNIX)
|
||||
|
||||
#define __USE_GNU 1
|
||||
#include <dlfcn.h>
|
||||
|
@ -314,7 +314,7 @@ CallTree(void **bp)
|
|||
return site;
|
||||
}
|
||||
|
||||
JSCallsite *
|
||||
JS_FRIEND_API(JSCallsite *)
|
||||
JS_Backtrace(int skip)
|
||||
{
|
||||
void **bp, **bpdown;
|
||||
|
@ -342,4 +342,14 @@ JS_Backtrace(int skip)
|
|||
return CallTree(bp);
|
||||
}
|
||||
|
||||
#endif /* DEBUG_notme && XP_UNIX */
|
||||
JS_FRIEND_API(void)
|
||||
JS_DumpBacktrace(JSCallsite *trace)
|
||||
{
|
||||
while (trace) {
|
||||
fprintf(stdout, "%s [%s +0x%X]\n", trace->name, trace->library,
|
||||
trace->offset);
|
||||
trace = trace->parent;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* defined(DEBUG_notme) && defined(XP_UNIX) */
|
||||
|
|
|
@ -144,7 +144,7 @@ JS_DumpHistogram(JSBasicStats *bs, FILE *fp);
|
|||
#endif /* JS_BASIC_STATS */
|
||||
|
||||
|
||||
#ifdef XP_UNIX
|
||||
#if defined(DEBUG_notme) && defined(XP_UNIX)
|
||||
|
||||
typedef struct JSCallsite JSCallsite;
|
||||
|
||||
|
@ -159,7 +159,11 @@ struct JSCallsite {
|
|||
void *handy;
|
||||
};
|
||||
|
||||
extern JSCallsite *JS_Backtrace(int skip);
|
||||
extern JS_FRIEND_API(JSCallsite *)
|
||||
JS_Backtrace(int skip);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
JS_DumpBacktrace(JSCallsite *trace);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -522,7 +522,6 @@ namespace nanojit
|
|||
|
||||
Fragment::~Fragment()
|
||||
{
|
||||
onDestroy();
|
||||
NanoAssert(_pages == 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -191,7 +191,6 @@ namespace nanojit
|
|||
void releaseTreeMem(Fragmento* frago);
|
||||
bool isAnchor() { return anchor == this; }
|
||||
bool isRoot() { return root == this; }
|
||||
void onDestroy();
|
||||
|
||||
verbose_only( uint32_t _called; )
|
||||
verbose_only( uint32_t _native; )
|
||||
|
|
|
@ -145,6 +145,10 @@ static __inline__ unsigned long long rdtsc(void)
|
|||
|
||||
struct JSContext;
|
||||
|
||||
namespace nanojit {
|
||||
class LirBuffer;
|
||||
}
|
||||
|
||||
namespace avmplus {
|
||||
|
||||
class GC;
|
||||
|
@ -158,13 +162,8 @@ namespace avmplus {
|
|||
return calloc(1, size);
|
||||
}
|
||||
|
||||
inline void*
|
||||
operator new(size_t size, char* c)
|
||||
{
|
||||
// We use placement-new in LIR buffers sometimes.
|
||||
memset(c, 0, size);
|
||||
return c;
|
||||
}
|
||||
// We use placement-new in LIR buffers sometimes.
|
||||
void* operator new(size_t size, nanojit::LirBuffer *buf);
|
||||
|
||||
static void operator delete (void *gcObject)
|
||||
{
|
||||
|
|
|
@ -4327,6 +4327,19 @@ function testSwitchUndefined()
|
|||
testSwitchUndefined.expected = 5;
|
||||
test(testSwitchUndefined);
|
||||
|
||||
function testGeneratorDeepBail() {
|
||||
function g() { yield 2; }
|
||||
var iterables = [[1], [], [], [], g()];
|
||||
|
||||
var total = 0;
|
||||
for (let i = 0; i < iterables.length; i++)
|
||||
for each (let j in iterables[i])
|
||||
total += j;
|
||||
return total;
|
||||
}
|
||||
testGeneratorDeepBail.expected = 3;
|
||||
test(testGeneratorDeepBail);
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* _____ _ _ _____ ______ _____ _______ *
|
||||
|
|
Загрузка…
Ссылка в новой задаче