Commit c8196163 authored by ishell's avatar ishell Committed by Commit bot

[ic] Prevent KeyedStoreIC from being generic when storing doubles to integer typed arrays.

BUG=chromium:666947

Review-Url: https://codereview.chromium.org/2539013002
Cr-Commit-Position: refs/heads/master@{#41390}
parent e19f43df
......@@ -258,6 +258,37 @@ Node* CodeStubAssembler::Float64Floor(Node* x) {
return var_x.value();
}
Node* CodeStubAssembler::Float64RoundToEven(Node* x) {
if (IsFloat64RoundTiesEvenSupported()) {
return Float64RoundTiesEven(x);
}
// See ES#sec-touint8clamp for details.
Node* f = Float64Floor(x);
Node* f_and_half = Float64Add(f, Float64Constant(0.5));
Variable var_result(this, MachineRepresentation::kFloat64);
Label return_f(this), return_f_plus_one(this), done(this);
GotoIf(Float64LessThan(f_and_half, x), &return_f_plus_one);
GotoIf(Float64LessThan(x, f_and_half), &return_f);
{
Node* f_mod_2 = Float64Mod(f, Float64Constant(2.0));
Branch(Float64Equal(f_mod_2, Float64Constant(0.0)), &return_f,
&return_f_plus_one);
}
Bind(&return_f);
var_result.Bind(f);
Goto(&done);
Bind(&return_f_plus_one);
var_result.Bind(Float64Add(f, Float64Constant(1.0)));
Goto(&done);
Bind(&done);
return var_result.value();
}
Node* CodeStubAssembler::Float64Trunc(Node* x) {
if (IsFloat64RoundTruncateSupported()) {
return Float64RoundTruncate(x);
......@@ -5505,21 +5536,6 @@ Node* CodeStubAssembler::LoadScriptContext(Node* context, int context_index) {
IntPtrConstant(offset));
}
Node* CodeStubAssembler::ClampedToUint8(Node* int32_value) {
Label done(this);
Node* int32_zero = Int32Constant(0);
Node* int32_255 = Int32Constant(255);
Variable var_value(this, MachineRepresentation::kWord32);
var_value.Bind(int32_value);
GotoIf(Uint32LessThanOrEqual(int32_value, int32_255), &done);
var_value.Bind(int32_zero);
GotoIf(Int32LessThan(int32_value, int32_zero), &done);
var_value.Bind(int32_255);
Goto(&done);
Bind(&done);
return var_value.value();
}
namespace {
// Converts typed array elements kind to a machine representations.
......@@ -5552,7 +5568,8 @@ void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind,
ParameterMode mode) {
if (IsFixedTypedArrayElementsKind(kind)) {
if (kind == UINT8_CLAMPED_ELEMENTS) {
value = ClampedToUint8(value);
CSA_ASSERT(this,
Word32Equal(value, Word32And(Int32Constant(0xff), value)));
}
Node* offset = ElementOffsetFromIndex(index, kind, mode, 0);
MachineRepresentation rep = ElementsKindToMachineRepresentation(kind);
......@@ -5571,6 +5588,106 @@ void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind,
}
}
Node* CodeStubAssembler::Int32ToUint8Clamped(Node* int32_value) {
Label done(this);
Node* int32_zero = Int32Constant(0);
Node* int32_255 = Int32Constant(255);
Variable var_value(this, MachineRepresentation::kWord32);
var_value.Bind(int32_value);
GotoIf(Uint32LessThanOrEqual(int32_value, int32_255), &done);
var_value.Bind(int32_zero);
GotoIf(Int32LessThan(int32_value, int32_zero), &done);
var_value.Bind(int32_255);
Goto(&done);
Bind(&done);
return var_value.value();
}
Node* CodeStubAssembler::Float64ToUint8Clamped(Node* float64_value) {
Label done(this);
Variable var_value(this, MachineRepresentation::kWord32);
var_value.Bind(Int32Constant(0));
GotoIf(Float64LessThanOrEqual(float64_value, Float64Constant(0.0)), &done);
var_value.Bind(Int32Constant(255));
GotoIf(Float64LessThanOrEqual(Float64Constant(255.0), float64_value), &done);
{
Node* rounded_value = Float64RoundToEven(float64_value);
var_value.Bind(TruncateFloat64ToWord32(rounded_value));
Goto(&done);
}
Bind(&done);
return var_value.value();
}
Node* CodeStubAssembler::PrepareValueForWriteToTypedArray(
Node* input, ElementsKind elements_kind, Label* bailout) {
DCHECK(IsFixedTypedArrayElementsKind(elements_kind));
MachineRepresentation rep;
switch (elements_kind) {
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
rep = MachineRepresentation::kWord32;
break;
case FLOAT32_ELEMENTS:
rep = MachineRepresentation::kFloat32;
break;
case FLOAT64_ELEMENTS:
rep = MachineRepresentation::kFloat64;
break;
default:
UNREACHABLE();
return nullptr;
}
Variable var_result(this, rep);
Label done(this, &var_result), if_smi(this);
GotoIf(TaggedIsSmi(input), &if_smi);
// Try to convert a heap number to a Smi.
GotoUnless(IsHeapNumberMap(LoadMap(input)), bailout);
{
Node* value = LoadHeapNumberValue(input);
if (rep == MachineRepresentation::kWord32) {
if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
value = Float64ToUint8Clamped(value);
} else {
value = TruncateFloat64ToWord32(value);
}
} else if (rep == MachineRepresentation::kFloat32) {
value = TruncateFloat64ToFloat32(value);
} else {
DCHECK_EQ(MachineRepresentation::kFloat64, rep);
}
var_result.Bind(value);
Goto(&done);
}
Bind(&if_smi);
{
Node* value = SmiToWord32(input);
if (rep == MachineRepresentation::kFloat32) {
value = RoundInt32ToFloat32(value);
} else if (rep == MachineRepresentation::kFloat64) {
value = ChangeInt32ToFloat64(value);
} else {
DCHECK_EQ(MachineRepresentation::kWord32, rep);
if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
value = Int32ToUint8Clamped(value);
}
}
var_result.Bind(value);
Goto(&done);
}
Bind(&done);
return var_result.value();
}
void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
bool is_jsarray,
ElementsKind elements_kind,
......@@ -5593,16 +5710,7 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
// TODO(ishell): call ToNumber() on value and don't bailout but be careful
// to call it only once if we decide to bailout because of bounds checks.
if (IsFixedFloatElementsKind(elements_kind)) {
// TODO(ishell): move float32 truncation into PrepareValueForWrite.
value = PrepareValueForWrite(value, Representation::Double(), bailout);
if (elements_kind == FLOAT32_ELEMENTS) {
value = TruncateFloat64ToFloat32(value);
}
} else {
// TODO(ishell): It's fine for word8/16/32 to truncate the result.
value = TryToIntptr(value, bailout);
}
value = PrepareValueForWriteToTypedArray(value, elements_kind, bailout);
// There must be no allocations between the buffer load and
// and the actual store to backing store, because GC may decide that
......@@ -5656,7 +5764,7 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
if (IsFastSmiElementsKind(elements_kind)) {
GotoUnless(TaggedIsSmi(value), bailout);
} else if (IsFastDoubleElementsKind(elements_kind)) {
value = PrepareValueForWrite(value, Representation::Double(), bailout);
value = TryTaggedToFloat64(value, bailout);
}
if (IsGrowStoreMode(store_mode)) {
......
......@@ -115,6 +115,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* Float64Ceil(Node* x);
Node* Float64Floor(Node* x);
Node* Float64Round(Node* x);
Node* Float64RoundToEven(Node* x);
Node* Float64Trunc(Node* x);
// Tag a Word as a Smi value.
......@@ -860,7 +861,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Loads script context from the script context table.
Node* LoadScriptContext(Node* context, int context_index);
Node* ClampedToUint8(Node* int32_value);
Node* Int32ToUint8Clamped(Node* int32_value);
Node* Float64ToUint8Clamped(Node* float64_value);
Node* PrepareValueForWriteToTypedArray(Node* key, ElementsKind elements_kind,
Label* bailout);
// Store value to an elements array with given elements kind.
void StoreElement(Node* elements, ElementsKind kind, Node* index, Node* value,
......
......@@ -93,6 +93,10 @@ bool CodeAssembler::IsFloat64RoundDownSupported() const {
return raw_assembler()->machine()->Float64RoundDown().IsSupported();
}
bool CodeAssembler::IsFloat64RoundTiesEvenSupported() const {
return raw_assembler()->machine()->Float64RoundTiesEven().IsSupported();
}
bool CodeAssembler::IsFloat64RoundTruncateSupported() const {
return raw_assembler()->machine()->Float64RoundTruncate().IsSupported();
}
......
......@@ -151,9 +151,11 @@ class RawMachineLabel;
V(ChangeUint32ToFloat64) \
V(ChangeUint32ToUint64) \
V(RoundFloat64ToInt32) \
V(RoundInt32ToFloat32) \
V(Float64SilenceNaN) \
V(Float64RoundDown) \
V(Float64RoundUp) \
V(Float64RoundTiesEven) \
V(Float64RoundTruncate) \
V(Word32Clz) \
V(Word32BinaryNot)
......@@ -189,6 +191,7 @@ class V8_EXPORT_PRIVATE CodeAssembler {
bool Is64() const;
bool IsFloat64RoundUpSupported() const;
bool IsFloat64RoundDownSupported() const;
bool IsFloat64RoundTiesEvenSupported() const;
bool IsFloat64RoundTruncateSupported() const;
class Label;
......
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