Kind of an Array initialiser tour-de-force for bug 452878:

1. Split FastNewArray from FastNewObject built-in for greater speed/specialization and further splitting into Array_1str, etc.
2. Add Array_1str, Array_2obj, and Array_3num builtins for benchmarked new Array(...) constructions.
3. Export ARRAY_SET_DENSE_LENGTH and ARRAY_GROWBY via jsarray.h to jstracer.cpp.
4. Tweaked SetArrayElement to make common/best case code be the predicted/prefetched path.
5. js_MakeArraySlow now preserves the pre-slow length in JSSLOT_ARRAY_COUTN as a jsval-tagged int if possible -- this will help the tracer avoid aborting on dense arrays that turned slow but not sparse by addition of a named property.
6. Export js_fun_apply and js_Object from their respective .cpp files, in these cases just to jstracer.cpp via local prototypes (no .h files involved).
7. More INS_CONSTPTR and INS_CONST macrology for better names in trace debug spew.
8. Fix TraceRecorder::test_property_cache to avoid aborting on JSOP_SETNAME that creates a new global, by setting it to undefined so it can be lazily imported. This helps 3d-raytrace.js, which has an unintended global loop control variable in a function.
9. JSTraceableNative loses its premature-deadwood tclasp member (my bad).
10. TraceRecorder::record_JSOP_NEW() handles 'new Object' now along with the 'new Array' variations. I also cut down the copy-paste code from JSOP_CALL's record method to mostly what is needed now.
11. Add KNOWN_NATIVE_DECL macro for concise prototype of library-private js_* native functions, and alphabetized the lists (too long for any other order to be winning).
12. Big honking special case for foo.apply(obj, [str]), which we can generalize as needed. Helps string-tagcloud.js. What's cool is how tracing allows us to rewrite this to foo(str) with this set to obj, eliminating the Function.prototype.apply. This requires some rewriting in JSOP_ENDINIT's record method.
This commit is contained in:
Brendan Eich
2008-09-01 01:24:58 -07:00
parent 962cb095df
commit 9f541e1e76
7 changed files with 305 additions and 184 deletions

View File

@@ -446,12 +446,42 @@ js_CallTree(InterpState* state, Fragment* f)
JS_STATIC_ASSERT(JSSLOT_PRIVATE == JSSLOT_ARRAY_LENGTH);
JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH + 1 == JSSLOT_ARRAY_COUNT);
JSObject* FASTCALL
js_FastNewArray(JSContext* cx, JSObject* proto)
{
JS_ASSERT(OBJ_IS_ARRAY(cx, proto));
JS_ASSERT(cx->executingTrace);
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
if (!obj)
return NULL;
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
JSClass* clasp = &js_ArrayClass;
obj->fslots[JSSLOT_CLASS] = PRIVATE_TO_JSVAL(clasp);
obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
obj->fslots[JSSLOT_ARRAY_COUNT] = 0;
for (unsigned i = JSSLOT_ARRAY_COUNT + 1; i != JS_INITIAL_NSLOTS; ++i)
obj->fslots[i] = JSVAL_VOID;
JSObjectOps* ops = clasp->getObjectOps(cx, clasp);
obj->map = ops->newObjectMap(cx, 1, ops, clasp, obj);
if (!obj->map)
return NULL;
obj->dslots = NULL;
return obj;
}
JSObject* FASTCALL
js_FastNewObject(JSContext* cx, JSObject* ctor)
{
JS_ASSERT(HAS_FUNCTION_CLASS(ctor));
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, ctor);
JSClass* clasp = FUN_INTERPRETED(fun) ? &js_ObjectClass : fun->u.n.clasp;
JS_ASSERT(clasp != &js_ArrayClass);
JS_ASSERT(cx->executingTrace);
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
@@ -474,24 +504,10 @@ js_FastNewObject(JSContext* cx, JSObject* ctor)
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
obj->fslots[JSSLOT_PARENT] = ctor->fslots[JSSLOT_PARENT];
obj->fslots[JSSLOT_CLASS] = PRIVATE_TO_JSVAL(clasp);
unsigned i = JSSLOT_PRIVATE;
if (clasp == &js_ArrayClass) {
obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
obj->fslots[JSSLOT_ARRAY_COUNT] = 0;
i += 2;
}
for (; i != JS_INITIAL_NSLOTS; ++i)
for (unsigned i = JSSLOT_PRIVATE; i != JS_INITIAL_NSLOTS; ++i)
obj->fslots[i] = JSVAL_VOID;
if (clasp == &js_ArrayClass) {
JSObjectOps* ops = clasp->getObjectOps(cx, clasp);
obj->map = ops->newObjectMap(cx, 1, ops, clasp, obj);
if (!obj->map)
return NULL;
} else {
obj->map = js_HoldObjectMap(cx, proto->map);
}
obj->map = js_HoldObjectMap(cx, proto->map);
obj->dslots = NULL;
return obj;
}
@@ -637,15 +653,59 @@ js_ObjectToString(JSContext* cx, JSObject* obj)
}
JSObject* FASTCALL
js_Array_1int(JSContext* cx, JSObject* ctor, jsint i)
js_Array_1int(JSContext* cx, JSObject* proto, jsint i)
{
JS_ASSERT(cx->executingTrace);
JSObject* obj = js_FastNewObject(cx, ctor);
JSObject* obj = js_FastNewArray(cx, proto);
if (obj)
obj->fslots[JSSLOT_ARRAY_LENGTH] = i;
return obj;
}
#define ARRAY_CTOR_GUTS(exact_len, newslots_code) \
JS_ASSERT(cx->executingTrace); \
JSObject* obj = js_FastNewArray(cx, proto); \
if (obj) { \
uint32 len = ARRAY_GROWBY; \
jsval* newslots = (jsval*) JS_malloc(cx, sizeof (jsval) * (len + 1)); \
if (newslots) { \
obj->dslots = newslots + 1; \
ARRAY_SET_DENSE_LENGTH(obj, len); \
{newslots_code} \
while (++newslots < obj->dslots + len) \
*newslots = JSVAL_HOLE; \
obj->fslots[JSSLOT_ARRAY_LENGTH] = (exact_len); \
return obj; \
} \
} \
return NULL;
JSObject* FASTCALL
js_Array_1str(JSContext* cx, JSObject* proto, JSString *str)
{
ARRAY_CTOR_GUTS(1, *++newslots = STRING_TO_JSVAL(str);)
}
JSObject* FASTCALL
js_Array_2obj(JSContext* cx, JSObject* proto, JSObject *obj1, JSObject* obj2)
{
ARRAY_CTOR_GUTS(2,
*++newslots = OBJECT_TO_JSVAL(obj1);
*++newslots = OBJECT_TO_JSVAL(obj2);)
}
JSObject* FASTCALL
js_Array_3num(JSContext* cx, JSObject* proto, jsdouble n1, jsdouble n2, jsdouble n3)
{
ARRAY_CTOR_GUTS(3,
if (!js_NewDoubleInRootedValue(cx, n1, ++newslots))
return NULL;
if (!js_NewDoubleInRootedValue(cx, n2, ++newslots))
return NULL;
if (!js_NewDoubleInRootedValue(cx, n3, ++newslots))
return NULL;)
}
#define LO ARGSIZE_LO
#define F ARGSIZE_F
#define Q ARGSIZE_Q