Bug 652746 - Implement js::ArgumentsObject, js::NormalArgumentsObject, and js::StrictArgumentsObject. r=njn
This commit is contained in:
@@ -82,6 +82,7 @@
|
||||
#include "jstypes.h"
|
||||
#include "jsstdint.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsarray.h"
|
||||
#include "jsatom.h"
|
||||
@@ -105,12 +106,15 @@
|
||||
#include "jsvector.h"
|
||||
#include "jswrapper.h"
|
||||
|
||||
#include "vm/ArgumentsObject.h"
|
||||
|
||||
#include "jsatominlines.h"
|
||||
#include "jscntxtinlines.h"
|
||||
#include "jsinterpinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
#include "jsstrinlines.h"
|
||||
|
||||
#include "vm/ArgumentsObject-inl.h"
|
||||
#include "vm/Stack-inl.h"
|
||||
|
||||
using namespace js;
|
||||
@@ -217,9 +221,12 @@ js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj->isArguments() && !obj->isArgsLengthOverridden()) {
|
||||
*lengthp = obj->getArgsInitialLength();
|
||||
return true;
|
||||
if (obj->isArguments()) {
|
||||
ArgumentsObject *argsobj = obj->asArguments();
|
||||
if (!argsobj->hasOverriddenLength()) {
|
||||
*lengthp = argsobj->initialLength();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
AutoValueRooter tvr(cx);
|
||||
@@ -263,7 +270,7 @@ BigIndexToId(JSContext *cx, JSObject *obj, jsuint index, JSBool createAtom,
|
||||
*/
|
||||
if (!createAtom &&
|
||||
((clasp = obj->getClass()) == &js_SlowArrayClass ||
|
||||
clasp == &js_ArgumentsClass ||
|
||||
obj->isArguments() ||
|
||||
clasp == &js_ObjectClass)) {
|
||||
atom = js_GetExistingStringAtom(cx, start, JS_ARRAY_END(buf) - start);
|
||||
if (!atom) {
|
||||
@@ -349,15 +356,17 @@ GetElement(JSContext *cx, JSObject *obj, jsdouble index, JSBool *hole, Value *vp
|
||||
*hole = JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (obj->isArguments() &&
|
||||
index < obj->getArgsInitialLength() &&
|
||||
!(*vp = obj->getArgsElement(uint32(index))).isMagic(JS_ARGS_HOLE)) {
|
||||
*hole = JS_FALSE;
|
||||
StackFrame *fp = (StackFrame *)obj->getPrivate();
|
||||
if (fp != JS_ARGUMENTS_OBJECT_ON_TRACE) {
|
||||
if (fp)
|
||||
*vp = fp->canonicalActualArg(index);
|
||||
return JS_TRUE;
|
||||
if (obj->isArguments()) {
|
||||
ArgumentsObject *argsobj = obj->asArguments();
|
||||
if (index < argsobj->initialLength() &&
|
||||
!(*vp = argsobj->element(uint32(index))).isMagic(JS_ARGS_HOLE)) {
|
||||
*hole = JS_FALSE;
|
||||
StackFrame *fp = reinterpret_cast<StackFrame *>(argsobj->getPrivate());
|
||||
if (fp != JS_ARGUMENTS_OBJECT_ON_TRACE) {
|
||||
if (fp)
|
||||
*vp = fp->canonicalActualArg(index);
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,17 +399,28 @@ namespace js {
|
||||
|
||||
struct STATIC_SKIP_INFERENCE CopyNonHoleArgsTo
|
||||
{
|
||||
CopyNonHoleArgsTo(JSObject *aobj, Value *dst) : aobj(aobj), dst(dst) {}
|
||||
JSObject *aobj;
|
||||
CopyNonHoleArgsTo(ArgumentsObject *argsobj, Value *dst) : argsobj(argsobj), dst(dst) {}
|
||||
ArgumentsObject *argsobj;
|
||||
Value *dst;
|
||||
bool operator()(uintN argi, Value *src) {
|
||||
if (aobj->getArgsElement(argi).isMagic(JS_ARGS_HOLE))
|
||||
if (argsobj->element(argi).isMagic(JS_ARGS_HOLE))
|
||||
return false;
|
||||
*dst++ = *src;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static bool
|
||||
GetElementsSlow(JSContext *cx, JSObject *aobj, uint32 length, Value *vp)
|
||||
{
|
||||
for (uint32 i = 0; i < length; i++) {
|
||||
if (!aobj->getProperty(cx, INT_TO_JSID(jsint(i)), &vp[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GetElements(JSContext *cx, JSObject *aobj, jsuint length, Value *vp)
|
||||
{
|
||||
@@ -411,38 +431,38 @@ GetElements(JSContext *cx, JSObject *aobj, jsuint length, Value *vp)
|
||||
Value *srcend = srcbeg + length;
|
||||
for (Value *dst = vp, *src = srcbeg; src < srcend; ++dst, ++src)
|
||||
*dst = src->isMagic(JS_ARRAY_HOLE) ? UndefinedValue() : *src;
|
||||
} else if (aobj->isArguments() && !aobj->isArgsLengthOverridden() &&
|
||||
!js_PrototypeHasIndexedProperties(cx, aobj)) {
|
||||
/*
|
||||
* If the argsobj is for an active call, then the elements are the
|
||||
* live args on the stack. Otherwise, the elements are the args that
|
||||
* were copied into the argsobj by PutActivationObjects when the
|
||||
* function returned. In both cases, it is necessary to fall off the
|
||||
* fast path for deleted properties (MagicValue(JS_ARGS_HOLE) since
|
||||
* this requires general-purpose property lookup.
|
||||
*/
|
||||
if (StackFrame *fp = (StackFrame *) aobj->getPrivate()) {
|
||||
JS_ASSERT(fp->numActualArgs() <= JS_ARGS_LENGTH_MAX);
|
||||
if (!fp->forEachCanonicalActualArg(CopyNonHoleArgsTo(aobj, vp)))
|
||||
goto found_deleted_prop;
|
||||
} else {
|
||||
Value *srcbeg = aobj->getArgsElements();
|
||||
Value *srcend = srcbeg + length;
|
||||
for (Value *dst = vp, *src = srcbeg; src < srcend; ++dst, ++src) {
|
||||
if (src->isMagic(JS_ARGS_HOLE))
|
||||
goto found_deleted_prop;
|
||||
*dst = *src;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aobj->isArguments()) {
|
||||
ArgumentsObject *argsobj = aobj->asArguments();
|
||||
if (!argsobj->hasOverriddenLength() && !js_PrototypeHasIndexedProperties(cx, argsobj)) {
|
||||
/*
|
||||
* If the argsobj is for an active call, then the elements are the
|
||||
* live args on the stack. Otherwise, the elements are the args that
|
||||
* were copied into the argsobj by PutActivationObjects when the
|
||||
* function returned. In both cases, it is necessary to fall off the
|
||||
* fast path for deleted properties (MagicValue(JS_ARGS_HOLE) since
|
||||
* this requires general-purpose property lookup.
|
||||
*/
|
||||
if (StackFrame *fp = reinterpret_cast<StackFrame *>(argsobj->getPrivate())) {
|
||||
JS_ASSERT(fp->numActualArgs() <= JS_ARGS_LENGTH_MAX);
|
||||
if (fp->forEachCanonicalActualArg(CopyNonHoleArgsTo(argsobj, vp)))
|
||||
return true;
|
||||
} else {
|
||||
Value *srcbeg = argsobj->elements();
|
||||
Value *srcend = srcbeg + length;
|
||||
for (Value *dst = vp, *src = srcbeg; src < srcend; ++dst, ++src) {
|
||||
if (src->isMagic(JS_ARGS_HOLE))
|
||||
return GetElementsSlow(cx, argsobj, length, vp);
|
||||
*dst = *src;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
found_deleted_prop:
|
||||
for (uintN i = 0; i < length; i++) {
|
||||
if (!aobj->getProperty(cx, INT_TO_JSID(jsint(i)), &vp[i]))
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return GetElementsSlow(cx, aobj, length, vp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user