Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Unified Diff: src/code-stub-assembler.cc

Issue 2539013002: [ic] Prevent KeyedStoreIC from being generic when storing doubles to integer typed arrays. (Closed)
Patch Set: Always use Float64RoundTiesEven instruction when available Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/compiler/code-assembler.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/code-stub-assembler.cc
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
index 6d4ce690ff97f01062099ea524a4ea1c767f1cef..0d071d969042dba7272e415729e5f4ece4e1c939 100644
--- a/src/code-stub-assembler.cc
+++ b/src/code-stub-assembler.cc
@@ -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);
@@ -5401,21 +5432,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.
@@ -5448,7 +5464,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);
@@ -5467,6 +5484,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,
@@ -5489,16 +5606,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
@@ -5552,7 +5660,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)) {
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/compiler/code-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698