summaryrefslogtreecommitdiffstats
path: root/chromium/v8/src/ic/unary-op-assembler.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/v8/src/ic/unary-op-assembler.cc
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/v8/src/ic/unary-op-assembler.cc')
-rw-r--r--chromium/v8/src/ic/unary-op-assembler.cc283
1 files changed, 283 insertions, 0 deletions
diff --git a/chromium/v8/src/ic/unary-op-assembler.cc b/chromium/v8/src/ic/unary-op-assembler.cc
new file mode 100644
index 00000000000..6580601a1f4
--- /dev/null
+++ b/chromium/v8/src/ic/unary-op-assembler.cc
@@ -0,0 +1,283 @@
+// Copyright 2020 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.
+
+#include "src/ic/unary-op-assembler.h"
+
+#include "src/common/globals.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+class UnaryOpAssemblerImpl final : public CodeStubAssembler {
+ public:
+ explicit UnaryOpAssemblerImpl(compiler::CodeAssemblerState* state)
+ : CodeStubAssembler(state) {}
+
+ TNode<Object> BitwiseNot(TNode<Context> context, TNode<Object> value,
+ TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector) {
+ // TODO(jgruber): Make this implementation more consistent with other unary
+ // ops (i.e. have them all use UnaryOpWithFeedback or some other common
+ // mechanism).
+ TVARIABLE(Word32T, var_word32);
+ TVARIABLE(Smi, var_feedback);
+ TVARIABLE(BigInt, var_bigint);
+ TVARIABLE(Object, var_result);
+ Label if_number(this), if_bigint(this, Label::kDeferred), out(this);
+ TaggedToWord32OrBigIntWithFeedback(context, value, &if_number, &var_word32,
+ &if_bigint, &var_bigint, &var_feedback);
+
+ // Number case.
+ BIND(&if_number);
+ var_result =
+ ChangeInt32ToTagged(Signed(Word32BitwiseNot(var_word32.value())));
+ TNode<Smi> result_type = SelectSmiConstant(
+ TaggedIsSmi(var_result.value()), BinaryOperationFeedback::kSignedSmall,
+ BinaryOperationFeedback::kNumber);
+ UpdateFeedback(SmiOr(result_type, var_feedback.value()),
+ maybe_feedback_vector, slot);
+ Goto(&out);
+
+ // BigInt case.
+ BIND(&if_bigint);
+ UpdateFeedback(SmiConstant(BinaryOperationFeedback::kBigInt),
+ maybe_feedback_vector, slot);
+ var_result =
+ CallRuntime(Runtime::kBigIntUnaryOp, context, var_bigint.value(),
+ SmiConstant(Operation::kBitwiseNot));
+ Goto(&out);
+
+ BIND(&out);
+ return var_result.value();
+ }
+
+ TNode<Object> Decrement(TNode<Context> context, TNode<Object> value,
+ TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector) {
+ return IncrementOrDecrement<Operation::kDecrement>(context, value, slot,
+ maybe_feedback_vector);
+ }
+
+ TNode<Object> Increment(TNode<Context> context, TNode<Object> value,
+ TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector) {
+ return IncrementOrDecrement<Operation::kIncrement>(context, value, slot,
+ maybe_feedback_vector);
+ }
+
+ TNode<Object> Negate(TNode<Context> context, TNode<Object> value,
+ TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector) {
+ SmiOperation smi_op = [=](TNode<Smi> smi_value,
+ TVariable<Smi>* var_feedback, Label* do_float_op,
+ TVariable<Float64T>* var_float) {
+ TVARIABLE(Number, var_result);
+ Label if_zero(this), if_min_smi(this), end(this);
+ // Return -0 if operand is 0.
+ GotoIf(SmiEqual(smi_value, SmiConstant(0)), &if_zero);
+
+ // Special-case the minimum Smi to avoid overflow.
+ GotoIf(SmiEqual(smi_value, SmiConstant(Smi::kMinValue)), &if_min_smi);
+
+ // Else simply subtract operand from 0.
+ CombineFeedback(var_feedback, BinaryOperationFeedback::kSignedSmall);
+ var_result = SmiSub(SmiConstant(0), smi_value);
+ Goto(&end);
+
+ BIND(&if_zero);
+ CombineFeedback(var_feedback, BinaryOperationFeedback::kNumber);
+ var_result = MinusZeroConstant();
+ Goto(&end);
+
+ BIND(&if_min_smi);
+ *var_float = SmiToFloat64(smi_value);
+ Goto(do_float_op);
+
+ BIND(&end);
+ return var_result.value();
+ };
+ FloatOperation float_op = [=](TNode<Float64T> float_value) {
+ return Float64Neg(float_value);
+ };
+ BigIntOperation bigint_op = [=](TNode<Context> context,
+ TNode<HeapObject> bigint_value) {
+ return CAST(CallRuntime(Runtime::kBigIntUnaryOp, context, bigint_value,
+ SmiConstant(Operation::kNegate)));
+ };
+ return UnaryOpWithFeedback(context, value, slot, maybe_feedback_vector,
+ smi_op, float_op, bigint_op);
+ }
+
+ private:
+ using SmiOperation = std::function<TNode<Number>(
+ TNode<Smi> /* smi_value */, TVariable<Smi>* /* var_feedback */,
+ Label* /* do_float_op */, TVariable<Float64T>* /* var_float */)>;
+ using FloatOperation =
+ std::function<TNode<Float64T>(TNode<Float64T> /* float_value */)>;
+ using BigIntOperation = std::function<TNode<HeapObject>(
+ TNode<Context> /* context */, TNode<HeapObject> /* bigint_value */)>;
+
+ TNode<Object> UnaryOpWithFeedback(TNode<Context> context, TNode<Object> value,
+ TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector,
+ const SmiOperation& smi_op,
+ const FloatOperation& float_op,
+ const BigIntOperation& bigint_op) {
+ TVARIABLE(Object, var_value, value);
+ TVARIABLE(Object, var_result);
+ TVARIABLE(Float64T, var_float_value);
+ TVARIABLE(Smi, var_feedback, SmiConstant(BinaryOperationFeedback::kNone));
+ Label start(this, {&var_value, &var_feedback}), end(this);
+ Label do_float_op(this, &var_float_value);
+ Goto(&start);
+ // We might have to try again after ToNumeric conversion.
+ BIND(&start);
+ {
+ Label if_smi(this), if_heapnumber(this), if_oddball(this);
+ Label if_bigint(this, Label::kDeferred);
+ Label if_other(this, Label::kDeferred);
+ TNode<Object> value = var_value.value();
+ GotoIf(TaggedIsSmi(value), &if_smi);
+
+ TNode<HeapObject> value_heap_object = CAST(value);
+ TNode<Map> map = LoadMap(value_heap_object);
+ GotoIf(IsHeapNumberMap(map), &if_heapnumber);
+ TNode<Uint16T> instance_type = LoadMapInstanceType(map);
+ GotoIf(IsBigIntInstanceType(instance_type), &if_bigint);
+ Branch(InstanceTypeEqual(instance_type, ODDBALL_TYPE), &if_oddball,
+ &if_other);
+
+ BIND(&if_smi);
+ {
+ var_result =
+ smi_op(CAST(value), &var_feedback, &do_float_op, &var_float_value);
+ Goto(&end);
+ }
+
+ BIND(&if_heapnumber);
+ {
+ var_float_value = LoadHeapNumberValue(value_heap_object);
+ Goto(&do_float_op);
+ }
+
+ BIND(&if_bigint);
+ {
+ var_result = bigint_op(context, value_heap_object);
+ CombineFeedback(&var_feedback, BinaryOperationFeedback::kBigInt);
+ Goto(&end);
+ }
+
+ BIND(&if_oddball);
+ {
+ // We do not require an Or with earlier feedback here because once we
+ // convert the value to a number, we cannot reach this path. We can
+ // only reach this path on the first pass when the feedback is kNone.
+ CSA_ASSERT(this, SmiEqual(var_feedback.value(),
+ SmiConstant(BinaryOperationFeedback::kNone)));
+ OverwriteFeedback(&var_feedback,
+ BinaryOperationFeedback::kNumberOrOddball);
+ var_value =
+ LoadObjectField(value_heap_object, Oddball::kToNumberOffset);
+ Goto(&start);
+ }
+
+ BIND(&if_other);
+ {
+ // We do not require an Or with earlier feedback here because once we
+ // convert the value to a number, we cannot reach this path. We can
+ // only reach this path on the first pass when the feedback is kNone.
+ CSA_ASSERT(this, SmiEqual(var_feedback.value(),
+ SmiConstant(BinaryOperationFeedback::kNone)));
+ OverwriteFeedback(&var_feedback, BinaryOperationFeedback::kAny);
+ var_value = CallBuiltin(Builtins::kNonNumberToNumeric, context,
+ value_heap_object);
+ Goto(&start);
+ }
+ }
+
+ BIND(&do_float_op);
+ {
+ CombineFeedback(&var_feedback, BinaryOperationFeedback::kNumber);
+ var_result =
+ AllocateHeapNumberWithValue(float_op(var_float_value.value()));
+ Goto(&end);
+ }
+
+ BIND(&end);
+ UpdateFeedback(var_feedback.value(), maybe_feedback_vector, slot);
+ return var_result.value();
+ }
+
+ template <Operation kOperation>
+ TNode<Object> IncrementOrDecrement(TNode<Context> context,
+ TNode<Object> value, TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector) {
+ STATIC_ASSERT(kOperation == Operation::kIncrement ||
+ kOperation == Operation::kDecrement);
+ static constexpr int kAddValue =
+ (kOperation == Operation::kIncrement) ? 1 : -1;
+
+ SmiOperation smi_op = [=](TNode<Smi> smi_value,
+ TVariable<Smi>* var_feedback, Label* do_float_op,
+ TVariable<Float64T>* var_float) {
+ Label if_overflow(this), out(this);
+ TNode<Smi> result =
+ TrySmiAdd(smi_value, SmiConstant(kAddValue), &if_overflow);
+ CombineFeedback(var_feedback, BinaryOperationFeedback::kSignedSmall);
+ Goto(&out);
+
+ BIND(&if_overflow);
+ *var_float = SmiToFloat64(smi_value);
+ Goto(do_float_op);
+
+ BIND(&out);
+ return result;
+ };
+ FloatOperation float_op = [=](TNode<Float64T> float_value) {
+ return Float64Add(float_value, Float64Constant(kAddValue));
+ };
+ BigIntOperation bigint_op = [=](TNode<Context> context,
+ TNode<HeapObject> bigint_value) {
+ return CAST(CallRuntime(Runtime::kBigIntUnaryOp, context, bigint_value,
+ SmiConstant(kOperation)));
+ };
+ return UnaryOpWithFeedback(context, value, slot, maybe_feedback_vector,
+ smi_op, float_op, bigint_op);
+ }
+};
+
+} // namespace
+
+TNode<Object> UnaryOpAssembler::Generate_BitwiseNotWithFeedback(
+ TNode<Context> context, TNode<Object> value, TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector) {
+ UnaryOpAssemblerImpl a(state_);
+ return a.BitwiseNot(context, value, slot, maybe_feedback_vector);
+}
+
+TNode<Object> UnaryOpAssembler::Generate_DecrementWithFeedback(
+ TNode<Context> context, TNode<Object> value, TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector) {
+ UnaryOpAssemblerImpl a(state_);
+ return a.Decrement(context, value, slot, maybe_feedback_vector);
+}
+
+TNode<Object> UnaryOpAssembler::Generate_IncrementWithFeedback(
+ TNode<Context> context, TNode<Object> value, TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector) {
+ UnaryOpAssemblerImpl a(state_);
+ return a.Increment(context, value, slot, maybe_feedback_vector);
+}
+
+TNode<Object> UnaryOpAssembler::Generate_NegateWithFeedback(
+ TNode<Context> context, TNode<Object> value, TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector) {
+ UnaryOpAssemblerImpl a(state_);
+ return a.Negate(context, value, slot, maybe_feedback_vector);
+}
+
+} // namespace internal
+} // namespace v8