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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user