Bug 1141862 - Part 1: Free up bits in JSFunction for isMethod() and, later, isClassConstructor(). (r=jandem)

This commit is contained in:
Eric Faust 2015-04-02 19:18:20 -07:00
parent 519f461431
commit a89ff47fc4
4 changed files with 58 additions and 25 deletions

View File

@ -1757,7 +1757,7 @@ void
CodeGenerator::emitLambdaInit(Register output, Register scopeChain,
const LambdaFunctionInfo& info)
{
MOZ_ASSERT(!!(info.flags & JSFunction::ARROW) == !!(info.flags & JSFunction::EXTENDED));
MOZ_ASSERT(info.fun->isArrow() == !!(info.flags & JSFunction::EXTENDED));
// Initialize nargs and flags. We do this with a single uint32 to avoid
// 16-bit writes.

View File

@ -2370,10 +2370,24 @@ MacroAssembler::branchIfNotInterpretedConstructor(Register fun, Register scratch
// Common case: if IS_FUN_PROTO, ARROW and SELF_HOSTED are not set,
// the function is an interpreted constructor and we're done.
Label done;
bits = IMM32_16ADJ( (JSFunction::IS_FUN_PROTO | JSFunction::ARROW | JSFunction::SELF_HOSTED) );
branchTest32(Assembler::Zero, scratch, Imm32(bits), &done);
Label done, moreChecks;
// Start with the easy ones. Check IS_FUN_PROTO and SELF_HOSTED.
bits = IMM32_16ADJ( (JSFunction::IS_FUN_PROTO | JSFunction::SELF_HOSTED) );
branchTest32(Assembler::NonZero, scratch, Imm32(bits), &moreChecks);
// Check !isArrow()
bits = IMM32_16ADJ(JSFunction::FUNCTION_KIND_MASK);
and32(Imm32(bits), scratch);
bits = IMM32_16ADJ(JSFunction::ARROW_KIND);
branch32(Assembler::NotEqual, scratch, Imm32(bits), &done);
// Reload the smashed flags and nargs for more checks.
load32(Address(fun, JSFunction::offsetOfNargs()), scratch);
{
bind(&moreChecks);
// The callee is either Function.prototype, an arrow function or
// self-hosted. None of these are constructible, except self-hosted
// constructors, so branch to |label| if SELF_HOSTED_CTOR is not set.

View File

@ -2396,7 +2396,7 @@ FunctionObjectToShadowFunction(JSObject* fun)
}
/* Statically asserted in jsfun.h. */
static const unsigned JS_FUNCTION_INTERPRETED_BITS = 0x1001;
static const unsigned JS_FUNCTION_INTERPRETED_BITS = 0x401;
// Return whether the given function object is native.
static MOZ_ALWAYS_INLINE bool

View File

@ -28,37 +28,48 @@ class JSFunction : public js::NativeObject
public:
static const js::Class class_;
enum FunctionKind {
NormalFunction = 0,
Arrow, /* ES6 '(args) => body' syntax */
AsmJS /* function is an asm.js module or exported function */
};
enum Flags {
INTERPRETED = 0x0001, /* function has a JSScript and environment. */
NATIVE_CTOR = 0x0002, /* native that can be called as a constructor */
EXTENDED = 0x0004, /* structure is FunctionExtended */
IS_FUN_PROTO = 0x0010, /* function is Function.prototype for some global object */
EXPR_BODY = 0x0020, /* arrow function with expression body or
IS_FUN_PROTO = 0x0008, /* function is Function.prototype for some global object */
EXPR_BODY = 0x0010, /* arrow function with expression body or
* expression closure: function(x) x*x */
HAS_GUESSED_ATOM = 0x0040, /* function had no explicit name, but a
HAS_GUESSED_ATOM = 0x0020, /* function had no explicit name, but a
name was guessed for it anyway */
LAMBDA = 0x0080, /* function comes from a FunctionExpression, ArrowFunction, or
LAMBDA = 0x0040, /* function comes from a FunctionExpression, ArrowFunction, or
Function() call (not a FunctionDeclaration or nonstandard
function-statement) */
SELF_HOSTED = 0x0100, /* function is self-hosted builtin and must not be
SELF_HOSTED = 0x0080, /* function is self-hosted builtin and must not be
decompilable nor constructible. */
SELF_HOSTED_CTOR = 0x0200, /* function is self-hosted builtin constructor and
SELF_HOSTED_CTOR = 0x0100, /* function is self-hosted builtin constructor and
must be constructible but not decompilable. */
HAS_REST = 0x0400, /* function has a rest (...) parameter */
ASMJS = 0x0800, /* function is an asm.js module or exported function */
INTERPRETED_LAZY = 0x1000, /* function is interpreted but doesn't have a script yet */
ARROW = 0x2000, /* ES6 '(args) => body' syntax */
RESOLVED_LENGTH = 0x4000, /* f.length has been resolved (see js::fun_resolve). */
RESOLVED_NAME = 0x8000, /* f.name has been resolved (see js::fun_resolve). */
HAS_REST = 0x0200, /* function has a rest (...) parameter */
INTERPRETED_LAZY = 0x0400, /* function is interpreted but doesn't have a script yet */
RESOLVED_LENGTH = 0x0800, /* f.length has been resolved (see js::fun_resolve). */
RESOLVED_NAME = 0x1000, /* f.name has been resolved (see js::fun_resolve). */
FUNCTION_KIND_SHIFT = 13,
FUNCTION_KIND_MASK = 0x3 << FUNCTION_KIND_SHIFT,
ASMJS_KIND = AsmJS << FUNCTION_KIND_SHIFT,
ARROW_KIND = Arrow << FUNCTION_KIND_SHIFT,
/* Derived Flags values for convenience: */
NATIVE_FUN = 0,
ASMJS_CTOR = ASMJS | NATIVE_CTOR,
ASMJS_LAMBDA_CTOR = ASMJS | NATIVE_CTOR | LAMBDA,
ASMJS_CTOR = ASMJS_KIND | NATIVE_CTOR,
ASMJS_LAMBDA_CTOR = ASMJS_KIND | NATIVE_CTOR | LAMBDA,
INTERPRETED_LAMBDA = INTERPRETED | LAMBDA,
INTERPRETED_LAMBDA_ARROW = INTERPRETED | LAMBDA | ARROW,
INTERPRETED_LAMBDA_ARROW = INTERPRETED | LAMBDA | ARROW_KIND,
STABLE_ACROSS_CLONES = NATIVE_CTOR | IS_FUN_PROTO | EXPR_BODY | HAS_GUESSED_ATOM |
LAMBDA | SELF_HOSTED | SELF_HOSTED_CTOR | HAS_REST | ASMJS | ARROW
LAMBDA | SELF_HOSTED | SELF_HOSTED_CTOR | HAS_REST |
FUNCTION_KIND_MASK
};
static_assert((INTERPRETED | INTERPRETED_LAZY) == js::JS_FUNCTION_INTERPRETED_BITS,
@ -67,7 +78,7 @@ class JSFunction : public js::NativeObject
private:
uint16_t nargs_; /* number of formal arguments
(including defaults and the rest parameter unlike f.length) */
uint16_t flags_; /* bitfield composed of the above Flags enum */
uint16_t flags_; /* bitfield composed of the above Flags enum, as well as the kind */
union U {
class Native {
friend class JSFunction;
@ -113,13 +124,17 @@ class JSFunction : public js::NativeObject
return flags_;
}
FunctionKind kind() const {
return static_cast<FunctionKind>((flags_ & FUNCTION_KIND_MASK) >> FUNCTION_KIND_SHIFT);
}
/* A function can be classified as either native (C++) or interpreted (JS): */
bool isInterpreted() const { return flags() & (INTERPRETED | INTERPRETED_LAZY); }
bool isNative() const { return !isInterpreted(); }
/* Possible attributes of a native function: */
bool isNativeConstructor() const { return flags() & NATIVE_CTOR; }
bool isAsmJSNative() const { return flags() & ASMJS; }
bool isAsmJSNative() const { return kind() == AsmJS; }
/* Possible attributes of an interpreted function: */
bool isFunctionPrototype() const { return flags() & IS_FUN_PROTO; }
@ -133,7 +148,7 @@ class JSFunction : public js::NativeObject
bool hasScript() const { return flags() & INTERPRETED; }
// Arrow functions store their lexical |this| in the first extended slot.
bool isArrow() const { return flags() & ARROW; }
bool isArrow() const { return kind() == Arrow; }
bool hasResolvedLength() const { return flags() & RESOLVED_LENGTH; }
bool hasResolvedName() const { return flags() & RESOLVED_NAME; }
@ -170,6 +185,10 @@ class JSFunction : public js::NativeObject
void setFlags(uint16_t flags) {
this->flags_ = flags;
}
void setKind(FunctionKind kind) {
this->flags_ &= ~FUNCTION_KIND_MASK;
this->flags_ |= static_cast<uint16_t>(kind) << FUNCTION_KIND_SHIFT;
}
// Can be called multiple times by the parser.
void setArgCount(uint16_t nargs) {
@ -202,7 +221,7 @@ class JSFunction : public js::NativeObject
}
void setArrow() {
flags_ |= ARROW;
setKind(Arrow);
}
void setResolvedLength() {