Backout bug 684110 (08b6eaf6aad0, cf8b35fa1010, 25ee45edabe1, 659f5c7d2cc9, 870f6dd82586 & e1ad65d6a7fd) and bug 684344 (cd1957f6628d) on a CLOSED TREE; a=bustage-fairies
This commit is contained in:
@@ -44,7 +44,7 @@
|
||||
* Array objects begin as "dense" arrays, optimized for index-only property
|
||||
* access over a vector of slots with high load factor. Array methods
|
||||
* optimize for denseness by testing that the object's class is
|
||||
* &ArrayClass, and can then directly manipulate the slots for efficiency.
|
||||
* &js_ArrayClass, and can then directly manipulate the slots for efficiency.
|
||||
*
|
||||
* We track these pieces of metadata for arrays in dense mode:
|
||||
* - The array's length property as a uint32, accessible with
|
||||
@@ -81,7 +81,7 @@
|
||||
* known to have no hole values below its initialized length, then it is a
|
||||
* "packed" array and can be accessed much faster by JIT code.
|
||||
*
|
||||
* Arrays are converted to use SlowArrayClass when any of these conditions
|
||||
* Arrays are converted to use js_SlowArrayClass when any of these conditions
|
||||
* are met:
|
||||
* - there are more than MIN_SPARSE_INDEX slots total and the load factor
|
||||
* (COUNT / capacity) is less than 0.25
|
||||
@@ -93,7 +93,7 @@
|
||||
* properties in the order they were created. We could instead maintain the
|
||||
* scope to track property enumeration order, but still use the fast slot
|
||||
* access. That would have the same memory cost as just using a
|
||||
* SlowArrayClass, but have the same performance characteristics as a dense
|
||||
* js_SlowArrayClass, but have the same performance characteristics as a dense
|
||||
* array for slot accesses, at some cost in code complexity.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
@@ -146,6 +146,13 @@ using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
static inline bool
|
||||
ENSURE_SLOW_ARRAY(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return obj->getClass() == &js_SlowArrayClass ||
|
||||
obj->makeDenseArraySlow(cx);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
|
||||
{
|
||||
@@ -239,11 +246,14 @@ static JSBool
|
||||
BigIndexToId(JSContext *cx, JSObject *obj, jsuint index, JSBool createAtom,
|
||||
jsid *idp)
|
||||
{
|
||||
jschar buf[10], *start;
|
||||
Class *clasp;
|
||||
JSAtom *atom;
|
||||
JS_STATIC_ASSERT((jsuint)-1 == 4294967295U);
|
||||
|
||||
JS_ASSERT(index > JSID_INT_MAX);
|
||||
|
||||
jschar buf[10];
|
||||
jschar *start = JS_ARRAY_END(buf);
|
||||
start = JS_ARRAY_END(buf);
|
||||
do {
|
||||
--start;
|
||||
*start = (jschar)('0' + index % 10);
|
||||
@@ -254,11 +264,14 @@ BigIndexToId(JSContext *cx, JSObject *obj, jsuint index, JSBool createAtom,
|
||||
* Skip the atomization if the class is known to store atoms corresponding
|
||||
* to big indexes together with elements. In such case we know that the
|
||||
* array does not have an element at the given index if its atom does not
|
||||
* exist. Dense arrays don't use atoms for any indexes, though it would be
|
||||
* rare to see them have a big index in any case.
|
||||
* exist. Fast arrays (clasp == &js_ArrayClass) don't use atoms for
|
||||
* any indexes, though it would be rare to see them have a big index
|
||||
* in any case.
|
||||
*/
|
||||
JSAtom *atom;
|
||||
if (!createAtom && (obj->isSlowArray() || obj->isArguments() || obj->isObject())) {
|
||||
if (!createAtom &&
|
||||
((clasp = obj->getClass()) == &js_SlowArrayClass ||
|
||||
obj->isArguments() ||
|
||||
clasp == &js_ObjectClass)) {
|
||||
atom = js_GetExistingStringAtom(cx, start, JS_ARRAY_END(buf) - start);
|
||||
if (!atom) {
|
||||
*idp = JSID_VOID;
|
||||
@@ -488,13 +501,13 @@ JSBool JS_FASTCALL
|
||||
js_EnsureDenseArrayCapacity(JSContext *cx, JSObject *obj, jsint i)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Class *origObjClasp = obj->getClass();
|
||||
Class *origObjClasp = obj->clasp;
|
||||
#endif
|
||||
jsuint u = jsuint(i);
|
||||
JSBool ret = (obj->ensureDenseArrayElements(cx, u, 1) == JSObject::ED_OK);
|
||||
|
||||
/* Partially check the CallInfo's storeAccSet is correct. */
|
||||
JS_ASSERT(obj->getClass() == origObjClasp);
|
||||
JS_ASSERT(obj->clasp == origObjClasp);
|
||||
return ret;
|
||||
}
|
||||
/* This function and its callees do not touch any object's .clasp field. */
|
||||
@@ -976,7 +989,7 @@ array_fix(JSContext *cx, JSObject *obj, bool *success, AutoIdVector *props)
|
||||
return true;
|
||||
}
|
||||
|
||||
Class js::ArrayClass = {
|
||||
Class js_ArrayClass = {
|
||||
"Array",
|
||||
Class::NON_NATIVE | JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
|
||||
PropertyStub, /* addProperty */
|
||||
@@ -1011,7 +1024,7 @@ Class js::ArrayClass = {
|
||||
}
|
||||
};
|
||||
|
||||
Class js::SlowArrayClass = {
|
||||
Class js_SlowArrayClass = {
|
||||
"Array",
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
|
||||
@@ -1056,7 +1069,7 @@ JSObject::makeDenseArraySlow(JSContext *cx)
|
||||
|
||||
/* Create a native scope. */
|
||||
gc::AllocKind kind = getAllocKind();
|
||||
if (!InitScopeForObject(cx, this, &SlowArrayClass, getProto()->getNewType(cx), kind))
|
||||
if (!InitScopeForObject(cx, this, &js_SlowArrayClass, getProto()->getNewType(cx), kind))
|
||||
return false;
|
||||
|
||||
backfillDenseArrayHoles(cx);
|
||||
@@ -1077,7 +1090,7 @@ JSObject::makeDenseArraySlow(JSContext *cx)
|
||||
JS_ASSERT(!denseArrayHasInlineSlots());
|
||||
}
|
||||
capacity = numFixedSlots() + arrayCapacity;
|
||||
clasp = &SlowArrayClass;
|
||||
clasp = &js_SlowArrayClass;
|
||||
|
||||
/*
|
||||
* Root all values in the array during conversion, as SlowArrayClass only
|
||||
@@ -1097,7 +1110,7 @@ JSObject::makeDenseArraySlow(JSContext *cx)
|
||||
setMap(oldMap);
|
||||
capacity = arrayCapacity;
|
||||
initializedLength = arrayInitialized;
|
||||
clasp = &ArrayClass;
|
||||
clasp = &js_ArrayClass;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1120,7 +1133,7 @@ JSObject::makeDenseArraySlow(JSContext *cx)
|
||||
setMap(oldMap);
|
||||
capacity = arrayCapacity;
|
||||
initializedLength = arrayInitialized;
|
||||
clasp = &ArrayClass;
|
||||
clasp = &js_ArrayClass;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1131,7 +1144,7 @@ JSObject::makeDenseArraySlow(JSContext *cx)
|
||||
|
||||
/*
|
||||
* Finally, update class. If |this| is Array.prototype, then js_InitClass
|
||||
* will create an emptyShape whose class is &SlowArrayClass, to ensure
|
||||
* will create an emptyShape whose class is &js_SlowArrayClass, to ensure
|
||||
* that delegating instances can share shapes in the tree rooted at the
|
||||
* proto's empty shape.
|
||||
*/
|
||||
@@ -1198,7 +1211,7 @@ array_toSource(JSContext *cx, uintN argc, Value *vp)
|
||||
if (!obj)
|
||||
return false;
|
||||
if (!obj->isArray()) {
|
||||
ReportIncompatibleMethod(cx, vp, &ArrayClass);
|
||||
ReportIncompatibleMethod(cx, vp, &js_ArrayClass);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1527,7 +1540,7 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, Valu
|
||||
return JS_TRUE;
|
||||
|
||||
/* Finish out any remaining elements past the max array index. */
|
||||
if (obj->isDenseArray() && !obj->makeDenseArraySlow(cx))
|
||||
if (obj->isDenseArray() && !ENSURE_SLOW_ARRAY(cx, obj))
|
||||
return JS_FALSE;
|
||||
|
||||
JS_ASSERT(start == MAX_ARRAY_INDEX + 1);
|
||||
@@ -3204,12 +3217,12 @@ js_InitArrayClass(JSContext *cx, JSObject *obj)
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
|
||||
JSObject *arrayProto = global->createBlankPrototype(cx, &SlowArrayClass);
|
||||
JSObject *arrayProto = global->createBlankPrototype(cx, &js_SlowArrayClass);
|
||||
if (!arrayProto || !AddLengthProperty(cx, arrayProto))
|
||||
return NULL;
|
||||
arrayProto->setArrayLength(cx, 0);
|
||||
|
||||
JSFunction *ctor = global->createConstructor(cx, js_Array, &ArrayClass,
|
||||
JSFunction *ctor = global->createConstructor(cx, js_Array, &js_ArrayClass,
|
||||
CLASS_ATOM(cx, Array), 1);
|
||||
if (!ctor)
|
||||
return NULL;
|
||||
@@ -3244,7 +3257,7 @@ NewArray(JSContext *cx, jsuint length, JSObject *proto)
|
||||
JS_ASSERT_IF(proto, proto->isArray());
|
||||
|
||||
gc::AllocKind kind = GuessObjectGCKind(length, true);
|
||||
JSObject *obj = detail::NewObject<WithProto::Class, false>(cx, &ArrayClass, proto, NULL, kind);
|
||||
JSObject *obj = detail::NewObject<WithProto::Class, false>(cx, &js_ArrayClass, proto, NULL, kind);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
@@ -3333,7 +3346,7 @@ JS_DEFINE_CALLINFO_3(extern, OBJECT, NewDenseUnallocatedArray, CONTEXT, UINT32,
|
||||
JSObject *
|
||||
NewSlowEmptyArray(JSContext *cx)
|
||||
{
|
||||
JSObject *obj = NewNonFunction<WithProto::Class>(cx, &SlowArrayClass, NULL, NULL);
|
||||
JSObject *obj = NewNonFunction<WithProto::Class>(cx, &js_SlowArrayClass, NULL, NULL);
|
||||
if (!obj || !AddLengthProperty(cx, obj))
|
||||
return NULL;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user