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
897328ff5b
commit
5be706faaf
@ -5104,7 +5104,7 @@ class CGGenericMethod(CGAbstractBindingMethod):
|
||||
return CGIndenter(CGGeneric(
|
||||
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\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);"))
|
||||
|
||||
class CGSpecializedMethod(CGAbstractStaticMethod):
|
||||
@ -5240,7 +5240,7 @@ class CGGenericGetter(CGAbstractBindingMethod):
|
||||
return CGIndenter(CGGeneric(
|
||||
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
|
||||
"MOZ_ASSERT(info->type == JSJitInfo::Getter);\n"
|
||||
"JSJitPropertyOp getter = info->op;\n"
|
||||
"JSJitGetterOp getter = info->getter;\n"
|
||||
"return getter(cx, obj, self, vp);"))
|
||||
|
||||
class CGSpecializedGetter(CGAbstractStaticMethod):
|
||||
@ -5324,7 +5324,7 @@ class CGGenericSetter(CGAbstractBindingMethod):
|
||||
"JS::Value* argv = JS_ARGV(cx, vp);\n"
|
||||
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\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"
|
||||
" return false;\n"
|
||||
"}\n"
|
||||
@ -5431,7 +5431,7 @@ class CGMemberJITInfo(CGThing):
|
||||
"")
|
||||
return ("\n"
|
||||
"static const JSJitInfo %s = {\n"
|
||||
" %s,\n"
|
||||
" { %s },\n"
|
||||
" %s,\n"
|
||||
" %s,\n"
|
||||
" JSJitInfo::%s,\n"
|
||||
@ -5445,7 +5445,9 @@ class CGMemberJITInfo(CGThing):
|
||||
def define(self):
|
||||
if self.member.isAttr():
|
||||
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)
|
||||
getterconst = self.member.getExtendedAttribute("Constant")
|
||||
getterpure = getterconst or self.member.getExtendedAttribute("Pure")
|
||||
@ -5457,7 +5459,9 @@ class CGMemberJITInfo(CGThing):
|
||||
[self.member.type])
|
||||
if not self.member.readonly or self.member.getExtendedAttribute("PutForwards") is not None:
|
||||
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.
|
||||
result += self.defineJitInfo(setterinfo, setter, "Setter",
|
||||
False, False, False,
|
||||
@ -5466,8 +5470,8 @@ class CGMemberJITInfo(CGThing):
|
||||
if self.member.isMethod():
|
||||
methodinfo = ("%s_methodinfo" % self.member.identifier.name)
|
||||
name = CppKeywords.checkMethodName(self.member.identifier.name)
|
||||
# Actually a JSJitMethodOp, but JSJitPropertyOp by struct definition.
|
||||
method = ("(JSJitPropertyOp)%s" % name)
|
||||
# Actually a JSJitMethodOp, but JSJitGetterOp is first in the union.
|
||||
method = ("(JSJitGetterOp)%s" % name)
|
||||
|
||||
# Methods are infallible if they are infallible, have no arguments
|
||||
# to unwrap, and have a return type that's infallible to wrap up for
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include "jstypes.h"
|
||||
|
||||
@ -92,30 +93,50 @@ namespace JS {
|
||||
* public interface are meant to be used by embedders! See inline comments to
|
||||
* 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:
|
||||
#ifdef DEBUG
|
||||
mutable bool usedRval_;
|
||||
void setUsedRval() const { usedRval_ = true; }
|
||||
void clearUsedRval() const { usedRval_ = false; }
|
||||
#else
|
||||
};
|
||||
|
||||
template<>
|
||||
class MOZ_STACK_CLASS UsedRvalBase<NoUsedRval>
|
||||
{
|
||||
protected:
|
||||
void setUsedRval() const {}
|
||||
void clearUsedRval() const {}
|
||||
};
|
||||
|
||||
template<UsedRval WantUsedRval>
|
||||
class MOZ_STACK_CLASS CallReceiverBase : public UsedRvalBase<
|
||||
#ifdef DEBUG
|
||||
WantUsedRval
|
||||
#else
|
||||
NoUsedRval
|
||||
#endif
|
||||
|
||||
>
|
||||
{
|
||||
protected:
|
||||
Value *argv_;
|
||||
|
||||
friend CallReceiver CallReceiverFromVp(Value *vp);
|
||||
friend CallReceiver CallReceiverFromArgv(Value *argv);
|
||||
|
||||
public:
|
||||
/*
|
||||
* Returns the function being called, as an object. Must not be called
|
||||
* after rval() has been used!
|
||||
*/
|
||||
JSObject &callee() const {
|
||||
MOZ_ASSERT(!usedRval_);
|
||||
MOZ_ASSERT(!this->usedRval_);
|
||||
return argv_[-2].toObject();
|
||||
}
|
||||
|
||||
@ -124,7 +145,7 @@ class MOZ_STACK_CLASS CallReceiver
|
||||
* rval() has been used!
|
||||
*/
|
||||
HandleValue calleev() const {
|
||||
MOZ_ASSERT(!usedRval_);
|
||||
MOZ_ASSERT(!this->usedRval_);
|
||||
return HandleValue::fromMarkedLocation(&argv_[-2]);
|
||||
}
|
||||
|
||||
@ -160,7 +181,7 @@ class MOZ_STACK_CLASS CallReceiver
|
||||
* fails.
|
||||
*/
|
||||
MutableHandleValue rval() const {
|
||||
setUsedRval();
|
||||
this->setUsedRval();
|
||||
return MutableHandleValue::fromMarkedLocation(&argv_[-2]);
|
||||
}
|
||||
|
||||
@ -171,7 +192,7 @@ class MOZ_STACK_CLASS CallReceiver
|
||||
Value *base() const { return argv_ - 2; }
|
||||
|
||||
Value *spAfterCall() const {
|
||||
setUsedRval();
|
||||
this->setUsedRval();
|
||||
return argv_ - 1;
|
||||
}
|
||||
|
||||
@ -181,7 +202,7 @@ class MOZ_STACK_CLASS CallReceiver
|
||||
// it. You probably don't want to use these!
|
||||
|
||||
void setCallee(Value aCalleev) const {
|
||||
clearUsedRval();
|
||||
this->clearUsedRval();
|
||||
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
|
||||
CallReceiverFromArgv(Value *argv)
|
||||
{
|
||||
@ -233,11 +263,63 @@ CallReceiverFromVp(Value *vp)
|
||||
* public interface are meant to be used by embedders! See inline comments to
|
||||
* 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:
|
||||
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 CallArgsFromSp(unsigned argc, Value *sp);
|
||||
|
||||
@ -249,45 +331,6 @@ class MOZ_STACK_CLASS CallArgs : public CallReceiver
|
||||
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
|
||||
|
@ -1453,7 +1453,7 @@ CodeGenerator::visitCallDOMNative(LCallDOMNative *call)
|
||||
masm.passABIArg(argPrivate);
|
||||
masm.passABIArg(argArgc);
|
||||
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) {
|
||||
masm.loadValue(Address(StackPointer, IonDOMMethodExitFrameLayout::offsetOfResult()),
|
||||
|
@ -7791,7 +7791,8 @@ IonBuilder::jsop_setprop(HandlePropertyName name)
|
||||
// properties.
|
||||
RootedFunction setter(cx, commonSetter);
|
||||
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)
|
||||
return false;
|
||||
|
||||
|
@ -6586,9 +6586,9 @@ class MSetDOMProperty
|
||||
: public MAryInstruction<2>,
|
||||
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)
|
||||
{
|
||||
setOperand(0, obj);
|
||||
@ -6598,12 +6598,12 @@ class MSetDOMProperty
|
||||
public:
|
||||
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);
|
||||
}
|
||||
|
||||
const JSJitPropertyOp fun() {
|
||||
const JSJitSetterOp fun() {
|
||||
return func_;
|
||||
}
|
||||
|
||||
@ -6631,6 +6631,7 @@ class MGetDOMProperty
|
||||
: info_(jitinfo)
|
||||
{
|
||||
JS_ASSERT(jitinfo);
|
||||
JS_ASSERT(jitinfo->type == JSJitInfo::Getter);
|
||||
|
||||
setOperand(0, obj);
|
||||
|
||||
@ -6657,8 +6658,8 @@ class MGetDOMProperty
|
||||
return new MGetDOMProperty(info, obj, guard);
|
||||
}
|
||||
|
||||
const JSJitPropertyOp fun() {
|
||||
return info_->op;
|
||||
const JSJitGetterOp fun() {
|
||||
return info_->getter;
|
||||
}
|
||||
bool isInfallible() const {
|
||||
return info_->isInfallible;
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "jspubtd.h"
|
||||
#include "jsprvtd.h"
|
||||
|
||||
#include "js/CallArgs.h"
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -1432,14 +1434,86 @@ JS_GetDataViewByteLength(JSObject *obj);
|
||||
JS_FRIEND_API(void *)
|
||||
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
|
||||
* optimizations on DOM property accessors. Eventually, this should be made
|
||||
* available to general JSAPI users, but we are not currently ready to do so.
|
||||
*/
|
||||
typedef bool
|
||||
(* JSJitPropertyOp)(JSContext *cx, JSHandleObject thisObj,
|
||||
void *specializedThis, JS::Value *vp);
|
||||
(* JSJitGetterOp)(JSContext *cx, JSHandleObject thisObj,
|
||||
void *specializedThis, JS::Value *vp);
|
||||
typedef bool
|
||||
(* JSJitSetterOp)(JSContext *cx, JSHandleObject thisObj,
|
||||
void *specializedThis, JS::Value *vp);
|
||||
typedef bool
|
||||
(* JSJitMethodOp)(JSContext *cx, JSHandleObject thisObj,
|
||||
void *specializedThis, unsigned argc, JS::Value *vp);
|
||||
@ -1451,7 +1525,11 @@ struct JSJitInfo {
|
||||
Method
|
||||
};
|
||||
|
||||
JSJitPropertyOp op;
|
||||
union {
|
||||
JSJitGetterOp getter;
|
||||
JSJitSetterOp setter;
|
||||
JSJitMethodOp method;
|
||||
};
|
||||
uint32_t protoID;
|
||||
uint32_t depth;
|
||||
OpType type;
|
||||
|
@ -4604,7 +4604,7 @@ dom_doFoo(JSContext* cx, JSHandleObject obj, void *self, unsigned argc, JS::Valu
|
||||
}
|
||||
|
||||
const JSJitInfo dom_x_getterinfo = {
|
||||
(JSJitPropertyOp)dom_get_x,
|
||||
{ (JSJitGetterOp)dom_get_x },
|
||||
0, /* protoID */
|
||||
0, /* depth */
|
||||
JSJitInfo::Getter,
|
||||
@ -4613,7 +4613,7 @@ const JSJitInfo dom_x_getterinfo = {
|
||||
};
|
||||
|
||||
const JSJitInfo dom_x_setterinfo = {
|
||||
(JSJitPropertyOp)dom_set_x,
|
||||
{ (JSJitGetterOp)dom_set_x },
|
||||
0, /* protoID */
|
||||
0, /* depth */
|
||||
JSJitInfo::Setter,
|
||||
@ -4622,7 +4622,7 @@ const JSJitInfo dom_x_setterinfo = {
|
||||
};
|
||||
|
||||
const JSJitInfo doFoo_methodinfo = {
|
||||
(JSJitPropertyOp)dom_doFoo,
|
||||
{ (JSJitGetterOp)dom_doFoo },
|
||||
0, /* protoID */
|
||||
0, /* depth */
|
||||
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));
|
||||
MOZ_ASSERT(info->type == JSJitInfo::Getter);
|
||||
JSJitPropertyOp getter = info->op;
|
||||
JSJitGetterOp getter = info->getter;
|
||||
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));
|
||||
MOZ_ASSERT(info->type == JSJitInfo::Setter);
|
||||
JSJitPropertyOp setter = info->op;
|
||||
JSJitSetterOp setter = info->setter;
|
||||
if (!setter(cx, obj, val.toPrivate(), argv))
|
||||
return false;
|
||||
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));
|
||||
MOZ_ASSERT(info->type == JSJitInfo::Method);
|
||||
JSJitMethodOp method = (JSJitMethodOp)info->op;
|
||||
JSJitMethodOp method = info->method;
|
||||
return method(cx, obj, val.toPrivate(), argc, vp);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user