Skip to content

Commit

Permalink
Merge tracemonkey to mozilla-central. a=blockers. CLOSED TREE
Browse files Browse the repository at this point in the history
  • Loading branch information
sayrer committed Feb 22, 2011
2 parents 85b9a80 + 530d512 commit 8b068c7
Show file tree
Hide file tree
Showing 26 changed files with 339 additions and 72 deletions.
6 changes: 6 additions & 0 deletions dom/base/nsJSEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3480,6 +3480,12 @@ DOMGCCallback(JSContext *cx, JSGCStatus status)
nsJSContext::PokeCC();
}
}

// If we didn't end up scheduling a GC, and there are unused
// chunks waiting to expire, make sure we will GC again soon.
if (!sGCTimer && JS_GetGCParameter(cx->runtime, JSGC_UNUSED_CHUNKS) > 0) {
nsJSContext::PokeGC();
}
}

JSBool result = gOldJSGCCallback ? gOldJSGCCallback(cx, status) : JS_TRUE;
Expand Down
10 changes: 7 additions & 3 deletions js/jsd/jsd_val.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,13 @@ jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
JS_RestoreExceptionState(cx, exceptionState);
JS_LeaveCrossCompartmentCall(call);

stringval = STRING_TO_JSVAL(string);
call = JS_EnterCrossCompartmentCall(cx, jsdc->glob);
if(!call || !JS_WrapValue(cx, &stringval)) {
if(string) {
stringval = STRING_TO_JSVAL(string);
call = JS_EnterCrossCompartmentCall(cx, jsdc->glob);
}
if(!string || !call || !JS_WrapValue(cx, &stringval)) {
if(call)
JS_LeaveCrossCompartmentCall(call);
JS_EndRequest(cx);
return NULL;
}
Expand Down
7 changes: 7 additions & 0 deletions js/src/jit-test/tests/basic/bug630377.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var a = [];
for (var i = 0; i < RUNLOOP; i++)
a[i] = 0;
var b = #1=[x === "0" && (#1#.slow = 1) for (x in a)];
assertEq(b[0], 1);
for (var i = 1; i < RUNLOOP; i++)
assertEq(b[i], false);
9 changes: 9 additions & 0 deletions js/src/jit-test/tests/basic/bug632901.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// don't crash when tracing
function f(o) {
var prop = "arguments";
f[prop] = f[prop];
}
for(var i=0; i<10; i++) {
f();
}

9 changes: 9 additions & 0 deletions js/src/jit-test/tests/basic/bug633890.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// |jit-test| error:Error
var p = /./, x = resolver({}, p), y = resolver({lastIndex: 2}, p), v;
var a = [];
for (var i = 0; i < HOTLOOP; i++)
a[i] = x;
a[HOTLOOP] = y;
for (i = 0; i < a.length; i++)
v = a[i].lastIndex;
assertEq(v, 2); // fails due to bug 458271
4 changes: 4 additions & 0 deletions js/src/jit-test/tests/basic/bug634593.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
this.__defineGetter__("x3", Function);
parseInt = x3;
parseInt.prototype = [];
for (var z = 0; z < 10; ++z) { new parseInt() }
8 changes: 6 additions & 2 deletions js/src/jsapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1447,8 +1447,10 @@ js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
ctor = JS_GetConstructor(cx, fun_proto);
if (!ctor)
return NULL;
obj->defineProperty(cx, ATOM_TO_JSID(CLASS_ATOM(cx, Function)),
ObjectValue(*ctor), 0, 0, 0);
if (!obj->defineProperty(cx, ATOM_TO_JSID(CLASS_ATOM(cx, Function)),
ObjectValue(*ctor), 0, 0, 0)) {
return NULL;
}
}

