Bug 1724031 - Part 3: Store JSFunction flags and arg count as a JS::Value r=jandem

In preparation for storing them in a slot, store them in a Value. The value is
encoded as a private uint32 value.

Differential Revision: https://phabricator.services.mozilla.com/D123083
This commit is contained in:
Jon Coppeard 2021-08-24 13:01:53 +00:00
parent 98f8f1c73d
commit 9fca780648
6 changed files with 33 additions and 19 deletions

View File

@ -15,6 +15,7 @@
#include "js/CallArgs.h" // JSNative
#include "js/shadow/Object.h" // JS::shadow::Object
#include "js/Value.h" // JS::Value
class JS_PUBLIC_API JSFunction;
class JSJitInfo;
@ -25,7 +26,7 @@ namespace shadow {
struct Function {
shadow::Object base;
uint32_t flagsAndArgCount;
JS::Value flagsAndArgCount;
/* Used only for natives */
JSNative native;
const JSJitInfo* jitinfo;

View File

@ -76,7 +76,7 @@ assertEq(tByteSize([1, 2, 3, 4, 5, 6, 7]), s(112, 120));
assertEq(tByteSize([1, 2, 3, 4, 5, 6, 7, 8]), s(112, 120));
// Various forms of functions.
assertEq(tByteSize(function () {}), s(32, 56));
assertEq(tByteSize(function () {}.bind()), s(48, 72));
assertEq(tByteSize(() => 1), s(48, 72));
assertEq(tByteSize(Math.sin), s(32, 56));
assertEq(tByteSize(function () {}), s(40, 56));
assertEq(tByteSize(function () {}.bind()), s(56, 72));
assertEq(tByteSize(() => 1), s(56, 72));
assertEq(tByteSize(Math.sin), s(40, 56));

View File

@ -3525,8 +3525,8 @@ void CodeGenerator::emitLambdaInit(Register output, Register envChain,
const LambdaFunctionInfo& info) {
uint32_t flagsAndArgs =
info.flags.toRaw() | (info.nargs << JSFunction::ArgCountShift);
masm.store32(Imm32(flagsAndArgs),
Address(output, JSFunction::offsetOfFlagsAndArgCount()));
masm.storeValue(JS::PrivateUint32Value(flagsAndArgs),
Address(output, JSFunction::offsetOfFlagsAndArgCount()));
masm.storePtr(ImmGCPtr(info.baseScript),
Address(output, JSFunction::offsetOfBaseScript()));
masm.storePtr(envChain, Address(output, JSFunction::offsetOfEnvironment()));

View File

@ -550,7 +550,8 @@ static MOZ_ALWAYS_INLINE const JSJitInfo* FUNCTION_VALUE_TO_JITINFO(
MOZ_ASSERT(JS::GetClass(obj) == js::FunctionClassPtr);
auto* fun = reinterpret_cast<JS::shadow::Function*>(obj);
MOZ_ASSERT(!(fun->flagsAndArgCount & js::JS_FUNCTION_INTERPRETED_BITS),
MOZ_ASSERT(!(fun->flagsAndArgCount.toPrivateUint32() &
js::JS_FUNCTION_INTERPRETED_BITS),
"Unexpected non-native function");
return fun->jitinfo;
@ -559,7 +560,8 @@ static MOZ_ALWAYS_INLINE const JSJitInfo* FUNCTION_VALUE_TO_JITINFO(
static MOZ_ALWAYS_INLINE void SET_JITINFO(JSFunction* func,
const JSJitInfo* info) {
auto* fun = reinterpret_cast<JS::shadow::Function*>(func);
MOZ_ASSERT(!(fun->flagsAndArgCount & js::JS_FUNCTION_INTERPRETED_BITS));
MOZ_ASSERT(!(fun->flagsAndArgCount.toPrivateUint32() &
js::JS_FUNCTION_INTERPRETED_BITS));
fun->jitinfo = info;
}

View File

@ -75,7 +75,7 @@ inline JSFunction* JSFunction::create(JSContext* cx, js::gc::AllocKind kind,
MOZ_ASSERT(shape->slotSpan() == 0);
JSFunction* fun = static_cast<JSFunction*>(nobj);
fun->setArgCount(0);
fun->initFlagsAndArgCount();
// This must be overwritten by some ultimate caller: there's no default
// value to which we could sensibly initialize this.

View File

@ -53,12 +53,13 @@ class JSFunction : public js::NativeObject {
using FunctionFlags = js::FunctionFlags;
/*
* Bitfield composed of FunctionFlags and argument count.
* Bitfield composed of FunctionFlags and argument count, stored as a
* PrivateUint32Value.
*
* If any of these flags needs to be accessed in off-thread JIT compilation,
* copy it to js::jit::WrappedFunction.
*/
uint32_t flagsAndArgCount_;
js::GCPtrValue flagsAndArgCount_;
union U {
class {
@ -151,12 +152,18 @@ class JSFunction : public js::NativeObject {
return needsFunctionEnvironmentObjects() || needsExtraBodyVarEnvironment();
}
uint32_t flagsAndArgCountRaw() const { return flagsAndArgCount_; }
uint32_t flagsAndArgCountRaw() const {
return flagsAndArgCount_.toPrivateUint32();
}
size_t nargs() const { return flagsAndArgCount_ >> ArgCountShift; }
void initFlagsAndArgCount() {
flagsAndArgCount_.init(JS::PrivateUint32Value(0));
}
size_t nargs() const { return flagsAndArgCountRaw() >> ArgCountShift; }
FunctionFlags flags() const {
return FunctionFlags(uint16_t(flagsAndArgCount_ & FlagsMask));
return FunctionFlags(uint16_t(flagsAndArgCountRaw() & FlagsMask));
}
FunctionFlags::FunctionKind kind() const { return flags().kind(); }
@ -269,8 +276,10 @@ class JSFunction : public js::NativeObject {
void setFlags(FunctionFlags flags) { setFlags(flags.toRaw()); }
void setFlags(uint16_t flags) {
flagsAndArgCount_ &= ~FlagsMask;
flagsAndArgCount_ |= flags;
uint32_t flagsAndArgCount = flagsAndArgCountRaw();
flagsAndArgCount &= ~FlagsMask;
flagsAndArgCount |= flags;
flagsAndArgCount_.unbarrieredSet(JS::PrivateUint32Value(flagsAndArgCount));
}
// Make the function constructible.
@ -278,8 +287,10 @@ class JSFunction : public js::NativeObject {
// Can be called multiple times by the parser.
void setArgCount(uint16_t nargs) {
flagsAndArgCount_ &= ~ArgCountMask;
flagsAndArgCount_ |= nargs << ArgCountShift;
uint32_t flagsAndArgCount = flagsAndArgCountRaw();
flagsAndArgCount &= ~ArgCountMask;
flagsAndArgCount |= nargs << ArgCountShift;
flagsAndArgCount_.set(JS::PrivateUint32Value(flagsAndArgCount));
}
void setIsBoundFunction() { setFlags(flags().setIsBoundFunction()); }