Merge tracemonkey to mozilla-central. a=blockers

This commit is contained in:
Robert Sayre 2010-11-26 12:50:29 -08:00
Родитель b038095ce2 5f3d75fcf2
Коммит ac5b3c36a5
37 изменённых файлов: 450 добавлений и 188 удалений

Просмотреть файл

@ -201,6 +201,11 @@ int ARMAssembler::genInt(int reg, ARMWord imm, bool positive)
return 1;
}
#ifdef __GNUC__
// If the result of this function isn't used, the caller should probably be
// using movImm.
__attribute__((warn_unused_result))
#endif
ARMWord ARMAssembler::getImm(ARMWord imm, int tmpReg, bool invert)
{
ARMWord tmp;

Просмотреть файл

@ -934,7 +934,9 @@ namespace JSC {
JmpDst label()
{
return JmpDst(m_buffer.size());
JmpDst label(m_buffer.size());
js::JaegerSpew(js::JSpew_Insns, IPFX "#label ((%d))\n", MAYBE_PAD, label.m_offset);
return label;
}
JmpDst align(int alignment)
@ -1055,10 +1057,11 @@ namespace JSC {
// Like repatchLoadPtrToLEA, this is specialized for our purpose.
ARMWord* insn = reinterpret_cast<ARMWord*>(from);
if ((*insn & 0x0ff00f00) == 0x05900000)
return;
ASSERT((*insn & 0xf00ff0ff) == 0x02800000);
return; // Valid ldr instruction
ASSERT((*insn & 0x0ff00000) == 0x02800000); // Valid add instruction
ASSERT((*insn & 0x00000f00) == 0x00000000); // Simple-to-handle immediates (no rotate)
*insn = (*insn & 0x0ff00f00) | 0x05900000;
*insn = (*insn & 0xf00ff0ff) | 0x05900000;
ExecutableAllocator::cacheFlush(insn, sizeof(ARMWord));
}
@ -1092,7 +1095,7 @@ namespace JSC {
ISPFX "##relinkJump ((%p)) jumps to ((%p))\n",
from, to);
patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to);
patchPointerInternal(reinterpret_cast<intptr_t>(from), to);
}
static bool canRelinkJump(void* from, void* to)
@ -1115,14 +1118,14 @@ namespace JSC {
ISPFX "##relinkCall ((%p)) jumps to ((%p))\n",
from, to);
patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to);
patchPointerInternal(reinterpret_cast<intptr_t>(from), to);
}
// Address operations
static void* getRelocatedAddress(void* code, JmpSrc jump)
{
return reinterpret_cast<void*>(reinterpret_cast<ARMWord*>(code) + jump.m_offset / sizeof(ARMWord) + 1);
return reinterpret_cast<void*>(reinterpret_cast<ARMWord*>(code) + jump.m_offset / sizeof(ARMWord));
}
static void* getRelocatedAddress(void* code, JmpDst label)
@ -1134,7 +1137,7 @@ namespace JSC {
static int getDifferenceBetweenLabels(JmpDst from, JmpSrc to)
{
return (to.m_offset + sizeof(ARMWord)) - from.m_offset;
return to.m_offset - from.m_offset;
}
static int getDifferenceBetweenLabels(JmpDst from, JmpDst to)

Просмотреть файл

@ -277,6 +277,7 @@ public:
DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
{
ASSERT(address.base != ARMRegisters::S0);
DataLabel32 dataLabel(this);
m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
m_assembler.dtr_ur(true, dest, address.base, ARMRegisters::S0);
@ -285,6 +286,8 @@ public:
DataLabel32 load64WithAddressOffsetPatch(Address address, RegisterID hi, RegisterID lo)
{
ASSERT(address.base != ARMRegisters::S0);
ASSERT(lo != ARMRegisters::S0);
DataLabel32 dataLabel(this);
m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, address.base);
@ -316,6 +319,7 @@ public:
DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
{
ASSERT(address.base != ARMRegisters::S0);
DataLabel32 dataLabel(this);
m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
m_assembler.dtr_ur(false, src, address.base, ARMRegisters::S0);
@ -324,6 +328,9 @@ public:
DataLabel32 store64WithAddressOffsetPatch(RegisterID hi, RegisterID lo, Address address)
{
ASSERT(hi != ARMRegisters::S0);
ASSERT(lo != ARMRegisters::S0);
ASSERT(address.base != ARMRegisters::S0);
DataLabel32 dataLabel(this);
m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, address.base);
@ -334,9 +341,14 @@ public:
DataLabel32 store64WithAddressOffsetPatch(Imm32 hi, RegisterID lo, Address address)
{
ASSERT(lo != ARMRegisters::S0);
ASSERT(lo != ARMRegisters::S1);
ASSERT(lo != address.base);
ASSERT(address.base != ARMRegisters::S0);
ASSERT(address.base != ARMRegisters::S1);
DataLabel32 dataLabel(this);
m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
m_assembler.getImm(hi.m_value, ARMRegisters::S1);
m_assembler.moveImm(hi.m_value, ARMRegisters::S1);
m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, address.base);
m_assembler.dtr_u(false, lo, ARMRegisters::S0, 0);
m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 4);

Просмотреть файл

@ -116,13 +116,6 @@
* all dtoa conversions in single-threaded executions with 8-byte
* pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte
* pointers, PRIVATE_MEM >= 7112 appears adequate.
* #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK
* #defined automatically on IEEE systems. On such systems,
* when INFNAN_CHECK is #defined, strtod checks
* for Infinity and NaN (case insensitively). On some systems
* (e.g., some HP systems), it may be necessary to #define NAN_WORD0
* appropriately -- to the most significant word of a quiet NaN.
* (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
* #define MULTIPLE_THREADS if the system offers preemptively scheduled
* multiple threads. In this case, you must provide (or suitably
* #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed
@ -212,15 +205,6 @@ extern void *MALLOC(size_t);
#define IEEE_Arith
#endif
#ifdef IEEE_Arith
#ifndef NO_INFNAN_CHECK
#undef INFNAN_CHECK
#define INFNAN_CHECK
#endif
#else
#undef INFNAN_CHECK
#endif
#include "errno.h"
#ifdef Bad_float_h
@ -1490,39 +1474,6 @@ static CONST double tinytens[] = { 1e-16, 1e-32 };
#endif
#endif
#ifdef INFNAN_CHECK
#ifndef NAN_WORD0
#define NAN_WORD0 0x7ff80000
#endif
#ifndef NAN_WORD1
#define NAN_WORD1 0
#endif
static int
match
#ifdef KR_headers
(sp, t) char **sp, *t;
#else
(CONST char **sp, CONST char *t)
#endif
{
int c, d;
CONST char *s = *sp;
while((d = *t++)) {
if ((c = *++s) >= 'A' && c <= 'Z')
c += 'a' - 'A';
if (c != d)
return 0;
}
*sp = s + 1;
return 1;
}
#endif /* INFNAN_CHECK */
static double
_strtod
#ifdef KR_headers
@ -1683,29 +1634,6 @@ _strtod
}
if (!nd) {
if (!nz && !nz0) {
#ifdef INFNAN_CHECK
/* Check for Nan and Infinity */
switch(c) {
case 'i':
case 'I':
if (match(&s,"nf")) {
--s;
if (!match(&s,"inity"))
++s;
word0(rv) = 0x7ff00000;
word1(rv) = 0;
goto ret;
}
break;
case 'n':
case 'N':
if (match(&s, "an")) {
word0(rv) = NAN_WORD0;
word1(rv) = NAN_WORD1;
goto ret;
}
}
#endif /* INFNAN_CHECK */
ret0:
s = s00;
sign = 0;

Просмотреть файл

@ -0,0 +1,11 @@
function f() { return 2; }
function g(o) {
with (o) {
var f = function() { return 4; }
}
return f();
}
assertEq(g({}), 4);

Просмотреть файл

@ -0,0 +1,21 @@
function f() {
var n;
var k;
for (var i = 0; i < 2*RUNLOOP; ++i) {
n = null;
k = n++;
if (k) { }
}
return [k, n];
}
var [a, b] = f();
assertEq(a, 0);
assertEq(b, 1);
checkStats({
recorderStarted: 1,
recorderAborted: 0,
traceCompleted: 1,
traceTriggered: 1
});

Просмотреть файл

@ -0,0 +1,27 @@
var a, b;
function f(str) {
var n;
var k;
for (var i = 0; i < 2*RUNLOOP; ++i) {
n = str;
k = n++;
if (k) { }
}
return [k, n];
}
[a, b] = f("10");
assertEq(a, 10);
assertEq(b, 11);
[a, b] = f("5");
assertEq(a, 5);
assertEq(b, 6);
checkStats({
recorderStarted: 1,
recorderAborted: 0,
traceCompleted: 1,
traceTriggered: 2
});

Просмотреть файл

@ -0,0 +1,22 @@
function f() {
var n;
var k;
for (var i = 0; i < 2*RUNLOOP; ++i) {
n = undefined;
k = n++;
if (k) { }
}
return [k, n];
}
var [a, b] = f();
assertEq(isNaN(a), true);
assertEq(isNaN(b), true);
checkStats({
recorderStarted: 1,
recorderAborted: 0,
traceCompleted: 1,
traceTriggered: 1
});

Просмотреть файл

@ -343,3 +343,4 @@ MSG_DEF(JSMSG_SC_BAD_SERIALIZED_DATA, 260, 1, JSEXN_INTERNALERR, "bad serialized
MSG_DEF(JSMSG_SC_UNSUPPORTED_TYPE, 261, 0, JSEXN_TYPEERR, "unsupported type for structured data")
MSG_DEF(JSMSG_SC_RECURSION, 262, 0, JSEXN_INTERNALERR, "recursive object")
MSG_DEF(JSMSG_CANT_WRAP_XML_OBJECT, 263, 0, JSEXN_TYPEERR, "can't wrap XML objects")
MSG_DEF(JSMSG_BAD_CLONE_VERSION, 264, 0, JSEXN_ERR, "unsupported structured clone version")

Просмотреть файл

@ -5448,8 +5448,12 @@ JS_FinishJSONParse(JSContext *cx, JSONParser *jp, jsval reviver)
}
JS_PUBLIC_API(JSBool)
JS_ReadStructuredClone(JSContext *cx, const uint64 *buf, size_t nbytes, jsval *vp)
JS_ReadStructuredClone(JSContext *cx, const uint64 *buf, size_t nbytes, uint32 version, jsval *vp)
{
if (version > JS_STRUCTURED_CLONE_VERSION) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CLONE_VERSION);
return false;
}
return ReadStructuredClone(cx, buf, nbytes, Valueify(vp));
}

Просмотреть файл

@ -3025,7 +3025,7 @@ JS_FinishJSONParse(JSContext *cx, JSONParser *jp, jsval reviver);
#define JS_STRUCTURED_CLONE_VERSION 1
JS_PUBLIC_API(JSBool)
JS_ReadStructuredClone(JSContext *cx, const uint64 *data, size_t nbytes, jsval *vp);
JS_ReadStructuredClone(JSContext *cx, const uint64 *data, size_t nbytes, uint32 version, jsval *vp);
/* Note: On success, the caller is responsible for calling js_free(*datap). */
JS_PUBLIC_API(JSBool)
@ -3040,9 +3040,12 @@ class JSAutoStructuredCloneBuffer {
JSContext *cx;
uint64 *data_;
size_t nbytes_;
uint32 version_;
public:
explicit JSAutoStructuredCloneBuffer(JSContext *cx) : cx(cx), data_(NULL), nbytes_(0) {}
explicit JSAutoStructuredCloneBuffer(JSContext *cx)
: cx(cx), data_(NULL), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION) {}
~JSAutoStructuredCloneBuffer() { clear(); }
uint64 *data() const { return data_; }
@ -3060,10 +3063,11 @@ class JSAutoStructuredCloneBuffer {
* Adopt some memory. It will be automatically freed by the destructor.
* data must have been allocated using JS_malloc.
*/
void adopt(uint64 *data, size_t nbytes) {
void adopt(uint64 *data, size_t nbytes, uint32 version=JS_STRUCTURED_CLONE_VERSION) {
clear();
data_ = data;
nbytes_ = nbytes;
version_ = version;
}
/*
@ -3079,7 +3083,7 @@ class JSAutoStructuredCloneBuffer {
bool read(jsval *vp) const {
JS_ASSERT(data_);
return !!JS_ReadStructuredClone(cx, data_, nbytes_, vp);
return !!JS_ReadStructuredClone(cx, data_, nbytes_, version_, vp);
}
bool write(jsval v) {

Просмотреть файл

@ -2048,6 +2048,7 @@ js_ArrayCompPush(JSContext *cx, JSObject *obj, const Value &vp)
return ArrayCompPushImpl(cx, obj, vp);
}
#ifdef JS_TRACER
JSBool JS_FASTCALL
js_ArrayCompPush_tn(JSContext *cx, JSObject *obj, ValueArgType v)
{
@ -2060,6 +2061,7 @@ js_ArrayCompPush_tn(JSContext *cx, JSObject *obj, ValueArgType v)
}
JS_DEFINE_CALLINFO_3(extern, BOOL_FAIL, js_ArrayCompPush_tn, CONTEXT, OBJECT,
VALUE, 0, nanojit::ACCSET_STORE_ANY)
#endif
static JSBool
array_push(JSContext *cx, uintN argc, Value *vp)
@ -2220,9 +2222,9 @@ array_unshift(JSContext *cx, uintN argc, Value *vp)
return JS_FALSE;
newlen += argc;
if (!js_SetLengthProperty(cx, obj, newlen))
return JS_FALSE;
}
if (!js_SetLengthProperty(cx, obj, newlen))
return JS_FALSE;
/* Follow Perl by returning the new array length. */
vp->setNumber(newlen);

Просмотреть файл

@ -1523,10 +1523,10 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
| (!shape->writable() ? JSPD_READONLY : 0)
| (!shape->configurable() ? JSPD_PERMANENT : 0);
pd->spare = 0;
if (shape->getter() == js_GetCallArg) {
if (shape->getter() == GetCallArg) {
pd->slot = shape->shortid;
pd->flags |= JSPD_ARGUMENT;
} else if (shape->getter() == js_GetCallVar) {
} else if (shape->getter() == GetCallVar) {
pd->slot = shape->shortid;
pd->flags |= JSPD_VARIABLE;
} else {

Просмотреть файл

@ -2273,7 +2273,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
* JSOP_DEFFUN could introduce a shadowing definition, so if it
* is present, we can't optimize to JSOP_GETGLOBAL.
*/
if (cg->hasDefFun())
if (cg->mightAliasLocals())
return JS_TRUE;
switch (op) {

Просмотреть файл

@ -252,9 +252,12 @@ struct JSStmtInfo {
#define TCF_COMPILE_FOR_EVAL 0x2000000
/*
* The function contains a JSOP_DEFFUN bytecode.
* The function has broken or incorrect def-use information, and it cannot
* safely optimize free variables to global names. This can happen because
* of a named function statement not at the top level (emitting a DEFFUN),
* or a variable declaration inside a "with".
*/
#define TCF_FUN_HAS_DEFFUN 0x4000000
#define TCF_FUN_MIGHT_ALIAS_LOCALS 0x4000000
/*
* Flags to check for return; vs. return expr; in a function.
@ -272,7 +275,7 @@ struct JSStmtInfo {
TCF_FUN_USES_OWN_NAME | \
TCF_HAS_SHARPS | \
TCF_FUN_CALLS_EVAL | \
TCF_FUN_HAS_DEFFUN | \
TCF_FUN_MIGHT_ALIAS_LOCALS | \
TCF_FUN_MUTATES_PARAMETER | \
TCF_STRICT_MODE_CODE)
@ -403,12 +406,12 @@ struct JSTreeContext { /* tree context for semantic checks */
return flags & TCF_FUN_CALLS_EVAL;
}
void noteHasDefFun() {
flags |= TCF_FUN_HAS_DEFFUN;
void noteMightAliasLocals() {
flags |= TCF_FUN_MIGHT_ALIAS_LOCALS;
}
bool hasDefFun() const {
return flags & TCF_FUN_HAS_DEFFUN;
bool mightAliasLocals() const {
return flags & TCF_FUN_MIGHT_ALIAS_LOCALS;
}
void noteParameterMutation() {

Просмотреть файл

@ -1036,7 +1036,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
JSProtoKey protoKey = GetExceptionProtoKey(i);
jsid id = ATOM_TO_JSID(cx->runtime->atomState.classAtoms[protoKey]);
JSFunction *fun = js_DefineFunction(cx, obj, id, Exception, 3, JSFUN_CONSTRUCTOR);
JSFunction *fun = js_DefineFunction(cx, obj, id, Exception, 1, JSFUN_CONSTRUCTOR);
if (!fun)
return NULL;
roots[2] = OBJECT_TO_JSVAL(FUN_OBJECT(fun));

Просмотреть файл

@ -1232,6 +1232,8 @@ CallPropertyOp(JSContext *cx, JSObject *obj, jsid id, Value *vp,
return true;
}
namespace js {
static JSBool
GetCallArguments(JSContext *cx, JSObject *obj, jsid id, Value *vp)
{
@ -1245,7 +1247,7 @@ SetCallArguments(JSContext *cx, JSObject *obj, jsid id, Value *vp)
}
JSBool
js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, Value *vp)
GetCallArg(JSContext *cx, JSObject *obj, jsid id, Value *vp)
{
return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG);
}
@ -1269,13 +1271,13 @@ SetFlatUpvar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
}
JSBool
js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
GetCallVar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
{
return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR);
}
JSBool
js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, Value *vp)
GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, Value *vp)
{
if (!CallPropertyOp(cx, obj, id, vp, JSCPK_VAR))
return false;
@ -1289,6 +1291,8 @@ SetCallVar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, true);
}
} // namespace js
#if JS_TRACER
JSBool JS_FASTCALL
js_SetCallArg(JSContext *cx, JSObject *obj, jsid slotid, ValueArgType arg)
@ -3070,7 +3074,7 @@ JSFunction::lastArg() const
{
const Shape *shape = lastVar();
if (u.i.nvars != 0) {
while (shape->previous() && shape->getter() != js_GetCallArg)
while (shape->previous() && shape->getter() != GetCallArg)
shape = shape->previous();
}
return shape;
@ -3107,7 +3111,7 @@ JSFunction::addLocal(JSContext *cx, JSAtom *atom, JSLocalKind kind)
JS_ASSERT(u.i.nupvars == 0);
indexp = &nargs;
getter = js_GetCallArg;
getter = GetCallArg;
setter = SetCallArg;
slot += nargs;
} else if (kind == JSLOCAL_UPVAR) {
@ -3119,7 +3123,7 @@ JSFunction::addLocal(JSContext *cx, JSAtom *atom, JSLocalKind kind)
JS_ASSERT(u.i.nupvars == 0);
indexp = &u.i.nvars;
getter = js_GetCallVar;
getter = GetCallVar;
setter = SetCallVar;
if (kind == JSLOCAL_CONST)
attrs |= JSPROP_READONLY;
@ -3168,7 +3172,7 @@ JSFunction::addLocal(JSContext *cx, JSAtom *atom, JSLocalKind kind)
}
if (findArgInsertionPoint) {
while (parent->parent && parent->getter() != js_GetCallArg) {
while (parent->parent && parent->getter() != GetCallArg) {
++parent->slot;
JS_ASSERT(parent->slot == parent->slotSpan);
++parent->slotSpan;
@ -3197,7 +3201,7 @@ JSFunction::lookupLocal(JSContext *cx, JSAtom *atom, uintN *indexp)
if (shape) {
JSLocalKind localKind;
if (shape->getter() == js_GetCallArg)
if (shape->getter() == GetCallArg)
localKind = JSLOCAL_ARG;
else if (shape->getter() == GetFlatUpvar)
localKind = JSLOCAL_UPVAR;
@ -3241,7 +3245,7 @@ JSFunction::getLocalNameArray(JSContext *cx, JSArenaPool *pool)
uintN index = uint16(shape.shortid);
jsuword constFlag = 0;
if (shape.getter() == js_GetCallArg) {
if (shape.getter() == GetCallArg) {
JS_ASSERT(index < nargs);
} else if (shape.getter() == GetFlatUpvar) {
JS_ASSERT(index < u.i.nupvars);
@ -3258,7 +3262,7 @@ JSFunction::getLocalNameArray(JSContext *cx, JSArenaPool *pool)
atom = JSID_TO_ATOM(shape.id);
} else {
JS_ASSERT(JSID_IS_INT(shape.id));
JS_ASSERT(shape.getter() == js_GetCallArg);
JS_ASSERT(shape.getter() == GetCallArg);
atom = NULL;
}

Просмотреть файл

@ -579,11 +579,20 @@ extern JSBool JS_FASTCALL
js_PutCallObjectOnTrace(JSContext *cx, JSObject *scopeChain, uint32 nargs,
js::Value *argv, uint32 nvars, js::Value *slots);
extern JSBool
js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
namespace js {
extern JSBool
js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
GetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSBool
GetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
/*
* Slower version of js_GetCallVar used when call_resolve detects an attempt to
* leak an optimized closure via indirect or debugger eval.
*/
extern JSBool
GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSBool
SetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
@ -591,12 +600,7 @@ SetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSBool
SetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
/*
* Slower version of js_GetCallVar used when call_resolve detects an attempt to
* leak an optimized closure via indirect or debugger eval.
*/
extern JSBool
js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
} // namespace js
extern JSBool
js_GetArgsValue(JSContext *cx, JSStackFrame *fp, js::Value *vp);

Просмотреть файл

@ -4486,7 +4486,9 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &valu
*propp = (JSProperty *) shape;
return true;
#ifdef JS_TRACER
error: // TRACE_2 jumps here on error.
#endif
return false;
}

Просмотреть файл

@ -3143,7 +3143,7 @@ Parser::functionDef(JSAtom *funAtom, FunctionType type, uintN lambda)
* sub-statement.
*/
op = JSOP_DEFFUN;
outertc->noteHasDefFun();
outertc->noteMightAliasLocals();
}
funbox->kids = funtc.functionList;
@ -3608,6 +3608,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
if (stmt && stmt->type == STMT_WITH) {
data->fresh = false;
pn->pn_dflags |= PND_DEOPTIMIZED;
tc->noteMightAliasLocals();
return true;
}

Просмотреть файл

@ -885,7 +885,7 @@ InitRegExpClassCompile(JSContext *cx, JSObject *obj)
JSObject *
js_InitRegExpClass(JSContext *cx, JSObject *obj)
{
JSObject *proto = js_InitClass(cx, obj, NULL, &js_RegExpClass, regexp_construct, 1,
JSObject *proto = js_InitClass(cx, obj, NULL, &js_RegExpClass, regexp_construct, 2,
NULL, regexp_methods, regexp_static_props, NULL);
if (!proto)
return NULL;

Просмотреть файл

@ -203,26 +203,21 @@ Shape::maybeHash(JSContext *cx)
# define LIVE_SCOPE_METER(cx,expr) /* nothing */
#endif
static inline bool
InitField(JSContext *cx, EmptyShape *JSRuntime:: *field, Class *clasp, uint32 shape)
{
if (EmptyShape *emptyShape = EmptyShape::create(cx, clasp)) {
cx->runtime->*field = emptyShape;
JS_ASSERT(emptyShape->shape == shape);
return true;
}
return false;
}
/* static */
bool
Shape::initRuntimeState(JSContext *cx)
{
JSRuntime *rt = cx->runtime;
#define SHAPE(Name) rt->empty##Name##Shape
#define CLASP(Name) &js_##Name##Class
#define INIT_EMPTY_SHAPE(Name,NAME) \
INIT_EMPTY_SHAPE_WITH_CLASS(Name, NAME, CLASP(Name))
#define INIT_EMPTY_SHAPE_WITH_CLASS(Name,NAME,clasp) \
JS_BEGIN_MACRO \
SHAPE(Name) = EmptyShape::create(cx, clasp); \
if (!SHAPE(Name)) \
return false; \
JS_ASSERT(SHAPE(Name)->shape == Shape::EMPTY_##NAME##_SHAPE); \
JS_END_MACRO
/*
* NewArguments allocates dslots to have enough room for the argc of the
* particular arguments object being created.
@ -233,30 +228,37 @@ Shape::initRuntimeState(JSContext *cx)
* arguments objects. This helps ensure that any arguments object needing
* its own mutable scope (with unique shape) is a rare event.
*/
INIT_EMPTY_SHAPE(Arguments, ARGUMENTS);
if (!InitField(cx, &JSRuntime::emptyArgumentsShape, &js_ArgumentsClass,
Shape::EMPTY_ARGUMENTS_SHAPE)) {
return false;
}
INIT_EMPTY_SHAPE(Block, BLOCK);
if (!InitField(cx, &JSRuntime::emptyBlockShape, &js_BlockClass, Shape::EMPTY_BLOCK_SHAPE))
return false;
/*
* Initialize the shared scope for all empty Call objects so gets for args
* and vars do not force the creation of a mutable scope for the particular
* call object being accessed.
*/
INIT_EMPTY_SHAPE(Call, CALL);
if (!InitField(cx, &JSRuntime::emptyCallShape, &js_CallClass, Shape::EMPTY_CALL_SHAPE))
return false;
/* A DeclEnv object holds the name binding for a named function expression. */
INIT_EMPTY_SHAPE(DeclEnv, DECL_ENV);
if (!InitField(cx, &JSRuntime::emptyDeclEnvShape, &js_DeclEnvClass,
Shape::EMPTY_DECL_ENV_SHAPE)) {
return false;
}
/* Non-escaping native enumerator objects share this empty scope. */
INIT_EMPTY_SHAPE_WITH_CLASS(Enumerator, ENUMERATOR, &js_IteratorClass);
if (!InitField(cx, &JSRuntime::emptyEnumeratorShape, &js_IteratorClass,
Shape::EMPTY_ENUMERATOR_SHAPE)) {
return false;
}
/* Same drill for With objects. */
INIT_EMPTY_SHAPE(With, WITH);
#undef SHAPE
#undef CLASP
#undef INIT_EMPTY_SHAPE
#undef INIT_EMPTY_SHAPE_WITH_CLASS
if (!InitField(cx, &JSRuntime::emptyWithShape, &js_WithClass, Shape::EMPTY_WITH_SHAPE))
return false;
return true;
}
@ -973,9 +975,9 @@ JSObject::putProperty(JSContext *cx, jsid id,
shape->rawGetter = getter;
shape->rawSetter = setter;
shape->attrs = attrs;
shape->attrs = uint8(attrs);
shape->flags = flags | Shape::IN_DICTIONARY;
shape->shortid = shortid;
shape->shortid = int16(shortid);
/*
* We are done updating shape and lastProp. Now we may need to update

Просмотреть файл

@ -8053,12 +8053,12 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, Value*& vp,
vp = NULL;
JSStackFrame* cfp = (JSStackFrame*) obj->getPrivate();
if (cfp) {
if (shape->getterOp() == js_GetCallArg) {
if (shape->getterOp() == GetCallArg) {
JS_ASSERT(slot < cfp->numFormalArgs());
vp = &cfp->formalArg(slot);
nr.v = *vp;
} else if (shape->getterOp() == js_GetCallVar ||
shape->getterOp() == js_GetCallVarChecked) {
} else if (shape->getterOp() == GetCallVar ||
shape->getterOp() == GetCallVarChecked) {
JS_ASSERT(slot < cfp->numSlots());
vp = &cfp->slots()[slot];
nr.v = *vp;
@ -8102,11 +8102,11 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, Value*& vp,
// object loses its frame it never regains one, on trace we will also
// have a null private in the Call object. So all we need to do is
// write the value to the Call object's slot.
if (shape->getterOp() == js_GetCallArg) {
if (shape->getterOp() == GetCallArg) {
JS_ASSERT(slot < ArgClosureTraits::slot_count(obj));
slot += ArgClosureTraits::slot_offset(obj);
} else if (shape->getterOp() == js_GetCallVar ||
shape->getterOp() == js_GetCallVarChecked) {
} else if (shape->getterOp() == GetCallVar ||
shape->getterOp() == GetCallVarChecked) {
JS_ASSERT(slot < VarClosureTraits::slot_count(obj));
slot += VarClosureTraits::slot_offset(obj);
} else {
@ -8139,10 +8139,10 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, Value*& vp,
cx_ins
};
const CallInfo* ci;
if (shape->getterOp() == js_GetCallArg) {
if (shape->getterOp() == GetCallArg) {
ci = &GetClosureArg_ci;
} else if (shape->getterOp() == js_GetCallVar ||
shape->getterOp() == js_GetCallVarChecked) {
} else if (shape->getterOp() == GetCallVar ||
shape->getterOp() == GetCallVarChecked) {
ci = &GetClosureVar_ci;
} else {
RETURN_STOP("dynamic property of Call object");
@ -8683,16 +8683,20 @@ TraceRecorder::inc(const Value &v, LIns*& v_ins, jsint incr, bool pre)
* Do an increment operation without storing anything to the stack.
*/
JS_REQUIRES_STACK RecordingStatus
TraceRecorder::incHelper(const Value &v, LIns* v_ins, LIns*& v_after, jsint incr)
TraceRecorder::incHelper(const Value &v, LIns*& v_ins, LIns*& v_after, jsint incr)
{
// FIXME: Bug 606071 on making this work for objects.
if (!v.isPrimitive())
RETURN_STOP("can inc primitives only");
// We need to modify |v_ins| the same way relational() modifies
// its RHS and LHS.
if (v.isUndefined()) {
v_after = w.immd(js_NaN);
v_ins = w.immd(js_NaN);
} else if (v.isNull()) {
v_after = w.immd(incr);
v_ins = w.immd(0.0);
} else {
if (v.isBoolean()) {
v_ins = w.i2d(v_ins);
@ -12904,13 +12908,7 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex)
// This happens moderately often, eg. close to 10% of the time in
// SunSpider, and for some benchmarks it's close to 100%.
Address dslotAddr = DSlotsAddress(elemp_ins);
LIns* isHole_ins = w.name(w.eqi(
#if JS_BITS_PER_WORD == 32
w.ldiValueTag(dslotAddr),
#else
w.q2i(w.rshuqN(w.ldq(dslotAddr), JSVAL_TAG_SHIFT)),
#endif
w.nameImmui(JSVAL_TAG_MAGIC)),
LIns* isHole_ins = w.name(is_boxed_magic(dslotAddr, JS_ARRAY_HOLE),
"isHole");
w.pauseAddingCSEValues();
if (MaybeBranch mbr1 = w.jf(isHole_ins)) {
@ -14779,10 +14777,44 @@ TraceRecorder::record_JSOP_IN()
if (lval.isInt32()) {
if (!js_Int32ToId(cx, lval.toInt32(), &id))
RETURN_ERROR_A("OOM converting left operand of JSOP_IN to string");
LIns* num_ins;
CHECK_STATUS_A(makeNumberInt32(get(&lval), &num_ins));
LIns* args[] = { num_ins, obj_ins, cx_ins };
x = w.call(&js_HasNamedPropertyInt32_ci, args);
if (obj->isDenseArray()) {
// Fast path for dense arrays
VMSideExit* branchExit = snapshot(BRANCH_EXIT);
guardDenseArray(obj_ins, branchExit);
// If our proto has indexed props, all bets are off on our
// "false" values and out-of-bounds access. Just guard on
// that.
CHECK_STATUS_A(guardPrototypeHasNoIndexedProperties(obj, obj_ins,
snapshot(MISMATCH_EXIT)));
LIns* idx_ins;
CHECK_STATUS_A(makeNumberInt32(get(&lval), &idx_ins));
idx_ins = w.name(idx_ins, "index");
LIns* capacity_ins = w.ldiDenseArrayCapacity(obj_ins);
LIns* inRange = w.ltui(idx_ins, capacity_ins);
if (jsuint(lval.toInt32()) < obj->getDenseArrayCapacity()) {
guard(true, inRange, branchExit);
LIns *elem_ins = w.getDslotAddress(obj_ins, idx_ins);
// Need to make sure we don't have a hole
LIns *is_hole_ins =
is_boxed_magic(DSlotsAddress(elem_ins), JS_ARRAY_HOLE);
// Set x to true (index in our array) if is_hole_ins == 0
x = w.eqi0(is_hole_ins);
} else {
guard(false, inRange, branchExit);
x = w.nameImmi(0);
}
} else {
LIns* num_ins;
CHECK_STATUS_A(makeNumberInt32(get(&lval), &num_ins));
LIns* args[] = { num_ins, obj_ins, cx_ins };
x = w.call(&js_HasNamedPropertyInt32_ci, args);
}
} else if (lval.isString()) {
if (!js_ValueToStringId(cx, lval, &id))
RETURN_ERROR_A("left operand of JSOP_IN didn't convert to a string-id");

Просмотреть файл

@ -1294,7 +1294,7 @@ class TraceRecorder
JS_REQUIRES_STACK RecordingStatus inc(Value& v, jsint incr, bool pre = true);
JS_REQUIRES_STACK RecordingStatus inc(const Value &v, nanojit::LIns*& v_ins, jsint incr,
bool pre = true);
JS_REQUIRES_STACK RecordingStatus incHelper(const Value &v, nanojit::LIns* v_ins,
JS_REQUIRES_STACK RecordingStatus incHelper(const Value &v, nanojit::LIns*& v_ins,
nanojit::LIns*& v_after, jsint incr);
JS_REQUIRES_STACK AbortableRecordingStatus incProp(jsint incr, bool pre = true);
JS_REQUIRES_STACK RecordingStatus incElem(jsint incr, bool pre = true);

Просмотреть файл

@ -1641,12 +1641,12 @@ mjit::Compiler::jsop_stricteq(JSOp op)
return;
}
RegisterID data = frame.tempRegForData(test);
frame.pinReg(data);
RegisterID result = frame.allocReg(Registers::SingleByteRegs);
frame.unpinReg(data);
RegisterID data = frame.copyDataIntoReg(test);
RegisterID result = data;
if (!(Registers::maskReg(data) & Registers::SingleByteRegs))
result = frame.allocReg(Registers::SingleByteRegs);
/* Is the other side boolean? */
Jump notBoolean;
if (!test->isTypeKnown())
notBoolean = frame.testBoolean(Assembler::NotEqual, test);
@ -1662,6 +1662,9 @@ mjit::Compiler::jsop_stricteq(JSOp op)
done.linkTo(masm.label(), &masm);
}
if (data != result)
frame.freeReg(data);
frame.popn(2);
frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, result);
return;

Просмотреть файл

@ -1329,9 +1329,9 @@ class ScopeNameCompiler : public PICStubCompiler
CallObjPropKind kind;
const Shape *shape = getprop.shape;
if (shape->getterOp() == js_GetCallArg) {
if (shape->getterOp() == GetCallArg) {
kind = ARG;
} else if (shape->getterOp() == js_GetCallVar) {
} else if (shape->getterOp() == GetCallVar) {
kind = VAR;
} else {
return disable("unhandled callobj sprop getter");

Просмотреть файл

@ -2081,8 +2081,8 @@ Disassemble(JSContext *cx, uintN argc, jsval *vp)
bool lines = false, recursive = false;
while (argc > 0 && JSVAL_IS_STRING(argv[0])) {
JSString *str = JSVAL_TO_STRING(argv[0]);
lines |= JS_MatchStringAndAscii(str, "-l");
recursive |= JS_MatchStringAndAscii(str, "-r");
lines |= !!JS_MatchStringAndAscii(str, "-l");
recursive |= !!JS_MatchStringAndAscii(str, "-r");
if (!lines && !recursive)
break;
argv++, argc--;
@ -4198,8 +4198,10 @@ Deserialize(JSContext *cx, uintN argc, jsval *vp)
return false;
}
if (!JS_ReadStructuredClone(cx, (uint64 *) array->data, array->byteLength, &v))
if (!JS_ReadStructuredClone(cx, (uint64 *) array->data, array->byteLength,
JS_STRUCTURED_CLONE_VERSION, &v)) {
return false;
}
JS_SET_RVAL(cx, vp, v);
return true;
}

Просмотреть файл

@ -294,7 +294,7 @@ class Event
}
bool deserializeData(JSContext *cx, jsval *vp) {
return !!JS_ReadStructuredClone(cx, data, nbytes, vp);
return !!JS_ReadStructuredClone(cx, data, nbytes, JS_STRUCTURED_CLONE_VERSION, vp);
}
virtual Result process(JSContext *cx) = 0;

Просмотреть файл

@ -2,3 +2,4 @@ url-prefix ../../jsreftest.html?test=ecma_5/Array/
script sort-01.js
script toString-01.js
script toLocaleString-01.js
script unshift-01.js

Просмотреть файл

@ -0,0 +1,41 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 614070;
var summary = 'Array.prototype.unshift without args';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var a = {};
a.length = 4294967296;
assertEq([].unshift.call(a), 0);
assertEq(a.length, 0);
function testGetSet(len, expected) {
var newlen;
var a = { get length() { return len; }, set length(v) { newlen = v; } };
var res = [].unshift.call(a);
assertEq(res, expected);
assertEq(newlen, expected);
}
testGetSet(0, 0);
testGetSet(10, 10);
testGetSet("1", 1);
testGetSet(null, 0);
testGetSet(4294967297, 1);
testGetSet(-5, 4294967291);
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("All tests passed!");

Просмотреть файл

@ -1,5 +1,6 @@
url-prefix ../../jsreftest.html?test=ecma_5/Global/
script parseInt-01.js
script parseFloat-01.js
script eval-01.js
script eval-02.js
script eval-inside-with-is-direct.js

Просмотреть файл

@ -0,0 +1,24 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
//-----------------------------------------------------------------------------
var BUGNUMBER = 613492;
var summary = "ES5 15.1.2.3 parseFloat(string)";
print(BUGNUMBER + ": " + summary);
assertEq(parseFloat("Infinity"), Infinity);
assertEq(parseFloat("+Infinity"), Infinity);
assertEq(parseFloat("-Infinity"), -Infinity);
assertEq(parseFloat("inf"), NaN);
assertEq(parseFloat("Inf"), NaN);
assertEq(parseFloat("infinity"), NaN);
assertEq(parseFloat("nan"), NaN);
assertEq(parseFloat("NaN"), NaN);
if (typeof reportCompare === "function")
reportCompare(true, true);
print("All tests passed!");

Просмотреть файл

@ -0,0 +1,21 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var BUGNUMBER = 614603;
var summary = "RegExp.length";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
assertEq(RegExp.length, 2);
assertEq(/a/.constructor.length, 2);
if (typeof reportCompare === "function")
reportCompare(true, true);
print("All tests passed!");

Просмотреть файл

@ -1,2 +1,3 @@
url-prefix ../../jsreftest.html?test=ecma_5/RegExp/
script 15.10.5-01.js
script 15.10.7.5-01.js

Просмотреть файл

@ -58,8 +58,6 @@
* To do this, just change the two LENGTH constants below -
*/
//-----------------------------------------------------------------------------
var LENGTH_RHINO = 1;
var LENGTH_SPIDERMONKEY = 3;
var UBound = 0;
var BUGNUMBER = 123002;
var summary = 'Testing Error.length';
@ -72,10 +70,7 @@ var expect= '';
var expectedvalues = [];
/*
* Are we in Rhino or SpiderMonkey?
*/
var LENGTH_EXPECTED = inRhino()? LENGTH_RHINO : LENGTH_SPIDERMONKEY;
var LENGTH_EXPECTED = 1;
/*
* The various NativeError objects; see ECMA-262 Edition 3, Section 15.11.6

Просмотреть файл

@ -0,0 +1,54 @@
// Give us enough room to work with some holes too
const array_size = RUNLOOP + 20;
function testArrayIn()
{
var arr = new Array(array_size);
var i;
for (i = 0; i < array_size; ++i) {
arr[i] = i;
}
// Sanity check here
checkStats({
traceCompleted: 1,
traceTriggered: 1,
sideExitIntoInterpreter: 1
});
delete arr[RUNLOOP + 5];
delete arr[RUNLOOP + 10];
var ret = [];
for (i = 0; i < array_size; ++i) {
ret.push(i in arr);
}
checkStats({
traceCompleted: 2,
traceTriggered: 2,
sideExitIntoInterpreter: 2
});
var ret2;
for (i = 0; i < RUNLOOP; ++i) {
ret2 = array_size in arr;
}
checkStats({
traceCompleted: 3,
traceTriggered: 3,
sideExitIntoInterpreter: 3
});
return [ret, ret2];
}
var [ret, ret2] = testArrayIn();
assertEq(ret2, false);
for (var i = 0; i < array_size; ++i) {
assertEq(ret[i], i != RUNLOOP + 5 && i != RUNLOOP + 10);
}

Просмотреть файл

@ -0,0 +1,31 @@
function testArrayInWithIndexedProto()
{
Array.prototype[0] = "Got me";
var zeroPresent, zeroPresent2;
// Need to go to 2*RUNLOOP because in the failure mode this is
// testing we have various side-exits in there due to interp and
// tracer not agreeing that confuse the issue and cause us to not
// hit the bad case within RUNLOOP iterations.
for (var j = 0; j < 2*RUNLOOP; ++j) {
zeroPresent = 0 in [];
}
var arr = [1, 2];
delete arr[0];
for (var j = 0; j < 2*RUNLOOP; ++j) {
zeroPresent2 = 0 in arr;
}
return [zeroPresent, zeroPresent2];
}
var [ret, ret2] = testArrayInWithIndexedProto();
assertEq(ret, true);
assertEq(ret2, true);
checkStats({
traceCompleted: 0,
traceTriggered: 0,
sideExitIntoInterpreter: 0,
recorderStarted: 2,
recorderAborted: 2
});