diff options
| author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
|---|---|---|
| committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
| commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
| tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/v8/src/ic/unary-op-assembler.cc | |
| parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (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.cc | 283 |
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 |