/* Initialize the object class next so Object.prototype works. */
Expand Down Expand Up @@ -2642,6 +2644,8 @@ JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
return rt->gcBytes;
case JSGC_MODE:
return uint32(rt->gcMode);
case JSGC_UNUSED_CHUNKS:
return uint32(rt->gcChunksWaitingToExpire);
default:
JS_ASSERT(key == JSGC_NUMBER);
return rt->gcNumber;
Expand Down
5 changes: 4 additions & 1 deletion js/src/jsapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1785,7 +1785,10 @@ typedef enum JSGCParamKey {
JSGC_MAX_CODE_CACHE_BYTES = 6,

/* Select GC mode. */
JSGC_MODE = 7
JSGC_MODE = 7,

/* Number of GC chunks waiting to expire. */
JSGC_UNUSED_CHUNKS = 8
} JSGCParamKey;

typedef enum JSGCMode {
Expand Down
18 changes: 12 additions & 6 deletions js/src/jsarray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2059,28 +2059,34 @@ array_push1_dense(JSContext* cx, JSObject* obj, const Value &v, Value *rval)
JS_ALWAYS_INLINE JSBool
ArrayCompPushImpl(JSContext *cx, JSObject *obj, const Value &v)
{
uint32 length = obj->getArrayLength();
if (obj->isSlowArray()) {
/* This can happen in one evil case. See bug 630377. */
jsid id;
return js_IndexToId(cx, length, &id) &&
js_DefineProperty(cx, obj, id, &v, NULL, NULL, JSPROP_ENUMERATE);
}

JS_ASSERT(obj->isDenseArray());
uint32_t length = obj->getArrayLength();
JS_ASSERT(length <= obj->getDenseArrayCapacity());

if (length == obj->getDenseArrayCapacity()) {
if (length > JS_ARGS_LENGTH_MAX) {
JS_ReportErrorNumberUC(cx, js_GetErrorMessage, NULL,
JSMSG_ARRAY_INIT_TOO_BIG);
return JS_FALSE;
return false;
}

/*
* Array comprehension cannot add holes to the array and never leaks
* the array before it is fully initialized. So we can use ensureSlots
* instead of ensureDenseArrayElements.
* An array comprehension cannot add holes to the array. So we can use
* ensureSlots instead of ensureDenseArrayElements.
*/
if (!obj->ensureSlots(cx, length + 1))
return false;
}
obj->setArrayLength(length + 1);
obj->setDenseArrayElement(length, v);
return JS_TRUE;
return true;
}

JSBool
Expand Down
1 change: 1 addition & 0 deletions js/src/jscntxt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,7 @@ struct JSRuntime {
size_t gcLastBytes;
size_t gcMaxBytes;
size_t gcMaxMallocBytes;
size_t gcChunksWaitingToExpire;
uint32 gcEmptyArenaPoolLifespan;
uint32 gcNumber;
js::GCMarker *gcMarkingTracer;
Expand Down
4 changes: 2 additions & 2 deletions js/src/jsdbgapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ CompartmentHasLiveScripts(JSCompartment *comp)
JS_FRIEND_API(JSBool)
JS_SetDebugModeForCompartment(JSContext *cx, JSCompartment *comp, JSBool debug)
{
if (comp->debugMode == debug)
if (comp->debugMode == !!debug)
return JS_TRUE;

// This should only be called when no scripts are live. It would even be
Expand All @@ -154,7 +154,7 @@ JS_SetDebugModeForCompartment(JSContext *cx, JSCompartment *comp, JSBool debug)
JS_ASSERT(!CompartmentHasLiveScripts(comp));

// All scripts compiled from this point on should be in the requested debugMode.
comp->debugMode = debug;
comp->debugMode = !!debug;

// Discard JIT code for any scripts that change debugMode. This function
// assumes that 'comp' is in the same thread as 'cx'.
Expand Down
22 changes: 10 additions & 12 deletions js/src/jsgc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,14 +360,6 @@ Chunk::releaseArena(Arena<T> *arena)
info.age = 0;
}

bool
Chunk::expire()
{
if (!unused())
return false;
return info.age++ > MaxAge;
}

JSRuntime *
Chunk::getRuntime()
{
Expand Down Expand Up @@ -456,16 +448,22 @@ PickChunk(JSRuntime *rt)
static void
ExpireGCChunks(JSRuntime *rt)
{
static const size_t MaxAge = 3;

/* Remove unused chunks. */
AutoLockGC lock(rt);

rt->gcChunksWaitingToExpire = 0;
for (GCChunkSet::Enum e(rt->gcChunkSet); !e.empty(); e.popFront()) {
Chunk *chunk = e.front();
JS_ASSERT(chunk->info.runtime == rt);
if (chunk->expire()) {
e.removeFront();
ReleaseGCChunk(rt, chunk);
continue;
if (chunk->unused()) {
if (chunk->info.age++ > MaxAge) {
e.removeFront();
ReleaseGCChunk(rt, chunk);
continue;
}
rt->gcChunksWaitingToExpire++;
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions js/src/jsgc.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,6 @@ struct Chunk {
sizeof(MarkingDelay);

static const size_t ArenasPerChunk = (GC_CHUNK_SIZE - sizeof(ChunkInfo)) / BytesPerArena;
static const size_t MaxAge = 3;

Arena<FreeCell> arenas[ArenasPerChunk];
ArenaBitmap bitmaps[ArenasPerChunk];
Expand All @@ -362,7 +361,6 @@ struct Chunk {
void releaseArena(Arena<T> *a);

JSRuntime *getRuntime();
bool expire();
};
JS_STATIC_ASSERT(sizeof(Chunk) <= GC_CHUNK_SIZE);
JS_STATIC_ASSERT(sizeof(Chunk) + Chunk::BytesPerArena > GC_CHUNK_SIZE);
Expand Down
57 changes: 39 additions & 18 deletions js/src/jsobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4772,7 +4772,7 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &valu
JS_ASSERT(existingShape->getter() != getter);

if (!obj->methodReadBarrier(cx, *existingShape, &valueCopy))
return NULL;
return false;
}
} else {
adding = true;
Expand Down Expand Up @@ -6794,20 +6794,30 @@ js_DumpId(jsid id)
}

static void
DumpShape(const Shape &shape)
DumpProperty(JSObject *obj, const Shape &shape)
{
jsid id = shape.id;
uint8 attrs = shape.attributes();

fprintf(stderr, " ");
fprintf(stderr, " ((Shape *) %p) ", (void *) &shape);
if (attrs & JSPROP_ENUMERATE) fprintf(stderr, "enumerate ");
if (attrs & JSPROP_READONLY) fprintf(stderr, "readonly ");
if (attrs & JSPROP_PERMANENT) fprintf(stderr, "permanent ");
if (attrs & JSPROP_GETTER) fprintf(stderr, "getter ");
if (attrs & JSPROP_SETTER) fprintf(stderr, "setter ");
if (attrs & JSPROP_SHARED) fprintf(stderr, "shared ");
if (shape.isAlias()) fprintf(stderr, "alias ");
if (shape.isMethod()) fprintf(stderr, "method(%p) ", (void *) &shape.methodObject());
if (shape.isMethod()) fprintf(stderr, "method=%p ", (void *) &shape.methodObject());

if (shape.hasGetterValue())
fprintf(stderr, "getterValue=%p ", (void *) shape.getterObject());
else if (!shape.hasDefaultGetter())
fprintf(stderr, "getterOp=%p ", JS_FUNC_TO_DATA_PTR(void *, shape.getterOp()));

if (shape.hasSetterValue())
fprintf(stderr, "setterValue=%p ", (void *) shape.setterObject());
else if (shape.setterOp() == js_watch_set)
fprintf(stderr, "setterOp=js_watch_set ");
else if (!shape.hasDefaultSetter())
fprintf(stderr, "setterOp=%p ", JS_FUNC_TO_DATA_PTR(void *, shape.setterOp()));

if (JSID_IS_ATOM(id))
dumpString(JSID_TO_STRING(id));
Expand All @@ -6816,6 +6826,12 @@ DumpShape(const Shape &shape)
else
fprintf(stderr, "unknown jsid %p", (void *) JSID_BITS(id));
fprintf(stderr, ": slot %d", shape.slot);
if (obj->containsSlot(shape.slot)) {
fprintf(stderr, " = ");
dumpValue(obj->getSlot(shape.slot));
} else if (shape.slot != SHAPE_INVALID_SLOT) {
fprintf(stderr, " (INVALID!)");
}
fprintf(stderr, "\n");
}

Expand All @@ -6830,7 +6846,7 @@ js_DumpObject(JSObject *obj)
uint32 flags = obj->flags;
if (flags & JSObject::DELEGATE) fprintf(stderr, " delegate");
if (flags & JSObject::SYSTEM) fprintf(stderr, " system");
if (flags & JSObject::NOT_EXTENSIBLE) fprintf(stderr, " not extensible");
if (flags & JSObject::NOT_EXTENSIBLE) fprintf(stderr, " not_extensible");
if (flags & JSObject::BRANDED) fprintf(stderr, " branded");
if (flags & JSObject::GENERIC) fprintf(stderr, " generic");
if (flags & JSObject::METHOD_BARRIER) fprintf(stderr, " method_barrier");
Expand Down Expand Up @@ -6865,15 +6881,6 @@ js_DumpObject(JSObject *obj)
return;
}

if (obj->isNative()) {
fprintf(stderr, "properties:\n");
for (Shape::Range r = obj->lastProperty()->all(); !r.empty(); r.popFront())
DumpShape(r.front());
} else {
if (!obj->isNative())
fprintf(stderr, "not native\n");
}

fprintf(stderr, "proto ");
dumpValue(ObjectOrNullValue(obj->getProto()));
fputc('\n', stderr);
Expand All @@ -6885,17 +6892,31 @@ js_DumpObject(JSObject *obj)
if (clasp->flags & JSCLASS_HAS_PRIVATE)
fprintf(stderr, "private %p\n", obj->getPrivate());

fprintf(stderr, "slots:\n");
if (!obj->isNative())
fprintf(stderr, "not native\n");

unsigned reservedEnd = JSCLASS_RESERVED_SLOTS(clasp);
unsigned slots = obj->slotSpan();
for (unsigned i = 0; i < slots; i++) {
unsigned stop = obj->isNative() ? reservedEnd : slots;
if (stop > 0)
fprintf(stderr, obj->isNative() ? "reserved slots:\n" : "slots:\n");
for (unsigned i = 0; i < stop; i++) {
fprintf(stderr, " %3d ", i);
if (i < reservedEnd)
fprintf(stderr, "(reserved) ");
fprintf(stderr, "= ");
dumpValue(obj->getSlot(i));
fputc('\n', stderr);
}

if (obj->isNative()) {
fprintf(stderr, "properties:\n");
Vector<const Shape *, 8, SystemAllocPolicy> props;
for (Shape::Range r = obj->lastProperty()->all(); !r.empty(); r.popFront())
props.append(&r.front());
for (size_t i = props.length(); i-- != 0;)
DumpProperty(obj, *props[i]);
}
fputc('\n', stderr);
}

Expand Down
1 change: 0 additions & 1 deletion js/src/jsobjinlines.h
Original file line number Diff line number Diff line change
Expand Up @@ -915,7 +915,6 @@ NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto,
JSObject *parent, gc::FinalizeKind kind)
{
JS_ASSERT(proto);
JS_ASSERT(proto->isNative());
JS_ASSERT(parent);

/*
Expand Down
4 changes: 2 additions & 2 deletions js/src/jsopcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5489,8 +5489,8 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
return ReconstructImacroPCStack(cx, script, imacstart, target, pcstack);
#endif

LOCAL_ASSERT(script->main <= target && target < script->code + script->length);
jsbytecode *pc = script->main;
LOCAL_ASSERT(script->code <= target && target < script->code + script->length);
jsbytecode *pc = script->code;
uintN pcdepth = 0;
ptrdiff_t oplen;
for (; pc < target; pc += oplen) {
Expand Down
1 change: 1 addition & 0 deletions js/src/jsscan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,7 @@ TokenStream::getTokenInternal()
c = getChar();
} while (JS_ISXMLSPACE(c));
ungetChar(c);
tp->pos.end.lineno = lineno;
tt = TOK_XMLSPACE;
goto out;
}
Expand Down
Loading

0 comments on commit 8b068c7

Please sign in to comment.