Commit 8bc54052 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[csa] Merge in- and out-of-object store paths

Rather than duplicating code paths for in- and out-of-object stores,
have one code path which checks whether it needs to load the property
store (and change the storage location to the HeapNumber value for
unboxed doubles).

As a drive-by, change the representation dispatch into a switch, and
inline the representation checks into that switch, to make explicit
what checks for what and which paths transform the value. Also, TNodify
some of the surrounding functions.

Change-Id: Ia1bf698b4cec3ffce9aaa5732cda2e3be9efd8e8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1795345Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63652}
parent d7d25d2a
......@@ -5609,45 +5609,22 @@ void CodeStubAssembler::InitializeAllocationMemento(Node* base,
Comment("]");
}
Node* CodeStubAssembler::TryTaggedToFloat64(Node* value,
Label* if_valueisnotnumber) {
Label out(this);
VARIABLE(var_result, MachineRepresentation::kFloat64);
// Check if the {value} is a Smi or a HeapObject.
Label if_valueissmi(this), if_valueisnotsmi(this);
Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
BIND(&if_valueissmi);
{
// Convert the Smi {value}.
var_result.Bind(SmiToFloat64(value));
Goto(&out);
}
BIND(&if_valueisnotsmi);
{
// Check if {value} is a HeapNumber.
Label if_valueisheapnumber(this);
Branch(IsHeapNumber(value), &if_valueisheapnumber, if_valueisnotnumber);
BIND(&if_valueisheapnumber);
{
// Load the floating point value.
var_result.Bind(LoadHeapNumberValue(value));
Goto(&out);
}
}
BIND(&out);
return var_result.value();
TNode<Float64T> CodeStubAssembler::TryTaggedToFloat64(
TNode<Object> value, Label* if_valueisnotnumber) {
return Select<Float64T>(
TaggedIsSmi(value), [&]() { return SmiToFloat64(CAST(value)); },
[&]() {
GotoIfNot(IsHeapNumber(CAST(value)), if_valueisnotnumber);
return LoadHeapNumberValue(CAST(value));
});
}
Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) {
TNode<Float64T> CodeStubAssembler::TruncateTaggedToFloat64(
SloppyTNode<Context> context, SloppyTNode<Object> value) {
// We might need to loop once due to ToNumber conversion.
VARIABLE(var_value, MachineRepresentation::kTagged);
VARIABLE(var_result, MachineRepresentation::kFloat64);
TVARIABLE(Object, var_value, value);
TVARIABLE(Float64T, var_result);
Label loop(this, &var_value), done_loop(this, &var_result);
var_value.Bind(value);
Goto(&loop);
BIND(&loop);
{
......@@ -5658,14 +5635,13 @@ Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) {
// Convert {value} to Float64 if it is a number and convert it to a number
// otherwise.
Node* const result = TryTaggedToFloat64(value, &if_valueisnotnumber);
var_result.Bind(result);
var_result = TryTaggedToFloat64(value, &if_valueisnotnumber);
Goto(&done_loop);
BIND(&if_valueisnotnumber);
{
// Convert the {value} to a Number first.
var_value.Bind(CallBuiltin(Builtins::kNonNumberToNumber, context, value));
var_value = CallBuiltin(Builtins::kNonNumberToNumber, context, value);
Goto(&loop);
}
}
......@@ -5673,13 +5649,14 @@ Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) {
return var_result.value();
}
Node* CodeStubAssembler::TruncateTaggedToWord32(Node* context, Node* value) {
TNode<Word32T> CodeStubAssembler::TruncateTaggedToWord32(
SloppyTNode<Context> context, SloppyTNode<Object> value) {
VARIABLE(var_result, MachineRepresentation::kWord32);
Label done(this);
TaggedToWord32OrBigIntImpl<Object::Conversion::kToNumber>(context, value,
&done, &var_result);
BIND(&done);
return var_result.value();
return UncheckedCast<Word32T>(var_result.value());
}
// Truncate {value} to word32 and jump to {if_number} if it is a Number,
......@@ -10945,7 +10922,7 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
if (IsSmiElementsKind(elements_kind)) {
GotoIfNot(TaggedIsSmi(value), bailout);
} else if (IsDoubleElementsKind(elements_kind)) {
value = TryTaggedToFloat64(value, bailout);
value = TryTaggedToFloat64(CAST(value), bailout);
}
if (IsGrowStoreMode(store_mode) &&
......
......@@ -2242,9 +2242,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
Node* base_allocation_size,
Node* allocation_site);
Node* TryTaggedToFloat64(Node* value, Label* if_valueisnotnumber);
Node* TruncateTaggedToFloat64(Node* context, Node* value);
Node* TruncateTaggedToWord32(Node* context, Node* value);
TNode<Float64T> TryTaggedToFloat64(TNode<Object> value,
Label* if_valueisnotnumber);
TNode<Float64T> TruncateTaggedToFloat64(SloppyTNode<Context> context,
SloppyTNode<Object> value);
TNode<Word32T> TruncateTaggedToWord32(SloppyTNode<Context> context,
SloppyTNode<Object> value);
void TaggedToWord32OrBigInt(Node* context, Node* value, Label* if_number,
Variable* var_word32, Label* if_bigint,
Variable* var_bigint);
......
This diff is collapsed.
......@@ -5,6 +5,7 @@
#ifndef V8_IC_ACCESSOR_ASSEMBLER_H_
#define V8_IC_ACCESSOR_ASSEMBLER_H_
#include "src/base/optional.h"
#include "src/codegen/code-stub-assembler.h"
namespace v8 {
......@@ -314,22 +315,24 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
TNode<StoreHandler> handler, Label* miss,
ICMode ic_mode,
ElementSupport support_elements);
void HandleStoreICSmiHandlerCase(Node* handler_word, Node* holder,
Node* value, Label* miss);
void HandleStoreFieldAndReturn(Node* handler_word, Node* holder,
Representation representation, Node* value,
Label* miss);
void HandleStoreICSmiHandlerCase(SloppyTNode<Word32T> handler_word,
SloppyTNode<JSObject> holder,
SloppyTNode<Object> value, Label* miss);
void HandleStoreFieldAndReturn(TNode<Word32T> handler_word,
TNode<JSObject> holder, TNode<Object> value,
base::Optional<TNode<Float64T>> double_value,
Representation representation, Label* miss);
void CheckPrototypeValidityCell(TNode<Object> maybe_validity_cell,
Label* miss);
void HandleStoreICNativeDataProperty(const StoreICParameters* p, Node* holder,
Node* handler_word);
TNode<Word32T> handler_word);
void HandleStoreToProxy(const StoreICParameters* p, Node* proxy, Label* miss,
ElementSupport support_elements);
void HandleStoreAccessor(const StoreICParameters* p, Node* holder,
Node* handler_word);
TNode<Word32T> handler_word);
// KeyedLoadIC_Generic implementation.
......@@ -355,18 +358,20 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
const OnFoundOnReceiver& on_found_on_receiver,
Label* miss, ICMode ic_mode);
Node* PrepareValueForStore(Node* handler_word, Node* holder,
Representation representation, Node* value,
Label* bailout);
void CheckHeapObjectTypeMatchesDescriptor(TNode<Word32T> handler_word,
TNode<JSObject> holder,
TNode<Object> value,
Label* bailout);
// Double fields store double values in a mutable box, where stores are
// writes into this box rather than HeapNumber assignment.
void CheckDescriptorConsidersNumbersMutable(TNode<Word32T> handler_word,
TNode<JSObject> holder,
Label* bailout);
// Extends properties backing store by JSObject::kFieldsAdded elements,
// returns updated properties backing store.
Node* ExtendPropertiesBackingStore(Node* object, Node* index);
void StoreNamedField(Node* handler_word, Node* object, bool is_inobject,
Representation representation, Node* value,
Label* bailout);
void EmitFastElementsBoundsCheck(Node* object, Node* elements,
Node* intptr_index,
Node* is_jsarray_condition, Label* miss);
......
......@@ -145,29 +145,12 @@ Handle<Smi> StoreHandler::StoreProxy(Isolate* isolate) {
Handle<Smi> StoreHandler::StoreField(Isolate* isolate, Kind kind,
int descriptor, FieldIndex field_index,
Representation representation) {
FieldRepresentation field_rep;
switch (representation.kind()) {
case Representation::kSmi:
field_rep = kSmi;
break;
case Representation::kDouble:
field_rep = kDouble;
break;
case Representation::kHeapObject:
field_rep = kHeapObject;
break;
case Representation::kTagged:
field_rep = kTagged;
break;
default:
UNREACHABLE();
}
DCHECK(!representation.IsNone());
DCHECK(kind == kField || kind == kConstField);
int config = KindBits::encode(kind) |
IsInobjectBits::encode(field_index.is_inobject()) |
FieldRepresentationBits::encode(field_rep) |
RepresentationBits::encode(representation.kind()) |
DescriptorBits::encode(descriptor) |
FieldIndexBits::encode(field_index.index());
return handle(Smi::FromInt(config), isolate);
......
......@@ -204,8 +204,6 @@ class StoreHandler final : public DataHandler {
};
using KindBits = BitField<Kind, 0, 4>;
enum FieldRepresentation { kSmi, kDouble, kHeapObject, kTagged };
// Applicable to kGlobalProxy, kProxy kinds.
// Defines whether access rights check should be done on receiver object.
......@@ -233,10 +231,10 @@ class StoreHandler final : public DataHandler {
// Encoding when KindBits contains kField or kTransitionToField.
//
using IsInobjectBits = DescriptorBits::Next<bool, 1>;
using FieldRepresentationBits = IsInobjectBits::Next<FieldRepresentation, 2>;
using RepresentationBits = IsInobjectBits::Next<Representation::Kind, 3>;
// +1 here is to cover all possible JSObject header sizes.
using FieldIndexBits =
FieldRepresentationBits::Next<unsigned, kDescriptorIndexBitCount + 1>;
RepresentationBits::Next<unsigned, kDescriptorIndexBitCount + 1>;
// Make sure we don't overflow the smi.
STATIC_ASSERT(FieldIndexBits::kLastUsedBit < kSmiValueSize);
......
......@@ -94,7 +94,7 @@ class KeyedStoreGenericAssembler : public AccessorAssembler {
void StoreElementWithCapacity(Node* receiver, TNode<Map> receiver_map,
SloppyTNode<FixedArrayBase> elements,
TNode<Word32T> elements_kind,
TNode<IntPtrT> index, Node* value,
TNode<IntPtrT> index, SloppyTNode<Object> value,
Node* context, Label* slow,
UpdateLength update_length);
......@@ -306,7 +306,7 @@ void KeyedStoreGenericAssembler::MaybeUpdateLengthAndReturn(
void KeyedStoreGenericAssembler::StoreElementWithCapacity(
Node* receiver, TNode<Map> receiver_map,
SloppyTNode<FixedArrayBase> elements, TNode<Word32T> elements_kind,
TNode<IntPtrT> index, Node* value, Node* context, Label* slow,
TNode<IntPtrT> index, SloppyTNode<Object> value, Node* context, Label* slow,
UpdateLength update_length) {
if (update_length != kDontChangeLength) {
CSA_ASSERT(this, InstanceTypeEqual(LoadMapInstanceType(receiver_map),
......@@ -388,7 +388,7 @@ void KeyedStoreGenericAssembler::StoreElementWithCapacity(
{
Label transition_to_double(this), transition_to_object(this);
TNode<Context> native_context = LoadNativeContext(context);
Branch(TaggedEqual(LoadMap(value), HeapNumberMapConstant()),
Branch(TaggedEqual(LoadMap(CAST(value)), HeapNumberMapConstant()),
&transition_to_double, &transition_to_object);
BIND(&transition_to_double);
{
......@@ -405,7 +405,7 @@ void KeyedStoreGenericAssembler::StoreElementWithCapacity(
index, PACKED_DOUBLE_ELEMENTS, INTPTR_PARAMETERS, kHeaderSize);
// Make sure we do not store signalling NaNs into double arrays.
TNode<Float64T> double_value =
Float64SilenceNaN(LoadHeapNumberValue(value));
Float64SilenceNaN(LoadHeapNumberValue(CAST(value)));
StoreNoWriteBarrier(MachineRepresentation::kFloat64, double_elements,
double_offset, double_value);
MaybeUpdateLengthAndReturn(receiver, index, value, update_length);
......
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