зеркало из https://github.com/mozilla/gecko-dev.git
Merge tracemonkey to mozilla-central. a=blockers
This commit is contained in:
Коммит
ac5b3c36a5
|
@ -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
|
||||
});
|
Загрузка…
Ссылка в новой задаче