Bug 456165. Trace |new Date()|. r=brendan

This commit is contained in:
Boris Zbarsky 2008-10-06 20:28:22 -04:00
parent 26d5db2cc5
commit cab53dbee6
6 changed files with 69 additions and 6 deletions

View File

@ -141,6 +141,7 @@ BUILTIN1(Arguments, LO, P, JSObject*, JSContext*, 0, 0)
// Don't really need an argument here, but we don't support arg-less builtins
BUILTIN1(Date_now, LO, F, jsdouble, JSContext*, 0, 0)
BUILTIN2(FastNewDate, LO, LO, P, JSObject*, JSContext*, JSObject*, 0, 0)
// soft float
BUILTIN1(fneg, F, F, jsdouble, jsdouble, 1, 1)

View File

@ -52,6 +52,7 @@
#include "jsmath.h"
#include "jsnum.h"
#include "prmjtime.h"
#include "jsdate.h"
#include "jsscope.h"
#include "jsstr.h"
#include "jstracer.h"
@ -875,6 +876,37 @@ js_Date_now(JSContext*)
return PRMJ_Now() / PRMJ_USEC_PER_MSEC;
}
JS_STATIC_ASSERT(JSSLOT_PRIVATE == JSSLOT_UTC_TIME);
JS_STATIC_ASSERT(JSSLOT_UTC_TIME + 1 == JSSLOT_LOCAL_TIME);
JSObject* FASTCALL
js_FastNewDate(JSContext* cx, JSObject* proto)
{
JS_ASSERT(JS_ON_TRACE(cx));
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
if (!obj)
return NULL;
JSClass* clasp = &js_DateClass;
obj->classword = jsuword(clasp);
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
jsdouble* date = js_NewWeaklyRootedDouble(cx, 0.0);
if (!date)
return NULL;
*date = js_Date_now(cx);
obj->fslots[JSSLOT_UTC_TIME] = DOUBLE_TO_JSVAL(date);
obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);;
JS_ASSERT(!clasp->getObjectOps);
JS_ASSERT(proto->map->ops == &js_ObjectOps);
obj->map = js_HoldObjectMap(cx, proto->map);
obj->dslots = NULL;
return obj;
}
/* soft float */
jsdouble FASTCALL

View File

@ -478,9 +478,6 @@ msFromTime(jsdouble t)
* We use the first reseved slot to store UTC time, and the second for caching
* the local time. The initial value of the cache entry is NaN.
*/
const uint32 JSSLOT_UTC_TIME = JSSLOT_PRIVATE;
const uint32 JSSLOT_LOCAL_TIME = JSSLOT_PRIVATE + 1;
const uint32 DATE_RESERVED_SLOTS = 2;
JSClass js_DateClass = {
@ -2027,8 +2024,8 @@ date_constructor(JSContext *cx, JSObject* obj)
return date;
}
static JSBool
Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
JSBool
js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
jsdouble *date;
JSString *str;
@ -2099,7 +2096,7 @@ js_InitDateClass(JSContext *cx, JSObject *obj)
/* set static LocalTZA */
LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
proto = JS_InitClass(cx, obj, NULL, &js_DateClass, Date, MAXARGS,
proto = JS_InitClass(cx, obj, NULL, &js_DateClass, js_Date, MAXARGS,
NULL, date_methods, NULL, date_static_methods);
if (!proto)
return NULL;

View File

@ -54,6 +54,15 @@ js_InitDateClass(JSContext *cx, JSObject *obj);
extern JSBool
js_date_now(JSContext *cx, uintN argc, jsval *vp);
extern JSClass js_DateClass;
/*
* We use the first reseved slot to store UTC time, and the second for caching
* the local time. The initial value of the cache entry is NaN.
*/
#define JSSLOT_UTC_TIME JSSLOT_PRIVATE
#define JSSLOT_LOCAL_TIME (JSSLOT_PRIVATE + 1)
/*
* These functions provide a C interface to the date/time object
*/

View File

@ -4359,6 +4359,9 @@ js_Array(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
JSBool
js_Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JSBool
js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
bool
TraceRecorder::record_JSOP_NEW()
{
@ -4401,6 +4404,7 @@ TraceRecorder::record_JSOP_NEW()
{ (JSFastNative)js_Array, F_Array_2obj, "pC", "oo", FAIL_NULL },
{ (JSFastNative)js_Array, F_Array_3num, "pC", "ddd", FAIL_NULL },
{ (JSFastNative)js_Object, F_FastNewObject, "fC", "", FAIL_NULL },
{ (JSFastNative)js_Date, F_FastNewDate, "pC", "", FAIL_NULL },
};
for (uintN i = 0; i < JS_ARRAY_LENGTH(knownNatives); i++) {

View File

@ -2026,6 +2026,26 @@ this.__proto__.a = 3; for (var j = 0; j < 4; ++j) { [a]; }
testGlobalProtoAccess.expected = "ok";
test(testGlobalProtoAccess);
function testNewDate()
{
// Accessing global.Date for the first time will change the global shape,
// so do it before the loop starts; otherwise we have to loop an extra time
// to pick things up.
var start = new Date();
var time = new Date();
for (var j = 0; j < RUNLOOP; ++j) {
time = new Date();
}
return time > 0 && time >= start;
}
testNewDate.expected = true;
testNewDate.jitstats = {
recorderStarted: 1,
recorderAborted: 0,
traceTriggered: 1
};
test(testNewDate);
/* Keep these at the end so that we can see the summary after the trace-debug spew. */
print("\npassed:", passes.length && passes.join(","));
print("\nFAILED:", fails.length && fails.join(","));