diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc index bc24a30968..301061d3fd 100644 --- a/src/compiler/effect-control-linearizer.cc +++ b/src/compiler/effect-control-linearizer.cc @@ -633,6 +633,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, case IrOpcode::kChangeTaggedToFloat64: result = LowerChangeTaggedToFloat64(node); break; + case IrOpcode::kChangeTaggedToTaggedSigned: + result = LowerChangeTaggedToTaggedSigned(node); + break; case IrOpcode::kTruncateTaggedToBit: result = LowerTruncateTaggedToBit(node); break; @@ -1032,6 +1035,27 @@ Node* EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node) { return LowerTruncateTaggedToFloat64(node); } +Node* EffectControlLinearizer::LowerChangeTaggedToTaggedSigned(Node* node) { + Node* value = node->InputAt(0); + + auto if_not_smi = __ MakeDeferredLabel<1>(); + auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); + + Node* check = ObjectIsSmi(value); + __ GotoUnless(check, &if_not_smi); + __ Goto(&done, value); + + __ Bind(&if_not_smi); + STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); + Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); + vfalse = __ ChangeFloat64ToInt32(vfalse); + vfalse = ChangeInt32ToSmi(vfalse); + __ Goto(&done, vfalse); + + __ Bind(&done); + return done.PhiAt(0); +} + Node* EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node) { Node* value = node->InputAt(0); diff --git a/src/compiler/effect-control-linearizer.h b/src/compiler/effect-control-linearizer.h index 59cbd15b1e..8a37274d74 100644 --- a/src/compiler/effect-control-linearizer.h +++ b/src/compiler/effect-control-linearizer.h @@ -51,6 +51,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer { Node* LowerChangeTaggedToBit(Node* node); Node* LowerChangeTaggedToInt32(Node* node); Node* LowerChangeTaggedToUint32(Node* node); + Node* LowerChangeTaggedToTaggedSigned(Node* node); Node* LowerCheckBounds(Node* node, Node* frame_state); Node* LowerCheckInternalizedString(Node* node, Node* frame_state); Node* LowerCheckMaps(Node* node, Node* frame_state); diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h index ef097d40d4..d79b166960 100644 --- a/src/compiler/opcodes.h +++ b/src/compiler/opcodes.h @@ -191,6 +191,7 @@ V(ChangeTaggedToInt32) \ V(ChangeTaggedToUint32) \ V(ChangeTaggedToFloat64) \ + V(ChangeTaggedToTaggedSigned) \ V(ChangeInt31ToTaggedSigned) \ V(ChangeInt32ToTagged) \ V(ChangeUint32ToTagged) \ diff --git a/src/compiler/representation-change.cc b/src/compiler/representation-change.cc index 7a5a43e61a..9b834d8417 100644 --- a/src/compiler/representation-change.cc +++ b/src/compiler/representation-change.cc @@ -271,9 +271,15 @@ Node* RepresentationChanger::GetTaggedSignedRepresentationFor( return TypeError(node, output_rep, output_type, MachineRepresentation::kTaggedSigned); } - } else if (CanBeTaggedPointer(output_rep) && - use_info.type_check() == TypeCheckKind::kSignedSmall) { - op = simplified()->CheckedTaggedToTaggedSigned(); + } else if (CanBeTaggedPointer(output_rep)) { + if (use_info.type_check() == TypeCheckKind::kSignedSmall) { + op = simplified()->CheckedTaggedToTaggedSigned(); + } else if (output_type->Is(Type::SignedSmall())) { + op = simplified()->ChangeTaggedToTaggedSigned(); + } else { + return TypeError(node, output_rep, output_type, + MachineRepresentation::kTaggedSigned); + } } else if (output_rep == MachineRepresentation::kBit && use_info.type_check() == TypeCheckKind::kSignedSmall) { // TODO(turbofan): Consider adding a Bailout operator that just deopts. diff --git a/src/compiler/simplified-operator.cc b/src/compiler/simplified-operator.cc index 5ae011618f..fc6ae965b0 100644 --- a/src/compiler/simplified-operator.cc +++ b/src/compiler/simplified-operator.cc @@ -469,6 +469,7 @@ UnicodeEncoding UnicodeEncodingOf(const Operator* op) { V(ChangeTaggedToInt32, Operator::kNoProperties, 1, 0) \ V(ChangeTaggedToUint32, Operator::kNoProperties, 1, 0) \ V(ChangeTaggedToFloat64, Operator::kNoProperties, 1, 0) \ + V(ChangeTaggedToTaggedSigned, Operator::kNoProperties, 1, 0) \ V(ChangeFloat64ToTagged, Operator::kNoProperties, 1, 0) \ V(ChangeFloat64ToTaggedPointer, Operator::kNoProperties, 1, 0) \ V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0) \ diff --git a/src/compiler/simplified-operator.h b/src/compiler/simplified-operator.h index 4cc1c98959..969c33070e 100644 --- a/src/compiler/simplified-operator.h +++ b/src/compiler/simplified-operator.h @@ -366,6 +366,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final const Operator* ChangeTaggedToInt32(); const Operator* ChangeTaggedToUint32(); const Operator* ChangeTaggedToFloat64(); + const Operator* ChangeTaggedToTaggedSigned(); const Operator* ChangeInt31ToTaggedSigned(); const Operator* ChangeInt32ToTagged(); const Operator* ChangeUint32ToTagged(); diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc index 6a97d576dd..1121f9cf2b 100644 --- a/src/compiler/verifier.cc +++ b/src/compiler/verifier.cc @@ -1012,6 +1012,8 @@ void Verifier::Visitor::Check(Node* node) { // CheckTypeIs(node, to)); break; } + case IrOpcode::kChangeTaggedToTaggedSigned: + break; case IrOpcode::kTruncateTaggedToFloat64: { // NumberOrUndefined /\ Tagged -> Number /\ UntaggedFloat64 // TODO(neis): Activate once ChangeRepresentation works in typer. diff --git a/test/mjsunit/regress/regress-crbug-687029.js b/test/mjsunit/regress/regress-crbug-687029.js new file mode 100644 index 0000000000..c3ca01fad1 --- /dev/null +++ b/test/mjsunit/regress/regress-crbug-687029.js @@ -0,0 +1,14 @@ +// Copyright 2017 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 + +function foo(x) { + x = Math.clz32(x); + return "a".indexOf("a", x); +} +foo(1); +foo(1); +%OptimizeFunctionOnNextCall(foo); +foo();