[INFER] Remove isTypeCallerMonitored and rejoin from native calls triggering recompilation, bug 638977.
This commit is contained in:
@@ -1402,14 +1402,39 @@ array_toLocaleString(JSContext *cx, uintN argc, Value *vp)
|
||||
return array_toString_sub(cx, obj, JS_TRUE, NULL, vp);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
InitArrayTypes(JSContext *cx, TypeObject *type, const Value *vector, unsigned count)
|
||||
{
|
||||
if (cx->typeInferenceEnabled() && !type->unknownProperties) {
|
||||
AutoEnterTypeInference enter(cx);
|
||||
|
||||
TypeSet *types = type->getProperty(cx, JSID_VOID, true);
|
||||
if (!types)
|
||||
return JS_FALSE;
|
||||
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
if (vector[i].isMagic(JS_ARRAY_HOLE))
|
||||
continue;
|
||||
jstype valtype = GetValueType(cx, vector[i]);
|
||||
types->addType(cx, valtype);
|
||||
}
|
||||
|
||||
return cx->compartment->types.checkPendingRecompiles(cx);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, Value *vector)
|
||||
InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, Value *vector, bool updateTypes)
|
||||
{
|
||||
JS_ASSERT(count < MAXINDEX);
|
||||
|
||||
if (count == 0)
|
||||
return JS_TRUE;
|
||||
|
||||
if (updateTypes && !InitArrayTypes(cx, obj->getType(), vector, count))
|
||||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
* Optimize for dense arrays so long as adding the given set of elements
|
||||
* wouldn't otherwise make the array slow.
|
||||
@@ -1479,6 +1504,9 @@ InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, const Value *vector
|
||||
if (!vector || !length)
|
||||
return true;
|
||||
|
||||
if (!InitArrayTypes(cx, obj->getType(), vector, length))
|
||||
return false;
|
||||
|
||||
/* Avoid ensureDenseArrayElements to skip sparse array checks there. */
|
||||
if (!obj->ensureSlots(cx, length))
|
||||
return false;
|
||||
@@ -2041,7 +2069,7 @@ js::array_sort(JSContext *cx, uintN argc, Value *vp)
|
||||
* InitArrayElements easier.
|
||||
*/
|
||||
tvr.changeLength(newlen);
|
||||
if (!InitArrayElements(cx, obj, 0, newlen, vec))
|
||||
if (!InitArrayElements(cx, obj, 0, newlen, vec, false))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2073,7 +2101,7 @@ array_push_slowly(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *
|
||||
|
||||
if (!js_GetLengthProperty(cx, obj, &length))
|
||||
return JS_FALSE;
|
||||
if (!InitArrayElements(cx, obj, length, argc, argv))
|
||||
if (!InitArrayElements(cx, obj, length, argc, argv, true))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Per ECMA-262, return the new array length. */
|
||||
@@ -2100,6 +2128,9 @@ array_push1_dense(JSContext* cx, JSObject* obj, const Value &v, Value *rval)
|
||||
break;
|
||||
}
|
||||
|
||||
if (cx->typeInferenceEnabled() && !cx->addTypePropertyId(obj->getType(), JSID_VOID, v))
|
||||
return false;
|
||||
|
||||
obj->setDenseArrayLength(length + 1);
|
||||
obj->setDenseArrayElement(length, v);
|
||||
rval->setNumber(obj->getArrayLength());
|
||||
@@ -2176,9 +2207,6 @@ array_push(JSContext *cx, uintN argc, Value *vp)
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
if (cx->isTypeCallerMonitored() && !cx->markTypeObjectUnknownProperties(obj->getType()))
|
||||
return false;
|
||||
|
||||
/* Insist on one argument and obj of the expected class. */
|
||||
if (argc != 1 || !obj->isDenseArray())
|
||||
return array_push_slowly(cx, obj, argc, vp + 2, vp);
|
||||
@@ -2312,9 +2340,6 @@ array_unshift(JSContext *cx, uintN argc, Value *vp)
|
||||
if (!js_GetLengthProperty(cx, obj, &length))
|
||||
return JS_FALSE;
|
||||
|
||||
if (cx->isTypeCallerMonitored() && !cx->markTypeObjectUnknownProperties(obj->getType()))
|
||||
return false;
|
||||
|
||||
newlen = length;
|
||||
if (argc > 0) {
|
||||
/* Slide up the array to make room for argc at the bottom. */
|
||||
@@ -2355,7 +2380,7 @@ array_unshift(JSContext *cx, uintN argc, Value *vp)
|
||||
}
|
||||
|
||||
/* Copy from argv to the bottom of the array. */
|
||||
if (!InitArrayElements(cx, obj, 0, argc, argv))
|
||||
if (!InitArrayElements(cx, obj, 0, argc, argv, true))
|
||||
return JS_FALSE;
|
||||
|
||||
newlen += argc;
|
||||
@@ -2402,9 +2427,6 @@ array_splice(JSContext *cx, uintN argc, Value *vp)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cx->isTypeCallerMonitored() && !cx->markTypeObjectUnknownProperties(type))
|
||||
return false;
|
||||
|
||||
/* Create a new array value to return. */
|
||||
JSObject *obj2 = NewDenseEmptyArray(cx);
|
||||
if (!obj2)
|
||||
@@ -2470,6 +2492,9 @@ array_splice(JSContext *cx, uintN argc, Value *vp)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!cx->addTypePropertyId(obj2->getType(), JSID_VOID, tvr.value()))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Copy tvr.value() to the new array unless it's a hole. */
|
||||
if (!hole && !SetArrayElement(cx, obj2, last - begin, tvr.value()))
|
||||
return JS_FALSE;
|
||||
@@ -2554,7 +2579,7 @@ array_splice(JSContext *cx, uintN argc, Value *vp)
|
||||
* Copy from argv into the hole to complete the splice, and update length in
|
||||
* case we deleted elements from the end.
|
||||
*/
|
||||
return InitArrayElements(cx, obj, begin, argc, argv) &&
|
||||
return InitArrayElements(cx, obj, begin, argc, argv, true) &&
|
||||
js_SetLengthProperty(cx, obj, length);
|
||||
}
|
||||
|
||||
@@ -2571,8 +2596,6 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
|
||||
TypeObject *ntype = cx->getTypeCallerInitObject(true);
|
||||
if (!ntype)
|
||||
return false;
|
||||
if (cx->isTypeCallerMonitored() && !cx->markTypeObjectUnknownProperties(ntype))
|
||||
return false;
|
||||
|
||||
/* Create a new Array object and root it using *vp. */
|
||||
JSObject *aobj = ToObject(cx, &vp[1]);
|
||||
@@ -2583,13 +2606,18 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
|
||||
jsuint length;
|
||||
if (aobj->isDenseArray()) {
|
||||
length = aobj->getArrayLength();
|
||||
Value *vector = aobj->getDenseArrayElements();
|
||||
jsuint initlen = aobj->getDenseArrayInitializedLength();
|
||||
nobj = NewDenseCopiedArray(cx, initlen, aobj->getDenseArrayElements());
|
||||
nobj = NewDenseCopiedArray(cx, initlen, vector);
|
||||
if (!nobj)
|
||||
return JS_FALSE;
|
||||
nobj->setType(ntype);
|
||||
if (!nobj->setArrayLength(cx, length))
|
||||
return JS_FALSE;
|
||||
if (!InitArrayTypes(cx, ntype, vector, length))
|
||||
return JS_FALSE;
|
||||
if (!aobj->isPackedDenseArray() && !nobj->setDenseArrayNotPacked(cx))
|
||||
return JS_FALSE;
|
||||
vp->setObject(*nobj);
|
||||
if (argc == 0)
|
||||
return JS_TRUE;
|
||||
@@ -2604,9 +2632,6 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
|
||||
length = 0;
|
||||
}
|
||||
|
||||
if (aobj->isDenseArray() && !aobj->isPackedDenseArray() && !nobj->setDenseArrayNotPacked(cx))
|
||||
return false;
|
||||
|
||||
AutoValueRooter tvr(cx);
|
||||
|
||||
/* Loop over [0, argc] to concat args into nobj, expanding all Arrays. */
|
||||
@@ -2631,6 +2656,9 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hole && !cx->addTypePropertyId(ntype, JSID_VOID, tvr.value()))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Per ECMA 262, 15.4.4.4, step 9, ignore nonexistent
|
||||
* properties.
|
||||
@@ -2645,10 +2673,6 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The type handler for Array.concat only handles array arguments.
|
||||
* Inform type inference of any non-array arguments passed in.
|
||||
*/
|
||||
if (!cx->addTypePropertyId(ntype, JSID_VOID, v))
|
||||
return false;
|
||||
|
||||
@@ -2726,9 +2750,6 @@ array_slice(JSContext *cx, uintN argc, Value *vp)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cx->isTypeCallerMonitored() && !cx->markTypeObjectUnknownProperties(type))
|
||||
return false;
|
||||
|
||||
if (obj->isDenseArray() && end <= obj->getDenseArrayCapacity() &&
|
||||
!js_PrototypeHasIndexedProperties(cx, obj)) {
|
||||
nobj = NewDenseCopiedArray(cx, end - begin, obj->getDenseArrayElements() + begin);
|
||||
@@ -2754,6 +2775,8 @@ array_slice(JSContext *cx, uintN argc, Value *vp)
|
||||
!GetElement(cx, obj, slot, &hole, tvr.addr())) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (!hole && !cx->addTypePropertyId(nobj->getType(), JSID_VOID, tvr.value()))
|
||||
return false;
|
||||
if (!hole && !SetArrayElement(cx, nobj, slot - begin, tvr.value()))
|
||||
return JS_FALSE;
|
||||
}
|
||||
@@ -2958,15 +2981,6 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
|
||||
|
||||
Value thisv = (argc > 1 && !REDUCE_MODE(mode)) ? argv[1] : UndefinedValue();
|
||||
|
||||
/*
|
||||
* If the callsite is being monitored for type inference, and we are modifying
|
||||
* the output array, monitor any reads on the array in the future.
|
||||
*/
|
||||
if (cx->isTypeCallerMonitored() && (mode == MAP || mode == FILTER) &&
|
||||
!cx->markTypeObjectUnknownProperties(newtype)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* For all but REDUCE, we call with 3 args (value, index, array). REDUCE
|
||||
* requires 4 args (accum, value, index, array).
|
||||
@@ -3367,12 +3381,12 @@ js_Array(JSContext *cx, uintN argc, Value *vp)
|
||||
if (argc == 0) {
|
||||
obj = NewDenseEmptyArray(cx);
|
||||
} else if (argc > 1) {
|
||||
if (!InitArrayTypes(cx, type, vp + 2, argc))
|
||||
return false;
|
||||
obj = NewDenseCopiedArray(cx, argc, vp + 2);
|
||||
} else if (!vp[2].isNumber()) {
|
||||
/* Unexpected case for type inference. */
|
||||
if (!cx->addTypeProperty(type, NULL, vp[2]))
|
||||
return false;
|
||||
|
||||
obj = NewDenseCopiedArray(cx, 1, vp + 2);
|
||||
} else {
|
||||
jsuint length;
|
||||
@@ -3385,8 +3399,6 @@ js_Array(JSContext *cx, uintN argc, Value *vp)
|
||||
return JS_FALSE;
|
||||
|
||||
obj->setType(type);
|
||||
if (cx->isTypeCallerMonitored() && !cx->markTypeObjectUnknownProperties(type))
|
||||
return false;
|
||||
|
||||
/* If the length calculation overflowed, make sure that is marked for the new type. */
|
||||
if (obj->getArrayLength() > INT32_MAX && !obj->setArrayLength(cx, obj->getArrayLength()))
|
||||
|
||||
Reference in New Issue
Block a user