зеркало из https://github.com/mozilla/pjs.git
Merge tracemonkey to mozilla-central. a=blockers. CLOSED TREE
This commit is contained in:
Коммит
cf782841df
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
|||
this.__defineGetter__("x3", Function);
|
||||
parseInt = x3;
|
||||
parseInt.prototype = [];
|
||||
for (var z = 0; z < 10; ++z) { new parseInt() }
|
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
@ -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'.
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -6885,10 +6892,15 @@ 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) ");
|
||||
|
@ -6896,6 +6908,15 @@ js_DumpObject(JSObject *obj)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -857,6 +857,7 @@ TokenStream::getTokenInternal()
|
|||
c = getChar();
|
||||
} while (JS_ISXMLSPACE(c));
|
||||
ungetChar(c);
|
||||
tp->pos.end.lineno = lineno;
|
||||
tt = TOK_XMLSPACE;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -10328,7 +10328,7 @@ class BoxArg
|
|||
* argument values into the object as properties in case it is used after
|
||||
* this frame returns.
|
||||
*/
|
||||
JS_REQUIRES_STACK void
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::putActivationObjects()
|
||||
{
|
||||
JSStackFrame *const fp = cx->fp();
|
||||
|
@ -10336,7 +10336,20 @@ TraceRecorder::putActivationObjects()
|
|||
bool have_call = fp->isFunctionFrame() && fp->fun()->isHeavyweight();
|
||||
|
||||
if (!have_args && !have_call)
|
||||
return;
|
||||
return ARECORD_CONTINUE;
|
||||
|
||||
if (have_args && !fp->script()->usesArguments) {
|
||||
/*
|
||||
* have_args is true, so |arguments| has been accessed, but
|
||||
* usesArguments is false, so there's no statically visible access.
|
||||
* It must have been a dodgy access like |f["arguments"]|; just
|
||||
* abort. (In the case where the record-time property name is not
|
||||
* "arguments" but a later run-time property name is, we wouldn't have
|
||||
* emitted the call to js_PutArgumentsOnTrace(), and js_GetArgsValue()
|
||||
* will deep bail asking for the top JSStackFrame.)
|
||||
*/
|
||||
RETURN_STOP_A("dodgy arguments access");
|
||||
}
|
||||
|
||||
uintN nformal = fp->numFormalArgs();
|
||||
uintN nactual = fp->numActualArgs();
|
||||
|
@ -10380,6 +10393,8 @@ TraceRecorder::putActivationObjects()
|
|||
w.nameImmi(fp->numFormalArgs()), scopeChain_ins, cx_ins };
|
||||
w.call(&js_PutCallObjectOnTrace_ci, args);
|
||||
}
|
||||
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
|
@ -10572,7 +10587,7 @@ TraceRecorder::record_JSOP_RETURN()
|
|||
return endLoop();
|
||||
}
|
||||
|
||||
putActivationObjects();
|
||||
CHECK_STATUS_A(putActivationObjects());
|
||||
|
||||
if (Probes::callTrackingActive(cx)) {
|
||||
LIns* args[] = { w.immi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins };
|
||||
|
@ -10639,7 +10654,7 @@ TraceRecorder::record_JSOP_IFNE()
|
|||
}
|
||||
|
||||
LIns*
|
||||
TraceRecorder::newArguments(LIns* callee_ins, bool strict)
|
||||
TraceRecorder::newArguments(LIns* callee_ins)
|
||||
{
|
||||
LIns* global_ins = w.immpObjGC(globalObj);
|
||||
LIns* argc_ins = w.nameImmi(cx->fp()->numActualArgs());
|
||||
|
@ -10648,13 +10663,6 @@ TraceRecorder::newArguments(LIns* callee_ins, bool strict)
|
|||
LIns* argsobj_ins = w.call(&js_NewArgumentsOnTrace_ci, args);
|
||||
guard(false, w.eqp0(argsobj_ins), OOM_EXIT);
|
||||
|
||||
if (strict) {
|
||||
LIns* argsData_ins = w.getObjPrivatizedSlot(argsobj_ins, JSObject::JSSLOT_ARGS_DATA);
|
||||
ptrdiff_t slotsOffset = offsetof(ArgumentsData, slots);
|
||||
cx->fp()->forEachCanonicalActualArg(BoxArg(this, ArgsSlotOffsetAddress(argsData_ins,
|
||||
slotsOffset)));
|
||||
}
|
||||
|
||||
return argsobj_ins;
|
||||
}
|
||||
|
||||
|
@ -10668,14 +10676,15 @@ TraceRecorder::record_JSOP_ARGUMENTS()
|
|||
|
||||
if (fp->hasOverriddenArgs())
|
||||
RETURN_STOP_A("Can't trace |arguments| if |arguments| is assigned to");
|
||||
if (fp->fun()->inStrictMode())
|
||||
RETURN_STOP_A("Can't trace strict-mode arguments");
|
||||
|
||||
LIns* a_ins = getFrameObjPtr(fp->addressOfArgs());
|
||||
LIns* args_ins;
|
||||
LIns* callee_ins = get(&fp->calleeValue());
|
||||
bool strict = fp->fun()->inStrictMode();
|
||||
if (a_ins->isImmP()) {
|
||||
// |arguments| is set to 0 by EnterFrame on this trace, so call to create it.
|
||||
args_ins = newArguments(callee_ins, strict);
|
||||
args_ins = newArguments(callee_ins);
|
||||
} else {
|
||||
// Generate LIR to create arguments only if it has not already been created.
|
||||
|
||||
|
@ -10685,7 +10694,7 @@ TraceRecorder::record_JSOP_ARGUMENTS()
|
|||
if (isZero_ins->isImmI(0)) {
|
||||
w.stAlloc(a_ins, mem_ins);
|
||||
} else if (isZero_ins->isImmI(1)) {
|
||||
LIns* call_ins = newArguments(callee_ins, strict);
|
||||
LIns* call_ins = newArguments(callee_ins);
|
||||
w.stAlloc(call_ins, mem_ins);
|
||||
} else {
|
||||
LIns* br1 = w.jtUnoptimizable(isZero_ins);
|
||||
|
@ -10693,7 +10702,7 @@ TraceRecorder::record_JSOP_ARGUMENTS()
|
|||
LIns* br2 = w.j(NULL);
|
||||
w.label(br1);
|
||||
|
||||
LIns* call_ins = newArguments(callee_ins, strict);
|
||||
LIns* call_ins = newArguments(callee_ins);
|
||||
w.stAlloc(call_ins, mem_ins);
|
||||
w.label(br2);
|
||||
}
|
||||
|
@ -12843,10 +12852,9 @@ GetPropertyWithNativeGetter(JSContext* cx, JSObject* obj, Shape* shape, Value* v
|
|||
LeaveTraceIfGlobalObject(cx, obj);
|
||||
|
||||
#ifdef DEBUG
|
||||
JSProperty* prop;
|
||||
JSObject* pobj;
|
||||
JS_ASSERT(obj->lookupProperty(cx, shape->id, &pobj, &prop));
|
||||
JS_ASSERT(prop == (JSProperty*) shape);
|
||||
const Shape* shape2;
|
||||
JS_ASSERT_IF(SafeLookup(cx, obj, shape->id, &pobj, &shape2), shape == shape2);
|
||||
#endif
|
||||
|
||||
// Shape::get contains a special case for With objects. We can elide it
|
||||
|
@ -13793,7 +13801,7 @@ TraceRecorder::interpretedFunctionCall(Value& fval, JSFunction* fun, uintN argc,
|
|||
if (constructing) {
|
||||
LIns* thisobj_ins;
|
||||
CHECK_STATUS(createThis(fval.toObject(), get(&fval), &thisobj_ins));
|
||||
stack(-argc - 1, thisobj_ins);
|
||||
stack(-int(argc) - 1, thisobj_ins);
|
||||
}
|
||||
|
||||
// Generate a type map for the outgoing frame and stash it in the LIR
|
||||
|
@ -16219,7 +16227,7 @@ TraceRecorder::record_JSOP_STOP()
|
|||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
putActivationObjects();
|
||||
CHECK_STATUS_A(putActivationObjects());
|
||||
|
||||
if (Probes::callTrackingActive(cx)) {
|
||||
LIns* args[] = { w.immi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins };
|
||||
|
@ -16309,7 +16317,6 @@ TraceRecorder::record_JSOP_ARRAYPUSH()
|
|||
JS_ASSERT(cx->fp()->slots() + slot < cx->regs->sp - 1);
|
||||
Value &arrayval = cx->fp()->slots()[slot];
|
||||
JS_ASSERT(arrayval.isObject());
|
||||
JS_ASSERT(arrayval.toObject().isDenseArray());
|
||||
LIns *array_ins = get(&arrayval);
|
||||
Value &elt = stackval(-1);
|
||||
LIns *elt_ins = box_value_for_native_call(elt, get(&elt));
|
||||
|
|
|
@ -1290,7 +1290,7 @@ class TraceRecorder
|
|||
JS_REQUIRES_STACK RecordingStatus makeNumberUint32(nanojit::LIns* d, nanojit::LIns** num_ins);
|
||||
JS_REQUIRES_STACK nanojit::LIns* stringify(const Value& v);
|
||||
|
||||
JS_REQUIRES_STACK nanojit::LIns* newArguments(nanojit::LIns* callee_ins, bool strict);
|
||||
JS_REQUIRES_STACK nanojit::LIns* newArguments(nanojit::LIns* callee_ins);
|
||||
|
||||
JS_REQUIRES_STACK bool canCallImacro() const;
|
||||
JS_REQUIRES_STACK RecordingStatus callImacro(jsbytecode* imacro);
|
||||
|
@ -1482,7 +1482,7 @@ class TraceRecorder
|
|||
VMSideExit* exit);
|
||||
JS_REQUIRES_STACK RecordingStatus guardNativeConversion(Value& v);
|
||||
JS_REQUIRES_STACK void clearReturningFrameFromNativeTracker();
|
||||
JS_REQUIRES_STACK void putActivationObjects();
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus putActivationObjects();
|
||||
JS_REQUIRES_STACK RecordingStatus createThis(JSObject& ctor, nanojit::LIns* ctor_ins,
|
||||
nanojit::LIns** thisobj_insp);
|
||||
JS_REQUIRES_STACK RecordingStatus guardCallee(Value& callee);
|
||||
|
|
|
@ -3564,6 +3564,127 @@ ShapeOf(JSContext *cx, uintN argc, jsval *vp)
|
|||
return JS_NewNumberValue(cx, obj->shape(), vp);
|
||||
}
|
||||
|
||||
/*
|
||||
* If referent has an own property named id, copy that property to obj[id].
|
||||
* Since obj is native, this isn't totally transparent; properties of a
|
||||
* non-native referent may be simplified to data properties.
|
||||
*/
|
||||
static JSBool
|
||||
CopyProperty(JSContext *cx, JSObject *obj, JSObject *referent, jsid id,
|
||||
uintN lookupFlags, JSObject **objp)
|
||||
{
|
||||
JSProperty *prop;
|
||||
PropertyDescriptor desc;
|
||||
uintN propFlags = 0;
|
||||
JSObject *obj2;
|
||||
|
||||
*objp = NULL;
|
||||
if (referent->isNative()) {
|
||||
if (js_LookupPropertyWithFlags(cx, referent, id, lookupFlags, &obj2, &prop) < 0)
|
||||
return false;
|
||||
if (obj2 != referent)
|
||||
return true;
|
||||
|
||||
const Shape *shape = (Shape *) prop;
|
||||
if (shape->isMethod()) {
|
||||
shape = referent->methodReadBarrier(cx, *shape, &desc.value);
|
||||
if (!shape)
|
||||
return false;
|
||||
} else if (shape->hasSlot()) {
|
||||
desc.value = referent->nativeGetSlot(shape->slot);
|
||||
} else {
|
||||
desc.value.setUndefined();
|
||||
}
|
||||
|
||||
desc.attrs = shape->attributes();
|
||||
desc.getter = shape->getter();
|
||||
if (!desc.getter && !(desc.attrs & JSPROP_GETTER))
|
||||
desc.getter = PropertyStub;
|
||||
desc.setter = shape->setter();
|
||||
if (!desc.setter && !(desc.attrs & JSPROP_SETTER))
|
||||
desc.setter = StrictPropertyStub;
|
||||
desc.shortid = shape->shortid;
|
||||
propFlags = shape->getFlags();
|
||||
} else if (referent->isProxy()) {
|
||||
PropertyDescriptor desc;
|
||||
if (!JSProxy::getOwnPropertyDescriptor(cx, referent, id, false, &desc))
|
||||
return false;
|
||||
if (!desc.obj)
|
||||
return true;
|
||||
} else {
|
||||
if (!referent->lookupProperty(cx, id, objp, &prop))
|
||||
return false;
|
||||
if (*objp != referent)
|
||||
return true;
|
||||
if (!referent->getProperty(cx, id, &desc.value) ||
|
||||
!referent->getAttributes(cx, id, &desc.attrs)) {
|
||||
return false;
|
||||
}
|
||||
desc.attrs &= JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
|
||||
desc.getter = PropertyStub;
|
||||
desc.setter = StrictPropertyStub;
|
||||
desc.shortid = 0;
|
||||
}
|
||||
|
||||
*objp = obj;
|
||||
return js_DefineNativeProperty(cx, obj, id, desc.value,
|
||||
desc.getter, desc.setter, desc.attrs, propFlags,
|
||||
desc.shortid, &prop);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
resolver_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp)
|
||||
{
|
||||
jsval v;
|
||||
JS_ALWAYS_TRUE(JS_GetReservedSlot(cx, obj, 0, &v));
|
||||
return CopyProperty(cx, obj, JSVAL_TO_OBJECT(v), id, flags, objp);
|
||||
}
|
||||
static JSNewResolveOp resolver_resolve_check = resolver_resolve;
|
||||
|
||||
static JSBool
|
||||
resolver_enumerate(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
jsval v;
|
||||
JS_ALWAYS_TRUE(JS_GetReservedSlot(cx, obj, 0, &v));
|
||||
JSObject *referent = JSVAL_TO_OBJECT(v);
|
||||
|
||||
AutoIdArray ida(cx, JS_Enumerate(cx, referent));
|
||||
bool ok = !!ida;
|
||||
JSObject *ignore;
|
||||
for (size_t i = 0; ok && i < ida.length(); i++)
|
||||
ok = CopyProperty(cx, obj, referent, ida[i], JSRESOLVE_QUALIFIED, &ignore);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static JSClass resolver_class = {
|
||||
"resolver",
|
||||
JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(1),
|
||||
JS_PropertyStub, JS_PropertyStub,
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
resolver_enumerate, (JSResolveOp)resolver_resolve,
|
||||
JS_ConvertStub, NULL,
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
|
||||
static JSBool
|
||||
Resolver(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *referent, *proto = NULL;
|
||||
if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "o/o", &referent, &proto))
|
||||
return false;
|
||||
|
||||
JSObject *result = (argc > 1
|
||||
? JS_NewObjectWithGivenProto
|
||||
: JS_NewObject)(cx, &resolver_class, proto, JS_GetParent(cx, referent));
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
JS_ALWAYS_TRUE(JS_SetReservedSlot(cx, result, 0, OBJECT_TO_JSVAL(referent)));
|
||||
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
/*
|
||||
|
@ -4416,6 +4537,7 @@ static JSFunctionSpec shell_functions[] = {
|
|||
JS_FN("evalcx", EvalInContext, 1,0),
|
||||
JS_FN("evalInFrame", EvalInFrame, 2,0),
|
||||
JS_FN("shapeOf", ShapeOf, 1,0),
|
||||
JS_FN("resolver", Resolver, 1,0),
|
||||
#ifdef MOZ_CALLGRIND
|
||||
JS_FN("startCallgrind", js_StartCallgrind, 0,0),
|
||||
JS_FN("stopCallgrind", js_StopCallgrind, 0,0),
|
||||
|
@ -4543,6 +4665,8 @@ static const char *const shell_help_messages[] = {
|
|||
"evalInFrame(n,str,save) Evaluate 'str' in the nth up frame.\n"
|
||||
" If 'save' (default false), save the frame chain",
|
||||
"shapeOf(obj) Get the shape of obj (an implementation detail)",
|
||||
"resolver(src[, proto]) Create object with resolve hook that copies properties\n"
|
||||
" from src. If proto is omitted, use Object.prototype.",
|
||||
#ifdef MOZ_CALLGRIND
|
||||
"startCallgrind() Start callgrind instrumentation",
|
||||
"stopCallgrind() Stop callgrind instrumentation",
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
var BUGNUMBER = 621432;
|
||||
var summary =
|
||||
"If a var statement can't create a global property because the global " +
|
||||
"object isn't extensible, and an error is thrown while decompiling the " +
|
||||
"global, don't assert";
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
/**************
|
||||
* BEGIN TEST *
|
||||
**************/
|
||||
|
||||
var toSource = [];
|
||||
Object.preventExtensions(this);
|
||||
|
||||
try
|
||||
{
|
||||
eval("var x;");
|
||||
throw new Error("no error thrown");
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
reportCompare(e instanceof TypeError, true, "expected TypeError, got: " + e);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
print("All tests passed!");
|
|
@ -1,4 +1,5 @@
|
|||
url-prefix ../../jsreftest.html?test=ecma_5/Global/
|
||||
fails-if(!xulRuntime.shell) script adding-global-var-nonextensible-error.js
|
||||
script parseInt-01.js
|
||||
script parseFloat-01.js
|
||||
script eval-01.js
|
||||
|
|
|
@ -32,4 +32,5 @@ script regress-627984-4.js
|
|||
script regress-627984-5.js
|
||||
script regress-627984-6.js
|
||||
script regress-627984-7.js
|
||||
script regress-630377.js
|
||||
script regress-631723.js
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
function f(x) {
|
||||
x.q = 1;
|
||||
}
|
||||
var a = #1=[f(#1#) for (i in [0])];
|
||||
assertEq(a.q, 1);
|
||||
assertEq(a[0], void 0);
|
||||
|
||||
reportCompare(0, 0, 'ok');
|
|
@ -84,6 +84,7 @@ script regress-624199.js
|
|||
script regress-624547.js
|
||||
script regress-624968.js
|
||||
script regress-626436.js
|
||||
fails-if(xulRuntime.shell) script regress-633741.js
|
||||
script regress-634210-1.js
|
||||
script regress-634210-2.js
|
||||
script regress-634210-3.js
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
* Contributors: Jan de Mooij
|
||||
*/
|
||||
|
||||
Object.preventExtensions(this);
|
||||
delete Function;
|
||||
|
||||
try {
|
||||
/* Don't assert. */
|
||||
Object.getOwnPropertyNames(this);
|
||||
} catch(e) {
|
||||
reportCompare(true, false, "this shouldn't have thrown");
|
||||
}
|
||||
reportCompare(0, 0, "ok");
|
||||
|
Загрузка…
Ссылка в новой задаче