[objects] Free one bit in the SharedFunctionInfo::flags.
We'll need one bit in the SharedFunctionInfo::flags to record whether it's safe to skip arguments adaptor frames (for v8:8895), so this just removes the SharedFunctionInfo::IsDerivedConstructorBit which is redundant, since the same information is already available in the SharedFunctionInfo::FunctionKindBits, and most places in the code use that already, with the exception of the JSConstructStubGeneric builtin. This changes the JSConstructStubGeneric builtin to just check the function kind instead of testing the explicit bit, which also makes this more consistent. It seems like there's not much overhead to that, doing an additional bitmasking plus two comparisons instead of one. This shouldn't really matter since invocation and execution of the constructors is going to dominate and optimized code inlines all of this anyways. If this turns out to affect performance, we can still look into encoding the FunctionKindBits more cleverly. Drive-by-fix: Move the FunctionKindBits first in the flags to avoid the shift when accessing the function kind. This seems logic, since for the actual boolean bit fields it doesn't matter where they are in the flags, whereas for the function kind this saves one shift. Bug: v8:8834, v8:8895 Change-Id: I184a8f5cc5c140bdc272cf9a5ad546093c457306 Reviewed-on: https://chromium-review.googlesource.com/c/1482915 Reviewed-by: Toon Verwaest <verwaest@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#59821}
This commit is contained in:
parent
83e88b338d
commit
591408cba7
@ -1728,6 +1728,20 @@ void MacroAssembler::CompareRoot(Register obj, RootIndex index) {
|
||||
cmp(obj, scratch);
|
||||
}
|
||||
|
||||
void MacroAssembler::JumpIfIsInRange(Register value, unsigned lower_limit,
|
||||
unsigned higher_limit,
|
||||
Label* on_in_range) {
|
||||
if (lower_limit != 0) {
|
||||
UseScratchRegisterScope temps(this);
|
||||
Register scratch = temps.Acquire();
|
||||
sub(scratch, value, Operand(lower_limit));
|
||||
cmp(scratch, Operand(higher_limit - lower_limit));
|
||||
} else {
|
||||
cmp(value, Operand(higher_limit));
|
||||
}
|
||||
b(ls, on_in_range);
|
||||
}
|
||||
|
||||
void MacroAssembler::TryDoubleToInt32Exact(Register result,
|
||||
DwVfpRegister double_input,
|
||||
LowDwVfpRegister double_scratch) {
|
||||
|
@ -682,6 +682,11 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
||||
b(ne, if_not_equal);
|
||||
}
|
||||
|
||||
// Checks if value is in range [lower_limit, higher_limit] using a single
|
||||
// comparison.
|
||||
void JumpIfIsInRange(Register value, unsigned lower_limit,
|
||||
unsigned higher_limit, Label* on_in_range);
|
||||
|
||||
// Try to convert a double to a signed 32-bit integer.
|
||||
// Z flag set to one and result assigned if the conversion is exact.
|
||||
void TryDoubleToInt32Exact(Register result,
|
||||
|
@ -2755,6 +2755,22 @@ void MacroAssembler::JumpIfNotRoot(const Register& obj, RootIndex index,
|
||||
B(ne, if_not_equal);
|
||||
}
|
||||
|
||||
void MacroAssembler::JumpIfIsInRange(const Register& value,
|
||||
unsigned lower_limit,
|
||||
unsigned higher_limit,
|
||||
Label* on_in_range) {
|
||||
if (lower_limit != 0) {
|
||||
UseScratchRegisterScope temps(this);
|
||||
Register scratch = temps.AcquireW();
|
||||
Sub(scratch, value, Operand(lower_limit));
|
||||
CompareAndBranch(scratch, Operand(higher_limit - lower_limit), ls,
|
||||
on_in_range);
|
||||
} else {
|
||||
CompareAndBranch(value, Operand(higher_limit - lower_limit), ls,
|
||||
on_in_range);
|
||||
}
|
||||
}
|
||||
|
||||
void TurboAssembler::LoadTaggedPointerField(const Register& destination,
|
||||
const MemOperand& field_operand) {
|
||||
#ifdef V8_COMPRESS_POINTERS
|
||||
|
@ -1837,6 +1837,11 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
||||
// Compare the object in a register to a value and jump if they are not equal.
|
||||
void JumpIfNotRoot(const Register& obj, RootIndex index, Label* if_not_equal);
|
||||
|
||||
// Checks if value is in range [lower_limit, higher_limit] using a single
|
||||
// comparison.
|
||||
void JumpIfIsInRange(const Register& value, unsigned lower_limit,
|
||||
unsigned higher_limit, Label* on_in_range);
|
||||
|
||||
// Compare the contents of a register with an operand, and branch to true,
|
||||
// false or fall through, depending on condition.
|
||||
void CompareAndSplit(const Register& lhs,
|
||||
|
@ -219,8 +219,9 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
|
||||
|
||||
__ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kFlagsOffset));
|
||||
__ tst(r4, Operand(SharedFunctionInfo::IsDerivedConstructorBit::kMask));
|
||||
__ b(ne, ¬_create_implicit_receiver);
|
||||
__ DecodeField<SharedFunctionInfo::FunctionKindBits>(r4);
|
||||
__ JumpIfIsInRange(r4, kDefaultDerivedConstructor, kDerivedConstructor,
|
||||
¬_create_implicit_receiver);
|
||||
|
||||
// If not derived class constructor: Allocate the new receiver object.
|
||||
__ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1,
|
||||
|
@ -278,9 +278,9 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
|
||||
__ LoadTaggedPointerField(
|
||||
x4, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ Ldr(w4, FieldMemOperand(x4, SharedFunctionInfo::kFlagsOffset));
|
||||
__ TestAndBranchIfAnySet(w4,
|
||||
SharedFunctionInfo::IsDerivedConstructorBit::kMask,
|
||||
¬_create_implicit_receiver);
|
||||
__ DecodeField<SharedFunctionInfo::FunctionKindBits>(w4);
|
||||
__ JumpIfIsInRange(w4, kDefaultDerivedConstructor, kDerivedConstructor,
|
||||
¬_create_implicit_receiver);
|
||||
|
||||
// If not derived class constructor: Allocate the new receiver object.
|
||||
__ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1,
|
||||
|
@ -206,9 +206,10 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
|
||||
// -----------------------------------
|
||||
|
||||
__ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ test(FieldOperand(eax, SharedFunctionInfo::kFlagsOffset),
|
||||
Immediate(SharedFunctionInfo::IsDerivedConstructorBit::kMask));
|
||||
__ j(not_zero, ¬_create_implicit_receiver);
|
||||
__ mov(eax, FieldOperand(eax, SharedFunctionInfo::kFlagsOffset));
|
||||
__ DecodeField<SharedFunctionInfo::FunctionKindBits>(eax);
|
||||
__ JumpIfIsInRange(eax, kDefaultDerivedConstructor, kDerivedConstructor,
|
||||
ecx, ¬_create_implicit_receiver, Label::kNear);
|
||||
|
||||
// If not derived class constructor: Allocate the new receiver object.
|
||||
__ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1,
|
||||
|
@ -198,9 +198,10 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
|
||||
|
||||
__ LoadTaggedPointerField(
|
||||
rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ testl(FieldOperand(rbx, SharedFunctionInfo::kFlagsOffset),
|
||||
Immediate(SharedFunctionInfo::IsDerivedConstructorBit::kMask));
|
||||
__ j(not_zero, ¬_create_implicit_receiver, Label::kNear);
|
||||
__ movl(rbx, FieldOperand(rbx, SharedFunctionInfo::kFlagsOffset));
|
||||
__ DecodeField<SharedFunctionInfo::FunctionKindBits>(rbx);
|
||||
__ JumpIfIsInRange(rbx, kDefaultDerivedConstructor, kDerivedConstructor,
|
||||
¬_create_implicit_receiver, Label::kNear);
|
||||
|
||||
// If not derived class constructor: Allocate the new receiver object.
|
||||
__ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
|
||||
|
@ -130,6 +130,19 @@ void MacroAssembler::PushRoot(RootIndex index) {
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::JumpIfIsInRange(Register value, unsigned lower_limit,
|
||||
unsigned higher_limit, Register scratch,
|
||||
Label* on_in_range,
|
||||
Label::Distance near_jump) {
|
||||
if (lower_limit != 0) {
|
||||
lea(scratch, Operand(value, 0u - lower_limit));
|
||||
cmp(scratch, Immediate(higher_limit - lower_limit));
|
||||
} else {
|
||||
cmp(value, Immediate(higher_limit));
|
||||
}
|
||||
j(below_equal, on_in_range, near_jump);
|
||||
}
|
||||
|
||||
Operand TurboAssembler::ExternalReferenceAsOperand(ExternalReference reference,
|
||||
Register scratch) {
|
||||
// TODO(jgruber): Add support for enable_root_array_delta_access.
|
||||
|
@ -460,6 +460,13 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
||||
j(not_equal, if_not_equal, if_not_equal_distance);
|
||||
}
|
||||
|
||||
// Checks if value is in range [lower_limit, higher_limit] using a single
|
||||
// comparison.
|
||||
void JumpIfIsInRange(Register value, unsigned lower_limit,
|
||||
unsigned higher_limit, Register scratch,
|
||||
Label* on_in_range,
|
||||
Label::Distance near_jump = Label::kFar);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// GC Support
|
||||
// Notify the garbage collector that we wrote a pointer into an object.
|
||||
|
@ -261,7 +261,6 @@ void SharedFunctionInfo::set_kind(FunctionKind kind) {
|
||||
int hints = flags();
|
||||
hints = FunctionKindBits::update(hints, kind);
|
||||
hints = IsClassConstructorBit::update(hints, IsClassConstructor(kind));
|
||||
hints = IsDerivedConstructorBit::update(hints, IsDerivedConstructor(kind));
|
||||
set_flags(hints);
|
||||
UpdateFunctionMapIndex();
|
||||
}
|
||||
|
@ -656,27 +656,27 @@ class SharedFunctionInfo : public HeapObject {
|
||||
class BodyDescriptor;
|
||||
|
||||
// Bit positions in |flags|.
|
||||
#define FLAGS_BIT_FIELDS(V, _) \
|
||||
V(IsNativeBit, bool, 1, _) \
|
||||
V(IsStrictBit, bool, 1, _) \
|
||||
V(IsWrappedBit, bool, 1, _) \
|
||||
V(IsClassConstructorBit, bool, 1, _) \
|
||||
V(IsDerivedConstructorBit, bool, 1, _) \
|
||||
V(FunctionKindBits, FunctionKind, 5, _) \
|
||||
V(HasDuplicateParametersBit, bool, 1, _) \
|
||||
V(AllowLazyCompilationBit, bool, 1, _) \
|
||||
V(NeedsHomeObjectBit, bool, 1, _) \
|
||||
V(IsDeclarationBit, bool, 1, _) \
|
||||
V(IsAsmWasmBrokenBit, bool, 1, _) \
|
||||
V(FunctionMapIndexBits, int, 5, _) \
|
||||
V(DisabledOptimizationReasonBits, BailoutReason, 4, _) \
|
||||
V(RequiresInstanceMembersInitializer, bool, 1, _) \
|
||||
V(ConstructAsBuiltinBit, bool, 1, _) \
|
||||
V(IsAnonymousExpressionBit, bool, 1, _) \
|
||||
V(NameShouldPrintAsAnonymousBit, bool, 1, _) \
|
||||
V(HasReportedBinaryCoverageBit, bool, 1, _) \
|
||||
V(IsNamedExpressionBit, bool, 1, _) \
|
||||
V(IsTopLevelBit, bool, 1, _) \
|
||||
#define FLAGS_BIT_FIELDS(V, _) \
|
||||
/* Have FunctionKind first to make it cheaper to access */ \
|
||||
V(FunctionKindBits, FunctionKind, 5, _) \
|
||||
V(IsNativeBit, bool, 1, _) \
|
||||
V(IsStrictBit, bool, 1, _) \
|
||||
V(IsWrappedBit, bool, 1, _) \
|
||||
V(IsClassConstructorBit, bool, 1, _) \
|
||||
V(HasDuplicateParametersBit, bool, 1, _) \
|
||||
V(AllowLazyCompilationBit, bool, 1, _) \
|
||||
V(NeedsHomeObjectBit, bool, 1, _) \
|
||||
V(IsDeclarationBit, bool, 1, _) \
|
||||
V(IsAsmWasmBrokenBit, bool, 1, _) \
|
||||
V(FunctionMapIndexBits, int, 5, _) \
|
||||
V(DisabledOptimizationReasonBits, BailoutReason, 4, _) \
|
||||
V(RequiresInstanceMembersInitializer, bool, 1, _) \
|
||||
V(ConstructAsBuiltinBit, bool, 1, _) \
|
||||
V(IsAnonymousExpressionBit, bool, 1, _) \
|
||||
V(NameShouldPrintAsAnonymousBit, bool, 1, _) \
|
||||
V(HasReportedBinaryCoverageBit, bool, 1, _) \
|
||||
V(IsNamedExpressionBit, bool, 1, _) \
|
||||
V(IsTopLevelBit, bool, 1, _) \
|
||||
V(IsOneshotIIFEBit, bool, 1, _)
|
||||
DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS)
|
||||
#undef FLAGS_BIT_FIELDS
|
||||
|
@ -1390,6 +1390,18 @@ void MacroAssembler::Cmp(Operand dst, Handle<Object> source) {
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::JumpIfIsInRange(Register value, unsigned lower_limit,
|
||||
unsigned higher_limit, Label* on_in_range,
|
||||
Label::Distance near_jump) {
|
||||
if (lower_limit != 0) {
|
||||
leal(kScratchRegister, Operand(value, 0u - lower_limit));
|
||||
cmpl(kScratchRegister, Immediate(higher_limit - lower_limit));
|
||||
} else {
|
||||
cmpl(value, Immediate(higher_limit));
|
||||
}
|
||||
j(below_equal, on_in_range, near_jump);
|
||||
}
|
||||
|
||||
void TurboAssembler::Push(Handle<HeapObject> source) {
|
||||
Move(kScratchRegister, source);
|
||||
Push(kScratchRegister);
|
||||
|
@ -709,6 +709,12 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
||||
void Cmp(Register dst, Smi src);
|
||||
void Cmp(Operand dst, Smi src);
|
||||
|
||||
// Checks if value is in range [lower_limit, higher_limit] using a single
|
||||
// comparison.
|
||||
void JumpIfIsInRange(Register value, unsigned lower_limit,
|
||||
unsigned higher_limit, Label* on_in_range,
|
||||
Label::Distance near_jump = Label::kFar);
|
||||
|
||||
// Emit code to discard a non-negative number of pointer-sized elements
|
||||
// from the stack, clobbering only the rsp register.
|
||||
void Drop(int stack_elements);
|
||||
|
Loading…
Reference in New Issue
Block a user