Reland "[maglev] Inline allocation for heap numbers"
This is a reland of commit ef1e65d9ae
Original change's description:
> [maglev] Inline allocation for heap numbers
>
> Bug: v8:7700
> Change-Id: I2ce46fcfaab6716e6a31167ed517d2e8d9e433d8
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3788094
> Reviewed-by: Leszek Swirski <leszeks@chromium.org>
> Commit-Queue: Victor Gomes <victorgomes@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#82027}
Bug: v8:7700
Change-Id: I3d86880c20ef4b5765a87d272f18cad9fac210fe
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3790971
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82041}
This commit is contained in:
parent
cda6dab9cf
commit
cd02fe8edb
@ -87,7 +87,7 @@ void UseFixed(Input& input, Register reg) {
|
|||||||
input.SetUnallocated(compiler::UnallocatedOperand::FIXED_REGISTER, reg.code(),
|
input.SetUnallocated(compiler::UnallocatedOperand::FIXED_REGISTER, reg.code(),
|
||||||
GetVirtualRegister(input.node()));
|
GetVirtualRegister(input.node()));
|
||||||
}
|
}
|
||||||
void UseFixed(Input& input, DoubleRegister reg) {
|
[[maybe_unused]] void UseFixed(Input& input, DoubleRegister reg) {
|
||||||
input.SetUnallocated(compiler::UnallocatedOperand::FIXED_FP_REGISTER,
|
input.SetUnallocated(compiler::UnallocatedOperand::FIXED_FP_REGISTER,
|
||||||
reg.code(), GetVirtualRegister(input.node()));
|
reg.code(), GetVirtualRegister(input.node()));
|
||||||
}
|
}
|
||||||
@ -225,6 +225,10 @@ struct CopyForDeferredHelper<EagerDeoptInfo*>
|
|||||||
template <>
|
template <>
|
||||||
struct CopyForDeferredHelper<ZoneLabelRef>
|
struct CopyForDeferredHelper<ZoneLabelRef>
|
||||||
: public CopyForDeferredByValue<ZoneLabelRef> {};
|
: public CopyForDeferredByValue<ZoneLabelRef> {};
|
||||||
|
// Register snapshots are copied by value.
|
||||||
|
template <>
|
||||||
|
struct CopyForDeferredHelper<RegisterSnapshot>
|
||||||
|
: public CopyForDeferredByValue<RegisterSnapshot> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T CopyForDeferred(MaglevCompilationInfo* compilation_info, T&& value) {
|
T CopyForDeferred(MaglevCompilationInfo* compilation_info, T&& value) {
|
||||||
@ -325,6 +329,68 @@ void JumpToDeferredIf(Condition cond, MaglevCodeGenState* code_gen_state,
|
|||||||
__ bind(&deferred_code->return_label);
|
__ bind(&deferred_code->return_label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---
|
||||||
|
// Inlined computations.
|
||||||
|
// ---
|
||||||
|
|
||||||
|
void AllocateRaw(MaglevCodeGenState* code_gen_state,
|
||||||
|
RegisterSnapshot& register_snapshot, Register object,
|
||||||
|
int size_in_bytes,
|
||||||
|
AllocationType alloc_type = AllocationType::kYoung,
|
||||||
|
AllocationAlignment alignment = kTaggedAligned) {
|
||||||
|
// TODO(victorgomes): Call the runtime for large object allocation.
|
||||||
|
// TODO(victorgomes): Support double alignment.
|
||||||
|
DCHECK_EQ(alignment, kTaggedAligned);
|
||||||
|
if (FLAG_single_generation) {
|
||||||
|
alloc_type = AllocationType::kOld;
|
||||||
|
}
|
||||||
|
bool in_new_space = alloc_type == AllocationType::kYoung;
|
||||||
|
Isolate* isolate = code_gen_state->isolate();
|
||||||
|
ExternalReference top =
|
||||||
|
in_new_space
|
||||||
|
? ExternalReference::new_space_allocation_top_address(isolate)
|
||||||
|
: ExternalReference::old_space_allocation_top_address(isolate);
|
||||||
|
ExternalReference limit =
|
||||||
|
in_new_space
|
||||||
|
? ExternalReference::new_space_allocation_limit_address(isolate)
|
||||||
|
: ExternalReference::old_space_allocation_limit_address(isolate);
|
||||||
|
|
||||||
|
ZoneLabelRef done(code_gen_state->compilation_info()->zone());
|
||||||
|
Register new_top = kScratchRegister;
|
||||||
|
// Check if there is enough space.
|
||||||
|
__ Move(object, __ ExternalReferenceAsOperand(top));
|
||||||
|
__ leaq(new_top, Operand(object, size_in_bytes));
|
||||||
|
__ cmpq(new_top, __ ExternalReferenceAsOperand(limit));
|
||||||
|
// Otherwise call runtime.
|
||||||
|
JumpToDeferredIf(
|
||||||
|
greater_equal, code_gen_state,
|
||||||
|
[](MaglevCodeGenState* code_gen_state, Label* return_label,
|
||||||
|
RegisterSnapshot register_snapshot, Register object, Builtin builtin,
|
||||||
|
int size_in_bytes, ZoneLabelRef done) {
|
||||||
|
// Remove {object} from snapshot, since it is the returned allocated
|
||||||
|
// HeapObject.
|
||||||
|
register_snapshot.live_registers.clear(object);
|
||||||
|
{
|
||||||
|
SaveRegisterStateForCall save_register_state(code_gen_state,
|
||||||
|
register_snapshot);
|
||||||
|
using D = AllocateDescriptor;
|
||||||
|
__ Move(D::GetRegisterParameter(D::kRequestedSize), size_in_bytes);
|
||||||
|
__ CallBuiltin(builtin);
|
||||||
|
save_register_state.DefineSafepoint();
|
||||||
|
__ Move(object, kReturnRegister0);
|
||||||
|
}
|
||||||
|
__ jmp(*done);
|
||||||
|
},
|
||||||
|
register_snapshot, object,
|
||||||
|
in_new_space ? Builtin::kAllocateRegularInYoungGeneration
|
||||||
|
: Builtin::kAllocateRegularInOldGeneration,
|
||||||
|
size_in_bytes, done);
|
||||||
|
// Store new top and tag object.
|
||||||
|
__ movq(__ ExternalReferenceAsOperand(top), new_top);
|
||||||
|
__ addq(object, Immediate(kHeapObjectTag));
|
||||||
|
__ bind(*done);
|
||||||
|
}
|
||||||
|
|
||||||
void ToBoolean(MaglevCodeGenState* code_gen_state, Register value,
|
void ToBoolean(MaglevCodeGenState* code_gen_state, Register value,
|
||||||
ZoneLabelRef is_true, ZoneLabelRef is_false,
|
ZoneLabelRef is_true, ZoneLabelRef is_false,
|
||||||
bool fallthrough_when_true) {
|
bool fallthrough_when_true) {
|
||||||
@ -1923,14 +1989,23 @@ void Int32Constant::PrintParams(std::ostream& os,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Float64Box::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
void Float64Box::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
||||||
using D = NewHeapNumberDescriptor;
|
UseRegister(input());
|
||||||
UseFixed(input(), D::GetDoubleRegisterParameter(D::kValue));
|
DefineAsRegister(vreg_state, this);
|
||||||
DefineAsFixed(vreg_state, this, kReturnRegister0);
|
|
||||||
}
|
}
|
||||||
void Float64Box::GenerateCode(MaglevCodeGenState* code_gen_state,
|
void Float64Box::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||||
const ProcessingState& state) {
|
const ProcessingState& state) {
|
||||||
// TODO(victorgomes): Inline heap number allocation.
|
DoubleRegister value = ToDoubleRegister(input());
|
||||||
__ CallBuiltin(Builtin::kNewHeapNumber);
|
Register object = ToRegister(result());
|
||||||
|
// In the case we need to call the runtime, we should spill the input
|
||||||
|
// register. Even if it is not live in the next node, otherwise the allocation
|
||||||
|
// call might trash it.
|
||||||
|
RegisterSnapshot save_registers = register_snapshot();
|
||||||
|
save_registers.live_double_registers.set(value);
|
||||||
|
AllocateRaw(code_gen_state, save_registers, object, HeapNumber::kSize);
|
||||||
|
__ LoadRoot(kScratchRegister, RootIndex::kHeapNumberMap);
|
||||||
|
__ StoreTaggedField(FieldOperand(object, HeapObject::kMapOffset),
|
||||||
|
kScratchRegister);
|
||||||
|
__ Movsd(FieldOperand(object, HeapNumber::kValueOffset), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckedFloat64Unbox::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
void CheckedFloat64Unbox::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
||||||
|
@ -1516,7 +1516,7 @@ class Float64Box : public FixedInputValueNodeT<1, Float64Box> {
|
|||||||
explicit Float64Box(uint64_t bitfield) : Base(bitfield) {}
|
explicit Float64Box(uint64_t bitfield) : Base(bitfield) {}
|
||||||
|
|
||||||
static constexpr OpProperties kProperties =
|
static constexpr OpProperties kProperties =
|
||||||
OpProperties::Call() | OpProperties::ConversionNode();
|
OpProperties::DeferredCall() | OpProperties::ConversionNode();
|
||||||
|
|
||||||
Input& input() { return Node::input(0); }
|
Input& input() { return Node::input(0); }
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user