Commit 7ada6c8b authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[maglev] Add LoadDoubleField

Add an unboxing double field load node, and fix a couple of locations
where it might be used enough to pass tests.

Bug: v8:7700
Change-Id: Ic134484e87a4fa363cbd8a3de667ac8e8116d502
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3610623Reviewed-by: 's avatarVictor Gomes <victorgomes@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80221}
parent c84b8fa4
......@@ -126,9 +126,13 @@ class MaglevCodeGeneratingNodeProcessor {
// We shouldn't spill nodes which already output to the stack.
if (!source.IsStackSlot()) {
if (FLAG_code_comments) __ RecordComment("-- Spill:");
DCHECK(!source.IsStackSlot());
__ movq(code_gen_state_->GetStackSlot(value_node->spill_slot()),
ToRegister(source));
if (source.IsRegister()) {
__ movq(code_gen_state_->GetStackSlot(value_node->spill_slot()),
ToRegister(source));
} else {
__ Movsd(code_gen_state_->GetStackSlot(value_node->spill_slot()),
ToDoubleRegister(source));
}
} else {
// Otherwise, the result source stack slot should be equal to the
// spill slot.
......
......@@ -534,9 +534,10 @@ void MaglevGraphBuilder::VisitGetNamedProperty() {
{object}, JSReceiver::kPropertiesOrHashOffset);
}
if (LoadHandler::IsDoubleBits::decode(smi_handler)) {
// TODO(leszeks): Create a LoadDoubleField which loads the
// raw double value.
MAGLEV_UNIMPLEMENTED("GetNamedProperty with double field");
SetAccumulator(AddNewNode<LoadDoubleField>(
{load_source},
LoadHandler::FieldIndexBits::decode(smi_handler) *
kTaggedSize));
} else {
SetAccumulator(AddNewNode<LoadTaggedField>(
{load_source},
......
......@@ -7,6 +7,7 @@
#include <type_traits>
#include "src/base/logging.h"
#include "src/base/optional.h"
#include "src/compiler/bytecode-analysis.h"
#include "src/compiler/bytecode-liveness-map.h"
......@@ -301,19 +302,30 @@ class MaglevGraphBuilder {
ValueNode* GetTaggedValue(interpreter::Register reg) {
// TODO(victorgomes): Add the representation (Tagged/Untagged) in the
// InterpreterFrameState, so that we don't need to derefence a node.
// TODO(victorgomes): Support Float64.
ValueNode* value = current_interpreter_frame_.get(reg);
if (value->properties().value_representation() ==
ValueRepresentation::kTagged) {
return value;
}
if (value->Is<CheckedSmiUntag>()) {
return value->input(0).node();
switch (value->properties().value_representation()) {
case ValueRepresentation::kTagged:
return value;
case ValueRepresentation::kInt32: {
if (value->Is<CheckedSmiUntag>()) {
return value->input(0).node();
}
DCHECK(value->Is<Int32AddWithOverflow>() || value->Is<Int32Constant>());
ValueNode* tagged = AddNewNode<CheckedSmiTag>({value});
current_interpreter_frame_.set(reg, tagged);
return tagged;
}
case ValueRepresentation::kFloat64: {
if (value->Is<CheckedFloat64Unbox>()) {
return value->input(0).node();
}
DCHECK(value->Is<LoadDoubleField>() || value->Is<Float64Add>());
ValueNode* tagged = AddNewNode<Float64Box>({value});
current_interpreter_frame_.set(reg, tagged);
return tagged;
}
}
DCHECK(value->Is<Int32AddWithOverflow>() || value->Is<Int32Constant>());
ValueNode* tagged = AddNewNode<CheckedSmiTag>({value});
current_interpreter_frame_.set(reg, tagged);
return tagged;
UNREACHABLE();
}
ValueNode* GetInt32(interpreter::Register reg) {
......
......@@ -81,6 +81,7 @@ class MaglevGraphVerifier {
case Opcode::kCheckedSmiUntag:
case Opcode::kGenericBitwiseNot:
case Opcode::kLoadTaggedField:
case Opcode::kLoadDoubleField:
case Opcode::kLoadGlobal:
// TODO(victorgomes): Can we check that the input is actually a map?
case Opcode::kCheckMaps:
......
......@@ -551,6 +551,27 @@ void LoadTaggedField::PrintParams(std::ostream& os,
os << "(0x" << std::hex << offset() << std::dec << ")";
}
void LoadDoubleField::AllocateVreg(MaglevVregAllocationState* vreg_state,
const ProcessingState& state) {
UseRegister(object_input());
DefineAsRegister(vreg_state, this);
set_temporaries_needed(1);
}
void LoadDoubleField::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
Register tmp = temporaries().PopFirst();
Register object = ToRegister(object_input());
__ AssertNotSmi(object);
__ DecompressAnyTagged(tmp, FieldOperand(object, offset()));
__ AssertNotSmi(tmp);
__ Movsd(ToDoubleRegister(result()),
FieldOperand(tmp, HeapNumber::kValueOffset));
}
void LoadDoubleField::PrintParams(std::ostream& os,
MaglevGraphLabeller* graph_labeller) const {
os << "(0x" << std::hex << offset() << std::dec << ")";
}
void StoreField::AllocateVreg(MaglevVregAllocationState* vreg_state,
const ProcessingState& state) {
UseRegister(object_input());
......
......@@ -70,6 +70,7 @@ class CompactInterpreterFrameState;
V(Constant) \
V(InitialValue) \
V(LoadTaggedField) \
V(LoadDoubleField) \
V(LoadGlobal) \
V(LoadNamedGeneric) \
V(Phi) \
......@@ -1296,6 +1297,29 @@ class LoadTaggedField : public FixedInputValueNodeT<1, LoadTaggedField> {
const int offset_;
};
class LoadDoubleField : public FixedInputValueNodeT<1, LoadDoubleField> {
using Base = FixedInputValueNodeT<1, LoadDoubleField>;
public:
explicit LoadDoubleField(uint32_t bitfield, int offset)
: Base(bitfield), offset_(offset) {}
static constexpr OpProperties kProperties =
OpProperties::Reading() | OpProperties::Float64();
int offset() const { return offset_; }
static constexpr int kObjectIndex = 0;
Input& object_input() { return input(kObjectIndex); }
void AllocateVreg(MaglevVregAllocationState*, const ProcessingState&);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const;
private:
const int offset_;
};
class StoreField : public FixedInputNodeT<2, StoreField> {
using Base = FixedInputNodeT<2, StoreField>;
......
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --maglev --no-stress-opt
// Checks simple monomorphic load of a Smi field works
(function() {
function load(o) {
return o.smi;
}
%PrepareFunctionForOptimization(load);
assertEquals(42, load({smi:42}));
%OptimizeMaglevOnNextCall(load);
assertEquals(42, load({smi:42}));
assertTrue(isMaglevved(load));
// We should deopt here.
assertEquals(42, load({y:0, smi:42}));
assertFalse(isMaglevved(load));
})();
// Checks simple monomorphic load of a Double field works
(function() {
function load(o) {
return o.float64;
}
%PrepareFunctionForOptimization(load);
assertEquals(42.5, load({float64:42.5}));
%OptimizeMaglevOnNextCall(load);
assertEquals(42.5, load({float64:42.5}));
assertTrue(isMaglevved(load));
// We should deopt here.
assertEquals(42.5, load({y:0, float64:42.5}));
assertFalse(isMaglevved(load));
})();
// Checks simple monomorphic load of a Double field works with a float64 add.
(function() {
function load(o) {
return o.float64 + o.float64;
}
%PrepareFunctionForOptimization(load);
assertEquals(85, load({float64:42.5}));
%OptimizeMaglevOnNextCall(load);
assertEquals(85, load({float64:42.5}));
assertTrue(isMaglevved(load));
// We should deopt here.
assertEquals(85, load({y:0, float64:42.5}));
assertFalse(isMaglevved(load));
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment