mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 877216. Add CallArgs-like structs for use in DOM specialized getters/setters/methods. r=waldo
This commit is contained in:
parent
7392630c95
commit
cb38fb46c2
@ -5104,7 +5104,7 @@ class CGGenericMethod(CGAbstractBindingMethod):
|
|||||||
return CGIndenter(CGGeneric(
|
return CGIndenter(CGGeneric(
|
||||||
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
|
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
|
||||||
"MOZ_ASSERT(info->type == JSJitInfo::Method);\n"
|
"MOZ_ASSERT(info->type == JSJitInfo::Method);\n"
|
||||||
"JSJitMethodOp method = (JSJitMethodOp)info->op;\n"
|
"JSJitMethodOp method = info->method;\n"
|
||||||
"return method(cx, obj, self, argc, vp);"))
|
"return method(cx, obj, self, argc, vp);"))
|
||||||
|
|
||||||
class CGSpecializedMethod(CGAbstractStaticMethod):
|
class CGSpecializedMethod(CGAbstractStaticMethod):
|
||||||
@ -5240,7 +5240,7 @@ class CGGenericGetter(CGAbstractBindingMethod):
|
|||||||
return CGIndenter(CGGeneric(
|
return CGIndenter(CGGeneric(
|
||||||
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
|
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
|
||||||
"MOZ_ASSERT(info->type == JSJitInfo::Getter);\n"
|
"MOZ_ASSERT(info->type == JSJitInfo::Getter);\n"
|
||||||
"JSJitPropertyOp getter = info->op;\n"
|
"JSJitGetterOp getter = info->getter;\n"
|
||||||
"return getter(cx, obj, self, vp);"))
|
"return getter(cx, obj, self, vp);"))
|
||||||
|
|
||||||
class CGSpecializedGetter(CGAbstractStaticMethod):
|
class CGSpecializedGetter(CGAbstractStaticMethod):
|
||||||
@ -5324,7 +5324,7 @@ class CGGenericSetter(CGAbstractBindingMethod):
|
|||||||
"JS::Value* argv = JS_ARGV(cx, vp);\n"
|
"JS::Value* argv = JS_ARGV(cx, vp);\n"
|
||||||
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
|
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
|
||||||
"MOZ_ASSERT(info->type == JSJitInfo::Setter);\n"
|
"MOZ_ASSERT(info->type == JSJitInfo::Setter);\n"
|
||||||
"JSJitPropertyOp setter = info->op;\n"
|
"JSJitSetterOp setter = info->setter;\n"
|
||||||
"if (!setter(cx, obj, self, argv)) {\n"
|
"if (!setter(cx, obj, self, argv)) {\n"
|
||||||
" return false;\n"
|
" return false;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
@ -5431,7 +5431,7 @@ class CGMemberJITInfo(CGThing):
|
|||||||
"")
|
"")
|
||||||
return ("\n"
|
return ("\n"
|
||||||
"static const JSJitInfo %s = {\n"
|
"static const JSJitInfo %s = {\n"
|
||||||
" %s,\n"
|
" { %s },\n"
|
||||||
" %s,\n"
|
" %s,\n"
|
||||||
" %s,\n"
|
" %s,\n"
|
||||||
" JSJitInfo::%s,\n"
|
" JSJitInfo::%s,\n"
|
||||||
@ -5445,7 +5445,9 @@ class CGMemberJITInfo(CGThing):
|
|||||||
def define(self):
|
def define(self):
|
||||||
if self.member.isAttr():
|
if self.member.isAttr():
|
||||||
getterinfo = ("%s_getterinfo" % self.member.identifier.name)
|
getterinfo = ("%s_getterinfo" % self.member.identifier.name)
|
||||||
getter = ("(JSJitPropertyOp)get_%s" % self.member.identifier.name)
|
# We need the cast here because JSJitGetterOp has a "void* self"
|
||||||
|
# while we have the right type.
|
||||||
|
getter = ("(JSJitGetterOp)get_%s" % self.member.identifier.name)
|
||||||
getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
|
getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
|
||||||
getterconst = self.member.getExtendedAttribute("Constant")
|
getterconst = self.member.getExtendedAttribute("Constant")
|
||||||
getterpure = getterconst or self.member.getExtendedAttribute("Pure")
|
getterpure = getterconst or self.member.getExtendedAttribute("Pure")
|
||||||
@ -5457,7 +5459,9 @@ class CGMemberJITInfo(CGThing):
|
|||||||
[self.member.type])
|
[self.member.type])
|
||||||
if not self.member.readonly or self.member.getExtendedAttribute("PutForwards") is not None:
|
if not self.member.readonly or self.member.getExtendedAttribute("PutForwards") is not None:
|
||||||
setterinfo = ("%s_setterinfo" % self.member.identifier.name)
|
setterinfo = ("%s_setterinfo" % self.member.identifier.name)
|
||||||
setter = ("(JSJitPropertyOp)set_%s" % self.member.identifier.name)
|
# Actually a JSJitSetterOp, but JSJitGetterOp is first in the
|
||||||
|
# union.
|
||||||
|
setter = ("(JSJitGetterOp)set_%s" % self.member.identifier.name)
|
||||||
# Setters are always fallible, since they have to do a typed unwrap.
|
# Setters are always fallible, since they have to do a typed unwrap.
|
||||||
result += self.defineJitInfo(setterinfo, setter, "Setter",
|
result += self.defineJitInfo(setterinfo, setter, "Setter",
|
||||||
False, False, False,
|
False, False, False,
|
||||||
@ -5466,8 +5470,8 @@ class CGMemberJITInfo(CGThing):
|
|||||||
if self.member.isMethod():
|
if self.member.isMethod():
|
||||||
methodinfo = ("%s_methodinfo" % self.member.identifier.name)
|
methodinfo = ("%s_methodinfo" % self.member.identifier.name)
|
||||||
name = CppKeywords.checkMethodName(self.member.identifier.name)
|
name = CppKeywords.checkMethodName(self.member.identifier.name)
|
||||||
# Actually a JSJitMethodOp, but JSJitPropertyOp by struct definition.
|
# Actually a JSJitMethodOp, but JSJitGetterOp is first in the union.
|
||||||
method = ("(JSJitPropertyOp)%s" % name)
|
method = ("(JSJitGetterOp)%s" % name)
|
||||||
|
|
||||||
# Methods are infallible if they are infallible, have no arguments
|
# Methods are infallible if they are infallible, have no arguments
|
||||||
# to unwrap, and have a return type that's infallible to wrap up for
|
# to unwrap, and have a return type that's infallible to wrap up for
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/TypeTraits.h"
|
||||||
|
|
||||||
#include "jstypes.h"
|
#include "jstypes.h"
|
||||||
|
|
||||||
@ -92,30 +93,50 @@ namespace JS {
|
|||||||
* public interface are meant to be used by embedders! See inline comments to
|
* public interface are meant to be used by embedders! See inline comments to
|
||||||
* for details.
|
* for details.
|
||||||
*/
|
*/
|
||||||
class MOZ_STACK_CLASS CallReceiver
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
enum UsedRval { IncludeUsedRval, NoUsedRval };
|
||||||
|
|
||||||
|
template<UsedRval WantUsedRval>
|
||||||
|
class MOZ_STACK_CLASS UsedRvalBase;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class MOZ_STACK_CLASS UsedRvalBase<IncludeUsedRval>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
#ifdef DEBUG
|
|
||||||
mutable bool usedRval_;
|
mutable bool usedRval_;
|
||||||
void setUsedRval() const { usedRval_ = true; }
|
void setUsedRval() const { usedRval_ = true; }
|
||||||
void clearUsedRval() const { usedRval_ = false; }
|
void clearUsedRval() const { usedRval_ = false; }
|
||||||
#else
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class MOZ_STACK_CLASS UsedRvalBase<NoUsedRval>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
void setUsedRval() const {}
|
void setUsedRval() const {}
|
||||||
void clearUsedRval() const {}
|
void clearUsedRval() const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<UsedRval WantUsedRval>
|
||||||
|
class MOZ_STACK_CLASS CallReceiverBase : public UsedRvalBase<
|
||||||
|
#ifdef DEBUG
|
||||||
|
WantUsedRval
|
||||||
|
#else
|
||||||
|
NoUsedRval
|
||||||
#endif
|
#endif
|
||||||
|
>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
Value *argv_;
|
Value *argv_;
|
||||||
|
|
||||||
friend CallReceiver CallReceiverFromVp(Value *vp);
|
|
||||||
friend CallReceiver CallReceiverFromArgv(Value *argv);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*
|
/*
|
||||||
* Returns the function being called, as an object. Must not be called
|
* Returns the function being called, as an object. Must not be called
|
||||||
* after rval() has been used!
|
* after rval() has been used!
|
||||||
*/
|
*/
|
||||||
JSObject &callee() const {
|
JSObject &callee() const {
|
||||||
MOZ_ASSERT(!usedRval_);
|
MOZ_ASSERT(!this->usedRval_);
|
||||||
return argv_[-2].toObject();
|
return argv_[-2].toObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +145,7 @@ class MOZ_STACK_CLASS CallReceiver
|
|||||||
* rval() has been used!
|
* rval() has been used!
|
||||||
*/
|
*/
|
||||||
HandleValue calleev() const {
|
HandleValue calleev() const {
|
||||||
MOZ_ASSERT(!usedRval_);
|
MOZ_ASSERT(!this->usedRval_);
|
||||||
return HandleValue::fromMarkedLocation(&argv_[-2]);
|
return HandleValue::fromMarkedLocation(&argv_[-2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +181,7 @@ class MOZ_STACK_CLASS CallReceiver
|
|||||||
* fails.
|
* fails.
|
||||||
*/
|
*/
|
||||||
MutableHandleValue rval() const {
|
MutableHandleValue rval() const {
|
||||||
setUsedRval();
|
this->setUsedRval();
|
||||||
return MutableHandleValue::fromMarkedLocation(&argv_[-2]);
|
return MutableHandleValue::fromMarkedLocation(&argv_[-2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +192,7 @@ class MOZ_STACK_CLASS CallReceiver
|
|||||||
Value *base() const { return argv_ - 2; }
|
Value *base() const { return argv_ - 2; }
|
||||||
|
|
||||||
Value *spAfterCall() const {
|
Value *spAfterCall() const {
|
||||||
setUsedRval();
|
this->setUsedRval();
|
||||||
return argv_ - 1;
|
return argv_ - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +202,7 @@ class MOZ_STACK_CLASS CallReceiver
|
|||||||
// it. You probably don't want to use these!
|
// it. You probably don't want to use these!
|
||||||
|
|
||||||
void setCallee(Value aCalleev) const {
|
void setCallee(Value aCalleev) const {
|
||||||
clearUsedRval();
|
this->clearUsedRval();
|
||||||
argv_[-2] = aCalleev;
|
argv_[-2] = aCalleev;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,6 +215,15 @@ class MOZ_STACK_CLASS CallReceiver
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
class MOZ_STACK_CLASS CallReceiver : public detail::CallReceiverBase<detail::IncludeUsedRval>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
friend CallReceiver CallReceiverFromVp(Value *vp);
|
||||||
|
friend CallReceiver CallReceiverFromArgv(Value *argv);
|
||||||
|
};
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE CallReceiver
|
MOZ_ALWAYS_INLINE CallReceiver
|
||||||
CallReceiverFromArgv(Value *argv)
|
CallReceiverFromArgv(Value *argv)
|
||||||
{
|
{
|
||||||
@ -233,11 +263,63 @@ CallReceiverFromVp(Value *vp)
|
|||||||
* public interface are meant to be used by embedders! See inline comments to
|
* public interface are meant to be used by embedders! See inline comments to
|
||||||
* for details.
|
* for details.
|
||||||
*/
|
*/
|
||||||
class MOZ_STACK_CLASS CallArgs : public CallReceiver
|
namespace detail {
|
||||||
|
|
||||||
|
template<UsedRval WantUsedRval>
|
||||||
|
class MOZ_STACK_CLASS CallArgsBase :
|
||||||
|
public mozilla::Conditional<WantUsedRval == detail::IncludeUsedRval,
|
||||||
|
CallReceiver,
|
||||||
|
CallReceiverBase<NoUsedRval> >::Type
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
unsigned argc_;
|
unsigned argc_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Returns the number of arguments. */
|
||||||
|
unsigned length() const { return argc_; }
|
||||||
|
|
||||||
|
/* Returns the i-th zero-indexed argument. */
|
||||||
|
Value &operator[](unsigned i) const {
|
||||||
|
MOZ_ASSERT(i < argc_);
|
||||||
|
return this->argv_[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns a mutable handle for the i-th zero-indexed argument. */
|
||||||
|
MutableHandleValue handleAt(unsigned i) const {
|
||||||
|
MOZ_ASSERT(i < argc_);
|
||||||
|
return MutableHandleValue::fromMarkedLocation(&this->argv_[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the i-th zero-indexed argument, or |undefined| if there's no
|
||||||
|
* such argument.
|
||||||
|
*/
|
||||||
|
Value get(unsigned i) const {
|
||||||
|
return i < length() ? this->argv_[i] : UndefinedValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true if the i-th zero-indexed argument is present and is not
|
||||||
|
* |undefined|.
|
||||||
|
*/
|
||||||
|
bool hasDefined(unsigned i) const {
|
||||||
|
return i < argc_ && !this->argv_[i].isUndefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// These methods are publicly exposed, but we're less sure of the interface
|
||||||
|
// here than we'd like (because they're hackish and drop assertions). Try
|
||||||
|
// to avoid using these if you can.
|
||||||
|
|
||||||
|
Value *array() const { return this->argv_; }
|
||||||
|
Value *end() const { return this->argv_ + argc_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
class MOZ_STACK_CLASS CallArgs : public detail::CallArgsBase<detail::IncludeUsedRval>
|
||||||
|
{
|
||||||
|
private:
|
||||||
friend CallArgs CallArgsFromVp(unsigned argc, Value *vp);
|
friend CallArgs CallArgsFromVp(unsigned argc, Value *vp);
|
||||||
friend CallArgs CallArgsFromSp(unsigned argc, Value *sp);
|
friend CallArgs CallArgsFromSp(unsigned argc, Value *sp);
|
||||||
|
|
||||||
@ -249,45 +331,6 @@ class MOZ_STACK_CLASS CallArgs : public CallReceiver
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
/* Returns the number of arguments. */
|
|
||||||
unsigned length() const { return argc_; }
|
|
||||||
|
|
||||||
/* Returns the i-th zero-indexed argument. */
|
|
||||||
Value &operator[](unsigned i) const {
|
|
||||||
MOZ_ASSERT(i < argc_);
|
|
||||||
return argv_[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns a mutable handle for the i-th zero-indexed argument. */
|
|
||||||
MutableHandleValue handleAt(unsigned i) const {
|
|
||||||
MOZ_ASSERT(i < argc_);
|
|
||||||
return MutableHandleValue::fromMarkedLocation(&argv_[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the i-th zero-indexed argument, or |undefined| if there's no
|
|
||||||
* such argument.
|
|
||||||
*/
|
|
||||||
Value get(unsigned i) const {
|
|
||||||
return i < length() ? argv_[i] : UndefinedValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns true if the i-th zero-indexed argument is present and is not
|
|
||||||
* |undefined|.
|
|
||||||
*/
|
|
||||||
bool hasDefined(unsigned i) const {
|
|
||||||
return i < argc_ && !argv_[i].isUndefined();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
// These methods are publicly exposed, but we're less sure of the interface
|
|
||||||
// here than we'd like (because they're hackish and drop assertions). Try
|
|
||||||
// to avoid using these if you can.
|
|
||||||
|
|
||||||
Value *array() const { return argv_; }
|
|
||||||
Value *end() const { return argv_ + argc_; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE CallArgs
|
MOZ_ALWAYS_INLINE CallArgs
|
||||||
|
@ -1453,7 +1453,7 @@ CodeGenerator::visitCallDOMNative(LCallDOMNative *call)
|
|||||||
masm.passABIArg(argPrivate);
|
masm.passABIArg(argPrivate);
|
||||||
masm.passABIArg(argArgc);
|
masm.passABIArg(argArgc);
|
||||||
masm.passABIArg(argVp);
|
masm.passABIArg(argVp);
|
||||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, target->jitInfo()->op));
|
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, target->jitInfo()->method));
|
||||||
|
|
||||||
if (target->jitInfo()->isInfallible) {
|
if (target->jitInfo()->isInfallible) {
|
||||||
masm.loadValue(Address(StackPointer, IonDOMMethodExitFrameLayout::offsetOfResult()),
|
masm.loadValue(Address(StackPointer, IonDOMMethodExitFrameLayout::offsetOfResult()),
|
||||||
|
@ -7791,7 +7791,8 @@ IonBuilder::jsop_setprop(HandlePropertyName name)
|
|||||||
// properties.
|
// properties.
|
||||||
RootedFunction setter(cx, commonSetter);
|
RootedFunction setter(cx, commonSetter);
|
||||||
if (isDOM && TestShouldDOMCall(cx, objTypes, setter, JSJitInfo::Setter)) {
|
if (isDOM && TestShouldDOMCall(cx, objTypes, setter, JSJitInfo::Setter)) {
|
||||||
MSetDOMProperty *set = MSetDOMProperty::New(setter->jitInfo()->op, obj, value);
|
JS_ASSERT(setter->jitInfo()->type == JSJitInfo::Setter);
|
||||||
|
MSetDOMProperty *set = MSetDOMProperty::New(setter->jitInfo()->setter, obj, value);
|
||||||
if (!set)
|
if (!set)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -6586,9 +6586,9 @@ class MSetDOMProperty
|
|||||||
: public MAryInstruction<2>,
|
: public MAryInstruction<2>,
|
||||||
public MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >
|
public MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >
|
||||||
{
|
{
|
||||||
const JSJitPropertyOp func_;
|
const JSJitSetterOp func_;
|
||||||
|
|
||||||
MSetDOMProperty(const JSJitPropertyOp func, MDefinition *obj, MDefinition *val)
|
MSetDOMProperty(const JSJitSetterOp func, MDefinition *obj, MDefinition *val)
|
||||||
: func_(func)
|
: func_(func)
|
||||||
{
|
{
|
||||||
setOperand(0, obj);
|
setOperand(0, obj);
|
||||||
@ -6598,12 +6598,12 @@ class MSetDOMProperty
|
|||||||
public:
|
public:
|
||||||
INSTRUCTION_HEADER(SetDOMProperty)
|
INSTRUCTION_HEADER(SetDOMProperty)
|
||||||
|
|
||||||
static MSetDOMProperty *New(const JSJitPropertyOp func, MDefinition *obj, MDefinition *val)
|
static MSetDOMProperty *New(const JSJitSetterOp func, MDefinition *obj, MDefinition *val)
|
||||||
{
|
{
|
||||||
return new MSetDOMProperty(func, obj, val);
|
return new MSetDOMProperty(func, obj, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
const JSJitPropertyOp fun() {
|
const JSJitSetterOp fun() {
|
||||||
return func_;
|
return func_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6631,6 +6631,7 @@ class MGetDOMProperty
|
|||||||
: info_(jitinfo)
|
: info_(jitinfo)
|
||||||
{
|
{
|
||||||
JS_ASSERT(jitinfo);
|
JS_ASSERT(jitinfo);
|
||||||
|
JS_ASSERT(jitinfo->type == JSJitInfo::Getter);
|
||||||
|
|
||||||
setOperand(0, obj);
|
setOperand(0, obj);
|
||||||
|
|
||||||
@ -6657,8 +6658,8 @@ class MGetDOMProperty
|
|||||||
return new MGetDOMProperty(info, obj, guard);
|
return new MGetDOMProperty(info, obj, guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
const JSJitPropertyOp fun() {
|
const JSJitGetterOp fun() {
|
||||||
return info_->op;
|
return info_->getter;
|
||||||
}
|
}
|
||||||
bool isInfallible() const {
|
bool isInfallible() const {
|
||||||
return info_->isInfallible;
|
return info_->isInfallible;
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include "jspubtd.h"
|
#include "jspubtd.h"
|
||||||
#include "jsprvtd.h"
|
#include "jsprvtd.h"
|
||||||
|
|
||||||
|
#include "js/CallArgs.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This macro checks if the stack pointer has exceeded a given limit. If
|
* This macro checks if the stack pointer has exceeded a given limit. If
|
||||||
* |tolerance| is non-zero, it returns true only if the stack pointer has
|
* |tolerance| is non-zero, it returns true only if the stack pointer has
|
||||||
@ -1432,14 +1434,86 @@ JS_GetDataViewByteLength(JSObject *obj);
|
|||||||
JS_FRIEND_API(void *)
|
JS_FRIEND_API(void *)
|
||||||
JS_GetDataViewData(JSObject *obj);
|
JS_GetDataViewData(JSObject *obj);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A class, expected to be passed by value, which represents the CallArgs for a
|
||||||
|
* JSJitGetterOp.
|
||||||
|
*/
|
||||||
|
class JSJitGetterCallArgs : protected JS::MutableHandleValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit JSJitGetterCallArgs(const JS::CallArgs& args)
|
||||||
|
: JS::MutableHandleValue(args.rval())
|
||||||
|
{}
|
||||||
|
|
||||||
|
JS::MutableHandleValue rval() {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A class, expected to be passed by value, which represents the CallArgs for a
|
||||||
|
* JSJitSetterOp.
|
||||||
|
*/
|
||||||
|
class JSJitSetterCallArgs : protected JS::MutableHandleValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit JSJitSetterCallArgs(const JS::CallArgs& args)
|
||||||
|
: JS::MutableHandleValue(args.handleAt(0))
|
||||||
|
{}
|
||||||
|
|
||||||
|
JS::MutableHandleValue handleAt(unsigned i) {
|
||||||
|
MOZ_ASSERT(i == 0);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned length() const { return 1; }
|
||||||
|
|
||||||
|
// Add get() or maybe hasDefined() as needed
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A class, expected to be passed by reference, which represents the CallArgs
|
||||||
|
* for a JSJitMethodOp.
|
||||||
|
*/
|
||||||
|
class JSJitMethodCallArgs : protected JS::detail::CallArgsBase<JS::detail::NoUsedRval>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef JS::detail::CallArgsBase<JS::detail::NoUsedRval> Base;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit JSJitMethodCallArgs(const JS::CallArgs& args) {
|
||||||
|
argv_ = args.array();
|
||||||
|
argc_ = args.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::MutableHandleValue rval() const {
|
||||||
|
return Base::rval();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned length() const { return Base::length(); }
|
||||||
|
|
||||||
|
JS::MutableHandleValue handleAt(unsigned i) const {
|
||||||
|
return Base::handleAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasDefined(unsigned i) const {
|
||||||
|
return Base::hasDefined(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add get() as needed
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This struct contains metadata passed from the DOM to the JS Engine for JIT
|
* This struct contains metadata passed from the DOM to the JS Engine for JIT
|
||||||
* optimizations on DOM property accessors. Eventually, this should be made
|
* optimizations on DOM property accessors. Eventually, this should be made
|
||||||
* available to general JSAPI users, but we are not currently ready to do so.
|
* available to general JSAPI users, but we are not currently ready to do so.
|
||||||
*/
|
*/
|
||||||
typedef bool
|
typedef bool
|
||||||
(* JSJitPropertyOp)(JSContext *cx, JSHandleObject thisObj,
|
(* JSJitGetterOp)(JSContext *cx, JSHandleObject thisObj,
|
||||||
void *specializedThis, JS::Value *vp);
|
void *specializedThis, JS::Value *vp);
|
||||||
|
typedef bool
|
||||||
|
(* JSJitSetterOp)(JSContext *cx, JSHandleObject thisObj,
|
||||||
|
void *specializedThis, JS::Value *vp);
|
||||||
typedef bool
|
typedef bool
|
||||||
(* JSJitMethodOp)(JSContext *cx, JSHandleObject thisObj,
|
(* JSJitMethodOp)(JSContext *cx, JSHandleObject thisObj,
|
||||||
void *specializedThis, unsigned argc, JS::Value *vp);
|
void *specializedThis, unsigned argc, JS::Value *vp);
|
||||||
@ -1451,7 +1525,11 @@ struct JSJitInfo {
|
|||||||
Method
|
Method
|
||||||
};
|
};
|
||||||
|
|
||||||
JSJitPropertyOp op;
|
union {
|
||||||
|
JSJitGetterOp getter;
|
||||||
|
JSJitSetterOp setter;
|
||||||
|
JSJitMethodOp method;
|
||||||
|
};
|
||||||
uint32_t protoID;
|
uint32_t protoID;
|
||||||
uint32_t depth;
|
uint32_t depth;
|
||||||
OpType type;
|
OpType type;
|
||||||
|
@ -4604,7 +4604,7 @@ dom_doFoo(JSContext* cx, JSHandleObject obj, void *self, unsigned argc, JS::Valu
|
|||||||
}
|
}
|
||||||
|
|
||||||
const JSJitInfo dom_x_getterinfo = {
|
const JSJitInfo dom_x_getterinfo = {
|
||||||
(JSJitPropertyOp)dom_get_x,
|
{ (JSJitGetterOp)dom_get_x },
|
||||||
0, /* protoID */
|
0, /* protoID */
|
||||||
0, /* depth */
|
0, /* depth */
|
||||||
JSJitInfo::Getter,
|
JSJitInfo::Getter,
|
||||||
@ -4613,7 +4613,7 @@ const JSJitInfo dom_x_getterinfo = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const JSJitInfo dom_x_setterinfo = {
|
const JSJitInfo dom_x_setterinfo = {
|
||||||
(JSJitPropertyOp)dom_set_x,
|
{ (JSJitGetterOp)dom_set_x },
|
||||||
0, /* protoID */
|
0, /* protoID */
|
||||||
0, /* depth */
|
0, /* depth */
|
||||||
JSJitInfo::Setter,
|
JSJitInfo::Setter,
|
||||||
@ -4622,7 +4622,7 @@ const JSJitInfo dom_x_setterinfo = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const JSJitInfo doFoo_methodinfo = {
|
const JSJitInfo doFoo_methodinfo = {
|
||||||
(JSJitPropertyOp)dom_doFoo,
|
{ (JSJitGetterOp)dom_doFoo },
|
||||||
0, /* protoID */
|
0, /* protoID */
|
||||||
0, /* depth */
|
0, /* depth */
|
||||||
JSJitInfo::Method,
|
JSJitInfo::Method,
|
||||||
@ -4684,7 +4684,7 @@ dom_genericGetter(JSContext *cx, unsigned argc, JS::Value *vp)
|
|||||||
|
|
||||||
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
|
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
|
||||||
MOZ_ASSERT(info->type == JSJitInfo::Getter);
|
MOZ_ASSERT(info->type == JSJitInfo::Getter);
|
||||||
JSJitPropertyOp getter = info->op;
|
JSJitGetterOp getter = info->getter;
|
||||||
return getter(cx, obj, val.toPrivate(), vp);
|
return getter(cx, obj, val.toPrivate(), vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4707,7 +4707,7 @@ dom_genericSetter(JSContext* cx, unsigned argc, JS::Value* vp)
|
|||||||
|
|
||||||
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
|
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
|
||||||
MOZ_ASSERT(info->type == JSJitInfo::Setter);
|
MOZ_ASSERT(info->type == JSJitInfo::Setter);
|
||||||
JSJitPropertyOp setter = info->op;
|
JSJitSetterOp setter = info->setter;
|
||||||
if (!setter(cx, obj, val.toPrivate(), argv))
|
if (!setter(cx, obj, val.toPrivate(), argv))
|
||||||
return false;
|
return false;
|
||||||
JS_SET_RVAL(cx, vp, UndefinedValue());
|
JS_SET_RVAL(cx, vp, UndefinedValue());
|
||||||
@ -4730,7 +4730,7 @@ dom_genericMethod(JSContext* cx, unsigned argc, JS::Value *vp)
|
|||||||
|
|
||||||
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
|
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
|
||||||
MOZ_ASSERT(info->type == JSJitInfo::Method);
|
MOZ_ASSERT(info->type == JSJitInfo::Method);
|
||||||
JSJitMethodOp method = (JSJitMethodOp)info->op;
|
JSJitMethodOp method = info->method;
|
||||||
return method(cx, obj, val.toPrivate(), argc, vp);
|
return method(cx, obj, val.toPrivate(), argc, vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user