mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge, style nits, no locking for tracing.
This commit is contained in:
commit
5b116ae998
@ -125,10 +125,15 @@ struct JSThread {
|
||||
|
||||
/* Property cache for faster call/get/set invocation. */
|
||||
JSPropertyCache propertyCache;
|
||||
|
||||
#ifdef JS_TRACER
|
||||
JSTraceMonitor traceMonitor;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define JS_GSN_CACHE(cx) ((cx)->thread->gsnCache)
|
||||
#define JS_PROPERTY_CACHE(cx) ((cx)->thread->propertyCache)
|
||||
#define JS_TRACE_MONITOR(cx) ((cx)->thread->traceMonitor)
|
||||
|
||||
extern void JS_DLL_CALLBACK
|
||||
js_ThreadDestructorCB(void *ptr);
|
||||
@ -395,10 +400,22 @@ struct JSRuntime {
|
||||
/* Property cache for faster call/get/set invocation. */
|
||||
JSPropertyCache propertyCache;
|
||||
|
||||
#ifdef JS_TRACER
|
||||
JSTraceMonitor traceMonitor;
|
||||
#endif
|
||||
|
||||
#define JS_GSN_CACHE(cx) ((cx)->runtime->gsnCache)
|
||||
#define JS_PROPERTY_CACHE(cx) ((cx)->runtime->propertyCache)
|
||||
#define JS_TRACE_MONITOR(cx) ((cx)->runtime->traceMonitor)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Loops are globally numbered (per runtime) using this counter. The actual
|
||||
* loop table that tracks loop statistics is per-thread in a multi-threaded
|
||||
* environment.
|
||||
*/
|
||||
uint32 loopTableIndexGen;
|
||||
|
||||
/*
|
||||
* Object shape (property cache structural type) identifier generator.
|
||||
*
|
||||
@ -482,10 +499,6 @@ struct JSRuntime {
|
||||
#ifdef JS_GCMETER
|
||||
JSGCStats gcStats;
|
||||
#endif
|
||||
|
||||
#ifdef JS_TRACER
|
||||
JSTraceMonitor traceMonitor;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -3900,24 +3900,15 @@ static JSBool
|
||||
EmitLoopHeader(JSContext *cx, JSCodeGenerator *cg)
|
||||
{
|
||||
#ifdef JS_TRACER
|
||||
JSTraceMonitor *tm = &cx->runtime->traceMonitor;
|
||||
ptrdiff_t off;
|
||||
jsbytecode *pc;
|
||||
|
||||
/*
|
||||
* Atomically increment the index generator and get us a unique index
|
||||
* number. If we get an index that exceeds the size of the loop table,
|
||||
* we request for its size to be increased.
|
||||
*/
|
||||
uint32 index = JS_ATOMIC_INCREMENT(&tm->loopIndexGen);
|
||||
JS_ASSERT(index < JS_BITMASK(24));
|
||||
if (index >= tm->loopTableSize)
|
||||
js_GrowLoopTableIfNeeded(cx->runtime, index);
|
||||
uint32 slot = js_AllocateLoopTableSlot(cx->runtime);
|
||||
off = js_EmitN(cx, cg, JSOP_HEADER, 3);
|
||||
if (off < 0)
|
||||
return JS_FALSE;
|
||||
pc = CG_CODE(cg, off);
|
||||
SET_UINT24(pc, index);
|
||||
SET_UINT24(pc, slot);
|
||||
#endif
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -2881,9 +2881,22 @@ js_TraceRuntime(JSTracer *trc, JSBool allAtoms)
|
||||
rt->gcExtraRootsTraceOp(trc, rt->gcExtraRootsData);
|
||||
|
||||
|
||||
/* Trace the loop table which can contain pointers to code objects. */
|
||||
JSTraceMonitor* tm = &rt->traceMonitor;
|
||||
TRACE_JSVALS(trc, tm->loopIndexGen, tm->loopTable, "rt->traceMonitor.loopTable");
|
||||
#ifdef JS_TRACER
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Trace the loop table(s) which can contain pointers to code objects. */
|
||||
while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {
|
||||
if (!acx->thread || acx->thread == cx->thread)
|
||||
continue;
|
||||
JSTraceMonitor* tm = &acx->thread->traceMonitor;
|
||||
TRACE_JSVALS(trc, tm->loopTableSize, tm->loopTable,
|
||||
"thread->traceMonitor.loopTable");
|
||||
}
|
||||
#else
|
||||
JSTraceMonitor* tm = &rt->traceMonitor;
|
||||
TRACE_JSVALS(trc, tm->loopTableSize, tm->loopTable,
|
||||
"rt->traceMonitor.loopTable");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2801,19 +2801,34 @@ JS_INTERPRET(JSContext *cx)
|
||||
|
||||
BEGIN_CASE(JSOP_HEADER)
|
||||
i = GET_UINT24(regs.pc);
|
||||
JS_ASSERT(((uint32)i) <= rt->traceMonitor.loopIndexGen);
|
||||
JS_ASSERT((i > 0) && (i <= (jsint)rt->loopTableIndexGen));
|
||||
JSTraceMonitor *tm = &JS_TRACE_MONITOR(cx);
|
||||
if (i >= (jsint)tm->loopTableSize)
|
||||
js_GrowLoopTableIfNeeded(cx, i);
|
||||
vp = &rt->traceMonitor.loopTable[i];
|
||||
rval = *vp;
|
||||
if (JSVAL_IS_INT(rval)) {
|
||||
/*
|
||||
* Try to atomically fast-increment (search for FAST_INC_DEC)
|
||||
* the counter. If another thread beats us to this and
|
||||
* changes the slot to a tree pointer, undo our write (which
|
||||
* just replaced the pointer with a counter value).
|
||||
if (JSVAL_IS_INT(rval)) {
|
||||
/*
|
||||
* There are no concurrent writes to slots. This point in
|
||||
* the program is the only place a slot is updated from.
|
||||
*/
|
||||
lval = JS_ATOMIC_SET(vp, rval + 2);
|
||||
if (!JSVAL_IS_INT(lval))
|
||||
JS_ATOMIC_SET(vp, lval);
|
||||
if (JSVAL_TO_INT(rval) >= TRACE_THRESHOLD) {
|
||||
/*
|
||||
* Once a thread hits the threshold, it should first consult
|
||||
* (read) the other threads' loop tables to see if anyone
|
||||
* already compiled a tree for us, and in that case reuse
|
||||
* that tree instead of recording a new one.
|
||||
*/
|
||||
*vp = OBJECT_TO_JSVAL(js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0));
|
||||
} else {
|
||||
/*
|
||||
* We use FAST_INC_DEC to increment the jsval counter, which
|
||||
* currently contains a jsint. *vp += 2 is equivalent to
|
||||
* INT_TO_JSVAL(JSVAL_TO_INT(*vp) + 1). JS_ATOMIC_ADD(v, 2)
|
||||
* is the atomic version of *vp += 2.
|
||||
*/
|
||||
JS_ATOMIC_ADD(vp, 2);
|
||||
}
|
||||
} else {
|
||||
JS_ASSERT(JSVAL_IS_GCTHING(rval));
|
||||
/* Execute the tree. */
|
||||
|
@ -43,45 +43,38 @@
|
||||
JSBool
|
||||
js_InitTracer(JSRuntime *rt)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
JSTraceMonitor *tm = &rt->traceMonitor;
|
||||
JS_ASSERT(!tm->lock);
|
||||
tm->lock = JS_NEW_LOCK();
|
||||
if (!tm->lock)
|
||||
return JS_FALSE;
|
||||
#endif
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* To grow the loop table that we take the traceMonitor lock, double check
|
||||
* that no other thread grew the table while we were deciding to grow the
|
||||
* table, and only then double the size of the loop table.
|
||||
*
|
||||
* The initial size of the table is 2^8 and grows to at most 2^24 entries.
|
||||
* It is extended at most a constant number of times (C=16) by doubling its
|
||||
* size every time. When extending the table, each slot is initially filled
|
||||
* with JS_ZERO.
|
||||
* that no other thread grew the table while we were deciding to grow the
|
||||
* table, and only then double the size of the loop table.
|
||||
*
|
||||
* The initial size of the table is 2^8 and grows to at most 2^24 entries. It
|
||||
* is extended at most a constant number of times (C=16) by doubling its size
|
||||
* every time. When extending the table, each slot is initially filled with
|
||||
* JS_ZERO.
|
||||
*/
|
||||
void
|
||||
js_GrowLoopTableIfNeeded(JSRuntime* rt, uint32 index)
|
||||
{
|
||||
JSTraceMonitor *tm = &rt->traceMonitor;
|
||||
JS_ACQUIRE_LOCK(&tm->lock);
|
||||
uint32 oldSize;
|
||||
if (index >= (oldSize = tm->loopTableSize)) {
|
||||
uint32 oldSize = tm->loopTableSize;
|
||||
|
||||
if (index >= oldSize) {
|
||||
uint32 newSize = oldSize << 1;
|
||||
jsval* t = tm->loopTable;
|
||||
if (t == NULL) {
|
||||
JS_ASSERT(oldSize == 0);
|
||||
newSize = 256;
|
||||
t = (jsval*)malloc(newSize * sizeof(jsval));
|
||||
} else
|
||||
} else {
|
||||
t = (jsval*)realloc(tm->loopTable, newSize * sizeof(jsval));
|
||||
}
|
||||
for (uint32 n = oldSize; n < newSize; ++n)
|
||||
t[n] = JSVAL_ZERO;
|
||||
tm->loopTable = t;
|
||||
tm->loopTableSize = newSize;
|
||||
}
|
||||
JS_RELEASE_LOCK(&tm->lock);
|
||||
}
|
||||
|
68
js/src/jstracer.h
Normal file
68
js/src/jstracer.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* May 28, 2008.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Brendan Eich <brendan@mozilla.org
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef jstracer_h___
|
||||
#define jstracer_h___
|
||||
|
||||
#include "jsstddef.h"
|
||||
#include "jslock.h"
|
||||
|
||||
/*
|
||||
* Trace monitor. Every runtime is associated with a trace monitor that
|
||||
* keeps track of loop frequencies for all JavaScript code loaded into
|
||||
* that runtime. For this we use a loop table. Entries in the loop
|
||||
* table are requested by jsemit.c during compilation. By using atomic
|
||||
* pre-increment obtaining the next index is lock free, but to allocate
|
||||
* more table space the trace monitor lock has to be aquired first.
|
||||
*
|
||||
* The loop table also doubles as tree pointer table once a loop
|
||||
* achieves a certain number of iterations and we recorded a tree for
|
||||
* that loop.
|
||||
*/
|
||||
struct JSTraceMonitor {
|
||||
jsval *loopTable;
|
||||
uint32 loopTableSize;
|
||||
};
|
||||
|
||||
#define TRACE_THRESHOLD 10
|
||||
|
||||
JSBool js_InitTracer(JSRuntime *rt);
|
||||
uint32 js_AllocateLoopTableSlot(JSRuntime *rt);
|
||||
void js_GrowLoopTableIfNeeded(JSContext *cx, uint32 index);
|
||||
|
||||
#endif /* jstracer_h___ */
|
Loading…
Reference in New Issue
Block a user