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:
Ed Morley
2011-09-03 03:21:25 +01:00
parent cb5431e87b
commit ee57bf1d01
75 changed files with 1010 additions and 740 deletions

View File

@@ -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;