summaryrefslogtreecommitdiff
path: root/chromium/v8/src/ic
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
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
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')
-rw-r--r--chromium/v8/src/ic/accessor-assembler.cc34
-rw-r--r--chromium/v8/src/ic/binary-op-assembler.cc13
-rw-r--r--chromium/v8/src/ic/binary-op-assembler.h66
-rw-r--r--chromium/v8/src/ic/ic.cc28
-rw-r--r--chromium/v8/src/ic/unary-op-assembler.cc283
-rw-r--r--chromium/v8/src/ic/unary-op-assembler.h45
6 files changed, 446 insertions, 23 deletions
diff --git a/chromium/v8/src/ic/accessor-assembler.cc b/chromium/v8/src/ic/accessor-assembler.cc
index fb82a23c32f..18287ecc482 100644
--- a/chromium/v8/src/ic/accessor-assembler.cc
+++ b/chromium/v8/src/ic/accessor-assembler.cc
@@ -1334,12 +1334,13 @@ void AccessorAssembler::OverwriteExistingFastDataProperty(
if (do_transitioning_store) {
StoreMap(object, object_map);
} else {
- Label if_mutable(this);
- GotoIfNot(IsPropertyDetailsConst(details), &if_mutable);
+ Label store_value(this);
+ GotoIfNot(IsPropertyDetailsConst(details), &store_value);
TNode<Float64T> current_value =
LoadObjectField<Float64T>(object, field_offset);
- BranchIfSameNumberValue(current_value, double_value, &done, slow);
- BIND(&if_mutable);
+ BranchIfSameNumberValue(current_value, double_value, &store_value,
+ slow);
+ BIND(&store_value);
}
StoreObjectFieldNoWriteBarrier(object, field_offset, double_value);
} else {
@@ -1351,11 +1352,12 @@ void AccessorAssembler::OverwriteExistingFastDataProperty(
} else {
TNode<HeapNumber> heap_number =
CAST(LoadObjectField(object, field_offset));
- Label if_mutable(this);
- GotoIfNot(IsPropertyDetailsConst(details), &if_mutable);
+ Label store_value(this);
+ GotoIfNot(IsPropertyDetailsConst(details), &store_value);
TNode<Float64T> current_value = LoadHeapNumberValue(heap_number);
- BranchIfSameNumberValue(current_value, double_value, &done, slow);
- BIND(&if_mutable);
+ BranchIfSameNumberValue(current_value, double_value, &store_value,
+ slow);
+ BIND(&store_value);
StoreHeapNumberValue(heap_number, double_value);
}
}
@@ -1968,23 +1970,21 @@ TNode<PropertyArray> AccessorAssembler::ExtendPropertiesBackingStore(
// Previous property deletion could have left behind unused backing store
// capacity even for a map that think it doesn't have any unused fields.
// Perform a bounds check to see if we actually have to grow the array.
- GotoIf(UintPtrLessThan(index, ParameterToIntPtr(var_length.value(), mode)),
+ GotoIf(UintPtrLessThan(index, ParameterToIntPtr(var_length.value())),
&done);
TNode<BInt> delta = BIntConstant(JSObject::kFieldsAdded);
- Node* new_capacity = IntPtrOrSmiAdd(var_length.value(), delta, mode);
+ TNode<BInt> new_capacity = IntPtrOrSmiAdd(var_length.value(), delta);
// Grow properties array.
DCHECK(kMaxNumberOfDescriptors + JSObject::kFieldsAdded <
FixedArrayBase::GetMaxLengthForNewSpaceAllocation(PACKED_ELEMENTS));
// The size of a new properties backing store is guaranteed to be small
// enough that the new backing store will be allocated in new space.
- CSA_ASSERT(this,
- UintPtrOrSmiLessThan(
- new_capacity,
- IntPtrOrSmiConstant(
- kMaxNumberOfDescriptors + JSObject::kFieldsAdded, mode),
- mode));
+ CSA_ASSERT(this, UintPtrOrSmiLessThan(
+ new_capacity,
+ IntPtrOrSmiConstant<BInt>(kMaxNumberOfDescriptors +
+ JSObject::kFieldsAdded)));
TNode<PropertyArray> new_properties =
AllocatePropertyArray(new_capacity, mode);
@@ -2002,7 +2002,7 @@ TNode<PropertyArray> AccessorAssembler::ExtendPropertiesBackingStore(
// TODO(gsathya): Clean up the type conversions by creating smarter
// helpers that do the correct op based on the mode.
TNode<Int32T> new_capacity_int32 =
- TruncateIntPtrToInt32(ParameterToIntPtr(new_capacity, mode));
+ TruncateIntPtrToInt32(ParameterToIntPtr(new_capacity));
TNode<Int32T> new_length_and_hash_int32 =
Word32Or(var_encoded_hash.value(), new_capacity_int32);
StoreObjectField(new_properties, PropertyArray::kLengthAndHashOffset,
diff --git a/chromium/v8/src/ic/binary-op-assembler.cc b/chromium/v8/src/ic/binary-op-assembler.cc
index 25c2181ab2d..8cba7172a2e 100644
--- a/chromium/v8/src/ic/binary-op-assembler.cc
+++ b/chromium/v8/src/ic/binary-op-assembler.cc
@@ -69,6 +69,8 @@ TNode<Object> BinaryOpAssembler::Generate_AddWithFeedback(
// Not overflowed.
{
var_type_feedback = SmiConstant(BinaryOperationFeedback::kSignedSmall);
+ UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector,
+ slot_id);
var_result = smi_result;
Goto(&end);
}
@@ -116,6 +118,7 @@ TNode<Object> BinaryOpAssembler::Generate_AddWithFeedback(
BIND(&do_fadd);
{
var_type_feedback = SmiConstant(BinaryOperationFeedback::kNumber);
+ UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
TNode<Float64T> value =
Float64Add(var_fadd_lhs.value(), var_fadd_rhs.value());
TNode<HeapNumber> result = AllocateHeapNumberWithValue(value);
@@ -166,6 +169,8 @@ TNode<Object> BinaryOpAssembler::Generate_AddWithFeedback(
&call_with_any_feedback);
var_type_feedback = SmiConstant(BinaryOperationFeedback::kString);
+ UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector,
+ slot_id);
var_result =
CallBuiltin(Builtins::kStringAdd_CheckNone, context, lhs, rhs);
@@ -194,6 +199,7 @@ TNode<Object> BinaryOpAssembler::Generate_AddWithFeedback(
GotoIf(TaggedIsSmi(var_result.value()), &bigint_too_big);
var_type_feedback = SmiConstant(BinaryOperationFeedback::kBigInt);
+ UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
Goto(&end);
BIND(&bigint_too_big);
@@ -219,12 +225,12 @@ TNode<Object> BinaryOpAssembler::Generate_AddWithFeedback(
BIND(&call_add_stub);
{
+ UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
var_result = CallBuiltin(Builtins::kAdd, context, lhs, rhs);
Goto(&end);
}
BIND(&end);
- UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
return var_result.value();
}
@@ -279,6 +285,7 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
{
Comment("perform smi operation");
var_result = smiOperation(lhs_smi, CAST(rhs), &var_type_feedback);
+ UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
Goto(&end);
}
}
@@ -321,6 +328,7 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
BIND(&do_float_operation);
{
var_type_feedback = SmiConstant(BinaryOperationFeedback::kNumber);
+ UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
TNode<Float64T> lhs_value = var_float_lhs.value();
TNode<Float64T> rhs_value = var_float_rhs.value();
TNode<Float64T> value = floatOperation(lhs_value, rhs_value);
@@ -384,6 +392,7 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
BIND(&if_both_bigint);
{
var_type_feedback = SmiConstant(BinaryOperationFeedback::kBigInt);
+ UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
if (op == Operation::kSubtract) {
Label bigint_too_big(this);
var_result =
@@ -415,6 +424,7 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
BIND(&call_stub);
{
+ UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
TNode<Object> result;
switch (op) {
case Operation::kSubtract:
@@ -437,7 +447,6 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
}
BIND(&end);
- UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector, slot_id);
return var_result.value();
}
diff --git a/chromium/v8/src/ic/binary-op-assembler.h b/chromium/v8/src/ic/binary-op-assembler.h
index 79b8cd221b9..4bd0d516089 100644
--- a/chromium/v8/src/ic/binary-op-assembler.h
+++ b/chromium/v8/src/ic/binary-op-assembler.h
@@ -50,6 +50,72 @@ class BinaryOpAssembler : public CodeStubAssembler {
TNode<UintPtrT> slot, TNode<HeapObject> maybe_feedback_vector,
bool rhs_known_smi);
+ TNode<Object> Generate_BitwiseOrWithFeedback(
+ TNode<Context> context, TNode<Object> left, TNode<Object> right,
+ TNode<UintPtrT> slot, TNode<HeapObject> maybe_feedback_vector,
+ bool /* unused */) {
+ TVARIABLE(Smi, feedback);
+ TNode<Object> result = Generate_BitwiseBinaryOpWithFeedback(
+ Operation::kBitwiseOr, left, right, context, &feedback);
+ UpdateFeedback(feedback.value(), maybe_feedback_vector, slot);
+ return result;
+ }
+
+ TNode<Object> Generate_BitwiseXorWithFeedback(
+ TNode<Context> context, TNode<Object> left, TNode<Object> right,
+ TNode<UintPtrT> slot, TNode<HeapObject> maybe_feedback_vector,
+ bool /* unused */) {
+ TVARIABLE(Smi, feedback);
+ TNode<Object> result = Generate_BitwiseBinaryOpWithFeedback(
+ Operation::kBitwiseXor, left, right, context, &feedback);
+ UpdateFeedback(feedback.value(), maybe_feedback_vector, slot);
+ return result;
+ }
+
+ TNode<Object> Generate_BitwiseAndWithFeedback(
+ TNode<Context> context, TNode<Object> left, TNode<Object> right,
+ TNode<UintPtrT> slot, TNode<HeapObject> maybe_feedback_vector,
+ bool /* unused */) {
+ TVARIABLE(Smi, feedback);
+ TNode<Object> result = Generate_BitwiseBinaryOpWithFeedback(
+ Operation::kBitwiseAnd, left, right, context, &feedback);
+ UpdateFeedback(feedback.value(), maybe_feedback_vector, slot);
+ return result;
+ }
+
+ TNode<Object> Generate_ShiftLeftWithFeedback(
+ TNode<Context> context, TNode<Object> left, TNode<Object> right,
+ TNode<UintPtrT> slot, TNode<HeapObject> maybe_feedback_vector,
+ bool /* unused */) {
+ TVARIABLE(Smi, feedback);
+ TNode<Object> result = Generate_BitwiseBinaryOpWithFeedback(
+ Operation::kShiftLeft, left, right, context, &feedback);
+ UpdateFeedback(feedback.value(), maybe_feedback_vector, slot);
+ return result;
+ }
+
+ TNode<Object> Generate_ShiftRightWithFeedback(
+ TNode<Context> context, TNode<Object> left, TNode<Object> right,
+ TNode<UintPtrT> slot, TNode<HeapObject> maybe_feedback_vector,
+ bool /* unused */) {
+ TVARIABLE(Smi, feedback);
+ TNode<Object> result = Generate_BitwiseBinaryOpWithFeedback(
+ Operation::kShiftRight, left, right, context, &feedback);
+ UpdateFeedback(feedback.value(), maybe_feedback_vector, slot);
+ return result;
+ }
+
+ TNode<Object> Generate_ShiftRightLogicalWithFeedback(
+ TNode<Context> context, TNode<Object> left, TNode<Object> right,
+ TNode<UintPtrT> slot, TNode<HeapObject> maybe_feedback_vector,
+ bool /* unused */) {
+ TVARIABLE(Smi, feedback);
+ TNode<Object> result = Generate_BitwiseBinaryOpWithFeedback(
+ Operation::kShiftRightLogical, left, right, context, &feedback);
+ UpdateFeedback(feedback.value(), maybe_feedback_vector, slot);
+ return result;
+ }
+
TNode<Object> Generate_BitwiseBinaryOpWithFeedback(Operation bitwise_op,
TNode<Object> left,
TNode<Object> right,
diff --git a/chromium/v8/src/ic/ic.cc b/chromium/v8/src/ic/ic.cc
index 452275d13f2..9251d772ddc 100644
--- a/chromium/v8/src/ic/ic.cc
+++ b/chromium/v8/src/ic/ic.cc
@@ -8,6 +8,7 @@
#include "src/api/api.h"
#include "src/ast/ast.h"
#include "src/base/bits.h"
+#include "src/base/logging.h"
#include "src/builtins/accessors.h"
#include "src/codegen/code-factory.h"
#include "src/execution/arguments-inl.h"
@@ -947,7 +948,9 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
if (receiver_is_holder) return smi_handler;
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
-
+ } else if (lookup->IsElement(*holder)) {
+ TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+ return LoadHandler::LoadSlow(isolate());
} else {
DCHECK_EQ(kField, lookup->property_details().location());
FieldIndex field = lookup->GetFieldIndex();
@@ -1769,6 +1772,12 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
return MaybeObjectHandle(StoreHandler::StoreNormal(isolate()));
}
+ // -------------- Elements (for TypedArrays) -------------
+ if (lookup->IsElement(*holder)) {
+ TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+ return MaybeObjectHandle(StoreHandler::StoreSlow(isolate()));
+ }
+
// -------------- Fields --------------
if (lookup->property_details().location() == kField) {
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldDH);
@@ -1856,6 +1865,12 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
if (receiver_map.is_identical_to(previous_receiver_map) &&
new_receiver_map.is_identical_to(receiver_map) &&
old_store_mode == STANDARD_STORE && store_mode != STANDARD_STORE) {
+ if (receiver_map->IsJSArrayMap() &&
+ JSArray::MayHaveReadOnlyLength(*receiver_map)) {
+ set_slow_stub_reason(
+ "can't generalize store mode (potentially read-only length)");
+ return;
+ }
// A "normal" IC that handles stores can switch to a version that can
// grow at the end of the array, handle OOB accesses or copy COW arrays
// and still stay MONOMORPHIC.
@@ -1900,13 +1915,18 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
}
// If the store mode isn't the standard mode, make sure that all polymorphic
- // receivers are either external arrays, or all "normal" arrays. Otherwise,
- // use the megamorphic stub.
+ // receivers are either external arrays, or all "normal" arrays with writable
+ // length. Otherwise, use the megamorphic stub.
if (store_mode != STANDARD_STORE) {
size_t external_arrays = 0;
for (MapAndHandler map_and_handler : target_maps_and_handlers) {
Handle<Map> map = map_and_handler.first;
- if (map->has_typed_array_elements()) {
+ if (map->IsJSArrayMap() && JSArray::MayHaveReadOnlyLength(*map)) {
+ set_slow_stub_reason(
+ "unsupported combination of arrays (potentially read-only length)");
+ return;
+
+ } else if (map->has_typed_array_elements()) {
DCHECK(!IsStoreInArrayLiteralICKind(kind()));
external_arrays++;
}
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
diff --git a/chromium/v8/src/ic/unary-op-assembler.h b/chromium/v8/src/ic/unary-op-assembler.h
new file mode 100644
index 00000000000..b22322ddf2a
--- /dev/null
+++ b/chromium/v8/src/ic/unary-op-assembler.h
@@ -0,0 +1,45 @@
+// 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.
+
+#ifndef V8_IC_UNARY_OP_ASSEMBLER_H_
+#define V8_IC_UNARY_OP_ASSEMBLER_H_
+
+#include "src/codegen/code-stub-assembler.h"
+
+namespace v8 {
+namespace internal {
+
+namespace compiler {
+class CodeAssemblerState;
+}
+
+class UnaryOpAssembler final {
+ public:
+ explicit UnaryOpAssembler(compiler::CodeAssemblerState* state)
+ : state_(state) {}
+
+ TNode<Object> Generate_BitwiseNotWithFeedback(
+ TNode<Context> context, TNode<Object> value, TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector);
+
+ TNode<Object> Generate_DecrementWithFeedback(
+ TNode<Context> context, TNode<Object> value, TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector);
+
+ TNode<Object> Generate_IncrementWithFeedback(
+ TNode<Context> context, TNode<Object> value, TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector);
+
+ TNode<Object> Generate_NegateWithFeedback(
+ TNode<Context> context, TNode<Object> value, TNode<UintPtrT> slot,
+ TNode<HeapObject> maybe_feedback_vector);
+
+ private:
+ compiler::CodeAssemblerState* const state_;
+};
+
+} // namespace internal
+} // namespace v8
+
+#endif // V8_IC_UNARY_OP_ASSEMBLER_H_