summaryrefslogtreecommitdiff
path: root/chromium/v8/src/code-stub-assembler.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-15 10:20:33 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-15 10:28:57 +0000
commitd17ea114e5ef69ad5d5d7413280a13e6428098aa (patch)
tree2c01a75df69f30d27b1432467cfe7c1467a498da /chromium/v8/src/code-stub-assembler.cc
parent8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec (diff)
downloadqtwebengine-chromium-d17ea114e5ef69ad5d5d7413280a13e6428098aa.tar.gz
BASELINE: Update Chromium to 67.0.3396.47
Change-Id: Idcb1341782e417561a2473eeecc82642dafda5b7 Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'chromium/v8/src/code-stub-assembler.cc')
-rw-r--r--chromium/v8/src/code-stub-assembler.cc1313
1 files changed, 747 insertions, 566 deletions
diff --git a/chromium/v8/src/code-stub-assembler.cc b/chromium/v8/src/code-stub-assembler.cc
index d3c81d0e812..556efe7d0af 100644
--- a/chromium/v8/src/code-stub-assembler.cc
+++ b/chromium/v8/src/code-stub-assembler.cc
@@ -154,10 +154,10 @@ void CodeStubAssembler::Check(const NodeGenerator& condition_body,
extra_node4_name, extra_node5, extra_node5_name);
}
-Node* CodeStubAssembler::Select(SloppyTNode<BoolT> condition,
- const NodeGenerator& true_body,
- const NodeGenerator& false_body,
- MachineRepresentation rep) {
+Node* CodeStubAssembler::SelectImpl(TNode<BoolT> condition,
+ const NodeGenerator& true_body,
+ const NodeGenerator& false_body,
+ MachineRepresentation rep) {
VARIABLE(value, rep);
Label vtrue(this), vfalse(this), end(this);
Branch(condition, &vtrue, &vfalse);
@@ -177,37 +177,28 @@ Node* CodeStubAssembler::Select(SloppyTNode<BoolT> condition,
return value.value();
}
-Node* CodeStubAssembler::SelectConstant(Node* condition, Node* true_value,
- Node* false_value,
- MachineRepresentation rep) {
- return Select(condition, [=] { return true_value; },
- [=] { return false_value; }, rep);
+TNode<Int32T> CodeStubAssembler::SelectInt32Constant(
+ SloppyTNode<BoolT> condition, int true_value, int false_value) {
+ return SelectConstant<Int32T>(condition, Int32Constant(true_value),
+ Int32Constant(false_value));
}
-Node* CodeStubAssembler::SelectInt32Constant(Node* condition, int true_value,
- int false_value) {
- return SelectConstant(condition, Int32Constant(true_value),
- Int32Constant(false_value),
- MachineRepresentation::kWord32);
+TNode<IntPtrT> CodeStubAssembler::SelectIntPtrConstant(
+ SloppyTNode<BoolT> condition, int true_value, int false_value) {
+ return SelectConstant<IntPtrT>(condition, IntPtrConstant(true_value),
+ IntPtrConstant(false_value));
}
-Node* CodeStubAssembler::SelectIntPtrConstant(Node* condition, int true_value,
- int false_value) {
- return SelectConstant(condition, IntPtrConstant(true_value),
- IntPtrConstant(false_value),
- MachineType::PointerRepresentation());
+TNode<Oddball> CodeStubAssembler::SelectBooleanConstant(
+ SloppyTNode<BoolT> condition) {
+ return SelectConstant<Oddball>(condition, TrueConstant(), FalseConstant());
}
-Node* CodeStubAssembler::SelectBooleanConstant(Node* condition) {
- return SelectConstant(condition, TrueConstant(), FalseConstant(),
- MachineRepresentation::kTagged);
-}
-
-Node* CodeStubAssembler::SelectSmiConstant(Node* condition, Smi* true_value,
- Smi* false_value) {
- return SelectConstant(condition, SmiConstant(true_value),
- SmiConstant(false_value),
- MachineRepresentation::kTaggedSigned);
+TNode<Smi> CodeStubAssembler::SelectSmiConstant(SloppyTNode<BoolT> condition,
+ Smi* true_value,
+ Smi* false_value) {
+ return SelectConstant<Smi>(condition, SmiConstant(true_value),
+ SmiConstant(false_value));
}
Node* CodeStubAssembler::NoContextConstant() {
@@ -312,11 +303,10 @@ Node* CodeStubAssembler::MatchesParameterMode(Node* value, ParameterMode mode) {
TNode<BoolT> CodeStubAssembler::WordIsPowerOfTwo(SloppyTNode<IntPtrT> value) {
// value && !(value & (value - 1))
return WordEqual(
- Select(
+ Select<IntPtrT>(
WordEqual(value, IntPtrConstant(0)),
[=] { return IntPtrConstant(1); },
- [=] { return WordAnd(value, IntPtrSub(value, IntPtrConstant(1))); },
- MachineType::PointerRepresentation()),
+ [=] { return WordAnd(value, IntPtrSub(value, IntPtrConstant(1))); }),
IntPtrConstant(0));
}
@@ -571,11 +561,11 @@ TNode<Float64T> CodeStubAssembler::SmiToFloat64(SloppyTNode<Smi> value) {
}
TNode<Smi> CodeStubAssembler::SmiMax(SloppyTNode<Smi> a, SloppyTNode<Smi> b) {
- return SelectTaggedConstant(SmiLessThan(a, b), b, a);
+ return SelectConstant<Smi>(SmiLessThan(a, b), b, a);
}
TNode<Smi> CodeStubAssembler::SmiMin(SloppyTNode<Smi> a, SloppyTNode<Smi> b) {
- return SelectTaggedConstant(SmiLessThan(a, b), a, b);
+ return SelectConstant<Smi>(SmiLessThan(a, b), a, b);
}
TNode<Object> CodeStubAssembler::NumberMax(SloppyTNode<Object> a,
@@ -633,9 +623,8 @@ TNode<IntPtrT> CodeStubAssembler::ConvertToRelativeIndex(
TNode<Smi> const index_smi = CAST(index_int);
result = Select<IntPtrT>(
IntPtrLessThan(SmiUntag(index_smi), zero),
- [&] { return IntPtrMax(IntPtrAdd(length, SmiUntag(index_smi)), zero); },
- [&] { return IntPtrMin(SmiUntag(index_smi), length); },
- MachineType::PointerRepresentation());
+ [=] { return IntPtrMax(IntPtrAdd(length, SmiUntag(index_smi)), zero); },
+ [=] { return IntPtrMin(SmiUntag(index_smi), length); });
Goto(&done);
}
@@ -647,37 +636,38 @@ TNode<IntPtrT> CodeStubAssembler::ConvertToRelativeIndex(
TNode<HeapNumber> const index_hn = CAST(index_int);
TNode<Float64T> const float_zero = Float64Constant(0.);
TNode<Float64T> const index_float = LoadHeapNumberValue(index_hn);
- result = SelectConstant(Float64LessThan(index_float, float_zero), zero,
- length, MachineType::PointerRepresentation());
+ result = SelectConstant<IntPtrT>(Float64LessThan(index_float, float_zero),
+ zero, length);
Goto(&done);
}
BIND(&done);
return result.value();
}
-Node* CodeStubAssembler::SmiMod(Node* a, Node* b) {
- VARIABLE(var_result, MachineRepresentation::kTagged);
+TNode<Number> CodeStubAssembler::SmiMod(SloppyTNode<Smi> a,
+ SloppyTNode<Smi> b) {
+ TVARIABLE(Number, var_result);
Label return_result(this, &var_result),
return_minuszero(this, Label::kDeferred),
return_nan(this, Label::kDeferred);
// Untag {a} and {b}.
- a = SmiToInt32(a);
- b = SmiToInt32(b);
+ TNode<Int32T> int_a = SmiToInt32(a);
+ TNode<Int32T> int_b = SmiToInt32(b);
// Return NaN if {b} is zero.
- GotoIf(Word32Equal(b, Int32Constant(0)), &return_nan);
+ GotoIf(Word32Equal(int_b, Int32Constant(0)), &return_nan);
// Check if {a} is non-negative.
Label if_aisnotnegative(this), if_aisnegative(this, Label::kDeferred);
- Branch(Int32LessThanOrEqual(Int32Constant(0), a), &if_aisnotnegative,
+ Branch(Int32LessThanOrEqual(Int32Constant(0), int_a), &if_aisnotnegative,
&if_aisnegative);
BIND(&if_aisnotnegative);
{
// Fast case, don't need to check any other edge cases.
- Node* r = Int32Mod(a, b);
- var_result.Bind(SmiFromInt32(r));
+ TNode<Int32T> r = Int32Mod(int_a, int_b);
+ var_result = SmiFromInt32(r);
Goto(&return_result);
}
@@ -687,14 +677,14 @@ Node* CodeStubAssembler::SmiMod(Node* a, Node* b) {
// Check if {a} is kMinInt and {b} is -1 (only relevant if the
// kMinInt is actually representable as a Smi).
Label join(this);
- GotoIfNot(Word32Equal(a, Int32Constant(kMinInt)), &join);
- GotoIf(Word32Equal(b, Int32Constant(-1)), &return_minuszero);
+ GotoIfNot(Word32Equal(int_a, Int32Constant(kMinInt)), &join);
+ GotoIf(Word32Equal(int_b, Int32Constant(-1)), &return_minuszero);
Goto(&join);
BIND(&join);
}
// Perform the integer modulus operation.
- Node* r = Int32Mod(a, b);
+ TNode<Int32T> r = Int32Mod(int_a, int_b);
// Check if {r} is zero, and if so return -0, because we have to
// take the sign of the left hand side {a}, which is negative.
@@ -702,20 +692,20 @@ Node* CodeStubAssembler::SmiMod(Node* a, Node* b) {
// The remainder {r} can be outside the valid Smi range on 32bit
// architectures, so we cannot just say SmiFromInt32(r) here.
- var_result.Bind(ChangeInt32ToTagged(r));
+ var_result = ChangeInt32ToTagged(r);
Goto(&return_result);
}
BIND(&return_minuszero);
- var_result.Bind(MinusZeroConstant());
+ var_result = MinusZeroConstant();
Goto(&return_result);
BIND(&return_nan);
- var_result.Bind(NanConstant());
+ var_result = NanConstant();
Goto(&return_result);
BIND(&return_result);
- return TNode<Object>::UncheckedCast(var_result.value());
+ return var_result.value();
}
TNode<Number> CodeStubAssembler::SmiMul(SloppyTNode<Smi> a,
@@ -950,20 +940,19 @@ TNode<BoolT> CodeStubAssembler::IsFastJSArrayWithNoCustomIteration(
TNode<Object> object, TNode<Context> context,
TNode<Context> native_context) {
Label if_false(this, Label::kDeferred), if_fast(this), exit(this);
+ TVARIABLE(BoolT, var_result);
GotoIfForceSlowPath(&if_false);
- TVARIABLE(BoolT, var_result, Int32TrueConstant());
BranchIfFastJSArray(object, context, &if_fast, &if_false);
BIND(&if_fast);
{
- // Check if the Array.prototype[@@iterator] may have changed.
- GotoIfNot(InitialArrayPrototypeHasInitialArrayPrototypeMap(native_context),
- &if_false);
- // Check if array[@@iterator] may have changed.
- GotoIfNot(HasInitialFastElementsKindMap(native_context, CAST(object)),
- &if_false);
- // Check if the array iterator has changed.
- Branch(HasInitialArrayIteratorPrototypeMap(native_context), &exit,
- &if_false);
+ // Check that the Array.prototype hasn't been modified in a way that would
+ // affect iteration.
+ Node* protector_cell = LoadRoot(Heap::kArrayIteratorProtectorRootIndex);
+ DCHECK(isolate()->heap()->array_iterator_protector()->IsPropertyCell());
+ var_result =
+ WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset),
+ SmiConstant(Isolate::kProtectorValid));
+ Goto(&exit);
}
BIND(&if_false);
{
@@ -997,7 +986,7 @@ void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context,
void CodeStubAssembler::BranchIfFastJSArrayForCopy(Node* object, Node* context,
Label* if_true,
Label* if_false) {
- GotoIf(IsSpeciesProtectorCellInvalid(), if_false);
+ GotoIf(IsArraySpeciesProtectorCellInvalid(), if_false);
BranchIfFastJSArray(object, context, if_true, if_false);
}
@@ -1264,12 +1253,14 @@ Node* CodeStubAssembler::LoadBufferObject(Node* buffer, int offset,
Node* CodeStubAssembler::LoadObjectField(SloppyTNode<HeapObject> object,
int offset, MachineType rep) {
+ AssertIsStrongHeapObject(object);
return Load(rep, object, IntPtrConstant(offset - kHeapObjectTag));
}
Node* CodeStubAssembler::LoadObjectField(SloppyTNode<HeapObject> object,
SloppyTNode<IntPtrT> offset,
MachineType rep) {
+ AssertIsStrongHeapObject(object);
return Load(rep, object, IntPtrSub(offset, IntPtrConstant(kHeapObjectTag)));
}
@@ -1363,21 +1354,11 @@ TNode<Int32T> CodeStubAssembler::LoadInstanceType(
return LoadMapInstanceType(LoadMap(object));
}
-Node* CodeStubAssembler::HasInstanceType(Node* object,
- InstanceType instance_type) {
+TNode<BoolT> CodeStubAssembler::HasInstanceType(SloppyTNode<HeapObject> object,
+ InstanceType instance_type) {
return InstanceTypeEqual(LoadInstanceType(object), instance_type);
}
-TNode<BoolT> CodeStubAssembler::HasInitialArrayIteratorPrototypeMap(
- TNode<Context> native_context) {
- CSA_ASSERT(this, IsNativeContext(native_context));
- TNode<Map> arr_it_proto_map = LoadMap(CAST(LoadContextElement(
- native_context, Context::INITIAL_ARRAY_ITERATOR_PROTOTYPE_INDEX)));
- TNode<Map> initial_map = CAST(LoadContextElement(
- native_context, Context::INITIAL_ARRAY_ITERATOR_PROTOTYPE_MAP_INDEX));
- return WordEqual(arr_it_proto_map, initial_map);
-}
-
TNode<BoolT>
CodeStubAssembler::InitialArrayPrototypeHasInitialArrayPrototypeMap(
TNode<Context> native_context) {
@@ -1399,34 +1380,38 @@ TNode<BoolT> CodeStubAssembler::HasInitialFastElementsKindMap(
return WordEqual(initial_jsarray_element_map, map);
}
-Node* CodeStubAssembler::DoesntHaveInstanceType(Node* object,
- InstanceType instance_type) {
+TNode<BoolT> CodeStubAssembler::DoesntHaveInstanceType(
+ SloppyTNode<HeapObject> object, InstanceType instance_type) {
return Word32NotEqual(LoadInstanceType(object), Int32Constant(instance_type));
}
-Node* CodeStubAssembler::TaggedDoesntHaveInstanceType(Node* any_tagged,
- InstanceType type) {
+TNode<BoolT> CodeStubAssembler::TaggedDoesntHaveInstanceType(
+ SloppyTNode<HeapObject> any_tagged, InstanceType type) {
/* return Phi <TaggedIsSmi(val), DoesntHaveInstanceType(val, type)> */
- Node* tagged_is_smi = TaggedIsSmi(any_tagged);
- return Select(tagged_is_smi, [=]() { return tagged_is_smi; },
- [=]() { return DoesntHaveInstanceType(any_tagged, type); },
- MachineRepresentation::kBit);
+ TNode<BoolT> tagged_is_smi = TaggedIsSmi(any_tagged);
+ return Select<BoolT>(
+ tagged_is_smi, [=]() { return tagged_is_smi; },
+ [=]() { return DoesntHaveInstanceType(any_tagged, type); });
}
TNode<HeapObject> CodeStubAssembler::LoadFastProperties(
SloppyTNode<JSObject> object) {
CSA_SLOW_ASSERT(this, Word32Not(IsDictionaryMap(LoadMap(object))));
- Node* properties = LoadObjectField(object, JSObject::kPropertiesOrHashOffset);
- return SelectTaggedConstant<HeapObject>(
- TaggedIsSmi(properties), EmptyFixedArrayConstant(), properties);
+ TNode<Object> properties =
+ LoadObjectField(object, JSObject::kPropertiesOrHashOffset);
+ return Select<HeapObject>(TaggedIsSmi(properties),
+ [=] { return EmptyFixedArrayConstant(); },
+ [=] { return CAST(properties); });
}
TNode<HeapObject> CodeStubAssembler::LoadSlowProperties(
SloppyTNode<JSObject> object) {
CSA_SLOW_ASSERT(this, IsDictionaryMap(LoadMap(object)));
- Node* properties = LoadObjectField(object, JSObject::kPropertiesOrHashOffset);
- return SelectTaggedConstant<HeapObject>(
- TaggedIsSmi(properties), EmptyPropertyDictionaryConstant(), properties);
+ TNode<Object> properties =
+ LoadObjectField(object, JSObject::kPropertiesOrHashOffset);
+ return Select<HeapObject>(TaggedIsSmi(properties),
+ [=] { return EmptyPropertyDictionaryConstant(); },
+ [=] { return CAST(properties); });
}
TNode<FixedArrayBase> CodeStubAssembler::LoadElements(
@@ -1434,9 +1419,9 @@ TNode<FixedArrayBase> CodeStubAssembler::LoadElements(
return CAST(LoadObjectField(object, JSObject::kElementsOffset));
}
-TNode<Object> CodeStubAssembler::LoadJSArrayLength(SloppyTNode<JSArray> array) {
+TNode<Number> CodeStubAssembler::LoadJSArrayLength(SloppyTNode<JSArray> array) {
CSA_ASSERT(this, IsJSArray(array));
- return LoadObjectField(array, JSArray::kLengthOffset);
+ return CAST(LoadObjectField(array, JSArray::kLengthOffset));
}
TNode<Smi> CodeStubAssembler::LoadFastJSArrayLength(
@@ -1500,14 +1485,20 @@ TNode<Object> CodeStubAssembler::LoadMapPrototype(SloppyTNode<Map> map) {
TNode<PrototypeInfo> CodeStubAssembler::LoadMapPrototypeInfo(
SloppyTNode<Map> map, Label* if_no_proto_info) {
+ Label if_strong_heap_object(this);
CSA_ASSERT(this, IsMap(map));
- Node* prototype_info =
+ Node* maybe_prototype_info =
LoadObjectField(map, Map::kTransitionsOrPrototypeInfoOffset);
- GotoIf(TaggedIsSmi(prototype_info), if_no_proto_info);
- GotoIfNot(WordEqual(LoadMap(prototype_info),
+ VARIABLE(prototype_info, MachineRepresentation::kTagged);
+ DispatchMaybeObject(maybe_prototype_info, if_no_proto_info, if_no_proto_info,
+ if_no_proto_info, &if_strong_heap_object,
+ &prototype_info);
+
+ BIND(&if_strong_heap_object);
+ GotoIfNot(WordEqual(LoadMap(prototype_info.value()),
LoadRoot(Heap::kPrototypeInfoMapRootIndex)),
if_no_proto_info);
- return CAST(prototype_info);
+ return CAST(prototype_info.value());
}
TNode<IntPtrT> CodeStubAssembler::LoadMapInstanceSizeInWords(
@@ -1564,11 +1555,11 @@ Node* CodeStubAssembler::LoadMapEnumLength(SloppyTNode<Map> map) {
return DecodeWordFromWord32<Map::EnumLengthBits>(bit_field3);
}
-Node* CodeStubAssembler::LoadMapBackPointer(SloppyTNode<Map> map) {
- Node* object = LoadObjectField(map, Map::kConstructorOrBackPointerOffset);
- return Select(IsMap(object), [=] { return object; },
- [=] { return UndefinedConstant(); },
- MachineRepresentation::kTagged);
+TNode<Object> CodeStubAssembler::LoadMapBackPointer(SloppyTNode<Map> map) {
+ TNode<Object> object =
+ LoadObjectField(map, Map::kConstructorOrBackPointerOffset);
+ return Select<Object>(IsMap(object), [=] { return object; },
+ [=] { return UndefinedConstant(); });
}
TNode<IntPtrT> CodeStubAssembler::LoadJSReceiverIdentityHash(
@@ -1614,8 +1605,8 @@ TNode<IntPtrT> CodeStubAssembler::LoadJSReceiverIdentityHash(
BIND(&if_property_dictionary);
{
- var_hash = SmiUntag(
- LoadFixedArrayElement(properties, NameDictionary::kObjectHashIndex));
+ var_hash = SmiUntag(CAST(
+ LoadFixedArrayElement(properties, NameDictionary::kObjectHashIndex)));
Goto(&done);
}
@@ -1685,17 +1676,49 @@ TNode<Object> CodeStubAssembler::LoadWeakCellValue(
return value;
}
-Node* CodeStubAssembler::LoadFixedArrayElement(Node* object, Node* index_node,
- int additional_offset,
- ParameterMode parameter_mode) {
+void CodeStubAssembler::DispatchMaybeObject(Node* maybe_object, Label* if_smi,
+ Label* if_cleared, Label* if_weak,
+ Label* if_strong,
+ Variable* extracted) {
+ Label inner_if_smi(this), inner_if_strong(this);
+
+ GotoIf(TaggedIsSmi(maybe_object), &inner_if_smi);
+
+ GotoIf(WordEqual(maybe_object, IntPtrConstant(reinterpret_cast<intptr_t>(
+ HeapObjectReference::ClearedValue()))),
+ if_cleared);
+
+ GotoIf(WordEqual(WordAnd(BitcastTaggedToWord(maybe_object),
+ IntPtrConstant(kWeakHeapObjectMask)),
+ IntPtrConstant(0)),
+ &inner_if_strong);
+
+ extracted->Bind(
+ BitcastWordToTagged(WordAnd(BitcastTaggedToWord(maybe_object),
+ IntPtrConstant(~kWeakHeapObjectMask))));
+ Goto(if_weak);
+
+ BIND(&inner_if_smi);
+ extracted->Bind(maybe_object);
+ Goto(if_smi);
+
+ BIND(&inner_if_strong);
+ extracted->Bind(maybe_object);
+ Goto(if_strong);
+}
+
+TNode<Object> CodeStubAssembler::LoadFixedArrayElement(
+ SloppyTNode<Object> object, Node* index_node, int additional_offset,
+ ParameterMode parameter_mode, LoadSensitivity needs_poisoning) {
CSA_SLOW_ASSERT(this, IntPtrGreaterThanOrEqual(
ParameterToIntPtr(index_node, parameter_mode),
IntPtrConstant(0)));
int32_t header_size =
FixedArray::kHeaderSize + additional_offset - kHeapObjectTag;
- Node* offset = ElementOffsetFromIndex(index_node, HOLEY_ELEMENTS,
- parameter_mode, header_size);
- return Load(MachineType::AnyTagged(), object, offset);
+ TNode<IntPtrT> offset = ElementOffsetFromIndex(index_node, HOLEY_ELEMENTS,
+ parameter_mode, header_size);
+ return UncheckedCast<Object>(
+ Load(MachineType::AnyTagged(), object, offset, needs_poisoning));
}
TNode<RawPtrT> CodeStubAssembler::LoadFixedTypedArrayBackingStore(
@@ -1746,11 +1769,19 @@ Node* CodeStubAssembler::LoadFixedBigInt64ArrayElementAsTagged(
TVARIABLE(WordT, var_sign, IntPtrConstant(BigInt::SignBits::encode(false)));
TVARIABLE(IntPtrT, var_low);
TVARIABLE(IntPtrT, var_high);
+#if defined(V8_TARGET_BIG_ENDIAN)
+ var_high = UncheckedCast<IntPtrT>(
+ Load(MachineType::UintPtr(), data_pointer, offset));
+ var_low = UncheckedCast<IntPtrT>(
+ Load(MachineType::UintPtr(), data_pointer,
+ Int32Add(offset, Int32Constant(kPointerSize))));
+#else
var_low = UncheckedCast<IntPtrT>(
Load(MachineType::UintPtr(), data_pointer, offset));
var_high = UncheckedCast<IntPtrT>(
Load(MachineType::UintPtr(), data_pointer,
Int32Add(offset, Int32Constant(kPointerSize))));
+#endif
Label high_zero(this), negative(this), allocate_one_digit(this),
allocate_two_digits(this);
@@ -1829,11 +1860,19 @@ Node* CodeStubAssembler::LoadFixedBigUint64ArrayElementAsTagged(
DCHECK(!Is64());
Label high_zero(this);
+#if defined(V8_TARGET_BIG_ENDIAN)
+ TNode<UintPtrT> high = UncheckedCast<UintPtrT>(
+ Load(MachineType::UintPtr(), data_pointer, offset));
+ TNode<UintPtrT> low = UncheckedCast<UintPtrT>(
+ Load(MachineType::UintPtr(), data_pointer,
+ Int32Add(offset, Int32Constant(kPointerSize))));
+#else
TNode<UintPtrT> low = UncheckedCast<UintPtrT>(
Load(MachineType::UintPtr(), data_pointer, offset));
TNode<UintPtrT> high = UncheckedCast<UintPtrT>(
Load(MachineType::UintPtr(), data_pointer,
Int32Add(offset, Int32Constant(kPointerSize))));
+#endif
GotoIf(WordEqual(high, IntPtrConstant(0)), &high_zero);
var_result = AllocateBigInt(IntPtrConstant(2));
@@ -1903,8 +1942,8 @@ TNode<Object> CodeStubAssembler::LoadFeedbackVectorSlot(
return UncheckedCast<Object>(Load(MachineType::AnyTagged(), object, offset));
}
-Node* CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement(
- Node* object, Node* index_node, int additional_offset,
+TNode<Int32T> CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement(
+ SloppyTNode<Object> object, Node* index_node, int additional_offset,
ParameterMode parameter_mode) {
CSA_SLOW_ASSERT(this, IsFixedArraySubclass(object));
CSA_SLOW_ASSERT(this, MatchesParameterMode(index_node, parameter_mode));
@@ -1918,7 +1957,7 @@ Node* CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement(
Node* offset = ElementOffsetFromIndex(index_node, HOLEY_ELEMENTS,
parameter_mode, header_size);
if (Is64()) {
- return Load(MachineType::Int32(), object, offset);
+ return UncheckedCast<Int32T>(Load(MachineType::Int32(), object, offset));
} else {
return SmiToInt32(Load(MachineType::AnyTagged(), object, offset));
}
@@ -2071,6 +2110,26 @@ Node* CodeStubAssembler::LoadJSFunctionPrototype(Node* function,
return var_result.value();
}
+Node* CodeStubAssembler::LoadSharedFunctionInfoBytecodeArray(Node* shared) {
+ CSA_ASSERT(this, TaggedIsNotSmi(shared));
+ CSA_ASSERT(this, IsSharedFunctionInfo(shared));
+
+ Node* function_data =
+ LoadObjectField(shared, SharedFunctionInfo::kFunctionDataOffset);
+
+ VARIABLE(var_result, MachineRepresentation::kTagged, function_data);
+ Label done(this, &var_result);
+
+ GotoIfNot(HasInstanceType(function_data, INTERPRETER_DATA_TYPE), &done);
+ Node* bytecode_array =
+ LoadObjectField(function_data, InterpreterData::kBytecodeArrayOffset);
+ var_result.Bind(bytecode_array);
+ Goto(&done);
+
+ BIND(&done);
+ return var_result.value();
+}
+
void CodeStubAssembler::StoreHeapNumberValue(SloppyTNode<HeapNumber> object,
SloppyTNode<Float64T> value) {
StoreObjectFieldNoWriteBarrier(object, HeapNumber::kValueOffset, value,
@@ -2136,14 +2195,26 @@ Node* CodeStubAssembler::StoreObjectFieldRoot(Node* object, int offset,
}
}
+Node* CodeStubAssembler::StoreJSArrayLength(TNode<JSArray> array,
+ TNode<Smi> length) {
+ return StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length);
+}
+
+Node* CodeStubAssembler::StoreElements(TNode<Object> object,
+ TNode<FixedArrayBase> elements) {
+ return StoreObjectField(object, JSObject::kElementsOffset, elements);
+}
+
Node* CodeStubAssembler::StoreFixedArrayElement(Node* object, Node* index_node,
Node* value,
WriteBarrierMode barrier_mode,
int additional_offset,
ParameterMode parameter_mode) {
CSA_SLOW_ASSERT(
- this, Word32Or(IsHashTable(object),
- Word32Or(IsFixedArray(object), IsPropertyArray(object))));
+ this,
+ Word32Or(IsHashTable(object),
+ Word32Or(IsFixedArray(object),
+ Word32Or(IsPropertyArray(object), IsContext(object)))));
CSA_SLOW_ASSERT(this, MatchesParameterMode(index_node, parameter_mode));
DCHECK(barrier_mode == SKIP_WRITE_BARRIER ||
barrier_mode == UPDATE_WRITE_BARRIER);
@@ -2193,36 +2264,45 @@ Node* CodeStubAssembler::StoreFeedbackVectorSlot(Node* object,
}
}
-void CodeStubAssembler::EnsureArrayLengthWritable(Node* map, Label* bailout) {
+void CodeStubAssembler::EnsureArrayLengthWritable(TNode<Map> map,
+ Label* bailout) {
+ // Don't support arrays in dictionary named property mode.
+ GotoIf(IsDictionaryMap(map), bailout);
+
// Check whether the length property is writable. The length property is the
// only default named property on arrays. It's nonconfigurable, hence is
// guaranteed to stay the first property.
- Node* descriptors = LoadMapDescriptors(map);
- Node* details =
- LoadFixedArrayElement(descriptors, DescriptorArray::ToDetailsIndex(0));
- GotoIf(IsSetSmi(details, PropertyDetails::kAttributesReadOnlyMask), bailout);
+ TNode<DescriptorArray> descriptors = LoadMapDescriptors(map);
+
+ int length_index = JSArray::kLengthDescriptorIndex;
+#ifdef DEBUG
+ TNode<Name> maybe_length = CAST(LoadFixedArrayElement(
+ descriptors, DescriptorArray::ToKeyIndex(length_index)));
+ CSA_ASSERT(this,
+ WordEqual(maybe_length, LoadRoot(Heap::klength_stringRootIndex)));
+#endif
+
+ TNode<Int32T> details = LoadAndUntagToWord32FixedArrayElement(
+ descriptors, DescriptorArray::ToDetailsIndex(length_index));
+ GotoIf(IsSetWord32(details, PropertyDetails::kAttributesReadOnlyMask),
+ bailout);
}
-Node* CodeStubAssembler::EnsureArrayPushable(Node* receiver, Label* bailout) {
+TNode<Int32T> CodeStubAssembler::EnsureArrayPushable(TNode<Map> map,
+ Label* bailout) {
// Disallow pushing onto prototypes. It might be the JSArray prototype.
// Disallow pushing onto non-extensible objects.
Comment("Disallow pushing onto prototypes");
- Node* map = LoadMap(receiver);
Node* bit_field2 = LoadMapBitField2(map);
int mask = Map::IsPrototypeMapBit::kMask | Map::IsExtensibleBit::kMask;
Node* test = Word32And(bit_field2, Int32Constant(mask));
GotoIf(Word32NotEqual(test, Int32Constant(Map::IsExtensibleBit::kMask)),
bailout);
- // Disallow pushing onto arrays in dictionary named property mode. We need
- // to figure out whether the length property is still writable.
- Comment("Disallow pushing onto arrays in dictionary named property mode");
- GotoIf(IsDictionaryMap(map), bailout);
-
EnsureArrayLengthWritable(map, bailout);
- Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
- return kind;
+ TNode<Uint32T> kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
+ return Signed(kind);
}
void CodeStubAssembler::PossiblyGrowElementsCapacity(
@@ -2387,8 +2467,7 @@ TNode<HeapNumber> CodeStubAssembler::AllocateHeapNumberWithValue(
TNode<BigInt> CodeStubAssembler::AllocateBigInt(TNode<IntPtrT> length) {
TNode<BigInt> result = AllocateRawBigInt(length);
- STATIC_ASSERT(BigInt::LengthBits::kShift == 0);
- StoreBigIntBitfield(result, length);
+ StoreBigIntBitfield(result, WordShl(length, BigInt::LengthBits::kShift));
return result;
}
@@ -2447,12 +2526,12 @@ TNode<String> CodeStubAssembler::AllocateSeqOneByteString(
return CAST(result);
}
-Node* CodeStubAssembler::IsZeroOrFixedArray(Node* object) {
+Node* CodeStubAssembler::IsZeroOrContext(Node* object) {
Label out(this);
VARIABLE(var_result, MachineRepresentation::kWord32, Int32Constant(1));
GotoIf(WordEqual(object, SmiConstant(0)), &out);
- GotoIf(IsFixedArray(object), &out);
+ GotoIf(IsContext(object), &out);
var_result.Bind(Int32Constant(0));
Goto(&out);
@@ -2464,7 +2543,7 @@ Node* CodeStubAssembler::IsZeroOrFixedArray(Node* object) {
TNode<String> CodeStubAssembler::AllocateSeqOneByteString(
Node* context, TNode<Smi> length, AllocationFlags flags) {
Comment("AllocateSeqOneByteString");
- CSA_SLOW_ASSERT(this, IsZeroOrFixedArray(context));
+ CSA_SLOW_ASSERT(this, IsZeroOrContext(context));
VARIABLE(var_result, MachineRepresentation::kTagged);
// Compute the SeqOneByteString size and check if it fits into new space.
@@ -2533,7 +2612,7 @@ TNode<String> CodeStubAssembler::AllocateSeqTwoByteString(
TNode<String> CodeStubAssembler::AllocateSeqTwoByteString(
Node* context, TNode<Smi> length, AllocationFlags flags) {
- CSA_SLOW_ASSERT(this, IsZeroOrFixedArray(context));
+ CSA_SLOW_ASSERT(this, IsZeroOrContext(context));
Comment("AllocateSeqTwoByteString");
VARIABLE(var_result, MachineRepresentation::kTagged);
@@ -2659,7 +2738,7 @@ TNode<String> CodeStubAssembler::NewConsString(Node* context, TNode<Smi> length,
TNode<String> left,
TNode<String> right,
AllocationFlags flags) {
- CSA_ASSERT(this, IsFixedArray(context));
+ CSA_ASSERT(this, IsContext(context));
// Added string can be a cons string.
Comment("Allocating ConsString");
Node* left_instance_type = LoadInstanceType(left);
@@ -3160,10 +3239,9 @@ Node* CodeStubAssembler::AllocateFixedArray(ElementsKind kind,
return array;
}
-Node* CodeStubAssembler::ExtractFixedArray(Node* fixed_array, Node* first,
- Node* count, Node* capacity,
- ExtractFixedArrayFlags extract_flags,
- ParameterMode parameter_mode) {
+TNode<FixedArray> CodeStubAssembler::ExtractFixedArray(
+ Node* fixed_array, Node* first, Node* count, Node* capacity,
+ ExtractFixedArrayFlags extract_flags, ParameterMode parameter_mode) {
VARIABLE(var_result, MachineRepresentation::kTagged);
VARIABLE(var_fixed_array_map, MachineRepresentation::kTagged);
const AllocationFlags flags =
@@ -3304,7 +3382,7 @@ Node* CodeStubAssembler::ExtractFixedArray(Node* fixed_array, Node* first,
}
BIND(&done);
- return var_result.value();
+ return UncheckedCast<FixedArray>(var_result.value());
}
void CodeStubAssembler::InitializePropertyArrayLength(Node* property_array,
@@ -3534,6 +3612,18 @@ void CodeStubAssembler::CopyFixedArrayElements(
Comment("] CopyFixedArrayElements");
}
+TNode<FixedArray> CodeStubAssembler::ConvertFixedArrayBaseToFixedArray(
+ TNode<FixedArrayBase> base, Label* cast_fail) {
+ Label fixed_array(this);
+ TNode<Map> map = LoadMap(base);
+ GotoIf(WordEqual(map, LoadRoot(Heap::kFixedArrayMapRootIndex)), &fixed_array);
+ GotoIf(WordNotEqual(map, LoadRoot(Heap::kFixedCOWArrayMapRootIndex)),
+ cast_fail);
+ Goto(&fixed_array);
+ BIND(&fixed_array);
+ return UncheckedCast<FixedArray>(base);
+}
+
void CodeStubAssembler::CopyPropertyArrayValues(Node* from_array,
Node* to_array,
Node* property_count,
@@ -4310,7 +4400,8 @@ void CodeStubAssembler::ThrowTypeError(Node* context,
Unreachable();
}
-Node* CodeStubAssembler::InstanceTypeEqual(Node* instance_type, int type) {
+TNode<BoolT> CodeStubAssembler::InstanceTypeEqual(
+ SloppyTNode<Int32T> instance_type, int type) {
return Word32Equal(instance_type, Int32Constant(type));
}
@@ -4347,6 +4438,13 @@ Node* CodeStubAssembler::IsNoElementsProtectorCellInvalid() {
return WordEqual(cell_value, invalid);
}
+Node* CodeStubAssembler::IsPromiseResolveProtectorCellInvalid() {
+ Node* invalid = SmiConstant(Isolate::kProtectorInvalid);
+ Node* cell = LoadRoot(Heap::kPromiseResolveProtectorRootIndex);
+ Node* cell_value = LoadObjectField(cell, Cell::kValueOffset);
+ return WordEqual(cell_value, invalid);
+}
+
Node* CodeStubAssembler::IsPromiseThenProtectorCellInvalid() {
Node* invalid = SmiConstant(Isolate::kProtectorInvalid);
Node* cell = LoadRoot(Heap::kPromiseThenProtectorRootIndex);
@@ -4354,9 +4452,23 @@ Node* CodeStubAssembler::IsPromiseThenProtectorCellInvalid() {
return WordEqual(cell_value, invalid);
}
-Node* CodeStubAssembler::IsSpeciesProtectorCellInvalid() {
+Node* CodeStubAssembler::IsArraySpeciesProtectorCellInvalid() {
+ Node* invalid = SmiConstant(Isolate::kProtectorInvalid);
+ Node* cell = LoadRoot(Heap::kArraySpeciesProtectorRootIndex);
+ Node* cell_value = LoadObjectField(cell, PropertyCell::kValueOffset);
+ return WordEqual(cell_value, invalid);
+}
+
+Node* CodeStubAssembler::IsTypedArraySpeciesProtectorCellInvalid() {
Node* invalid = SmiConstant(Isolate::kProtectorInvalid);
- Node* cell = LoadRoot(Heap::kSpeciesProtectorRootIndex);
+ Node* cell = LoadRoot(Heap::kTypedArraySpeciesProtectorRootIndex);
+ Node* cell_value = LoadObjectField(cell, PropertyCell::kValueOffset);
+ return WordEqual(cell_value, invalid);
+}
+
+Node* CodeStubAssembler::IsPromiseSpeciesProtectorCellInvalid() {
+ Node* invalid = SmiConstant(Isolate::kProtectorInvalid);
+ Node* cell = LoadRoot(Heap::kPromiseSpeciesProtectorRootIndex);
Node* cell_value = LoadObjectField(cell, PropertyCell::kValueOffset);
return WordEqual(cell_value, invalid);
}
@@ -4378,7 +4490,7 @@ TNode<BoolT> CodeStubAssembler::IsPrototypeTypedArrayPrototype(
TNode<Object> proto = LoadMapPrototype(map);
TNode<Object> proto_of_proto = Select<Object>(
IsJSObject(proto), [=] { return LoadMapPrototype(LoadMap(CAST(proto))); },
- [=] { return NullConstant(); }, MachineRepresentation::kTagged);
+ [=] { return NullConstant(); });
return WordEqual(proto_of_proto, typed_array_prototype);
}
@@ -4408,7 +4520,8 @@ Node* CodeStubAssembler::IsFunctionWithPrototypeSlotMap(Node* map) {
return IsSetWord32<Map::HasPrototypeSlotBit>(LoadMapBitField(map));
}
-Node* CodeStubAssembler::IsSpecialReceiverInstanceType(Node* instance_type) {
+TNode<BoolT> CodeStubAssembler::IsSpecialReceiverInstanceType(
+ Node* instance_type) {
STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE);
return Int32LessThanOrEqual(instance_type,
Int32Constant(LAST_SPECIAL_RECEIVER_TYPE));
@@ -4467,12 +4580,6 @@ Node* CodeStubAssembler::IsJSReceiverInstanceType(Node* instance_type) {
Int32Constant(FIRST_JS_RECEIVER_TYPE));
}
-Node* CodeStubAssembler::IsArrayIteratorInstanceType(Node* instance_type) {
- return Uint32LessThan(
- Int32Constant(LAST_ARRAY_ITERATOR_TYPE - FIRST_ARRAY_ITERATOR_TYPE),
- Int32Sub(instance_type, Int32Constant(FIRST_ARRAY_ITERATOR_TYPE)));
-}
-
Node* CodeStubAssembler::IsJSReceiverMap(Node* map) {
return IsJSReceiverInstanceType(LoadMapInstanceType(map));
}
@@ -4551,10 +4658,21 @@ Node* CodeStubAssembler::IsJSArrayMap(Node* map) {
return IsJSArrayInstanceType(LoadMapInstanceType(map));
}
+Node* CodeStubAssembler::IsJSArrayIterator(Node* object) {
+ return HasInstanceType(object, JS_ARRAY_ITERATOR_TYPE);
+}
+
Node* CodeStubAssembler::IsJSAsyncGeneratorObject(Node* object) {
return HasInstanceType(object, JS_ASYNC_GENERATOR_OBJECT_TYPE);
}
+Node* CodeStubAssembler::IsContext(Node* object) {
+ Node* instance_type = LoadInstanceType(object);
+ return Word32And(
+ Int32GreaterThanOrEqual(instance_type, Int32Constant(FIRST_CONTEXT_TYPE)),
+ Int32LessThanOrEqual(instance_type, Int32Constant(LAST_CONTEXT_TYPE)));
+}
+
Node* CodeStubAssembler::IsFixedArray(Node* object) {
return HasInstanceType(object, FIXED_ARRAY_TYPE);
}
@@ -4638,7 +4756,7 @@ Node* CodeStubAssembler::IsAnyHeapNumber(Node* object) {
return Word32Or(IsMutableHeapNumber(object), IsHeapNumber(object));
}
-Node* CodeStubAssembler::IsHeapNumber(Node* object) {
+TNode<BoolT> CodeStubAssembler::IsHeapNumber(Node* object) {
return IsHeapNumberMap(LoadMap(object));
}
@@ -4684,8 +4802,8 @@ Node* CodeStubAssembler::IsPrimitiveInstanceType(Node* instance_type) {
Int32Constant(LAST_PRIMITIVE_TYPE));
}
-Node* CodeStubAssembler::IsPrivateSymbol(Node* object) {
- return Select(
+TNode<BoolT> CodeStubAssembler::IsPrivateSymbol(Node* object) {
+ return Select<BoolT>(
IsSymbol(object),
[=] {
TNode<Symbol> symbol = CAST(object);
@@ -4693,7 +4811,7 @@ Node* CodeStubAssembler::IsPrivateSymbol(Node* object) {
SmiToInt32(LoadObjectField<Smi>(symbol, Symbol::kFlagsOffset));
return IsSetWord32(flags, 1 << Symbol::kPrivateBit);
},
- [=] { return Int32Constant(0); }, MachineRepresentation::kWord32);
+ [=] { return Int32FalseConstant(); });
}
Node* CodeStubAssembler::IsNativeContext(Node* object) {
@@ -4754,65 +4872,54 @@ Node* CodeStubAssembler::IsJSRegExp(Node* object) {
return HasInstanceType(object, JS_REGEXP_TYPE);
}
-Node* CodeStubAssembler::IsNumeric(Node* object) {
- return Select(
- TaggedIsSmi(object), [=] { return Int32Constant(1); },
- [=] { return Word32Or(IsHeapNumber(object), IsBigInt(object)); },
- MachineRepresentation::kWord32);
+TNode<BoolT> CodeStubAssembler::IsNumber(SloppyTNode<Object> object) {
+ return Select<BoolT>(TaggedIsSmi(object), [=] { return Int32TrueConstant(); },
+ [=] { return IsHeapNumber(object); });
}
-Node* CodeStubAssembler::IsNumber(Node* object) {
- return Select(TaggedIsSmi(object), [=] { return Int32Constant(1); },
- [=] { return IsHeapNumber(object); },
- MachineRepresentation::kWord32);
-}
-
-Node* CodeStubAssembler::FixedArraySizeDoesntFitInNewSpace(Node* element_count,
- int base_size,
- ParameterMode mode) {
- int max_newspace_elements =
- (kMaxRegularHeapObjectSize - base_size) / kPointerSize;
- return IntPtrOrSmiGreaterThan(
- element_count, IntPtrOrSmiConstant(max_newspace_elements, mode), mode);
+TNode<BoolT> CodeStubAssembler::IsNumeric(SloppyTNode<Object> object) {
+ return Select<BoolT>(TaggedIsSmi(object), [=] { return Int32TrueConstant(); },
+ [=] {
+ return UncheckedCast<BoolT>(
+ Word32Or(IsHeapNumber(object), IsBigInt(object)));
+ });
}
-Node* CodeStubAssembler::IsNumberNormalized(Node* number) {
- CSA_ASSERT(this, IsNumber(number));
-
- VARIABLE(var_result, MachineRepresentation::kWord32, Int32Constant(1));
+TNode<BoolT> CodeStubAssembler::IsNumberNormalized(SloppyTNode<Number> number) {
+ TVARIABLE(BoolT, var_result, Int32TrueConstant());
Label out(this);
GotoIf(TaggedIsSmi(number), &out);
- Node* const value = LoadHeapNumberValue(number);
- Node* const smi_min = Float64Constant(static_cast<double>(Smi::kMinValue));
- Node* const smi_max = Float64Constant(static_cast<double>(Smi::kMaxValue));
+ TNode<Float64T> value = LoadHeapNumberValue(CAST(number));
+ TNode<Float64T> smi_min =
+ Float64Constant(static_cast<double>(Smi::kMinValue));
+ TNode<Float64T> smi_max =
+ Float64Constant(static_cast<double>(Smi::kMaxValue));
GotoIf(Float64LessThan(value, smi_min), &out);
GotoIf(Float64GreaterThan(value, smi_max), &out);
GotoIfNot(Float64Equal(value, value), &out); // NaN.
- var_result.Bind(Int32Constant(0));
+ var_result = Int32FalseConstant();
Goto(&out);
BIND(&out);
return var_result.value();
}
-Node* CodeStubAssembler::IsNumberPositive(Node* number) {
- CSA_ASSERT(this, IsNumber(number));
- Node* const float_zero = Float64Constant(0.);
- return Select(TaggedIsSmi(number),
- [=] { return TaggedIsPositiveSmi(number); },
- [=] {
- Node* v = LoadHeapNumberValue(number);
- return Float64GreaterThanOrEqual(v, float_zero);
- },
- MachineRepresentation::kWord32);
+TNode<BoolT> CodeStubAssembler::IsNumberPositive(SloppyTNode<Number> number) {
+ TNode<Float64T> float_zero = Float64Constant(0.);
+ return Select<BoolT>(TaggedIsSmi(number),
+ [=] { return TaggedIsPositiveSmi(number); },
+ [=] {
+ TNode<Float64T> v = LoadHeapNumberValue(CAST(number));
+ return Float64GreaterThanOrEqual(v, float_zero);
+ });
}
-Node* CodeStubAssembler::IsNumberArrayIndex(Node* number) {
- VARIABLE(var_result, MachineRepresentation::kWord32, Int32Constant(1));
+TNode<BoolT> CodeStubAssembler::IsNumberArrayIndex(SloppyTNode<Number> number) {
+ TVARIABLE(BoolT, var_result, Int32TrueConstant());
Label check_upper_bound(this), check_is_integer(this), out(this),
return_false(this);
@@ -4828,19 +4935,28 @@ Node* CodeStubAssembler::IsNumberArrayIndex(Node* number) {
BIND(&check_is_integer);
GotoIf(TaggedIsSmi(number), &out);
// Check that the HeapNumber is a valid uint32
- Node* value = LoadHeapNumberValue(number);
- Node* int_value = ChangeFloat64ToUint32(value);
+ TNode<Float64T> value = LoadHeapNumberValue(CAST(number));
+ TNode<Uint32T> int_value = ChangeFloat64ToUint32(value);
GotoIf(Float64Equal(value, ChangeUint32ToFloat64(int_value)), &out);
Goto(&return_false);
BIND(&return_false);
- var_result.Bind(Int32Constant(0));
+ var_result = Int32FalseConstant();
Goto(&out);
BIND(&out);
return var_result.value();
}
+Node* CodeStubAssembler::FixedArraySizeDoesntFitInNewSpace(Node* element_count,
+ int base_size,
+ ParameterMode mode) {
+ int max_newspace_elements =
+ (kMaxRegularHeapObjectSize - base_size) / kPointerSize;
+ return IntPtrOrSmiGreaterThan(
+ element_count, IntPtrOrSmiConstant(max_newspace_elements, mode), mode);
+}
+
TNode<Int32T> CodeStubAssembler::StringCharCodeAt(SloppyTNode<String> string,
SloppyTNode<IntPtrT> index) {
CSA_ASSERT(this, IsString(string));
@@ -4891,7 +5007,7 @@ TNode<Int32T> CodeStubAssembler::StringCharCodeAt(SloppyTNode<String> string,
return var_result.value();
}
-TNode<String> CodeStubAssembler::StringFromCharCode(TNode<Int32T> code) {
+TNode<String> CodeStubAssembler::StringFromSingleCharCode(TNode<Int32T> code) {
VARIABLE(var_result, MachineRepresentation::kTagged);
// Check if the {code} is a one-byte char code.
@@ -5089,7 +5205,7 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string,
BIND(&single_char);
{
TNode<Int32T> char_code = StringCharCodeAt(string, from);
- var_result = StringFromCharCode(char_code);
+ var_result = StringFromSingleCharCode(char_code);
Goto(&end);
}
@@ -5282,6 +5398,16 @@ void CodeStubAssembler::BranchIfCanDerefIndirectString(Node* string,
Goto(cannot_deref);
}
+Node* CodeStubAssembler::DerefIndirectString(TNode<String> string,
+ TNode<Int32T> instance_type,
+ Label* cannot_deref) {
+ Label deref(this);
+ BranchIfCanDerefIndirectString(string, instance_type, &deref, cannot_deref);
+ BIND(&deref);
+ STATIC_ASSERT(ThinString::kActualOffset == ConsString::kFirstOffset);
+ return LoadObjectField(string, ThinString::kActualOffset);
+}
+
void CodeStubAssembler::DerefIndirectString(Variable* var_string,
Node* instance_type) {
#ifdef DEBUG
@@ -5454,8 +5580,8 @@ TNode<String> CodeStubAssembler::StringAdd(Node* context, TNode<String> left,
return result.value();
}
-TNode<String> CodeStubAssembler::StringFromCodePoint(TNode<Int32T> codepoint,
- UnicodeEncoding encoding) {
+TNode<String> CodeStubAssembler::StringFromSingleCodePoint(
+ TNode<Int32T> codepoint, UnicodeEncoding encoding) {
VARIABLE(var_result, MachineRepresentation::kTagged, EmptyStringConstant());
Label if_isword16(this), if_isword32(this), return_result(this);
@@ -5465,7 +5591,7 @@ TNode<String> CodeStubAssembler::StringFromCodePoint(TNode<Int32T> codepoint,
BIND(&if_isword16);
{
- var_result.Bind(StringFromCharCode(codepoint));
+ var_result.Bind(StringFromSingleCharCode(codepoint));
Goto(&return_result);
}
@@ -5607,25 +5733,26 @@ TNode<String> CodeStubAssembler::NumberToString(TNode<Number> input) {
return result.value();
}
-Node* CodeStubAssembler::ToName(Node* context, Node* value) {
+TNode<Name> CodeStubAssembler::ToName(SloppyTNode<Context> context,
+ SloppyTNode<Object> value) {
Label end(this);
- VARIABLE(var_result, MachineRepresentation::kTagged);
+ TVARIABLE(Name, var_result);
Label is_number(this);
GotoIf(TaggedIsSmi(value), &is_number);
Label not_name(this);
- Node* value_instance_type = LoadInstanceType(value);
+ TNode<Int32T> value_instance_type = LoadInstanceType(CAST(value));
STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE);
GotoIf(Int32GreaterThan(value_instance_type, Int32Constant(LAST_NAME_TYPE)),
&not_name);
- var_result.Bind(value);
+ var_result = CAST(value);
Goto(&end);
BIND(&is_number);
{
- var_result.Bind(CallBuiltin(Builtins::kNumberToString, context, value));
+ var_result = CAST(CallBuiltin(Builtins::kNumberToString, context, value));
Goto(&end);
}
@@ -5638,18 +5765,17 @@ Node* CodeStubAssembler::ToName(Node* context, Node* value) {
GotoIfNot(InstanceTypeEqual(value_instance_type, ODDBALL_TYPE),
&not_oddball);
- var_result.Bind(LoadObjectField(value, Oddball::kToStringOffset));
+ var_result = LoadObjectField<String>(CAST(value), Oddball::kToStringOffset);
Goto(&end);
BIND(&not_oddball);
{
- var_result.Bind(CallRuntime(Runtime::kToName, context, value));
+ var_result = CAST(CallRuntime(Runtime::kToName, context, value));
Goto(&end);
}
}
BIND(&end);
- CSA_ASSERT(this, IsName(var_result.value()));
return var_result.value();
}
@@ -5799,8 +5925,7 @@ TNode<Number> CodeStubAssembler::ToNumber_Inline(SloppyTNode<Context> context,
[=] {
return CAST(CallBuiltin(Builtins::kNonNumberToNumber,
context, input));
- },
- MachineRepresentation::kTagged);
+ });
Goto(&end);
}
@@ -6167,23 +6292,23 @@ TNode<Smi> CodeStubAssembler::ToSmiLength(TNode<Object> input,
return result.value();
}
-Node* CodeStubAssembler::ToLength_Inline(Node* const context,
- Node* const input) {
- Node* const smi_zero = SmiConstant(0);
- return Select(
- TaggedIsSmi(input), [=] { return SmiMax(input, smi_zero); },
- [=] { return CallBuiltin(Builtins::kToLength, context, input); },
- MachineRepresentation::kTagged);
+TNode<Number> CodeStubAssembler::ToLength_Inline(SloppyTNode<Context> context,
+ SloppyTNode<Object> input) {
+ TNode<Smi> smi_zero = SmiConstant(0);
+ return Select<Number>(
+ TaggedIsSmi(input), [=] { return SmiMax(CAST(input), smi_zero); },
+ [=] { return CAST(CallBuiltin(Builtins::kToLength, context, input)); });
}
TNode<Number> CodeStubAssembler::ToInteger_Inline(
- TNode<Context> context, TNode<Object> input, ToIntegerTruncationMode mode) {
+ SloppyTNode<Context> context, SloppyTNode<Object> input,
+ ToIntegerTruncationMode mode) {
Builtins::Name builtin = (mode == kNoTruncation)
? Builtins::kToInteger
: Builtins::kToInteger_TruncateMinusZero;
- return CAST(Select(TaggedIsSmi(input), [=] { return input; },
- [=] { return CallBuiltin(builtin, context, input); },
- MachineRepresentation::kTagged));
+ return Select<Number>(
+ TaggedIsSmi(input), [=] { return CAST(input); },
+ [=] { return CAST(CallBuiltin(builtin, context, input)); });
}
TNode<Number> CodeStubAssembler::ToInteger(SloppyTNode<Context> context,
@@ -6244,8 +6369,9 @@ TNode<Number> CodeStubAssembler::ToInteger(SloppyTNode<Context> context,
}
BIND(&out);
- if (mode == kTruncateMinusZero)
- CSA_ASSERT(this, IsNumberNormalized(var_arg.value()));
+ if (mode == kTruncateMinusZero) {
+ CSA_ASSERT(this, IsNumberNormalized(CAST(var_arg.value())));
+ }
return CAST(var_arg.value());
}
@@ -6422,8 +6548,8 @@ TNode<IntPtrT> CodeStubAssembler::IntPtrMax(SloppyTNode<IntPtrT> left,
ToIntPtrConstant(right, right_constant)) {
return IntPtrConstant(std::max(left_constant, right_constant));
}
- return SelectConstant(IntPtrGreaterThanOrEqual(left, right), left, right,
- MachineType::PointerRepresentation());
+ return SelectConstant<IntPtrT>(IntPtrGreaterThanOrEqual(left, right), left,
+ right);
}
TNode<IntPtrT> CodeStubAssembler::IntPtrMin(SloppyTNode<IntPtrT> left,
@@ -6434,8 +6560,8 @@ TNode<IntPtrT> CodeStubAssembler::IntPtrMin(SloppyTNode<IntPtrT> left,
ToIntPtrConstant(right, right_constant)) {
return IntPtrConstant(std::min(left_constant, right_constant));
}
- return SelectConstant(IntPtrLessThanOrEqual(left, right), left, right,
- MachineType::PointerRepresentation());
+ return SelectConstant<IntPtrT>(IntPtrLessThanOrEqual(left, right), left,
+ right);
}
template <class Dictionary>
@@ -6725,109 +6851,148 @@ void CodeStubAssembler::Add(Node* dictionary, Node* key, Node* value,
template void CodeStubAssembler::Add<NameDictionary>(Node*, Node*, Node*,
Label*);
-void CodeStubAssembler::DescriptorLookupLinear(Node* unique_name,
- Node* descriptors, Node* nof,
- Label* if_found,
- Variable* var_name_index,
- Label* if_not_found) {
- Comment("DescriptorLookupLinear");
- Node* first_inclusive = IntPtrConstant(DescriptorArray::ToKeyIndex(0));
- Node* factor = IntPtrConstant(DescriptorArray::kEntrySize);
- Node* last_exclusive = IntPtrAdd(first_inclusive, IntPtrMul(nof, factor));
+template <typename Array>
+void CodeStubAssembler::LookupLinear(TNode<Name> unique_name,
+ TNode<Array> array,
+ TNode<Uint32T> number_of_valid_entries,
+ Label* if_found,
+ TVariable<IntPtrT>* var_name_index,
+ Label* if_not_found) {
+ Comment("LookupLinear");
+ TNode<IntPtrT> first_inclusive = IntPtrConstant(Array::ToKeyIndex(0));
+ TNode<IntPtrT> factor = IntPtrConstant(Array::kEntrySize);
+ TNode<IntPtrT> last_exclusive = IntPtrAdd(
+ first_inclusive,
+ IntPtrMul(ChangeInt32ToIntPtr(number_of_valid_entries), factor));
BuildFastLoop(last_exclusive, first_inclusive,
- [this, descriptors, unique_name, if_found,
- var_name_index](Node* name_index) {
- Node* candidate_name =
- LoadFixedArrayElement(descriptors, name_index);
- var_name_index->Bind(name_index);
+ [=](SloppyTNode<IntPtrT> name_index) {
+ TNode<Name> candidate_name =
+ CAST(LoadFixedArrayElement(array, name_index));
+ *var_name_index = name_index;
GotoIf(WordEqual(candidate_name, unique_name), if_found);
},
- -DescriptorArray::kEntrySize, INTPTR_PARAMETERS,
- IndexAdvanceMode::kPre);
+ -Array::kEntrySize, INTPTR_PARAMETERS, IndexAdvanceMode::kPre);
Goto(if_not_found);
}
-Node* CodeStubAssembler::DescriptorArrayNumberOfEntries(Node* descriptors) {
- return LoadAndUntagToWord32FixedArrayElement(
- descriptors, IntPtrConstant(DescriptorArray::kDescriptorLengthIndex));
+template <>
+TNode<Uint32T> CodeStubAssembler::NumberOfEntries<DescriptorArray>(
+ TNode<DescriptorArray> descriptors) {
+ return Unsigned(LoadAndUntagToWord32FixedArrayElement(
+ descriptors, IntPtrConstant(DescriptorArray::kDescriptorLengthIndex)));
+}
+
+template <>
+TNode<Uint32T> CodeStubAssembler::NumberOfEntries<TransitionArray>(
+ TNode<TransitionArray> transitions) {
+ TNode<IntPtrT> length = LoadAndUntagFixedArrayBaseLength(transitions);
+ return Select<Uint32T>(
+ UintPtrLessThan(length, IntPtrConstant(TransitionArray::kFirstIndex)),
+ [=] { return Unsigned(Int32Constant(0)); },
+ [=] {
+ return Unsigned(LoadAndUntagToWord32FixedArrayElement(
+ transitions,
+ IntPtrConstant(TransitionArray::kTransitionLengthIndex)));
+ });
}
-Node* CodeStubAssembler::DescriptorNumberToIndex(
- SloppyTNode<Uint32T> descriptor_number) {
- Node* descriptor_size = Int32Constant(DescriptorArray::kEntrySize);
- Node* index = Int32Mul(descriptor_number, descriptor_size);
+template <typename Array>
+TNode<IntPtrT> CodeStubAssembler::EntryIndexToIndex(
+ TNode<Uint32T> entry_index) {
+ TNode<Int32T> entry_size = Int32Constant(Array::kEntrySize);
+ TNode<Word32T> index = Int32Mul(entry_index, entry_size);
return ChangeInt32ToIntPtr(index);
}
-Node* CodeStubAssembler::DescriptorArrayToKeyIndex(Node* descriptor_number) {
- return IntPtrAdd(IntPtrConstant(DescriptorArray::ToKeyIndex(0)),
- DescriptorNumberToIndex(descriptor_number));
+template <typename Array>
+TNode<IntPtrT> CodeStubAssembler::ToKeyIndex(TNode<Uint32T> entry_index) {
+ return IntPtrAdd(IntPtrConstant(Array::ToKeyIndex(0)),
+ EntryIndexToIndex<Array>(entry_index));
}
-Node* CodeStubAssembler::DescriptorArrayGetSortedKeyIndex(
- Node* descriptors, Node* descriptor_number) {
- Node* details = DescriptorArrayGetDetails(
- TNode<DescriptorArray>::UncheckedCast(descriptors),
- TNode<Uint32T>::UncheckedCast(descriptor_number));
+template TNode<IntPtrT> CodeStubAssembler::ToKeyIndex<DescriptorArray>(
+ TNode<Uint32T>);
+template TNode<IntPtrT> CodeStubAssembler::ToKeyIndex<TransitionArray>(
+ TNode<Uint32T>);
+
+template <>
+TNode<Uint32T> CodeStubAssembler::GetSortedKeyIndex<DescriptorArray>(
+ TNode<DescriptorArray> descriptors, TNode<Uint32T> descriptor_number) {
+ TNode<Uint32T> details =
+ DescriptorArrayGetDetails(descriptors, descriptor_number);
return DecodeWord32<PropertyDetails::DescriptorPointer>(details);
}
-Node* CodeStubAssembler::DescriptorArrayGetKey(Node* descriptors,
- Node* descriptor_number) {
+template <>
+TNode<Uint32T> CodeStubAssembler::GetSortedKeyIndex<TransitionArray>(
+ TNode<TransitionArray> transitions, TNode<Uint32T> transition_number) {
+ return transition_number;
+}
+
+template <typename Array>
+TNode<Name> CodeStubAssembler::GetKey(TNode<Array> array,
+ TNode<Uint32T> entry_index) {
const int key_offset = DescriptorArray::ToKeyIndex(0) * kPointerSize;
- return LoadFixedArrayElement(
- descriptors, DescriptorNumberToIndex(descriptor_number), key_offset);
+ return CAST(LoadFixedArrayElement(
+ array, EntryIndexToIndex<Array>(entry_index), key_offset));
}
+template TNode<Name> CodeStubAssembler::GetKey<DescriptorArray>(
+ TNode<DescriptorArray>, TNode<Uint32T>);
+template TNode<Name> CodeStubAssembler::GetKey<TransitionArray>(
+ TNode<TransitionArray>, TNode<Uint32T>);
+
TNode<Uint32T> CodeStubAssembler::DescriptorArrayGetDetails(
TNode<DescriptorArray> descriptors, TNode<Uint32T> descriptor_number) {
const int details_offset = DescriptorArray::ToDetailsIndex(0) * kPointerSize;
- return TNode<Uint32T>::UncheckedCast(LoadAndUntagToWord32FixedArrayElement(
- descriptors, DescriptorNumberToIndex(descriptor_number), details_offset));
-}
-
-void CodeStubAssembler::DescriptorLookupBinary(Node* unique_name,
- Node* descriptors, Node* nof,
- Label* if_found,
- Variable* var_name_index,
- Label* if_not_found) {
- Comment("DescriptorLookupBinary");
- VARIABLE(var_low, MachineRepresentation::kWord32, Int32Constant(0));
- Node* limit =
- Int32Sub(DescriptorArrayNumberOfEntries(descriptors), Int32Constant(1));
- VARIABLE(var_high, MachineRepresentation::kWord32, limit);
- Node* hash = LoadNameHashField(unique_name);
+ return Unsigned(LoadAndUntagToWord32FixedArrayElement(
+ descriptors, EntryIndexToIndex<DescriptorArray>(descriptor_number),
+ details_offset));
+}
+
+template <typename Array>
+void CodeStubAssembler::LookupBinary(TNode<Name> unique_name,
+ TNode<Array> array,
+ TNode<Uint32T> number_of_valid_entries,
+ Label* if_found,
+ TVariable<IntPtrT>* var_name_index,
+ Label* if_not_found) {
+ Comment("LookupBinary");
+ TVARIABLE(Uint32T, var_low, Unsigned(Int32Constant(0)));
+ TNode<Uint32T> limit =
+ Unsigned(Int32Sub(NumberOfEntries<Array>(array), Int32Constant(1)));
+ TVARIABLE(Uint32T, var_high, limit);
+ TNode<Uint32T> hash = LoadNameHashField(unique_name);
CSA_ASSERT(this, Word32NotEqual(hash, Int32Constant(0)));
// Assume non-empty array.
CSA_ASSERT(this, Uint32LessThanOrEqual(var_low.value(), var_high.value()));
- Variable* loop_vars[] = {&var_high, &var_low};
- Label binary_loop(this, 2, loop_vars);
+ Label binary_loop(this, {&var_high, &var_low});
Goto(&binary_loop);
BIND(&binary_loop);
{
// mid = low + (high - low) / 2 (to avoid overflow in "(low + high) / 2").
- Node* mid =
+ TNode<Uint32T> mid = Unsigned(
Int32Add(var_low.value(),
- Word32Shr(Int32Sub(var_high.value(), var_low.value()), 1));
- // mid_name = descriptors->GetSortedKey(mid).
- Node* sorted_key_index = DescriptorArrayGetSortedKeyIndex(descriptors, mid);
- Node* mid_name = DescriptorArrayGetKey(descriptors, sorted_key_index);
+ Word32Shr(Int32Sub(var_high.value(), var_low.value()), 1)));
+ // mid_name = array->GetSortedKey(mid).
+ TNode<Uint32T> sorted_key_index = GetSortedKeyIndex<Array>(array, mid);
+ TNode<Name> mid_name = GetKey<Array>(array, sorted_key_index);
- Node* mid_hash = LoadNameHashField(mid_name);
+ TNode<Uint32T> mid_hash = LoadNameHashField(mid_name);
Label mid_greater(this), mid_less(this), merge(this);
Branch(Uint32GreaterThanOrEqual(mid_hash, hash), &mid_greater, &mid_less);
BIND(&mid_greater);
{
- var_high.Bind(mid);
+ var_high = mid;
Goto(&merge);
}
BIND(&mid_less);
{
- var_low.Bind(Int32Add(mid, Int32Constant(1)));
+ var_low = Unsigned(Int32Add(mid, Int32Constant(1)));
Goto(&merge);
}
BIND(&merge);
@@ -6840,85 +7005,121 @@ void CodeStubAssembler::DescriptorLookupBinary(Node* unique_name,
{
GotoIf(Int32GreaterThan(var_low.value(), limit), if_not_found);
- Node* sort_index =
- DescriptorArrayGetSortedKeyIndex(descriptors, var_low.value());
- Node* current_name = DescriptorArrayGetKey(descriptors, sort_index);
- Node* current_hash = LoadNameHashField(current_name);
+ TNode<Uint32T> sort_index =
+ GetSortedKeyIndex<Array>(array, var_low.value());
+ TNode<Name> current_name = GetKey<Array>(array, sort_index);
+ TNode<Uint32T> current_hash = LoadNameHashField(current_name);
GotoIf(Word32NotEqual(current_hash, hash), if_not_found);
Label next(this);
GotoIf(WordNotEqual(current_name, unique_name), &next);
- GotoIf(Int32GreaterThanOrEqual(sort_index, nof), if_not_found);
- var_name_index->Bind(DescriptorArrayToKeyIndex(sort_index));
+ GotoIf(Uint32GreaterThanOrEqual(sort_index, number_of_valid_entries),
+ if_not_found);
+ *var_name_index = ToKeyIndex<Array>(sort_index);
Goto(if_found);
BIND(&next);
- var_low.Bind(Int32Add(var_low.value(), Int32Constant(1)));
+ var_low = Unsigned(Int32Add(var_low.value(), Int32Constant(1)));
Goto(&scan_loop);
}
}
-void CodeStubAssembler::DescriptorLookup(Node* unique_name, Node* descriptors,
- Node* bitfield3, Label* if_found,
- Variable* var_name_index,
- Label* if_not_found) {
+void CodeStubAssembler::DescriptorLookup(
+ SloppyTNode<Name> unique_name, SloppyTNode<DescriptorArray> descriptors,
+ SloppyTNode<Uint32T> bitfield3, Label* if_found,
+ TVariable<IntPtrT>* var_name_index, Label* if_not_found) {
Comment("DescriptorArrayLookup");
- Node* nof = DecodeWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3);
- GotoIf(Word32Equal(nof, Int32Constant(0)), if_not_found);
+ TNode<Uint32T> nof = DecodeWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3);
+ Lookup<DescriptorArray>(unique_name, descriptors, nof, if_found,
+ var_name_index, if_not_found);
+}
+
+void CodeStubAssembler::TransitionLookup(
+ SloppyTNode<Name> unique_name, SloppyTNode<TransitionArray> transitions,
+ Label* if_found, TVariable<IntPtrT>* var_name_index, Label* if_not_found) {
+ Comment("TransitionArrayLookup");
+ TNode<Uint32T> number_of_valid_transitions =
+ NumberOfEntries<TransitionArray>(transitions);
+ Lookup<TransitionArray>(unique_name, transitions, number_of_valid_transitions,
+ if_found, var_name_index, if_not_found);
+}
+
+template <typename Array>
+void CodeStubAssembler::Lookup(TNode<Name> unique_name, TNode<Array> array,
+ TNode<Uint32T> number_of_valid_entries,
+ Label* if_found,
+ TVariable<IntPtrT>* var_name_index,
+ Label* if_not_found) {
+ Comment("ArrayLookup");
+ if (!number_of_valid_entries) {
+ number_of_valid_entries = NumberOfEntries(array);
+ }
+ GotoIf(Word32Equal(number_of_valid_entries, Int32Constant(0)), if_not_found);
Label linear_search(this), binary_search(this);
const int kMaxElementsForLinearSearch = 32;
- Branch(Int32LessThanOrEqual(nof, Int32Constant(kMaxElementsForLinearSearch)),
+ Branch(Uint32LessThanOrEqual(number_of_valid_entries,
+ Int32Constant(kMaxElementsForLinearSearch)),
&linear_search, &binary_search);
BIND(&linear_search);
{
- DescriptorLookupLinear(unique_name, descriptors, ChangeInt32ToIntPtr(nof),
- if_found, var_name_index, if_not_found);
+ LookupLinear<Array>(unique_name, array, number_of_valid_entries, if_found,
+ var_name_index, if_not_found);
}
BIND(&binary_search);
{
- DescriptorLookupBinary(unique_name, descriptors, nof, if_found,
- var_name_index, if_not_found);
+ LookupBinary<Array>(unique_name, array, number_of_valid_entries, if_found,
+ var_name_index, if_not_found);
}
}
-void CodeStubAssembler::TryLookupProperty(
- Node* object, Node* map, Node* instance_type, Node* unique_name,
- Label* if_found_fast, Label* if_found_dict, Label* if_found_global,
- Variable* var_meta_storage, Variable* var_name_index, Label* if_not_found,
- Label* if_bailout) {
- DCHECK_EQ(MachineRepresentation::kTagged, var_meta_storage->rep());
- DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep());
-
- Label if_objectisspecial(this);
- STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE);
- GotoIf(Int32LessThanOrEqual(instance_type,
- Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
- &if_objectisspecial);
+void CodeStubAssembler::TryLookupPropertyInSimpleObject(
+ TNode<JSObject> object, TNode<Map> map, TNode<Name> unique_name,
+ Label* if_found_fast, Label* if_found_dict,
+ TVariable<HeapObject>* var_meta_storage, TVariable<IntPtrT>* var_name_index,
+ Label* if_not_found) {
+ CSA_ASSERT(
+ this,
+ Word32BinaryNot(IsSpecialReceiverInstanceType(LoadMapInstanceType(map))));
uint32_t mask =
Map::HasNamedInterceptorBit::kMask | Map::IsAccessCheckNeededBit::kMask;
CSA_ASSERT(this, Word32BinaryNot(IsSetWord32(LoadMapBitField(map), mask)));
USE(mask);
- Node* bit_field3 = LoadMapBitField3(map);
+ TNode<Uint32T> bit_field3 = LoadMapBitField3(map);
Label if_isfastmap(this), if_isslowmap(this);
Branch(IsSetWord32<Map::IsDictionaryMapBit>(bit_field3), &if_isslowmap,
&if_isfastmap);
BIND(&if_isfastmap);
{
- Node* descriptors = LoadMapDescriptors(map);
- var_meta_storage->Bind(descriptors);
+ TNode<DescriptorArray> descriptors = LoadMapDescriptors(map);
+ *var_meta_storage = descriptors;
DescriptorLookup(unique_name, descriptors, bit_field3, if_found_fast,
var_name_index, if_not_found);
}
BIND(&if_isslowmap);
{
- Node* dictionary = LoadSlowProperties(object);
- var_meta_storage->Bind(dictionary);
+ TNode<NameDictionary> dictionary = CAST(LoadSlowProperties(object));
+ *var_meta_storage = dictionary;
NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict,
var_name_index, if_not_found);
}
+}
+
+void CodeStubAssembler::TryLookupProperty(
+ SloppyTNode<JSObject> object, SloppyTNode<Map> map,
+ SloppyTNode<Int32T> instance_type, SloppyTNode<Name> unique_name,
+ Label* if_found_fast, Label* if_found_dict, Label* if_found_global,
+ TVariable<HeapObject>* var_meta_storage, TVariable<IntPtrT>* var_name_index,
+ Label* if_not_found, Label* if_bailout) {
+ Label if_objectisspecial(this);
+ GotoIf(IsSpecialReceiverInstanceType(instance_type), &if_objectisspecial);
+
+ TryLookupPropertyInSimpleObject(object, map, unique_name, if_found_fast,
+ if_found_dict, var_meta_storage,
+ var_name_index, if_not_found);
+
BIND(&if_objectisspecial);
{
// Handle global object here and bailout for other special objects.
@@ -6926,13 +7127,13 @@ void CodeStubAssembler::TryLookupProperty(
if_bailout);
// Handle interceptors and access checks in runtime.
- Node* bit_field = LoadMapBitField(map);
+ TNode<Int32T> bit_field = LoadMapBitField(map);
int mask =
Map::HasNamedInterceptorBit::kMask | Map::IsAccessCheckNeededBit::kMask;
GotoIf(IsSetWord32(bit_field, mask), if_bailout);
- Node* dictionary = LoadSlowProperties(object);
- var_meta_storage->Bind(dictionary);
+ TNode<GlobalDictionary> dictionary = CAST(LoadSlowProperties(object));
+ *var_meta_storage = dictionary;
NameDictionaryLookup<GlobalDictionary>(
dictionary, unique_name, if_found_global, var_name_index, if_not_found);
@@ -6945,8 +7146,8 @@ void CodeStubAssembler::TryHasOwnProperty(Node* object, Node* map,
Label* if_not_found,
Label* if_bailout) {
Comment("TryHasOwnProperty");
- VARIABLE(var_meta_storage, MachineRepresentation::kTagged);
- VARIABLE(var_name_index, MachineType::PointerRepresentation());
+ TVARIABLE(HeapObject, var_meta_storage);
+ TVARIABLE(IntPtrT, var_name_index);
Label if_found_global(this);
TryLookupProperty(object, map, instance_type, unique_name, if_found, if_found,
@@ -7127,10 +7328,9 @@ void CodeStubAssembler::LoadPropertyFromGlobalDictionary(Node* dictionary,
// |value| is the property backing store's contents, which is either a value
// or an accessor pair, as specified by |details|.
// Returns either the original value, or the result of the getter call.
-Node* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details,
- Node* context, Node* receiver,
- Label* if_bailout,
- GetOwnPropertyMode mode) {
+TNode<Object> CodeStubAssembler::CallGetterIfAccessor(
+ Node* value, Node* details, Node* context, Node* receiver,
+ Label* if_bailout, GetOwnPropertyMode mode) {
VARIABLE(var_value, MachineRepresentation::kTagged, value);
Label done(this), if_accessor_info(this, Label::kDeferred);
@@ -7228,7 +7428,7 @@ Node* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details,
}
BIND(&done);
- return var_value.value();
+ return UncheckedCast<Object>(var_value.value());
}
void CodeStubAssembler::TryGetOwnProperty(
@@ -7248,8 +7448,8 @@ void CodeStubAssembler::TryGetOwnProperty(
DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep());
Comment("TryGetOwnProperty");
- VARIABLE(var_meta_storage, MachineRepresentation::kTagged);
- VARIABLE(var_entry, MachineType::PointerRepresentation());
+ TVARIABLE(HeapObject, var_meta_storage);
+ TVARIABLE(IntPtrT, var_entry);
Label if_found_fast(this), if_found_dict(this), if_found_global(this);
@@ -7257,8 +7457,7 @@ void CodeStubAssembler::TryGetOwnProperty(
if (!var_details) {
var_details = &local_var_details;
}
- Variable* vars[] = {var_value, var_details};
- Label if_found(this, 2, vars);
+ Label if_found(this, {var_value, var_details});
TryLookupProperty(object, map, instance_type, unique_name, &if_found_fast,
&if_found_dict, &if_found_global, &var_meta_storage,
@@ -7308,9 +7507,7 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
Label* if_absent, Label* if_not_found,
Label* if_bailout) {
// Handle special objects in runtime.
- GotoIf(Int32LessThanOrEqual(instance_type,
- Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
- if_bailout);
+ GotoIf(IsSpecialReceiverInstanceType(instance_type), if_bailout);
Node* elements_kind = LoadMapElementsKind(map);
@@ -7712,10 +7909,10 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
return var_result.value();
}
-Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node,
- ElementsKind kind,
- ParameterMode mode,
- int base_size) {
+TNode<IntPtrT> CodeStubAssembler::ElementOffsetFromIndex(Node* index_node,
+ ElementsKind kind,
+ ParameterMode mode,
+ int base_size) {
int element_size_shift = ElementsKindToShiftSize(kind);
int element_size = 1 << element_size_shift;
int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize;
@@ -7735,13 +7932,13 @@ Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node,
return IntPtrConstant(base_size + element_size * index);
}
- Node* shifted_index =
+ TNode<WordT> shifted_index =
(element_size_shift == 0)
- ? index_node
+ ? UncheckedCast<WordT>(index_node)
: ((element_size_shift > 0)
? WordShl(index_node, IntPtrConstant(element_size_shift))
: WordSar(index_node, IntPtrConstant(-element_size_shift)));
- return IntPtrAdd(IntPtrConstant(base_size), shifted_index);
+ return IntPtrAdd(IntPtrConstant(base_size), Signed(shifted_index));
}
Node* CodeStubAssembler::LoadFeedbackVector(Node* closure) {
@@ -7820,19 +8017,22 @@ void CodeStubAssembler::CheckForAssociatedProtector(Node* name,
if_protector);
GotoIf(WordEqual(name, LoadRoot(Heap::kiterator_symbolRootIndex)),
if_protector);
+ GotoIf(WordEqual(name, LoadRoot(Heap::knext_stringRootIndex)), if_protector);
GotoIf(WordEqual(name, LoadRoot(Heap::kspecies_symbolRootIndex)),
if_protector);
GotoIf(WordEqual(name, LoadRoot(Heap::kis_concat_spreadable_symbolRootIndex)),
if_protector);
+ GotoIf(WordEqual(name, LoadRoot(Heap::kresolve_stringRootIndex)),
+ if_protector);
GotoIf(WordEqual(name, LoadRoot(Heap::kthen_stringRootIndex)), if_protector);
// Fall through if no case matched.
}
-Node* CodeStubAssembler::LoadReceiverMap(Node* receiver) {
- return Select(TaggedIsSmi(receiver),
- [=] { return LoadRoot(Heap::kHeapNumberMapRootIndex); },
- [=] { return LoadMap(receiver); },
- MachineRepresentation::kTagged);
+TNode<Map> CodeStubAssembler::LoadReceiverMap(SloppyTNode<Object> receiver) {
+ return Select<Map>(
+ TaggedIsSmi(receiver),
+ [=] { return CAST(LoadRoot(Heap::kHeapNumberMapRootIndex)); },
+ [=] { return LoadMap(UncheckedCast<HeapObject>(receiver)); });
}
TNode<IntPtrT> CodeStubAssembler::TryToIntptr(Node* key, Label* miss) {
@@ -7961,10 +8161,10 @@ TNode<Context> CodeStubAssembler::LoadScriptContext(
TNode<ScriptContextTable> script_context_table = CAST(
LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX));
- Node* script_context = LoadFixedArrayElement(
+ TNode<Context> script_context = CAST(LoadFixedArrayElement(
script_context_table, context_index,
- ScriptContextTable::kFirstContextSlotIndex * kPointerSize);
- return CAST(script_context);
+ ScriptContextTable::kFirstContextSlotIndex * kPointerSize));
+ return script_context;
}
namespace {
@@ -8178,12 +8378,23 @@ void CodeStubAssembler::EmitBigTypedArrayElementStore(
Node* offset = ElementOffsetFromIndex(intptr_key, BIGINT64_ELEMENTS,
INTPTR_PARAMETERS, 0);
MachineRepresentation rep = WordT::kMachineRepresentation;
+#if defined(V8_TARGET_BIG_ENDIAN)
+ if (!Is64()) {
+ StoreNoWriteBarrier(rep, backing_store, offset, var_high.value());
+ StoreNoWriteBarrier(rep, backing_store,
+ IntPtrAdd(offset, IntPtrConstant(kPointerSize)),
+ var_low.value());
+ } else {
+ StoreNoWriteBarrier(rep, backing_store, offset, var_low.value());
+ }
+#else
StoreNoWriteBarrier(rep, backing_store, offset, var_low.value());
if (!Is64()) {
StoreNoWriteBarrier(rep, backing_store,
IntPtrAdd(offset, IntPtrConstant(kPointerSize)),
var_high.value());
}
+#endif
}
void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
@@ -10022,7 +10233,7 @@ void CodeStubAssembler::BranchIfSameValue(Node* lhs, Node* rhs, Label* if_true,
}
TNode<Oddball> CodeStubAssembler::HasProperty(SloppyTNode<HeapObject> object,
- SloppyTNode<Name> key,
+ SloppyTNode<Object> key,
SloppyTNode<Context> context,
HasPropertyLookupMode mode) {
Label call_runtime(this, Label::kDeferred), return_true(this),
@@ -10053,7 +10264,7 @@ TNode<Oddball> CodeStubAssembler::HasProperty(SloppyTNode<HeapObject> object,
BIND(&if_proxy);
{
- TNode<Name> name = CAST(ToName(context, key));
+ TNode<Name> name = ToName(context, key);
switch (mode) {
case kHasProperty:
GotoIf(IsPrivateSymbol(name), &return_false);
@@ -10187,19 +10398,17 @@ Node* CodeStubAssembler::Typeof(Node* value) {
return result_var.value();
}
-Node* CodeStubAssembler::GetSuperConstructor(Node* active_function,
- Node* context) {
- CSA_ASSERT(this, IsJSFunction(active_function));
-
+TNode<Object> CodeStubAssembler::GetSuperConstructor(
+ SloppyTNode<Context> context, SloppyTNode<JSFunction> active_function) {
Label is_not_constructor(this, Label::kDeferred), out(this);
- VARIABLE(result, MachineRepresentation::kTagged);
+ TVARIABLE(Object, result);
- Node* map = LoadMap(active_function);
- Node* prototype = LoadMapPrototype(map);
- Node* prototype_map = LoadMap(prototype);
+ TNode<Map> map = LoadMap(active_function);
+ TNode<Object> prototype = LoadMapPrototype(map);
+ TNode<Map> prototype_map = LoadMap(CAST(prototype));
GotoIfNot(IsConstructorMap(prototype_map), &is_not_constructor);
- result.Bind(prototype);
+ result = prototype;
Goto(&out);
BIND(&is_not_constructor);
@@ -10213,14 +10422,14 @@ Node* CodeStubAssembler::GetSuperConstructor(Node* active_function,
return result.value();
}
-Node* CodeStubAssembler::SpeciesConstructor(Node* context, Node* object,
- Node* default_constructor) {
+TNode<Object> CodeStubAssembler::SpeciesConstructor(
+ SloppyTNode<Context> context, SloppyTNode<Object> object,
+ SloppyTNode<Object> default_constructor) {
Isolate* isolate = this->isolate();
- VARIABLE(var_result, MachineRepresentation::kTagged);
- var_result.Bind(default_constructor);
+ TVARIABLE(Object, var_result, default_constructor);
// 2. Let C be ? Get(O, "constructor").
- Node* const constructor =
+ TNode<Object> constructor =
GetProperty(context, object, isolate->factory()->constructor_string());
// 3. If C is undefined, return defaultConstructor.
@@ -10232,7 +10441,7 @@ Node* CodeStubAssembler::SpeciesConstructor(Node* context, Node* object,
MessageTemplate::kConstructorNotReceiver);
// 5. Let S be ? Get(C, @@species).
- Node* const species =
+ TNode<Object> species =
GetProperty(context, constructor, isolate->factory()->species_symbol());
// 6. If S is either undefined or null, return defaultConstructor.
@@ -10241,8 +10450,8 @@ Node* CodeStubAssembler::SpeciesConstructor(Node* context, Node* object,
// 7. If IsConstructor(S) is true, return S.
Label throw_error(this);
GotoIf(TaggedIsSmi(species), &throw_error);
- GotoIfNot(IsConstructorMap(LoadMap(species)), &throw_error);
- var_result.Bind(species);
+ GotoIfNot(IsConstructorMap(LoadMap(CAST(species))), &throw_error);
+ var_result = species;
Goto(&out);
// 8. Throw a TypeError exception.
@@ -10546,201 +10755,25 @@ Node* CodeStubAssembler::BitwiseOp(Node* left32, Node* right32,
UNREACHABLE();
}
-Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map,
- Node* array_type, Node* context,
- IterationKind mode) {
- int kBaseMapIndex = 0;
- switch (mode) {
- case IterationKind::kKeys:
- kBaseMapIndex = Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX;
- break;
- case IterationKind::kValues:
- kBaseMapIndex = Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX;
- break;
- case IterationKind::kEntries:
- kBaseMapIndex = Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX;
- break;
- }
-
- // Fast Array iterator map index:
- // (kBaseIndex + kFastIteratorOffset) + ElementsKind (for JSArrays)
- // kBaseIndex + (ElementsKind - UINT8_ELEMENTS) (for JSTypedArrays)
- const int kFastIteratorOffset =
- Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX -
- Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX;
- STATIC_ASSERT(kFastIteratorOffset ==
- (Context::FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX -
- Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX));
-
- // Slow Array iterator map index: (kBaseIndex + kSlowIteratorOffset)
- const int kSlowIteratorOffset =
- Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX -
- Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX;
- STATIC_ASSERT(kSlowIteratorOffset ==
- (Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX -
- Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX));
-
- // Assert: Type(array) is Object
- CSA_ASSERT(this, IsJSReceiverInstanceType(array_type));
-
- VARIABLE(var_result, MachineRepresentation::kTagged);
- VARIABLE(var_map_index, MachineType::PointerRepresentation());
- VARIABLE(var_array_map, MachineRepresentation::kTagged);
-
- Label return_result(this);
- Label allocate_iterator(this);
-
- if (mode == IterationKind::kKeys) {
- // There are only two key iterator maps, branch depending on whether or not
- // the receiver is a TypedArray or not.
-
- Label if_istypedarray(this), if_isgeneric(this);
-
- Branch(InstanceTypeEqual(array_type, JS_TYPED_ARRAY_TYPE), &if_istypedarray,
- &if_isgeneric);
-
- BIND(&if_isgeneric);
- {
- Label if_isfast(this), if_isslow(this);
- BranchIfFastJSArray(array, context, &if_isfast, &if_isslow);
-
- BIND(&if_isfast);
- {
- var_map_index.Bind(
- IntPtrConstant(Context::FAST_ARRAY_KEY_ITERATOR_MAP_INDEX));
- var_array_map.Bind(array_map);
- Goto(&allocate_iterator);
- }
-
- BIND(&if_isslow);
- {
- var_map_index.Bind(
- IntPtrConstant(Context::GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX));
- var_array_map.Bind(UndefinedConstant());
- Goto(&allocate_iterator);
- }
- }
-
- BIND(&if_istypedarray);
- {
- var_map_index.Bind(
- IntPtrConstant(Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX));
- var_array_map.Bind(UndefinedConstant());
- Goto(&allocate_iterator);
- }
- } else {
- Label if_istypedarray(this), if_isgeneric(this);
- Branch(InstanceTypeEqual(array_type, JS_TYPED_ARRAY_TYPE), &if_istypedarray,
- &if_isgeneric);
-
- BIND(&if_isgeneric);
- {
- Label if_isfast(this), if_isslow(this);
- BranchIfFastJSArray(array, context, &if_isfast, &if_isslow);
-
- BIND(&if_isfast);
- {
- Label if_ispacked(this), if_isholey(this);
- Node* elements_kind = LoadMapElementsKind(array_map);
- Branch(IsHoleyFastElementsKind(elements_kind), &if_isholey,
- &if_ispacked);
-
- BIND(&if_isholey);
- {
- // Fast holey JSArrays can treat the hole as undefined if the
- // protector cell is valid, and the prototype chain is unchanged from
- // its initial state (because the protector cell is only tracked for
- // initial the Array and Object prototypes). Check these conditions
- // here, and take the slow path if any fail.
- GotoIf(IsNoElementsProtectorCellInvalid(), &if_isslow);
-
- Node* native_context = LoadNativeContext(context);
-
- Node* prototype = LoadMapPrototype(array_map);
- Node* array_prototype = LoadContextElement(
- native_context, Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
- GotoIfNot(WordEqual(prototype, array_prototype), &if_isslow);
-
- Node* map = LoadMap(prototype);
- prototype = LoadMapPrototype(map);
- Node* object_prototype = LoadContextElement(
- native_context, Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
- GotoIfNot(WordEqual(prototype, object_prototype), &if_isslow);
-
- map = LoadMap(prototype);
- prototype = LoadMapPrototype(map);
- Branch(IsNull(prototype), &if_ispacked, &if_isslow);
- }
- BIND(&if_ispacked);
- {
- Node* map_index =
- IntPtrAdd(IntPtrConstant(kBaseMapIndex + kFastIteratorOffset),
- ChangeUint32ToWord(LoadMapElementsKind(array_map)));
- CSA_ASSERT(this, IntPtrGreaterThanOrEqual(
- map_index, IntPtrConstant(kBaseMapIndex +
- kFastIteratorOffset)));
- CSA_ASSERT(this, IntPtrLessThan(map_index,
- IntPtrConstant(kBaseMapIndex +
- kSlowIteratorOffset)));
-
- var_map_index.Bind(map_index);
- var_array_map.Bind(array_map);
- Goto(&allocate_iterator);
- }
- }
-
- BIND(&if_isslow);
- {
- Node* map_index = IntPtrAdd(IntPtrConstant(kBaseMapIndex),
- IntPtrConstant(kSlowIteratorOffset));
- var_map_index.Bind(map_index);
- var_array_map.Bind(UndefinedConstant());
- Goto(&allocate_iterator);
- }
- }
-
- BIND(&if_istypedarray);
- {
- Node* map_index =
- IntPtrAdd(IntPtrConstant(kBaseMapIndex - UINT8_ELEMENTS),
- ChangeUint32ToWord(LoadMapElementsKind(array_map)));
- CSA_ASSERT(
- this, IntPtrLessThan(map_index, IntPtrConstant(kBaseMapIndex +
- kFastIteratorOffset)));
- CSA_ASSERT(this, IntPtrGreaterThanOrEqual(map_index,
- IntPtrConstant(kBaseMapIndex)));
- var_map_index.Bind(map_index);
- var_array_map.Bind(UndefinedConstant());
- Goto(&allocate_iterator);
- }
- }
-
- BIND(&allocate_iterator);
- {
- Node* map = LoadFixedArrayElement(LoadNativeContext(context),
- var_map_index.value());
- var_result.Bind(AllocateJSArrayIterator(array, var_array_map.value(), map));
- Goto(&return_result);
- }
-
- BIND(&return_result);
- return var_result.value();
-}
-
-Node* CodeStubAssembler::AllocateJSArrayIterator(Node* array, Node* array_map,
- Node* map) {
+// ES #sec-createarrayiterator
+Node* CodeStubAssembler::CreateArrayIterator(Node* context, Node* object,
+ IterationKind kind) {
+ Node* native_context = LoadNativeContext(context);
+ Node* iterator_map = LoadContextElement(
+ native_context, Context::INITIAL_ARRAY_ITERATOR_MAP_INDEX);
Node* iterator = Allocate(JSArrayIterator::kSize);
- StoreMapNoWriteBarrier(iterator, map);
+ StoreMapNoWriteBarrier(iterator, iterator_map);
StoreObjectFieldRoot(iterator, JSArrayIterator::kPropertiesOrHashOffset,
Heap::kEmptyFixedArrayRootIndex);
StoreObjectFieldRoot(iterator, JSArrayIterator::kElementsOffset,
Heap::kEmptyFixedArrayRootIndex);
- StoreObjectFieldNoWriteBarrier(iterator,
- JSArrayIterator::kIteratedObjectOffset, array);
+ StoreObjectFieldNoWriteBarrier(
+ iterator, JSArrayIterator::kIteratedObjectOffset, object);
StoreObjectFieldNoWriteBarrier(iterator, JSArrayIterator::kNextIndexOffset,
SmiConstant(0));
StoreObjectFieldNoWriteBarrier(
- iterator, JSArrayIterator::kIteratedObjectMapOffset, array_map);
+ iterator, JSArrayIterator::kKindOffset,
+ SmiConstant(Smi::FromInt(static_cast<int>(kind))));
return iterator;
}
@@ -10796,6 +10829,15 @@ Node* CodeStubAssembler::AllocateJSIteratorResultForEntry(Node* context,
return result;
}
+Node* CodeStubAssembler::ArraySpeciesCreate(TNode<Context> context,
+ TNode<Object> o,
+ TNode<Number> len) {
+ Node* constructor =
+ CallRuntime(Runtime::kArraySpeciesConstructor, context, o);
+ return ConstructJS(CodeFactory::Construct(isolate()), context, constructor,
+ len);
+}
+
Node* CodeStubAssembler::IsDetachedBuffer(Node* buffer) {
CSA_ASSERT(this, HasInstanceType(buffer, JS_ARRAY_BUFFER_TYPE));
@@ -10852,7 +10894,7 @@ TNode<Object> CodeStubArguments::AtIndex(int index) const {
}
TNode<Object> CodeStubArguments::GetOptionalArgumentValue(
- int index, SloppyTNode<Object> default_value) {
+ int index, TNode<Object> default_value) {
CodeStubAssembler::TVariable<Object> result(assembler_);
CodeStubAssembler::Label argument_missing(assembler_),
argument_done(assembler_, &result);
@@ -10872,6 +10914,27 @@ TNode<Object> CodeStubArguments::GetOptionalArgumentValue(
return result.value();
}
+TNode<Object> CodeStubArguments::GetOptionalArgumentValue(
+ TNode<IntPtrT> index, TNode<Object> default_value) {
+ CodeStubAssembler::TVariable<Object> result(assembler_);
+ CodeStubAssembler::Label argument_missing(assembler_),
+ argument_done(assembler_, &result);
+
+ assembler_->GotoIf(
+ assembler_->UintPtrOrSmiGreaterThanOrEqual(
+ assembler_->IntPtrToParameter(index, argc_mode_), argc_, argc_mode_),
+ &argument_missing);
+ result = AtIndex(index);
+ assembler_->Goto(&argument_done);
+
+ assembler_->BIND(&argument_missing);
+ result = default_value;
+ assembler_->Goto(&argument_done);
+
+ assembler_->BIND(&argument_done);
+ return result.value();
+}
+
void CodeStubArguments::ForEach(
const CodeStubAssembler::VariableList& vars,
const CodeStubArguments::ForEachBodyFunction& body, Node* first, Node* last,
@@ -10923,6 +10986,11 @@ Node* CodeStubAssembler::IsFastSmiOrTaggedElementsKind(Node* elements_kind) {
Int32Constant(TERMINAL_FAST_ELEMENTS_KIND));
}
+Node* CodeStubAssembler::IsFastSmiElementsKind(Node* elements_kind) {
+ return Uint32LessThanOrEqual(elements_kind,
+ Int32Constant(HOLEY_SMI_ELEMENTS));
+}
+
Node* CodeStubAssembler::IsHoleyFastElementsKind(Node* elements_kind) {
CSA_ASSERT(this, IsFastElementsKind(elements_kind));
@@ -10953,13 +11021,105 @@ Node* CodeStubAssembler::IsPromiseHookEnabledOrDebugIsActive() {
return Word32NotEqual(promise_hook_or_debug_is_active, Int32Constant(0));
}
+TNode<Code> CodeStubAssembler::LoadBuiltin(TNode<Smi> builtin_id) {
+ CSA_ASSERT(this, SmiGreaterThanOrEqual(builtin_id, SmiConstant(0)));
+ CSA_ASSERT(this,
+ SmiLessThan(builtin_id, SmiConstant(Builtins::builtin_count)));
+
+ int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize;
+ int index_shift = kPointerSizeLog2 - kSmiShiftBits;
+ TNode<WordT> table_index =
+ index_shift >= 0 ? WordShl(BitcastTaggedToWord(builtin_id), index_shift)
+ : WordSar(BitcastTaggedToWord(builtin_id), -index_shift);
+
+ return CAST(
+ Load(MachineType::TaggedPointer(),
+ ExternalConstant(ExternalReference::builtins_address(isolate())),
+ table_index));
+}
+
+TNode<Code> CodeStubAssembler::GetSharedFunctionInfoCode(
+ SloppyTNode<SharedFunctionInfo> shared_info) {
+ TNode<Object> sfi_data =
+ LoadObjectField(shared_info, SharedFunctionInfo::kFunctionDataOffset);
+
+ TYPED_VARIABLE_DEF(Code, sfi_code, this);
+
+ Label done(this);
+ Label check_instance_type(this);
+
+ // IsSmi: Is builtin
+ GotoIf(TaggedIsNotSmi(sfi_data), &check_instance_type);
+ sfi_code = LoadBuiltin(CAST(sfi_data));
+ Goto(&done);
+
+ // Switch on data's instance type.
+ BIND(&check_instance_type);
+ TNode<Int32T> data_type = LoadInstanceType(CAST(sfi_data));
+
+ int32_t case_values[] = {BYTECODE_ARRAY_TYPE, CODE_TYPE, FIXED_ARRAY_TYPE,
+ TUPLE2_TYPE, FUNCTION_TEMPLATE_INFO_TYPE};
+ Label check_is_bytecode_array(this);
+ Label check_is_code(this);
+ Label check_is_fixed_array(this);
+ Label check_is_pre_parsed_scope_data(this);
+ Label check_is_function_template_info(this);
+ Label check_is_interpreter_data(this);
+ Label* case_labels[] = {
+ &check_is_bytecode_array, &check_is_code, &check_is_fixed_array,
+ &check_is_pre_parsed_scope_data, &check_is_function_template_info};
+ STATIC_ASSERT(arraysize(case_values) == arraysize(case_labels));
+ Switch(data_type, &check_is_interpreter_data, case_values, case_labels,
+ arraysize(case_labels));
+
+ // IsBytecodeArray: Interpret bytecode
+ BIND(&check_is_bytecode_array);
+ DCHECK(!Builtins::IsLazy(Builtins::kInterpreterEntryTrampoline));
+ sfi_code = HeapConstant(BUILTIN_CODE(isolate(), InterpreterEntryTrampoline));
+ Goto(&done);
+
+ // IsCode: Run code
+ BIND(&check_is_code);
+ sfi_code = CAST(sfi_data);
+ Goto(&done);
+
+ // IsFixedArray: Instantiate using AsmWasmData,
+ BIND(&check_is_fixed_array);
+ DCHECK(!Builtins::IsLazy(Builtins::kInstantiateAsmJs));
+ sfi_code = HeapConstant(BUILTIN_CODE(isolate(), InstantiateAsmJs));
+ Goto(&done);
+
+ // IsPreParsedScopeData: Compile lazy
+ BIND(&check_is_pre_parsed_scope_data);
+ DCHECK(!Builtins::IsLazy(Builtins::kCompileLazy));
+ sfi_code = HeapConstant(BUILTIN_CODE(isolate(), CompileLazy));
+ Goto(&done);
+
+ // IsFunctionTemplateInfo: API call
+ BIND(&check_is_function_template_info);
+ DCHECK(!Builtins::IsLazy(Builtins::kHandleApiCall));
+ sfi_code = HeapConstant(BUILTIN_CODE(isolate(), HandleApiCall));
+ Goto(&done);
+
+ // IsInterpreterData: Interpret bytecode
+ BIND(&check_is_interpreter_data);
+ // This is the default branch, so assert that we have the expected data type.
+ CSA_ASSERT(this,
+ Word32Equal(data_type, Int32Constant(INTERPRETER_DATA_TYPE)));
+ sfi_code = CAST(LoadObjectField(
+ CAST(sfi_data), InterpreterData::kInterpreterTrampolineOffset));
+ Goto(&done);
+
+ BIND(&done);
+ return sfi_code.value();
+}
+
Node* CodeStubAssembler::AllocateFunctionWithMapAndContext(Node* map,
Node* shared_info,
Node* context) {
CSA_SLOW_ASSERT(this, IsMap(map));
- Node* const code =
- LoadObjectField(shared_info, SharedFunctionInfo::kCodeOffset);
+ Node* const code = GetSharedFunctionInfoCode(shared_info);
// TODO(ishell): All the callers of this function pass map loaded from
// Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX. So we can remove
@@ -11073,6 +11233,20 @@ Node* CodeStubAssembler::CheckEnumCache(Node* receiver, Label* if_empty,
return receiver_map;
}
+TNode<IntPtrT> CodeStubAssembler::GetArgumentsLength(CodeStubArguments* args) {
+ return args->GetLength();
+}
+
+TNode<Object> CodeStubAssembler::GetArgumentValue(CodeStubArguments* args,
+ TNode<IntPtrT> index) {
+ return args->GetOptionalArgumentValue(index);
+}
+
+TNode<Object> CodeStubAssembler::GetArgumentValue(CodeStubArguments* args,
+ TNode<Smi> index) {
+ return args->GetOptionalArgumentValue(SmiUntag(index));
+}
+
void CodeStubAssembler::Print(const char* s) {
std::string formatted(s);
formatted += "\n";
@@ -11130,5 +11304,12 @@ void CodeStubAssembler::InitializeFunctionContext(Node* native_context,
native_context);
}
+void CodeStubAssembler::AssertIsStrongHeapObject(
+ SloppyTNode<HeapObject> object) {
+ CSA_SLOW_ASSERT(this, WordEqual(WordAnd(BitcastTaggedToWord(object),
+ IntPtrConstant(kHeapObjectTagMask)),
+ IntPtrConstant(kHeapObjectTag)));
+}
+
} // namespace internal
} // namespace v8