diff options
Diffstat (limited to 'deps/v8/src/code-stub-assembler.cc')
-rw-r--r-- | deps/v8/src/code-stub-assembler.cc | 1250 |
1 files changed, 605 insertions, 645 deletions
diff --git a/deps/v8/src/code-stub-assembler.cc b/deps/v8/src/code-stub-assembler.cc index e36a5cc796..f98e7fe519 100644 --- a/deps/v8/src/code-stub-assembler.cc +++ b/deps/v8/src/code-stub-assembler.cc @@ -175,7 +175,9 @@ Node* CodeStubAssembler::SelectSmiConstant(Node* condition, Smi* true_value, MachineRepresentation::kTaggedSigned); } -Node* CodeStubAssembler::NoContextConstant() { return SmiConstant(0); } +Node* CodeStubAssembler::NoContextConstant() { + return SmiConstant(Context::kNoContext); +} #define HEAP_CONSTANT_ACCESSOR(rootIndexName, rootAccessorName, name) \ compiler::TNode<std::remove_reference<decltype( \ @@ -546,8 +548,8 @@ TNode<Object> CodeStubAssembler::NumberMax(SloppyTNode<Object> a, // TODO(danno): This could be optimized by specifically handling smi cases. VARIABLE(result, MachineRepresentation::kTagged); Label done(this), greater_than_equal_a(this), greater_than_equal_b(this); - GotoIfNumericGreaterThanOrEqual(a, b, &greater_than_equal_a); - GotoIfNumericGreaterThanOrEqual(b, a, &greater_than_equal_b); + GotoIfNumberGreaterThanOrEqual(a, b, &greater_than_equal_a); + GotoIfNumberGreaterThanOrEqual(b, a, &greater_than_equal_b); result.Bind(NanConstant()); Goto(&done); BIND(&greater_than_equal_a); @@ -565,8 +567,8 @@ TNode<Object> CodeStubAssembler::NumberMin(SloppyTNode<Object> a, // TODO(danno): This could be optimized by specifically handling smi cases. VARIABLE(result, MachineRepresentation::kTagged); Label done(this), greater_than_equal_a(this), greater_than_equal_b(this); - GotoIfNumericGreaterThanOrEqual(a, b, &greater_than_equal_a); - GotoIfNumericGreaterThanOrEqual(b, a, &greater_than_equal_b); + GotoIfNumberGreaterThanOrEqual(a, b, &greater_than_equal_a); + GotoIfNumberGreaterThanOrEqual(b, a, &greater_than_equal_b); result.Bind(NanConstant()); Goto(&done); BIND(&greater_than_equal_a); @@ -642,8 +644,9 @@ Node* CodeStubAssembler::SmiMod(Node* a, Node* b) { return TNode<Object>::UncheckedCast(var_result.value()); } -Node* CodeStubAssembler::SmiMul(Node* a, Node* b) { - VARIABLE(var_result, MachineRepresentation::kTagged); +TNode<Number> CodeStubAssembler::SmiMul(SloppyTNode<Smi> a, + SloppyTNode<Smi> b) { + TVARIABLE(Number, var_result); VARIABLE(var_lhs_float64, MachineRepresentation::kFloat64); VARIABLE(var_rhs_float64, MachineRepresentation::kFloat64); Label return_result(this, &var_result); @@ -668,7 +671,7 @@ Node* CodeStubAssembler::SmiMul(Node* a, Node* b) { Branch(Word32Equal(answer, zero), &answer_zero, &answer_not_zero); BIND(&answer_not_zero); { - var_result.Bind(ChangeInt32ToTagged(answer)); + var_result = ChangeInt32ToTagged(answer); Goto(&return_result); } BIND(&answer_zero); @@ -679,12 +682,12 @@ Node* CodeStubAssembler::SmiMul(Node* a, Node* b) { &if_should_be_zero); BIND(&if_should_be_negative_zero); { - var_result.Bind(MinusZeroConstant()); + var_result = MinusZeroConstant(); Goto(&return_result); } BIND(&if_should_be_zero); { - var_result.Bind(SmiConstant(0)); + var_result = SmiConstant(0); Goto(&return_result); } } @@ -694,13 +697,12 @@ Node* CodeStubAssembler::SmiMul(Node* a, Node* b) { var_lhs_float64.Bind(SmiToFloat64(a)); var_rhs_float64.Bind(SmiToFloat64(b)); Node* value = Float64Mul(var_lhs_float64.value(), var_rhs_float64.value()); - Node* result = AllocateHeapNumberWithValue(value); - var_result.Bind(result); + var_result = AllocateHeapNumberWithValue(value); Goto(&return_result); } BIND(&return_result); - return var_result.value(); + return var_result; } Node* CodeStubAssembler::TrySmiDiv(Node* dividend, Node* divisor, @@ -898,7 +900,7 @@ void CodeStubAssembler::BranchIfFastJSArrayForCopy(Node* object, Node* context, } void CodeStubAssembler::GotoIfForceSlowPath(Label* if_true) { -#if defined(DEBUG) || defined(ENABLE_FASTSLOW_SWITCH) +#ifdef V8_ENABLE_FORCE_SLOW_PATH Node* const force_slow_path_addr = ExternalConstant(ExternalReference::force_slow_path(isolate())); Node* const force_slow = Load(MachineType::Uint8(), force_slow_path_addr); @@ -1534,14 +1536,15 @@ Node* CodeStubAssembler::LoadJSValueValue(Node* object) { return LoadObjectField(object, JSValue::kValueOffset); } -Node* CodeStubAssembler::LoadWeakCellValueUnchecked(Node* weak_cell) { +TNode<Object> CodeStubAssembler::LoadWeakCellValueUnchecked(Node* weak_cell) { // TODO(ishell): fix callers. return LoadObjectField(weak_cell, WeakCell::kValueOffset); } -Node* CodeStubAssembler::LoadWeakCellValue(Node* weak_cell, Label* if_cleared) { +TNode<Object> CodeStubAssembler::LoadWeakCellValue( + SloppyTNode<WeakCell> weak_cell, Label* if_cleared) { CSA_ASSERT(this, IsWeakCell(weak_cell)); - Node* value = LoadWeakCellValueUnchecked(weak_cell); + TNode<Object> value = LoadWeakCellValueUnchecked(weak_cell); if (if_cleared != nullptr) { GotoIf(WordEqual(value, IntPtrConstant(0)), if_cleared); } @@ -1624,17 +1627,16 @@ Node* CodeStubAssembler::LoadFixedTypedArrayElementAsTagged( } } -Node* CodeStubAssembler::LoadFeedbackVectorSlot(Node* object, - Node* slot_index_node, - int additional_offset, - ParameterMode parameter_mode) { +TNode<Object> CodeStubAssembler::LoadFeedbackVectorSlot( + Node* object, Node* slot_index_node, int additional_offset, + ParameterMode parameter_mode) { CSA_SLOW_ASSERT(this, IsFeedbackVector(object)); CSA_SLOW_ASSERT(this, MatchesParameterMode(slot_index_node, parameter_mode)); int32_t header_size = FeedbackVector::kFeedbackSlotsOffset + additional_offset - kHeapObjectTag; Node* offset = ElementOffsetFromIndex(slot_index_node, HOLEY_ELEMENTS, parameter_mode, header_size); - return Load(MachineType::AnyTagged(), object, offset); + return UncheckedCast<Object>(Load(MachineType::AnyTagged(), object, offset)); } Node* CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement( @@ -1788,8 +1790,8 @@ Node* CodeStubAssembler::LoadJSFunctionPrototype(Node* function, CSA_ASSERT(this, TaggedIsNotSmi(function)); CSA_ASSERT(this, IsJSFunction(function)); CSA_ASSERT(this, IsFunctionWithPrototypeSlotMap(LoadMap(function))); - CSA_ASSERT(this, IsClearWord32(LoadMapBitField(LoadMap(function)), - 1 << Map::kHasNonInstancePrototype)); + CSA_ASSERT(this, IsClearWord32<Map::HasNonInstancePrototypeBit>( + LoadMapBitField(LoadMap(function)))); Node* proto_or_map = LoadObjectField(function, JSFunction::kPrototypeOrInitialMapOffset); GotoIf(IsTheHole(proto_or_map), if_bailout); @@ -1943,10 +1945,10 @@ Node* CodeStubAssembler::EnsureArrayPushable(Node* receiver, Label* bailout) { Comment("Disallow pushing onto prototypes"); Node* map = LoadMap(receiver); Node* bit_field2 = LoadMapBitField2(map); - int mask = static_cast<int>(Map::IsPrototypeMapBits::kMask) | - (1 << Map::kIsExtensible); + int mask = Map::IsPrototypeMapBit::kMask | Map::IsExtensibleBit::kMask; Node* test = Word32And(bit_field2, Int32Constant(mask)); - GotoIf(Word32NotEqual(test, Int32Constant(1 << Map::kIsExtensible)), bailout); + 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. @@ -1994,7 +1996,10 @@ TNode<Smi> CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, // Resize the capacity of the fixed array if it doesn't fit. TNode<IntPtrT> first = *arg_index; - Node* growth = WordToParameter(IntPtrSub(args->GetLength(), first), mode); + Node* growth = WordToParameter( + IntPtrSub(UncheckedCast<IntPtrT>(args->GetLength(INTPTR_PARAMETERS)), + first), + mode); PossiblyGrowElementsCapacity(mode, kind, array, var_length.value(), &var_elements, growth, &pre_bailout); @@ -2548,8 +2553,8 @@ void CodeStubAssembler::InitializeJSObjectFromMap( void CodeStubAssembler::InitializeJSObjectBodyNoSlackTracking( Node* object, Node* map, Node* instance_size, int start_offset) { STATIC_ASSERT(Map::kNoSlackTracking == 0); - CSA_ASSERT(this, - IsClearWord32<Map::ConstructionCounter>(LoadMapBitField3(map))); + CSA_ASSERT( + this, IsClearWord32<Map::ConstructionCounterBits>(LoadMapBitField3(map))); InitializeFieldsWithRoot(object, IntPtrConstant(start_offset), instance_size, Heap::kUndefinedValueRootIndex); } @@ -2564,7 +2569,8 @@ void CodeStubAssembler::InitializeJSObjectBodyWithSlackTracking( Node* bit_field3 = LoadMapBitField3(map); Label end(this), slack_tracking(this), complete(this, Label::kDeferred); STATIC_ASSERT(Map::kNoSlackTracking == 0); - GotoIf(IsSetWord32<Map::ConstructionCounter>(bit_field3), &slack_tracking); + GotoIf(IsSetWord32<Map::ConstructionCounterBits>(bit_field3), + &slack_tracking); Comment("No slack tracking"); InitializeJSObjectBodyNoSlackTracking(object, map, instance_size); Goto(&end); @@ -2574,9 +2580,9 @@ void CodeStubAssembler::InitializeJSObjectBodyWithSlackTracking( Comment("Decrease construction counter"); // Slack tracking is only done on initial maps. CSA_ASSERT(this, IsUndefined(LoadMapBackPointer(map))); - STATIC_ASSERT(Map::ConstructionCounter::kNext == 32); + STATIC_ASSERT(Map::ConstructionCounterBits::kNext == 32); Node* new_bit_field3 = Int32Sub( - bit_field3, Int32Constant(1 << Map::ConstructionCounter::kShift)); + bit_field3, Int32Constant(1 << Map::ConstructionCounterBits::kShift)); StoreObjectFieldNoWriteBarrier(map, Map::kBitField3Offset, new_bit_field3, MachineRepresentation::kWord32); STATIC_ASSERT(Map::kSlackTrackingCounterEnd == 1); @@ -2595,7 +2601,9 @@ void CodeStubAssembler::InitializeJSObjectBodyWithSlackTracking( InitializeFieldsWithRoot(object, IntPtrConstant(start_offset), used_size, Heap::kUndefinedValueRootIndex); - GotoIf(IsClearWord32<Map::ConstructionCounter>(new_bit_field3), &complete); + STATIC_ASSERT(Map::kNoSlackTracking == 0); + GotoIf(IsClearWord32<Map::ConstructionCounterBits>(new_bit_field3), + &complete); Goto(&end); } @@ -3346,7 +3354,8 @@ Node* CodeStubAssembler::CalculateNewElementsCapacity(Node* old_capacity, CSA_SLOW_ASSERT(this, MatchesParameterMode(old_capacity, mode)); Node* half_old_capacity = WordOrSmiShr(old_capacity, 1, mode); Node* new_capacity = IntPtrOrSmiAdd(half_old_capacity, old_capacity, mode); - Node* padding = IntPtrOrSmiConstant(16, mode); + Node* padding = + IntPtrOrSmiConstant(JSObject::kMinAddedElementsCapacity, mode); return IntPtrOrSmiAdd(new_capacity, padding, mode); } @@ -3505,8 +3514,8 @@ Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) { Node* CodeStubAssembler::TruncateTaggedToWord32(Node* context, Node* value) { VARIABLE(var_result, MachineRepresentation::kWord32); Label done(this); - TaggedToWord32OrBigIntImpl<Feedback::kNone, Object::Conversion::kToNumber>( - context, value, &done, &var_result); + TaggedToWord32OrBigIntImpl<Object::Conversion::kToNumber>(context, value, + &done, &var_result); BIND(&done); return var_result.value(); } @@ -3518,7 +3527,7 @@ void CodeStubAssembler::TaggedToWord32OrBigInt(Node* context, Node* value, Variable* var_word32, Label* if_bigint, Variable* var_bigint) { - TaggedToWord32OrBigIntImpl<Feedback::kNone, Object::Conversion::kToNumeric>( + TaggedToWord32OrBigIntImpl<Object::Conversion::kToNumeric>( context, value, if_number, var_word32, if_bigint, var_bigint); } @@ -3528,13 +3537,12 @@ void CodeStubAssembler::TaggedToWord32OrBigInt(Node* context, Node* value, void CodeStubAssembler::TaggedToWord32OrBigIntWithFeedback( Node* context, Node* value, Label* if_number, Variable* var_word32, Label* if_bigint, Variable* var_bigint, Variable* var_feedback) { - TaggedToWord32OrBigIntImpl<Feedback::kCollect, - Object::Conversion::kToNumeric>( + TaggedToWord32OrBigIntImpl<Object::Conversion::kToNumeric>( context, value, if_number, var_word32, if_bigint, var_bigint, var_feedback); } -template <CodeStubAssembler::Feedback feedback, Object::Conversion conversion> +template <Object::Conversion conversion> void CodeStubAssembler::TaggedToWord32OrBigIntImpl( Node* context, Node* value, Label* if_number, Variable* var_word32, Label* if_bigint, Variable* var_bigint, Variable* var_feedback) { @@ -3546,14 +3554,10 @@ void CodeStubAssembler::TaggedToWord32OrBigIntImpl( // We might need to loop after conversion. VARIABLE(var_value, MachineRepresentation::kTagged, value); - if (feedback == Feedback::kCollect) { - var_feedback->Bind(SmiConstant(BinaryOperationFeedback::kNone)); - } else { - DCHECK(var_feedback == nullptr); - } + OverwriteFeedback(var_feedback, BinaryOperationFeedback::kNone); Variable* loop_vars[] = {&var_value, var_feedback}; - int num_vars = feedback == Feedback::kCollect ? arraysize(loop_vars) - : arraysize(loop_vars) - 1; + int num_vars = + var_feedback != nullptr ? arraysize(loop_vars) : arraysize(loop_vars) - 1; Label loop(this, num_vars, loop_vars); Goto(&loop); BIND(&loop); @@ -3565,11 +3569,7 @@ void CodeStubAssembler::TaggedToWord32OrBigIntImpl( // {value} is a Smi. var_word32->Bind(SmiToWord32(value)); - if (feedback == Feedback::kCollect) { - var_feedback->Bind( - SmiOr(var_feedback->value(), - SmiConstant(BinaryOperationFeedback::kSignedSmall))); - } + CombineFeedback(var_feedback, BinaryOperationFeedback::kSignedSmall); Goto(if_number); BIND(¬_smi); @@ -3582,7 +3582,7 @@ void CodeStubAssembler::TaggedToWord32OrBigIntImpl( // Not HeapNumber (or BigInt if conversion == kToNumeric). { - if (feedback == Feedback::kCollect) { + if (var_feedback != nullptr) { // We do not require an Or with earlier feedback here because once we // convert the value to a Numeric, we cannot reach this path. We can // only reach this path on the first pass when the feedback is kNone. @@ -3595,36 +3595,25 @@ void CodeStubAssembler::TaggedToWord32OrBigIntImpl( ? Builtins::kNonNumberToNumeric : Builtins::kNonNumberToNumber; var_value.Bind(CallBuiltin(builtin, context, value)); - if (feedback == Feedback::kCollect) { - var_feedback->Bind(SmiConstant(BinaryOperationFeedback::kAny)); - } + OverwriteFeedback(var_feedback, BinaryOperationFeedback::kAny); Goto(&loop); BIND(&is_oddball); var_value.Bind(LoadObjectField(value, Oddball::kToNumberOffset)); - if (feedback == Feedback::kCollect) { - var_feedback->Bind( - SmiConstant(BinaryOperationFeedback::kNumberOrOddball)); - } + OverwriteFeedback(var_feedback, + BinaryOperationFeedback::kNumberOrOddball); Goto(&loop); } BIND(&is_heap_number); var_word32->Bind(TruncateHeapNumberValueToWord32(value)); - if (feedback == Feedback::kCollect) { - var_feedback->Bind(SmiOr(var_feedback->value(), - SmiConstant(BinaryOperationFeedback::kNumber))); - } + CombineFeedback(var_feedback, BinaryOperationFeedback::kNumber); Goto(if_number); if (conversion == Object::Conversion::kToNumeric) { BIND(&is_bigint); var_bigint->Bind(value); - if (feedback == Feedback::kCollect) { - var_feedback->Bind( - SmiOr(var_feedback->value(), - SmiConstant(BinaryOperationFeedback::kBigInt))); - } + CombineFeedback(var_feedback, BinaryOperationFeedback::kBigInt); Goto(if_bigint); } } @@ -3822,9 +3811,7 @@ TNode<Float64T> CodeStubAssembler::ChangeNumberToFloat64( } TNode<UintPtrT> CodeStubAssembler::ChangeNonnegativeNumberToUintPtr( - SloppyTNode<Number> value) { - // TODO(tebbi): Remove assert once argument is TNode instead of SloppyTNode. - CSA_SLOW_ASSERT(this, IsNumber(value)); + TNode<Number> value) { TVARIABLE(UintPtrT, result); Label smi(this), done(this, &result); GotoIf(TaggedIsSmi(value), &smi); @@ -4032,43 +4019,30 @@ Node* CodeStubAssembler::InstanceTypeEqual(Node* instance_type, int type) { return Word32Equal(instance_type, Int32Constant(type)); } -Node* CodeStubAssembler::IsSpecialReceiverMap(Node* map) { - CSA_SLOW_ASSERT(this, IsMap(map)); - Node* is_special = IsSpecialReceiverInstanceType(LoadMapInstanceType(map)); - uint32_t mask = - 1 << Map::kHasNamedInterceptor | 1 << Map::kIsAccessCheckNeeded; - USE(mask); - // Interceptors or access checks imply special receiver. - CSA_ASSERT(this, - SelectConstant(IsSetWord32(LoadMapBitField(map), mask), is_special, - Int32Constant(1), MachineRepresentation::kWord32)); - return is_special; -} - TNode<BoolT> CodeStubAssembler::IsDictionaryMap(SloppyTNode<Map> map) { CSA_SLOW_ASSERT(this, IsMap(map)); Node* bit_field3 = LoadMapBitField3(map); - return IsSetWord32<Map::DictionaryMap>(bit_field3); + return IsSetWord32<Map::IsDictionaryMapBit>(bit_field3); } Node* CodeStubAssembler::IsExtensibleMap(Node* map) { CSA_ASSERT(this, IsMap(map)); - return IsSetWord32(LoadMapBitField2(map), 1 << Map::kIsExtensible); + return IsSetWord32<Map::IsExtensibleBit>(LoadMapBitField2(map)); } Node* CodeStubAssembler::IsCallableMap(Node* map) { CSA_ASSERT(this, IsMap(map)); - return IsSetWord32(LoadMapBitField(map), 1 << Map::kIsCallable); + return IsSetWord32<Map::IsCallableBit>(LoadMapBitField(map)); } Node* CodeStubAssembler::IsDeprecatedMap(Node* map) { CSA_ASSERT(this, IsMap(map)); - return IsSetWord32<Map::Deprecated>(LoadMapBitField3(map)); + return IsSetWord32<Map::IsDeprecatedBit>(LoadMapBitField3(map)); } Node* CodeStubAssembler::IsUndetectableMap(Node* map) { CSA_ASSERT(this, IsMap(map)); - return IsSetWord32(LoadMapBitField(map), 1 << Map::kIsUndetectable); + return IsSetWord32<Map::IsUndetectableBit>(LoadMapBitField(map)); } Node* CodeStubAssembler::IsNoElementsProtectorCellInvalid() { @@ -4104,7 +4078,7 @@ Node* CodeStubAssembler::IsCell(Node* object) { Node* CodeStubAssembler::IsConstructorMap(Node* map) { CSA_ASSERT(this, IsMap(map)); - return IsSetWord32(LoadMapBitField(map), 1 << Map::kIsConstructor); + return IsSetWord32<Map::IsConstructorBit>(LoadMapBitField(map)); } Node* CodeStubAssembler::IsConstructor(Node* object) { @@ -4113,7 +4087,7 @@ Node* CodeStubAssembler::IsConstructor(Node* object) { Node* CodeStubAssembler::IsFunctionWithPrototypeSlotMap(Node* map) { CSA_ASSERT(this, IsMap(map)); - return IsSetWord32(LoadMapBitField(map), 1 << Map::kHasPrototypeSlot); + return IsSetWord32<Map::HasPrototypeSlotBit>(LoadMapBitField(map)); } Node* CodeStubAssembler::IsSpecialReceiverInstanceType(Node* instance_type) { @@ -4500,13 +4474,12 @@ Node* CodeStubAssembler::IsNumberArrayIndex(Node* number) { Label check_upper_bound(this), check_is_integer(this), out(this), return_false(this); - GotoIfNumericGreaterThanOrEqual(number, NumberConstant(0), - &check_upper_bound); + GotoIfNumberGreaterThanOrEqual(number, NumberConstant(0), &check_upper_bound); Goto(&return_false); BIND(&check_upper_bound); - GotoIfNumericGreaterThanOrEqual(number, NumberConstant(kMaxUInt32), - &return_false); + GotoIfNumberGreaterThanOrEqual(number, NumberConstant(kMaxUInt32), + &return_false); Goto(&check_is_integer); BIND(&check_is_integer); @@ -4525,14 +4498,14 @@ Node* CodeStubAssembler::IsNumberArrayIndex(Node* number) { return var_result.value(); } -TNode<Uint32T> CodeStubAssembler::StringCharCodeAt(SloppyTNode<String> string, - SloppyTNode<IntPtrT> index) { +TNode<Int32T> CodeStubAssembler::StringCharCodeAt(SloppyTNode<String> string, + SloppyTNode<IntPtrT> index) { CSA_ASSERT(this, IsString(string)); CSA_ASSERT(this, IntPtrGreaterThanOrEqual(index, IntPtrConstant(0))); CSA_ASSERT(this, IntPtrLessThan(index, LoadStringLengthAsWord(string))); - VARIABLE(var_result, MachineRepresentation::kWord32); + TVARIABLE(Int32T, var_result); Label return_result(this), if_runtime(this, Label::kDeferred), if_stringistwobyte(this), if_stringisonebyte(this); @@ -4550,14 +4523,16 @@ TNode<Uint32T> CodeStubAssembler::StringCharCodeAt(SloppyTNode<String> string, BIND(&if_stringisonebyte); { - var_result.Bind(Load(MachineType::Uint8(), string_data, offset)); + var_result = + UncheckedCast<Int32T>(Load(MachineType::Uint8(), string_data, offset)); Goto(&return_result); } BIND(&if_stringistwobyte); { - var_result.Bind(Load(MachineType::Uint16(), string_data, - WordShl(offset, IntPtrConstant(1)))); + var_result = + UncheckedCast<Int32T>(Load(MachineType::Uint16(), string_data, + WordShl(offset, IntPtrConstant(1)))); Goto(&return_result); } @@ -4565,15 +4540,15 @@ TNode<Uint32T> CodeStubAssembler::StringCharCodeAt(SloppyTNode<String> string, { Node* result = CallRuntime(Runtime::kStringCharCodeAt, NoContextConstant(), string, SmiTag(index)); - var_result.Bind(SmiToWord32(result)); + var_result = SmiToWord32(result); Goto(&return_result); } BIND(&return_result); - return UncheckedCast<Uint32T>(var_result.value()); + return var_result; } -Node* CodeStubAssembler::StringFromCharCode(Node* code) { +TNode<String> CodeStubAssembler::StringFromCharCode(TNode<Int32T> code) { VARIABLE(var_result, MachineRepresentation::kTagged); // Check if the {code} is a one-byte char code. @@ -4627,7 +4602,7 @@ Node* CodeStubAssembler::StringFromCharCode(Node* code) { BIND(&if_done); CSA_ASSERT(this, IsString(var_result.value())); - return var_result.value(); + return CAST(var_result.value()); } // A wrapper around CopyStringCharacters which determines the correct string @@ -4787,7 +4762,7 @@ Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from, // Substrings of length 1 are generated through CharCodeAt and FromCharCode. BIND(&single_char); { - Node* char_code = StringCharCodeAt(string, SmiUntag(from)); + TNode<Int32T> char_code = StringCharCodeAt(string, SmiUntag(from)); var_result.Bind(StringFromCharCode(char_code)); Goto(&end); } @@ -5161,8 +5136,8 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, return result.value(); } -Node* CodeStubAssembler::StringFromCodePoint(Node* codepoint, - UnicodeEncoding encoding) { +TNode<String> CodeStubAssembler::StringFromCodePoint(TNode<Int32T> codepoint, + UnicodeEncoding encoding) { VARIABLE(var_result, MachineRepresentation::kTagged, EmptyStringConstant()); Label if_isword16(this), if_isword32(this), return_result(this); @@ -5194,7 +5169,7 @@ Node* CodeStubAssembler::StringFromCodePoint(Node* codepoint, Int32Constant(0xDC00)); // codpoint = (trail << 16) | lead; - codepoint = Word32Or(Word32Shl(trail, Int32Constant(16)), lead); + codepoint = Signed(Word32Or(Word32Shl(trail, Int32Constant(16)), lead)); break; } } @@ -5209,12 +5184,10 @@ Node* CodeStubAssembler::StringFromCodePoint(Node* codepoint, } BIND(&return_result); - CSA_ASSERT(this, IsString(var_result.value())); - return var_result.value(); + return CAST(var_result.value()); } -TNode<Number> CodeStubAssembler::StringToNumber(SloppyTNode<Context> context, - SloppyTNode<String> input) { +TNode<Number> CodeStubAssembler::StringToNumber(SloppyTNode<String> input) { CSA_SLOW_ASSERT(this, IsString(input)); Label runtime(this, Label::kDeferred); Label end(this); @@ -5226,12 +5199,14 @@ TNode<Number> CodeStubAssembler::StringToNumber(SloppyTNode<Context> context, GotoIf(IsSetWord32(hash, Name::kDoesNotContainCachedArrayIndexMask), &runtime); - var_result = SmiTag(DecodeWordFromWord32<String::ArrayIndexValueBits>(hash)); + var_result = + SmiTag(Signed(DecodeWordFromWord32<String::ArrayIndexValueBits>(hash))); Goto(&end); BIND(&runtime); { - var_result = CAST(CallRuntime(Runtime::kStringToNumber, context, input)); + var_result = + CAST(CallRuntime(Runtime::kStringToNumber, NoContextConstant(), input)); Goto(&end); } @@ -5239,7 +5214,7 @@ TNode<Number> CodeStubAssembler::StringToNumber(SloppyTNode<Context> context, return var_result; } -Node* CodeStubAssembler::NumberToString(Node* context, Node* argument) { +Node* CodeStubAssembler::NumberToString(Node* argument) { VARIABLE(result, MachineRepresentation::kTagged); Label runtime(this, Label::kDeferred), smi(this), done(this, &result); @@ -5290,7 +5265,8 @@ Node* CodeStubAssembler::NumberToString(Node* context, Node* argument) { BIND(&runtime); { // No cache entry, go to the runtime. - result.Bind(CallRuntime(Runtime::kNumberToString, context, argument)); + result.Bind(CallRuntime(Runtime::kNumberToStringSkipCache, + NoContextConstant(), argument)); } Goto(&done); @@ -5393,7 +5369,7 @@ Node* CodeStubAssembler::NonNumberToNumberOrNumeric( BIND(&if_inputisstring); { // The {input} is a String, use the fast stub to convert it to a Number. - var_result.Bind(StringToNumber(context, input)); + var_result.Bind(StringToNumber(input)); Goto(&end); } @@ -5525,18 +5501,17 @@ TNode<Number> CodeStubAssembler::ToNumber(SloppyTNode<Context> context, void CodeStubAssembler::TaggedToNumeric(Node* context, Node* value, Label* done, Variable* var_numeric) { - TaggedToNumeric<Feedback::kNone>(context, value, done, var_numeric); + TaggedToNumeric(context, value, done, var_numeric, nullptr); } void CodeStubAssembler::TaggedToNumericWithFeedback(Node* context, Node* value, Label* done, Variable* var_numeric, Variable* var_feedback) { - TaggedToNumeric<Feedback::kCollect>(context, value, done, var_numeric, - var_feedback); + DCHECK_NOT_NULL(var_feedback); + TaggedToNumeric(context, value, done, var_numeric, var_feedback); } -template <CodeStubAssembler::Feedback feedback> void CodeStubAssembler::TaggedToNumeric(Node* context, Node* value, Label* done, Variable* var_numeric, Variable* var_feedback) { @@ -5551,34 +5526,24 @@ void CodeStubAssembler::TaggedToNumeric(Node* context, Node* value, Label* done, // {value} is not a Numeric yet. GotoIf(Word32Equal(instance_type, Int32Constant(ODDBALL_TYPE)), &if_oddball); var_numeric->Bind(CallBuiltin(Builtins::kNonNumberToNumeric, context, value)); - if (feedback == Feedback::kCollect) { - var_feedback->Bind(SmiConstant(BinaryOperationFeedback::kAny)); - } + OverwriteFeedback(var_feedback, BinaryOperationFeedback::kAny); Goto(done); BIND(&if_smi); - if (feedback == Feedback::kCollect) { - var_feedback->Bind(SmiConstant(BinaryOperationFeedback::kSignedSmall)); - } + OverwriteFeedback(var_feedback, BinaryOperationFeedback::kSignedSmall); Goto(done); BIND(&if_heapnumber); - if (feedback == Feedback::kCollect) { - var_feedback->Bind(SmiConstant(BinaryOperationFeedback::kNumber)); - } + OverwriteFeedback(var_feedback, BinaryOperationFeedback::kNumber); Goto(done); BIND(&if_bigint); - if (feedback == Feedback::kCollect) { - var_feedback->Bind(SmiConstant(BinaryOperationFeedback::kBigInt)); - } + OverwriteFeedback(var_feedback, BinaryOperationFeedback::kBigInt); Goto(done); BIND(&if_oddball); + OverwriteFeedback(var_feedback, BinaryOperationFeedback::kNumberOrOddball); var_numeric->Bind(LoadObjectField(value, Oddball::kToNumberOffset)); - if (feedback == Feedback::kCollect) { - var_feedback->Bind(SmiConstant(BinaryOperationFeedback::kNumberOrOddball)); - } Goto(done); } @@ -5702,7 +5667,7 @@ TNode<String> CodeStubAssembler::ToString(SloppyTNode<Context> context, Branch(IsHeapNumberMap(input_map), &is_number, ¬_heap_number); BIND(&is_number); - result.Bind(NumberToString(context, input)); + result.Bind(NumberToString(input)); Goto(&done); BIND(¬_heap_number); @@ -5774,8 +5739,8 @@ Node* CodeStubAssembler::ToSmiIndex(Node* const input, Node* const context, Branch(IsUndefined(result.value()), &return_zero, &defined); BIND(&defined); - result.Bind(ToInteger(context, result.value(), - CodeStubAssembler::kTruncateMinusZero)); + result.Bind(ToInteger_Inline(CAST(context), CAST(result.value()), + CodeStubAssembler::kTruncateMinusZero)); GotoIfNot(TaggedIsSmi(result.value()), range_error); CSA_ASSERT(this, TaggedIsSmi(result.value())); Goto(&negative_check); @@ -5799,8 +5764,8 @@ Node* CodeStubAssembler::ToSmiLength(Node* input, Node* const context, Branch(TaggedIsSmi(result.value()), &negative_check, &to_integer); BIND(&to_integer); - result.Bind(ToInteger(context, result.value(), - CodeStubAssembler::kTruncateMinusZero)); + result.Bind(ToInteger_Inline(CAST(context), CAST(result.value()), + CodeStubAssembler::kTruncateMinusZero)); GotoIf(TaggedIsSmi(result.value()), &negative_check); // result.value() can still be a negative HeapNumber here. Branch(IsTrue(CallBuiltin(Builtins::kLessThan, context, result.value(), @@ -5828,6 +5793,16 @@ Node* CodeStubAssembler::ToLength_Inline(Node* const context, MachineRepresentation::kTagged); } +TNode<Number> CodeStubAssembler::ToInteger_Inline( + TNode<Context> context, TNode<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)); +} + TNode<Number> CodeStubAssembler::ToInteger(SloppyTNode<Context> context, SloppyTNode<Object> input, ToIntegerTruncationMode mode) { @@ -5886,6 +5861,7 @@ TNode<Number> CodeStubAssembler::ToInteger(SloppyTNode<Context> context, } BIND(&out); + if (mode == kTruncateMinusZero) CSA_ASSERT(this, IsNumberNormalized(var_arg)); return CAST(var_arg); } @@ -5895,8 +5871,10 @@ TNode<Uint32T> CodeStubAssembler::DecodeWord32(SloppyTNode<Word32T> word32, Word32And(word32, Int32Constant(mask)), static_cast<int>(shift))); } -Node* CodeStubAssembler::DecodeWord(Node* word, uint32_t shift, uint32_t mask) { - return WordShr(WordAnd(word, IntPtrConstant(mask)), static_cast<int>(shift)); +TNode<UintPtrT> CodeStubAssembler::DecodeWord(SloppyTNode<WordT> word, + uint32_t shift, uint32_t mask) { + return Unsigned( + WordShr(WordAnd(word, IntPtrConstant(mask)), static_cast<int>(shift))); } Node* CodeStubAssembler::UpdateWord(Node* word, Node* value, uint32_t shift, @@ -6187,14 +6165,14 @@ Node* CodeStubAssembler::ComputeIntegerHash(Node* key, Node* seed) { // See v8::internal::ComputeIntegerHash() Node* hash = TruncateWordToWord32(key); hash = Word32Xor(hash, seed); - hash = Int32Add(Word32Xor(hash, Int32Constant(0xffffffff)), + hash = Int32Add(Word32Xor(hash, Int32Constant(0xFFFFFFFF)), Word32Shl(hash, Int32Constant(15))); hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12))); hash = Int32Add(hash, Word32Shl(hash, Int32Constant(2))); hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(4))); hash = Int32Mul(hash, Int32Constant(2057)); hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16))); - return Word32And(hash, Int32Constant(0x3fffffff)); + return Word32And(hash, Int32Constant(0x3FFFFFFF)); } void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, @@ -6391,36 +6369,38 @@ Node* CodeStubAssembler::DescriptorArrayNumberOfEntries(Node* descriptors) { descriptors, IntPtrConstant(DescriptorArray::kDescriptorLengthIndex)); } -namespace { - -Node* DescriptorNumberToIndex(CodeStubAssembler* a, Node* descriptor_number) { - Node* descriptor_size = a->Int32Constant(DescriptorArray::kEntrySize); - Node* index = a->Int32Mul(descriptor_number, descriptor_size); - return a->ChangeInt32ToIntPtr(index); +Node* CodeStubAssembler::DescriptorNumberToIndex( + SloppyTNode<Uint32T> descriptor_number) { + Node* descriptor_size = Int32Constant(DescriptorArray::kEntrySize); + Node* index = Int32Mul(descriptor_number, descriptor_size); + return ChangeInt32ToIntPtr(index); } -} // namespace - Node* CodeStubAssembler::DescriptorArrayToKeyIndex(Node* descriptor_number) { return IntPtrAdd(IntPtrConstant(DescriptorArray::ToKeyIndex(0)), - DescriptorNumberToIndex(this, descriptor_number)); + DescriptorNumberToIndex(descriptor_number)); } Node* CodeStubAssembler::DescriptorArrayGetSortedKeyIndex( Node* descriptors, Node* descriptor_number) { - const int details_offset = DescriptorArray::ToDetailsIndex(0) * kPointerSize; - Node* details = LoadAndUntagToWord32FixedArrayElement( - descriptors, DescriptorNumberToIndex(this, descriptor_number), - details_offset); + Node* details = DescriptorArrayGetDetails( + TNode<DescriptorArray>::UncheckedCast(descriptors), + TNode<Uint32T>::UncheckedCast(descriptor_number)); return DecodeWord32<PropertyDetails::DescriptorPointer>(details); } Node* CodeStubAssembler::DescriptorArrayGetKey(Node* descriptors, Node* descriptor_number) { const int key_offset = DescriptorArray::ToKeyIndex(0) * kPointerSize; - return LoadFixedArrayElement(descriptors, - DescriptorNumberToIndex(this, descriptor_number), - key_offset); + return LoadFixedArrayElement( + descriptors, DescriptorNumberToIndex(descriptor_number), key_offset); +} + +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, @@ -6531,13 +6511,13 @@ void CodeStubAssembler::TryLookupProperty( &if_objectisspecial); uint32_t mask = - 1 << Map::kHasNamedInterceptor | 1 << Map::kIsAccessCheckNeeded; + Map::HasNamedInterceptorBit::kMask | Map::IsAccessCheckNeededBit::kMask; CSA_ASSERT(this, Word32BinaryNot(IsSetWord32(LoadMapBitField(map), mask))); USE(mask); Node* bit_field3 = LoadMapBitField3(map); Label if_isfastmap(this), if_isslowmap(this); - Branch(IsSetWord32<Map::DictionaryMap>(bit_field3), &if_isslowmap, + Branch(IsSetWord32<Map::IsDictionaryMapBit>(bit_field3), &if_isslowmap, &if_isfastmap); BIND(&if_isfastmap); { @@ -6563,7 +6543,8 @@ void CodeStubAssembler::TryLookupProperty( // Handle interceptors and access checks in runtime. Node* bit_field = LoadMapBitField(map); - int mask = 1 << Map::kHasNamedInterceptor | 1 << Map::kIsAccessCheckNeeded; + int mask = + Map::HasNamedInterceptorBit::kMask | Map::IsAccessCheckNeededBit::kMask; GotoIf(IsSetWord32(bit_field, mask), if_bailout); Node* dictionary = LoadSlowProperties(object); @@ -6618,12 +6599,22 @@ void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map, Variable* var_value) { DCHECK_EQ(MachineRepresentation::kWord32, var_details->rep()); DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep()); - Comment("[ LoadPropertyFromFastObject"); Node* details = LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index); var_details->Bind(details); + LoadPropertyFromFastObject(object, map, descriptors, name_index, details, + var_value); +} + +void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map, + Node* descriptors, + Node* name_index, + Node* details, + Variable* var_value) { + Comment("[ LoadPropertyFromFastObject"); + Node* location = DecodeWord32<PropertyDetails::LocationField>(details); Label if_in_field(this), if_in_descriptor(this), done(this); @@ -6826,13 +6817,12 @@ Node* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details, // if (!(has_prototype_slot() && !has_non_instance_prototype())) use // generic property loading mechanism. - int has_prototype_slot_mask = 1 << Map::kHasPrototypeSlot; - int has_non_instance_prototype_mask = 1 << Map::kHasNonInstancePrototype; GotoIfNot( - Word32Equal(Word32And(LoadMapBitField(receiver_map), - Int32Constant(has_prototype_slot_mask | - has_non_instance_prototype_mask)), - Int32Constant(has_prototype_slot_mask)), + Word32Equal( + Word32And(LoadMapBitField(receiver_map), + Int32Constant(Map::HasPrototypeSlotBit::kMask | + Map::HasNonInstancePrototypeBit::kMask)), + Int32Constant(Map::HasPrototypeSlotBit::kMask)), if_bailout); var_value.Bind(LoadJSFunctionPrototype(receiver, if_bailout)); Goto(&done); @@ -7061,6 +7051,35 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map, } } +void CodeStubAssembler::BranchIfMaybeSpecialIndex(TNode<String> name_string, + Label* if_maybe_special_index, + Label* if_not_special_index) { + // TODO(cwhan.tunz): Implement fast cases more. + + // If a name is empty or too long, it's not a special index + // Max length of canonical double: -X.XXXXXXXXXXXXXXXXX-eXXX + const int kBufferSize = 24; + TNode<Smi> string_length = LoadStringLengthAsSmi(name_string); + GotoIf(SmiEqual(string_length, SmiConstant(0)), if_not_special_index); + GotoIf(SmiGreaterThan(string_length, SmiConstant(kBufferSize)), + if_not_special_index); + + // If the first character of name is not a digit or '-', or we can't match it + // to Infinity or NaN, then this is not a special index. + TNode<Int32T> first_char = StringCharCodeAt(name_string, IntPtrConstant(0)); + // If the name starts with '-', it can be a negative index. + GotoIf(Word32Equal(first_char, Int32Constant('-')), if_maybe_special_index); + // If the name starts with 'I', it can be "Infinity". + GotoIf(Word32Equal(first_char, Int32Constant('I')), if_maybe_special_index); + // If the name starts with 'N', it can be "NaN". + GotoIf(Word32Equal(first_char, Int32Constant('N')), if_maybe_special_index); + // Finally, if the first character is not a digit either, then we are sure + // that the name is not a special index. + GotoIf(Uint32LessThan(first_char, Int32Constant('0')), if_not_special_index); + GotoIf(Uint32LessThan(Int32Constant('9'), first_char), if_not_special_index); + Goto(if_maybe_special_index); +} + void CodeStubAssembler::TryPrototypeChainLookup( Node* receiver, Node* key, const LookupInHolder& lookup_property_in_holder, const LookupInHolder& lookup_element_in_holder, Label* if_end, @@ -7108,15 +7127,22 @@ void CodeStubAssembler::TryPrototypeChainLookup( Node* holder_map = var_holder_map.value(); Node* holder_instance_type = var_holder_instance_type.value(); - Label next_proto(this); + Label next_proto(this), check_integer_indexed_exotic(this); lookup_property_in_holder(receiver, var_holder.value(), holder_map, holder_instance_type, var_unique.value(), - &next_proto, if_bailout); - BIND(&next_proto); + &check_integer_indexed_exotic, if_bailout); - // Bailout if it can be an integer indexed exotic case. - GotoIf(InstanceTypeEqual(holder_instance_type, JS_TYPED_ARRAY_TYPE), - if_bailout); + BIND(&check_integer_indexed_exotic); + { + // Bailout if it can be an integer indexed exotic case. + GotoIfNot(InstanceTypeEqual(holder_instance_type, JS_TYPED_ARRAY_TYPE), + &next_proto); + GotoIfNot(IsString(var_unique.value()), &next_proto); + BranchIfMaybeSpecialIndex(CAST(var_unique.value()), if_bailout, + &next_proto); + } + + BIND(&next_proto); Node* proto = LoadMapPrototype(holder_map); @@ -7192,8 +7218,8 @@ Node* CodeStubAssembler::HasInPrototypeChain(Node* context, Node* object, GotoIf(InstanceTypeEqual(object_instance_type, JS_PROXY_TYPE), &return_runtime); Node* object_bitfield = LoadMapBitField(object_map); - int mask = - 1 << Map::kHasNamedInterceptor | 1 << Map::kIsAccessCheckNeeded; + int mask = Map::HasNamedInterceptorBit::kMask | + Map::IsAccessCheckNeededBit::kMask; Branch(IsSetWord32(object_bitfield, mask), &return_runtime, &if_objectisdirect); } @@ -7252,12 +7278,12 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, // Goto runtime if {callable} is not a constructor or has // a non-instance "prototype". Node* callable_bitfield = LoadMapBitField(callable_map); - GotoIfNot( - Word32Equal(Word32And(callable_bitfield, - Int32Constant((1 << Map::kHasNonInstancePrototype) | - (1 << Map::kIsConstructor))), - Int32Constant(1 << Map::kIsConstructor)), - &return_runtime); + GotoIfNot(Word32Equal( + Word32And(callable_bitfield, + Int32Constant(Map::HasNonInstancePrototypeBit::kMask | + Map::IsConstructorBit::kMask)), + Int32Constant(Map::IsConstructorBit::kMask)), + &return_runtime); // Get the "prototype" (or initial map) of the {callable}. Node* callable_prototype = @@ -7326,7 +7352,7 @@ Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node, ? index_node : ((element_size_shift > 0) ? WordShl(index_node, IntPtrConstant(element_size_shift)) - : WordShr(index_node, IntPtrConstant(-element_size_shift))); + : WordSar(index_node, IntPtrConstant(-element_size_shift))); return IntPtrAdd(IntPtrConstant(base_size), shifted_index); } @@ -7377,8 +7403,22 @@ void CodeStubAssembler::ReportFeedbackUpdate( #endif // V8_TRACE_FEEDBACK_UPDATES } +void CodeStubAssembler::OverwriteFeedback(Variable* existing_feedback, + int new_feedback) { + if (existing_feedback == nullptr) return; + existing_feedback->Bind(SmiConstant(new_feedback)); +} + +void CodeStubAssembler::CombineFeedback(Variable* existing_feedback, + int feedback) { + if (existing_feedback == nullptr) return; + existing_feedback->Bind( + SmiOr(existing_feedback->value(), SmiConstant(feedback))); +} + void CodeStubAssembler::CombineFeedback(Variable* existing_feedback, Node* feedback) { + if (existing_feedback == nullptr) return; existing_feedback->Bind(SmiOr(existing_feedback->value(), feedback)); } @@ -7524,15 +7564,16 @@ Node* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key, return var_result.value(); } -Node* CodeStubAssembler::LoadScriptContext(Node* context, int context_index) { - Node* native_context = LoadNativeContext(context); - Node* script_context_table = - LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX); +TNode<Context> CodeStubAssembler::LoadScriptContext( + TNode<Context> context, TNode<IntPtrT> context_index) { + TNode<Context> native_context = LoadNativeContext(context); + TNode<ScriptContextTable> script_context_table = CAST( + LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX)); - int offset = - ScriptContextTable::GetContextOffset(context_index) - kHeapObjectTag; - return Load(MachineType::AnyTagged(), script_context_table, - IntPtrConstant(offset)); + Node* script_context = LoadFixedArrayElement( + script_context_table, context_index, + ScriptContextTable::kFirstContextSlotIndex * kPointerSize); + return CAST(script_context); } namespace { @@ -7567,7 +7608,7 @@ void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind, if (IsFixedTypedArrayElementsKind(kind)) { if (kind == UINT8_CLAMPED_ELEMENTS) { CSA_ASSERT(this, - Word32Equal(value, Word32And(Int32Constant(0xff), value))); + Word32Equal(value, Word32And(Int32Constant(0xFF), value))); } Node* offset = ElementOffsetFromIndex(index, kind, mode, 0); MachineRepresentation rep = ElementsKindToMachineRepresentation(kind); @@ -8029,8 +8070,8 @@ Node* CodeStubAssembler::BuildFastLoop( ? MachineType::PointerRepresentation() : MachineRepresentation::kTaggedSigned; VARIABLE(var, index_rep, start_index); - VariableList vars_copy(vars, zone()); - vars_copy.Add(&var, zone()); + VariableList vars_copy(vars.begin(), vars.end(), zone()); + vars_copy.push_back(&var); Label loop(this, vars_copy); Label after_loop(this); // Introduce an explicit second check of the termination condition before the @@ -8135,109 +8176,86 @@ void CodeStubAssembler::InitializeFieldsWithRoot( CodeStubAssembler::IndexAdvanceMode::kPre); } -void CodeStubAssembler::BranchIfNumericRelationalComparison( - Operation op, Node* lhs, Node* rhs, Label* if_true, Label* if_false) { - CSA_SLOW_ASSERT(this, IsNumber(lhs)); - CSA_SLOW_ASSERT(this, IsNumber(rhs)); +void CodeStubAssembler::BranchIfNumberRelationalComparison( + Operation op, Node* left, Node* right, Label* if_true, Label* if_false) { + CSA_SLOW_ASSERT(this, IsNumber(left)); + CSA_SLOW_ASSERT(this, IsNumber(right)); - Label end(this); - VARIABLE(result, MachineRepresentation::kTagged); - - // Shared entry for floating point comparison. - Label do_fcmp(this); - VARIABLE(var_fcmp_lhs, MachineRepresentation::kFloat64); - VARIABLE(var_fcmp_rhs, MachineRepresentation::kFloat64); + Label do_float_comparison(this); + TVARIABLE(Float64T, var_left_float); + TVARIABLE(Float64T, var_right_float); - // Check if the {lhs} is a Smi or a HeapObject. - Label if_lhsissmi(this), if_lhsisnotsmi(this); - Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); + Label if_left_smi(this), if_left_not_smi(this); + Branch(TaggedIsSmi(left), &if_left_smi, &if_left_not_smi); - BIND(&if_lhsissmi); + BIND(&if_left_smi); { - // Check if {rhs} is a Smi or a HeapObject. - Label if_rhsissmi(this), if_rhsisnotsmi(this); - Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); + Label if_right_not_smi(this); + GotoIfNot(TaggedIsSmi(right), &if_right_not_smi); - BIND(&if_rhsissmi); - { - // Both {lhs} and {rhs} are Smi, so just perform a fast Smi comparison. - switch (op) { - case Operation::kLessThan: - BranchIfSmiLessThan(lhs, rhs, if_true, if_false); - break; - case Operation::kLessThanOrEqual: - BranchIfSmiLessThanOrEqual(lhs, rhs, if_true, if_false); - break; - case Operation::kGreaterThan: - BranchIfSmiLessThan(rhs, lhs, if_true, if_false); - break; - case Operation::kGreaterThanOrEqual: - BranchIfSmiLessThanOrEqual(rhs, lhs, if_true, if_false); - break; - default: - UNREACHABLE(); - } + // Both {left} and {right} are Smi, so just perform a fast Smi comparison. + switch (op) { + case Operation::kLessThan: + BranchIfSmiLessThan(left, right, if_true, if_false); + break; + case Operation::kLessThanOrEqual: + BranchIfSmiLessThanOrEqual(left, right, if_true, if_false); + break; + case Operation::kGreaterThan: + BranchIfSmiLessThan(right, left, if_true, if_false); + break; + case Operation::kGreaterThanOrEqual: + BranchIfSmiLessThanOrEqual(right, left, if_true, if_false); + break; + default: + UNREACHABLE(); } - BIND(&if_rhsisnotsmi); + BIND(&if_right_not_smi); { - CSA_ASSERT(this, IsHeapNumber(rhs)); - // Convert the {lhs} and {rhs} to floating point values, and - // perform a floating point comparison. - var_fcmp_lhs.Bind(SmiToFloat64(lhs)); - var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs)); - Goto(&do_fcmp); + CSA_ASSERT(this, IsHeapNumber(right)); + var_left_float = SmiToFloat64(left); + var_right_float = LoadHeapNumberValue(right); + Goto(&do_float_comparison); } } - BIND(&if_lhsisnotsmi); + BIND(&if_left_not_smi); { - CSA_ASSERT(this, IsHeapNumber(lhs)); + CSA_ASSERT(this, IsHeapNumber(left)); + var_left_float = LoadHeapNumberValue(left); - // Check if {rhs} is a Smi or a HeapObject. - Label if_rhsissmi(this), if_rhsisnotsmi(this); - Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); + Label if_right_not_smi(this); + GotoIfNot(TaggedIsSmi(right), &if_right_not_smi); + var_right_float = SmiToFloat64(right); + Goto(&do_float_comparison); - BIND(&if_rhsissmi); + BIND(&if_right_not_smi); { - // Convert the {lhs} and {rhs} to floating point values, and - // perform a floating point comparison. - var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs)); - var_fcmp_rhs.Bind(SmiToFloat64(rhs)); - Goto(&do_fcmp); - } - - BIND(&if_rhsisnotsmi); - { - CSA_ASSERT(this, IsHeapNumber(rhs)); - - // Convert the {lhs} and {rhs} to floating point values, and - // perform a floating point comparison. - var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs)); - var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs)); - Goto(&do_fcmp); + CSA_ASSERT(this, IsHeapNumber(right)); + var_right_float = LoadHeapNumberValue(right); + Goto(&do_float_comparison); } } - BIND(&do_fcmp); + BIND(&do_float_comparison); { - // Load the {lhs} and {rhs} floating point values. - Node* lhs = var_fcmp_lhs.value(); - Node* rhs = var_fcmp_rhs.value(); - - // Perform a fast floating point comparison. switch (op) { case Operation::kLessThan: - Branch(Float64LessThan(lhs, rhs), if_true, if_false); + Branch(Float64LessThan(var_left_float, var_right_float), if_true, + if_false); break; case Operation::kLessThanOrEqual: - Branch(Float64LessThanOrEqual(lhs, rhs), if_true, if_false); + Branch(Float64LessThanOrEqual(var_left_float, var_right_float), if_true, + if_false); break; case Operation::kGreaterThan: - Branch(Float64GreaterThan(lhs, rhs), if_true, if_false); + Branch(Float64GreaterThan(var_left_float, var_right_float), if_true, + if_false); break; case Operation::kGreaterThanOrEqual: - Branch(Float64GreaterThanOrEqual(lhs, rhs), if_true, if_false); + Branch(Float64GreaterThanOrEqual(var_left_float, var_right_float), + if_true, if_false); break; default: UNREACHABLE(); @@ -8245,11 +8263,11 @@ void CodeStubAssembler::BranchIfNumericRelationalComparison( } } -void CodeStubAssembler::GotoIfNumericGreaterThanOrEqual(Node* lhs, Node* rhs, - Label* if_true) { +void CodeStubAssembler::GotoIfNumberGreaterThanOrEqual(Node* left, Node* right, + Label* if_true) { Label if_false(this); - BranchIfNumericRelationalComparison(Operation::kGreaterThanOrEqual, lhs, rhs, - if_true, &if_false); + BranchIfNumberRelationalComparison(Operation::kGreaterThanOrEqual, left, + right, if_true, &if_false); BIND(&if_false); } @@ -8271,423 +8289,354 @@ Operation Reverse(Operation op) { } } // anonymous namespace -Node* CodeStubAssembler::RelationalComparison(Operation op, Node* lhs, - Node* rhs, Node* context, +Node* CodeStubAssembler::RelationalComparison(Operation op, Node* left, + Node* right, Node* context, Variable* var_type_feedback) { - Label return_true(this), return_false(this), end(this); - VARIABLE(result, MachineRepresentation::kTagged); - - // Shared entry for floating point comparison. - Label do_fcmp(this); - VARIABLE(var_fcmp_lhs, MachineRepresentation::kFloat64); - VARIABLE(var_fcmp_rhs, MachineRepresentation::kFloat64); + Label return_true(this), return_false(this), do_float_comparison(this), + end(this); + TVARIABLE(Oddball, var_result); // Actually only "true" or "false". + TVARIABLE(Float64T, var_left_float); + TVARIABLE(Float64T, var_right_float); // We might need to loop several times due to ToPrimitive and/or ToNumeric // conversions. - VARIABLE(var_lhs, MachineRepresentation::kTagged, lhs); - VARIABLE(var_rhs, MachineRepresentation::kTagged, rhs); - VariableList loop_variable_list({&var_lhs, &var_rhs}, zone()); + VARIABLE(var_left, MachineRepresentation::kTagged, left); + VARIABLE(var_right, MachineRepresentation::kTagged, right); + VariableList loop_variable_list({&var_left, &var_right}, zone()); if (var_type_feedback != nullptr) { // Initialize the type feedback to None. The current feedback is combined // with the previous feedback. var_type_feedback->Bind(SmiConstant(CompareOperationFeedback::kNone)); - loop_variable_list.Add(var_type_feedback, zone()); + loop_variable_list.push_back(var_type_feedback); } Label loop(this, loop_variable_list); Goto(&loop); BIND(&loop); { - // Load the current {lhs} and {rhs} values. - lhs = var_lhs.value(); - rhs = var_rhs.value(); + left = var_left.value(); + right = var_right.value(); - // Check if the {lhs} is a Smi or a HeapObject. - Label if_lhsissmi(this), if_lhsisnotsmi(this); - Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); + Label if_left_smi(this), if_left_not_smi(this); + Branch(TaggedIsSmi(left), &if_left_smi, &if_left_not_smi); - BIND(&if_lhsissmi); + BIND(&if_left_smi); { - Label if_rhsissmi(this), if_rhsisheapnumber(this), - if_rhsisbigint(this, Label::kDeferred), - if_rhsisnotnumeric(this, Label::kDeferred); - GotoIf(TaggedIsSmi(rhs), &if_rhsissmi); - Node* rhs_map = LoadMap(rhs); - GotoIf(IsHeapNumberMap(rhs_map), &if_rhsisheapnumber); - Node* rhs_instance_type = LoadMapInstanceType(rhs_map); - Branch(IsBigIntInstanceType(rhs_instance_type), &if_rhsisbigint, - &if_rhsisnotnumeric); + Label if_right_smi(this), if_right_heapnumber(this), + if_right_bigint(this, Label::kDeferred), + if_right_not_numeric(this, Label::kDeferred); + GotoIf(TaggedIsSmi(right), &if_right_smi); + Node* right_map = LoadMap(right); + GotoIf(IsHeapNumberMap(right_map), &if_right_heapnumber); + Node* right_instance_type = LoadMapInstanceType(right_map); + Branch(IsBigIntInstanceType(right_instance_type), &if_right_bigint, + &if_right_not_numeric); - BIND(&if_rhsissmi); + BIND(&if_right_smi); { - // Both {lhs} and {rhs} are Smi, so just perform a fast Smi comparison. - if (var_type_feedback != nullptr) { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kSignedSmall)); - } + CombineFeedback(var_type_feedback, + CompareOperationFeedback::kSignedSmall); switch (op) { case Operation::kLessThan: - BranchIfSmiLessThan(lhs, rhs, &return_true, &return_false); + BranchIfSmiLessThan(left, right, &return_true, &return_false); break; case Operation::kLessThanOrEqual: - BranchIfSmiLessThanOrEqual(lhs, rhs, &return_true, &return_false); + BranchIfSmiLessThanOrEqual(left, right, &return_true, + &return_false); break; case Operation::kGreaterThan: - BranchIfSmiLessThan(rhs, lhs, &return_true, &return_false); + BranchIfSmiLessThan(right, left, &return_true, &return_false); break; case Operation::kGreaterThanOrEqual: - BranchIfSmiLessThanOrEqual(rhs, lhs, &return_true, &return_false); + BranchIfSmiLessThanOrEqual(right, left, &return_true, + &return_false); break; default: UNREACHABLE(); } } - BIND(&if_rhsisheapnumber); + BIND(&if_right_heapnumber); { - // Convert the {lhs} and {rhs} to floating point values, and - // perform a floating point comparison. - if (var_type_feedback != nullptr) { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kNumber)); - } - var_fcmp_lhs.Bind(SmiToFloat64(lhs)); - var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs)); - Goto(&do_fcmp); + CombineFeedback(var_type_feedback, CompareOperationFeedback::kNumber); + var_left_float = SmiToFloat64(left); + var_right_float = LoadHeapNumberValue(right); + Goto(&do_float_comparison); } - BIND(&if_rhsisbigint); + BIND(&if_right_bigint); { - // The {lhs} is a Smi and {rhs} is a BigInt. - if (var_type_feedback != nullptr) { - var_type_feedback->Bind(SmiConstant(CompareOperationFeedback::kAny)); - } - result.Bind(CallRuntime(Runtime::kBigIntCompareToNumber, - NoContextConstant(), SmiConstant(Reverse(op)), - rhs, lhs)); + OverwriteFeedback(var_type_feedback, CompareOperationFeedback::kAny); + var_result = CAST(CallRuntime(Runtime::kBigIntCompareToNumber, + NoContextConstant(), + SmiConstant(Reverse(op)), right, left)); Goto(&end); } - BIND(&if_rhsisnotnumeric); + BIND(&if_right_not_numeric); { - // The {lhs} is a Smi and {rhs} is not a Numeric. - if (var_type_feedback != nullptr) { - var_type_feedback->Bind(SmiConstant(CompareOperationFeedback::kAny)); - } - // Convert the {rhs} to a Numeric; we don't need to perform the - // dedicated ToPrimitive(rhs, hint Number) operation, as the - // ToNumeric(rhs) will by itself already invoke ToPrimitive with + OverwriteFeedback(var_type_feedback, CompareOperationFeedback::kAny); + // Convert {right} to a Numeric; we don't need to perform the + // dedicated ToPrimitive(right, hint Number) operation, as the + // ToNumeric(right) will by itself already invoke ToPrimitive with // a Number hint. - var_rhs.Bind(CallBuiltin(Builtins::kNonNumberToNumeric, context, rhs)); + var_right.Bind( + CallBuiltin(Builtins::kNonNumberToNumeric, context, right)); Goto(&loop); } } - BIND(&if_lhsisnotsmi); + BIND(&if_left_not_smi); { - Node* lhs_map = LoadMap(lhs); + Node* left_map = LoadMap(left); - // Check if {rhs} is a Smi or a HeapObject. - Label if_rhsissmi(this), if_rhsisnotsmi(this); - Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi); + Label if_right_smi(this), if_right_not_smi(this); + Branch(TaggedIsSmi(right), &if_right_smi, &if_right_not_smi); - BIND(&if_rhsissmi); + BIND(&if_right_smi); { - Label if_lhsisheapnumber(this), if_lhsisbigint(this, Label::kDeferred), - if_lhsisnotnumeric(this, Label::kDeferred); - GotoIf(IsHeapNumberMap(lhs_map), &if_lhsisheapnumber); - Node* lhs_instance_type = LoadMapInstanceType(lhs_map); - Branch(IsBigIntInstanceType(lhs_instance_type), &if_lhsisbigint, - &if_lhsisnotnumeric); - - BIND(&if_lhsisheapnumber); + Label if_left_heapnumber(this), if_left_bigint(this, Label::kDeferred), + if_left_not_numeric(this, Label::kDeferred); + GotoIf(IsHeapNumberMap(left_map), &if_left_heapnumber); + Node* left_instance_type = LoadMapInstanceType(left_map); + Branch(IsBigIntInstanceType(left_instance_type), &if_left_bigint, + &if_left_not_numeric); + + BIND(&if_left_heapnumber); { - // Convert the {lhs} and {rhs} to floating point values, and - // perform a floating point comparison. - if (var_type_feedback != nullptr) { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kNumber)); - } - var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs)); - var_fcmp_rhs.Bind(SmiToFloat64(rhs)); - Goto(&do_fcmp); + CombineFeedback(var_type_feedback, CompareOperationFeedback::kNumber); + var_left_float = LoadHeapNumberValue(left); + var_right_float = SmiToFloat64(right); + Goto(&do_float_comparison); } - BIND(&if_lhsisbigint); + BIND(&if_left_bigint); { - if (var_type_feedback != nullptr) { - var_type_feedback->Bind( - SmiConstant(CompareOperationFeedback::kAny)); - } - result.Bind(CallRuntime(Runtime::kBigIntCompareToNumber, - NoContextConstant(), SmiConstant(op), lhs, - rhs)); + OverwriteFeedback(var_type_feedback, CompareOperationFeedback::kAny); + var_result = CAST(CallRuntime(Runtime::kBigIntCompareToNumber, + NoContextConstant(), SmiConstant(op), + left, right)); Goto(&end); } - BIND(&if_lhsisnotnumeric); + BIND(&if_left_not_numeric); { - // The {lhs} is not a Numeric and {rhs} is an Smi. - if (var_type_feedback != nullptr) { - var_type_feedback->Bind( - SmiConstant(CompareOperationFeedback::kAny)); - } - // Convert the {lhs} to a Numeric; we don't need to perform the - // dedicated ToPrimitive(lhs, hint Number) operation, as the - // ToNumeric(lhs) will by itself already invoke ToPrimitive with + OverwriteFeedback(var_type_feedback, CompareOperationFeedback::kAny); + // Convert {left} to a Numeric; we don't need to perform the + // dedicated ToPrimitive(left, hint Number) operation, as the + // ToNumeric(left) will by itself already invoke ToPrimitive with // a Number hint. - var_lhs.Bind( - CallBuiltin(Builtins::kNonNumberToNumeric, context, lhs)); + var_left.Bind( + CallBuiltin(Builtins::kNonNumberToNumeric, context, left)); Goto(&loop); } } - BIND(&if_rhsisnotsmi); + BIND(&if_right_not_smi); { - // Load the map of {rhs}. - Node* rhs_map = LoadMap(rhs); + Node* right_map = LoadMap(right); - // Further analyze {lhs}. - Label if_lhsisheapnumber(this), if_lhsisbigint(this, Label::kDeferred), - if_lhsisstring(this), if_lhsisother(this, Label::kDeferred); - GotoIf(IsHeapNumberMap(lhs_map), &if_lhsisheapnumber); - Node* lhs_instance_type = LoadMapInstanceType(lhs_map); - GotoIf(IsBigIntInstanceType(lhs_instance_type), &if_lhsisbigint); - Branch(IsStringInstanceType(lhs_instance_type), &if_lhsisstring, - &if_lhsisother); + Label if_left_heapnumber(this), if_left_bigint(this, Label::kDeferred), + if_left_string(this), if_left_other(this, Label::kDeferred); + GotoIf(IsHeapNumberMap(left_map), &if_left_heapnumber); + Node* left_instance_type = LoadMapInstanceType(left_map); + GotoIf(IsBigIntInstanceType(left_instance_type), &if_left_bigint); + Branch(IsStringInstanceType(left_instance_type), &if_left_string, + &if_left_other); - BIND(&if_lhsisheapnumber); + BIND(&if_left_heapnumber); { - // Further inspect {rhs}. - Label if_rhsisheapnumber(this), - if_rhsisbigint(this, Label::kDeferred), - if_rhsisnotnumeric(this, Label::kDeferred); - GotoIf(WordEqual(rhs_map, lhs_map), &if_rhsisheapnumber); - Node* rhs_instance_type = LoadMapInstanceType(rhs_map); - Branch(IsBigIntInstanceType(rhs_instance_type), &if_rhsisbigint, - &if_rhsisnotnumeric); - - BIND(&if_rhsisheapnumber); + Label if_right_heapnumber(this), + if_right_bigint(this, Label::kDeferred), + if_right_not_numeric(this, Label::kDeferred); + GotoIf(WordEqual(right_map, left_map), &if_right_heapnumber); + Node* right_instance_type = LoadMapInstanceType(right_map); + Branch(IsBigIntInstanceType(right_instance_type), &if_right_bigint, + &if_right_not_numeric); + + BIND(&if_right_heapnumber); { - // Convert the {lhs} and {rhs} to floating point values, and - // perform a floating point comparison. - if (var_type_feedback != nullptr) { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kNumber)); - } - var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs)); - var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs)); - Goto(&do_fcmp); + CombineFeedback(var_type_feedback, + CompareOperationFeedback::kNumber); + var_left_float = LoadHeapNumberValue(left); + var_right_float = LoadHeapNumberValue(right); + Goto(&do_float_comparison); } - BIND(&if_rhsisbigint); + BIND(&if_right_bigint); { - if (var_type_feedback != nullptr) { - var_type_feedback->Bind( - SmiConstant(CompareOperationFeedback::kAny)); - } - result.Bind(CallRuntime(Runtime::kBigIntCompareToNumber, - NoContextConstant(), - SmiConstant(Reverse(op)), rhs, lhs)); + OverwriteFeedback(var_type_feedback, + CompareOperationFeedback::kAny); + var_result = CAST(CallRuntime( + Runtime::kBigIntCompareToNumber, NoContextConstant(), + SmiConstant(Reverse(op)), right, left)); Goto(&end); } - BIND(&if_rhsisnotnumeric); + BIND(&if_right_not_numeric); { - // The {lhs} is a HeapNumber and {rhs} is not a Numeric. - if (var_type_feedback != nullptr) { - var_type_feedback->Bind( - SmiConstant(CompareOperationFeedback::kAny)); - } - // Convert the {rhs} to a Numeric; we don't need to perform - // dedicated ToPrimitive(rhs, hint Number) operation, as the - // ToNumeric(rhs) will by itself already invoke ToPrimitive with + OverwriteFeedback(var_type_feedback, + CompareOperationFeedback::kAny); + // Convert {right} to a Numeric; we don't need to perform + // dedicated ToPrimitive(right, hint Number) operation, as the + // ToNumeric(right) will by itself already invoke ToPrimitive with // a Number hint. - var_rhs.Bind( - CallBuiltin(Builtins::kNonNumberToNumeric, context, rhs)); + var_right.Bind( + CallBuiltin(Builtins::kNonNumberToNumeric, context, right)); Goto(&loop); } } - BIND(&if_lhsisbigint); + BIND(&if_left_bigint); { - if (var_type_feedback != nullptr) { - var_type_feedback->Bind( - SmiConstant(CompareOperationFeedback::kAny)); - } - - Label if_rhsisheapnumber(this), if_rhsisbigint(this), - if_rhsisnotnumeric(this); - GotoIf(IsHeapNumberMap(rhs_map), &if_rhsisheapnumber); - Node* rhs_instance_type = LoadMapInstanceType(rhs_map); - Branch(IsBigIntInstanceType(rhs_instance_type), &if_rhsisbigint, - &if_rhsisnotnumeric); - - BIND(&if_rhsisheapnumber); + Label if_right_heapnumber(this), if_right_bigint(this), + if_right_not_numeric(this); + GotoIf(IsHeapNumberMap(right_map), &if_right_heapnumber); + Node* right_instance_type = LoadMapInstanceType(right_map); + Branch(IsBigIntInstanceType(right_instance_type), &if_right_bigint, + &if_right_not_numeric); + + BIND(&if_right_heapnumber); { - result.Bind(CallRuntime(Runtime::kBigIntCompareToNumber, - NoContextConstant(), SmiConstant(op), lhs, - rhs)); + OverwriteFeedback(var_type_feedback, + CompareOperationFeedback::kAny); + var_result = CAST(CallRuntime(Runtime::kBigIntCompareToNumber, + NoContextConstant(), SmiConstant(op), + left, right)); Goto(&end); } - BIND(&if_rhsisbigint); + BIND(&if_right_bigint); { - result.Bind(CallRuntime(Runtime::kBigIntCompareToBigInt, - NoContextConstant(), SmiConstant(op), lhs, - rhs)); + CombineFeedback(var_type_feedback, + CompareOperationFeedback::kBigInt); + var_result = CAST(CallRuntime(Runtime::kBigIntCompareToBigInt, + NoContextConstant(), SmiConstant(op), + left, right)); Goto(&end); } - BIND(&if_rhsisnotnumeric); + BIND(&if_right_not_numeric); { - // Convert the {rhs} to a Numeric; we don't need to perform - // dedicated ToPrimitive(rhs, hint Number) operation, as the - // ToNumeric(rhs) will by itself already invoke ToPrimitive with + OverwriteFeedback(var_type_feedback, + CompareOperationFeedback::kAny); + // Convert {right} to a Numeric; we don't need to perform + // dedicated ToPrimitive(right, hint Number) operation, as the + // ToNumeric(right) will by itself already invoke ToPrimitive with // a Number hint. - var_rhs.Bind( - CallBuiltin(Builtins::kNonNumberToNumeric, context, rhs)); + var_right.Bind( + CallBuiltin(Builtins::kNonNumberToNumeric, context, right)); Goto(&loop); } } - BIND(&if_lhsisstring); + BIND(&if_left_string); { - // Load the instance type of {rhs}. - Node* rhs_instance_type = LoadMapInstanceType(rhs_map); - - // Check if {rhs} is also a String. - Label if_rhsisstring(this, Label::kDeferred), - if_rhsisnotstring(this, Label::kDeferred); - Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring, - &if_rhsisnotstring); - - BIND(&if_rhsisstring); - { - // Both {lhs} and {rhs} are strings. - if (var_type_feedback != nullptr) { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kString)); - } - switch (op) { - case Operation::kLessThan: - result.Bind( - CallBuiltin(Builtins::kStringLessThan, context, lhs, rhs)); - Goto(&end); - break; - case Operation::kLessThanOrEqual: - result.Bind(CallBuiltin(Builtins::kStringLessThanOrEqual, - context, lhs, rhs)); - Goto(&end); - break; - case Operation::kGreaterThan: - result.Bind(CallBuiltin(Builtins::kStringGreaterThan, context, - lhs, rhs)); - Goto(&end); - break; - case Operation::kGreaterThanOrEqual: - result.Bind(CallBuiltin(Builtins::kStringGreaterThanOrEqual, - context, lhs, rhs)); - Goto(&end); - break; - default: - UNREACHABLE(); - } + Node* right_instance_type = LoadMapInstanceType(right_map); + + Label if_right_not_string(this, Label::kDeferred); + GotoIfNot(IsStringInstanceType(right_instance_type), + &if_right_not_string); + + // Both {left} and {right} are strings. + CombineFeedback(var_type_feedback, CompareOperationFeedback::kString); + Builtins::Name builtin; + switch (op) { + case Operation::kLessThan: + builtin = Builtins::kStringLessThan; + break; + case Operation::kLessThanOrEqual: + builtin = Builtins::kStringLessThanOrEqual; + break; + case Operation::kGreaterThan: + builtin = Builtins::kStringGreaterThan; + break; + case Operation::kGreaterThanOrEqual: + builtin = Builtins::kStringGreaterThanOrEqual; + break; + default: + UNREACHABLE(); } + var_result = CAST(CallBuiltin(builtin, context, left, right)); + Goto(&end); - BIND(&if_rhsisnotstring); + BIND(&if_right_not_string); { - // The {lhs} is a String and {rhs} is not a String. - if (var_type_feedback != nullptr) { - var_type_feedback->Bind( - SmiConstant(CompareOperationFeedback::kAny)); - } - // The {lhs} is a String, while {rhs} isn't. So we call - // ToPrimitive(rhs, hint Number) if {rhs} is a receiver, or - // ToNumeric(lhs) and then ToNumeric(rhs) in the other cases. + OverwriteFeedback(var_type_feedback, + CompareOperationFeedback::kAny); + // {left} is a String, while {right} isn't. So we call + // ToPrimitive(right, hint Number) if {right} is a receiver, or + // ToNumeric(left) and then ToNumeric(right) in the other cases. STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); - Label if_rhsisreceiver(this, Label::kDeferred), - if_rhsisnotreceiver(this, Label::kDeferred); - Branch(IsJSReceiverInstanceType(rhs_instance_type), - &if_rhsisreceiver, &if_rhsisnotreceiver); + Label if_right_receiver(this, Label::kDeferred); + GotoIf(IsJSReceiverInstanceType(right_instance_type), + &if_right_receiver); + + var_left.Bind( + CallBuiltin(Builtins::kNonNumberToNumeric, context, left)); + var_right.Bind(CallBuiltin(Builtins::kToNumeric, context, right)); + Goto(&loop); - BIND(&if_rhsisreceiver); + BIND(&if_right_receiver); { - // Convert {rhs} to a primitive first passing Number hint. Callable callable = CodeFactory::NonPrimitiveToPrimitive( isolate(), ToPrimitiveHint::kNumber); - var_rhs.Bind(CallStub(callable, context, rhs)); - Goto(&loop); - } - - BIND(&if_rhsisnotreceiver); - { - // Convert both {lhs} and {rhs} to Numeric. - var_lhs.Bind( - CallBuiltin(Builtins::kNonNumberToNumeric, context, lhs)); - var_rhs.Bind(CallBuiltin(Builtins::kToNumeric, context, rhs)); + var_right.Bind(CallStub(callable, context, right)); Goto(&loop); } } } - BIND(&if_lhsisother); + BIND(&if_left_other); { - // The {lhs} is neither a Numeric nor a String, and {rhs} is not - // an Smi. + // {left} is neither a Numeric nor a String, and {right} is not a Smi. if (var_type_feedback != nullptr) { - // Collect NumberOrOddball feedback if {lhs} is an Oddball - // and {rhs} is either a HeapNumber or Oddball. Otherwise collect + // Collect NumberOrOddball feedback if {left} is an Oddball + // and {right} is either a HeapNumber or Oddball. Otherwise collect // Any feedback. Label collect_any_feedback(this), collect_oddball_feedback(this), collect_feedback_done(this); - GotoIfNot(InstanceTypeEqual(lhs_instance_type, ODDBALL_TYPE), + GotoIfNot(InstanceTypeEqual(left_instance_type, ODDBALL_TYPE), &collect_any_feedback); - Node* rhs_instance_type = LoadMapInstanceType(rhs_map); - GotoIf(InstanceTypeEqual(rhs_instance_type, HEAP_NUMBER_TYPE), - &collect_oddball_feedback); - Branch(InstanceTypeEqual(rhs_instance_type, ODDBALL_TYPE), + GotoIf(IsHeapNumberMap(right_map), &collect_oddball_feedback); + Node* right_instance_type = LoadMapInstanceType(right_map); + Branch(InstanceTypeEqual(right_instance_type, ODDBALL_TYPE), &collect_oddball_feedback, &collect_any_feedback); BIND(&collect_oddball_feedback); { - CombineFeedback( - var_type_feedback, - SmiConstant(CompareOperationFeedback::kNumberOrOddball)); + CombineFeedback(var_type_feedback, + CompareOperationFeedback::kNumberOrOddball); Goto(&collect_feedback_done); } BIND(&collect_any_feedback); { - var_type_feedback->Bind( - SmiConstant(CompareOperationFeedback::kAny)); + OverwriteFeedback(var_type_feedback, + CompareOperationFeedback::kAny); Goto(&collect_feedback_done); } BIND(&collect_feedback_done); } - // If {lhs} is a receiver, we must call ToPrimitive(lhs, hint Number). - // Otherwise we must call ToNumeric(lhs) and then ToNumeric(rhs). + // If {left} is a receiver, call ToPrimitive(left, hint Number). + // Otherwise call ToNumeric(left) and then ToNumeric(right). STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); - Label if_lhsisreceiver(this, Label::kDeferred), - if_lhsisnotreceiver(this, Label::kDeferred); - Branch(IsJSReceiverInstanceType(lhs_instance_type), &if_lhsisreceiver, - &if_lhsisnotreceiver); + Label if_left_receiver(this, Label::kDeferred); + GotoIf(IsJSReceiverInstanceType(left_instance_type), + &if_left_receiver); + + var_left.Bind( + CallBuiltin(Builtins::kNonNumberToNumeric, context, left)); + var_right.Bind(CallBuiltin(Builtins::kToNumeric, context, right)); + Goto(&loop); - BIND(&if_lhsisreceiver); + BIND(&if_left_receiver); { Callable callable = CodeFactory::NonPrimitiveToPrimitive( isolate(), ToPrimitiveHint::kNumber); - var_lhs.Bind(CallStub(callable, context, lhs)); - Goto(&loop); - } - - BIND(&if_lhsisnotreceiver); - { - var_lhs.Bind( - CallBuiltin(Builtins::kNonNumberToNumeric, context, lhs)); - var_rhs.Bind(CallBuiltin(Builtins::kToNumeric, context, rhs)); + var_left.Bind(CallStub(callable, context, left)); Goto(&loop); } } @@ -8695,26 +8644,24 @@ Node* CodeStubAssembler::RelationalComparison(Operation op, Node* lhs, } } - BIND(&do_fcmp); + BIND(&do_float_comparison); { - // Load the {lhs} and {rhs} floating point values. - Node* lhs = var_fcmp_lhs.value(); - Node* rhs = var_fcmp_rhs.value(); - - // Perform a fast floating point comparison. switch (op) { case Operation::kLessThan: - Branch(Float64LessThan(lhs, rhs), &return_true, &return_false); + Branch(Float64LessThan(var_left_float, var_right_float), &return_true, + &return_false); break; case Operation::kLessThanOrEqual: - Branch(Float64LessThanOrEqual(lhs, rhs), &return_true, &return_false); + Branch(Float64LessThanOrEqual(var_left_float, var_right_float), + &return_true, &return_false); break; case Operation::kGreaterThan: - Branch(Float64GreaterThan(lhs, rhs), &return_true, &return_false); + Branch(Float64GreaterThan(var_left_float, var_right_float), + &return_true, &return_false); break; case Operation::kGreaterThanOrEqual: - Branch(Float64GreaterThanOrEqual(lhs, rhs), &return_true, - &return_false); + Branch(Float64GreaterThanOrEqual(var_left_float, var_right_float), + &return_true, &return_false); break; default: UNREACHABLE(); @@ -8723,18 +8670,18 @@ Node* CodeStubAssembler::RelationalComparison(Operation op, Node* lhs, BIND(&return_true); { - result.Bind(TrueConstant()); + var_result = TrueConstant(); Goto(&end); } BIND(&return_false); { - result.Bind(FalseConstant()); + var_result = FalseConstant(); Goto(&end); } BIND(&end); - return result.value(); + return var_result; } Node* CodeStubAssembler::CollectFeedbackForString(Node* instance_type) { @@ -8764,10 +8711,11 @@ void CodeStubAssembler::GenerateEqual_Same(Node* value, Label* if_equal, if (var_type_feedback != nullptr) { Node* instance_type = LoadMapInstanceType(value_map); - Label if_string(this), if_receiver(this), if_symbol(this), + Label if_string(this), if_receiver(this), if_symbol(this), if_bigint(this), if_other(this, Label::kDeferred); GotoIf(IsStringInstanceType(instance_type), &if_string); GotoIf(IsJSReceiverInstanceType(instance_type), &if_receiver); + GotoIf(IsBigIntInstanceType(instance_type), &if_bigint); Branch(IsSymbolInstanceType(instance_type), &if_symbol, &if_other); BIND(&if_string); @@ -8779,25 +8727,25 @@ void CodeStubAssembler::GenerateEqual_Same(Node* value, Label* if_equal, BIND(&if_symbol); { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kSymbol)); + CombineFeedback(var_type_feedback, CompareOperationFeedback::kSymbol); Goto(if_equal); } BIND(&if_receiver); { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kReceiver)); + CombineFeedback(var_type_feedback, CompareOperationFeedback::kReceiver); Goto(if_equal); } - // TODO(neis): Introduce BigInt CompareOperationFeedback and collect here - // and elsewhere? + BIND(&if_bigint); + { + CombineFeedback(var_type_feedback, CompareOperationFeedback::kBigInt); + Goto(if_equal); + } BIND(&if_other); { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kAny)); + CombineFeedback(var_type_feedback, CompareOperationFeedback::kAny); Goto(if_equal); } } else { @@ -8806,20 +8754,14 @@ void CodeStubAssembler::GenerateEqual_Same(Node* value, Label* if_equal, BIND(&if_heapnumber); { - if (var_type_feedback != nullptr) { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kNumber)); - } + CombineFeedback(var_type_feedback, CompareOperationFeedback::kNumber); Node* number_value = LoadHeapNumberValue(value); BranchIfFloat64IsNaN(number_value, if_notequal, if_equal); } BIND(&if_smi); { - if (var_type_feedback != nullptr) { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kSignedSmall)); - } + CombineFeedback(var_type_feedback, CompareOperationFeedback::kSignedSmall); Goto(if_equal); } } @@ -8847,10 +8789,10 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context, VARIABLE(var_right, MachineRepresentation::kTagged, right); VariableList loop_variable_list({&var_left, &var_right}, zone()); if (var_type_feedback != nullptr) { - // Initialize the type feedback to None. The current feedback is combined - // with the previous feedback. - var_type_feedback->Bind(SmiConstant(CompareOperationFeedback::kNone)); - loop_variable_list.Add(var_type_feedback, zone()); + // Initialize the type feedback to None. The current feedback will be + // combined with the previous feedback. + OverwriteFeedback(var_type_feedback, CompareOperationFeedback::kNone); + loop_variable_list.push_back(var_type_feedback); } Label loop(this, loop_variable_list); Goto(&loop); @@ -8880,10 +8822,8 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context, { // We have already checked for {left} and {right} being the same value, // so when we get here they must be different Smis. - if (var_type_feedback != nullptr) { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kSignedSmall)); - } + CombineFeedback(var_type_feedback, + CompareOperationFeedback::kSignedSmall); Goto(&if_notequal); } @@ -8908,10 +8848,7 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context, { var_left_float = SmiToFloat64(left); var_right_float = LoadHeapNumberValue(right); - if (var_type_feedback != nullptr) { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kNumber)); - } + CombineFeedback(var_type_feedback, CompareOperationFeedback::kNumber); Goto(&do_float_comparison); } @@ -8961,11 +8898,9 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context, { GotoIfNot(IsStringInstanceType(right_type), &use_symmetry); result.Bind(CallBuiltin(Builtins::kStringEqual, context, left, right)); - if (var_type_feedback != nullptr) { - CombineFeedback(var_type_feedback, - SmiOr(CollectFeedbackForString(left_type), - CollectFeedbackForString(right_type))); - } + CombineFeedback(var_type_feedback, + SmiOr(CollectFeedbackForString(left_type), + CollectFeedbackForString(right_type))); Goto(&end); } @@ -8976,10 +8911,7 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context, var_left_float = LoadHeapNumberValue(left); var_right_float = LoadHeapNumberValue(right); - if (var_type_feedback != nullptr) { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kNumber)); - } + CombineFeedback(var_type_feedback, CompareOperationFeedback::kNumber); Goto(&do_float_comparison); BIND(&if_right_not_number); @@ -9005,10 +8937,6 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context, BIND(&if_left_bigint); { - if (var_type_feedback != nullptr) { - var_type_feedback->Bind(SmiConstant(CompareOperationFeedback::kAny)); - } - Label if_right_heapnumber(this), if_right_bigint(this), if_right_string(this), if_right_boolean(this); GotoIf(IsHeapNumberMap(right_map), &if_right_heapnumber); @@ -9020,6 +8948,10 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context, BIND(&if_right_heapnumber); { + if (var_type_feedback != nullptr) { + var_type_feedback->Bind( + SmiConstant(CompareOperationFeedback::kAny)); + } result.Bind(CallRuntime(Runtime::kBigIntEqualToNumber, NoContextConstant(), left, right)); Goto(&end); @@ -9027,6 +8959,7 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context, BIND(&if_right_bigint); { + CombineFeedback(var_type_feedback, CompareOperationFeedback::kBigInt); result.Bind(CallRuntime(Runtime::kBigIntEqualToBigInt, NoContextConstant(), left, right)); Goto(&end); @@ -9034,6 +8967,10 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context, BIND(&if_right_string); { + if (var_type_feedback != nullptr) { + var_type_feedback->Bind( + SmiConstant(CompareOperationFeedback::kAny)); + } result.Bind(CallRuntime(Runtime::kBigIntEqualToString, NoContextConstant(), left, right)); Goto(&end); @@ -9041,6 +8978,10 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context, BIND(&if_right_boolean); { + if (var_type_feedback != nullptr) { + var_type_feedback->Bind( + SmiConstant(CompareOperationFeedback::kAny)); + } var_right.Bind(LoadObjectField(right, Oddball::kToNumberOffset)); Goto(&loop); } @@ -9083,7 +9024,7 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context, BIND(&if_right_symbol); { CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kSymbol)); + CompareOperationFeedback::kSymbol); Goto(&if_notequal); } } else { @@ -9109,10 +9050,7 @@ Node* CodeStubAssembler::Equal(Node* left, Node* right, Node* context, GotoIfNot(IsJSReceiverInstanceType(right_type), &if_right_not_receiver); // {left} and {right} are different JSReceiver references. - if (var_type_feedback != nullptr) { - CombineFeedback(var_type_feedback, - SmiConstant(CompareOperationFeedback::kReceiver)); - } + CombineFeedback(var_type_feedback, CompareOperationFeedback::kReceiver); Goto(&if_notequal); BIND(&if_right_not_receiver); @@ -9380,10 +9318,8 @@ Node* CodeStubAssembler::StrictEqual(Node* lhs, Node* rhs, BIND(&if_rhsisbigint); { if (var_type_feedback != nullptr) { - CSA_ASSERT( - this, - WordEqual(var_type_feedback->value(), - SmiConstant(CompareOperationFeedback::kAny))); + var_type_feedback->Bind( + SmiConstant(CompareOperationFeedback::kBigInt)); } result.Bind(CallRuntime(Runtime::kBigIntEqualToBigInt, NoContextConstant(), lhs, rhs)); @@ -9607,8 +9543,10 @@ void CodeStubAssembler::BranchIfSameValue(Node* lhs, Node* rhs, Label* if_true, } } -Node* CodeStubAssembler::HasProperty(Node* object, Node* key, Node* context, - HasPropertyLookupMode mode) { +TNode<Oddball> CodeStubAssembler::HasProperty(SloppyTNode<HeapObject> object, + SloppyTNode<Name> key, + SloppyTNode<Context> context, + HasPropertyLookupMode mode) { Label call_runtime(this, Label::kDeferred), return_true(this), return_false(this), end(this), if_proxy(this, Label::kDeferred); @@ -9633,16 +9571,16 @@ Node* CodeStubAssembler::HasProperty(Node* object, Node* key, Node* context, lookup_element_in_holder, &return_false, &call_runtime, &if_proxy); - VARIABLE(result, MachineRepresentation::kTagged); + TVARIABLE(Oddball, result); BIND(&if_proxy); { - Node* name = ToName(context, key); + TNode<Name> name = CAST(ToName(context, key)); switch (mode) { case kHasProperty: GotoIf(IsPrivateSymbol(name), &return_false); - result.Bind( + result = CAST( CallBuiltin(Builtins::kProxyHasProperty, context, object, name)); Goto(&end); break; @@ -9654,13 +9592,13 @@ Node* CodeStubAssembler::HasProperty(Node* object, Node* key, Node* context, BIND(&return_true); { - result.Bind(TrueConstant()); + result = TrueConstant(); Goto(&end); } BIND(&return_false); { - result.Bind(FalseConstant()); + result = FalseConstant(); Goto(&end); } @@ -9676,13 +9614,14 @@ Node* CodeStubAssembler::HasProperty(Node* object, Node* key, Node* context, break; } - result.Bind( - CallRuntime(fallback_runtime_function_id, context, object, key)); + result = + CAST(CallRuntime(fallback_runtime_function_id, context, object, key)); Goto(&end); } BIND(&end); - return result.value(); + CSA_ASSERT(this, IsBoolean(result)); + return result; } Node* CodeStubAssembler::ClassOf(Node* value) { @@ -9769,10 +9708,10 @@ Node* CodeStubAssembler::Typeof(Node* value) { Node* callable_or_undetectable_mask = Word32And( LoadMapBitField(map), - Int32Constant(1 << Map::kIsCallable | 1 << Map::kIsUndetectable)); + Int32Constant(Map::IsCallableBit::kMask | Map::IsUndetectableBit::kMask)); GotoIf(Word32Equal(callable_or_undetectable_mask, - Int32Constant(1 << Map::kIsCallable)), + Int32Constant(Map::IsCallableBit::kMask)), &return_function); GotoIfNot(Word32Equal(callable_or_undetectable_mask, Int32Constant(0)), @@ -10139,17 +10078,17 @@ Node* CodeStubAssembler::BitwiseOp(Node* left32, Node* right32, return ChangeInt32ToTagged(Signed(Word32Xor(left32, right32))); case Operation::kShiftLeft: if (!Word32ShiftIsSafe()) { - right32 = Word32And(right32, Int32Constant(0x1f)); + right32 = Word32And(right32, Int32Constant(0x1F)); } return ChangeInt32ToTagged(Signed(Word32Shl(left32, right32))); case Operation::kShiftRight: if (!Word32ShiftIsSafe()) { - right32 = Word32And(right32, Int32Constant(0x1f)); + right32 = Word32And(right32, Int32Constant(0x1F)); } return ChangeInt32ToTagged(Signed(Word32Sar(left32, right32))); case Operation::kShiftRightLogical: if (!Word32ShiftIsSafe()) { - right32 = Word32And(right32, Int32Constant(0x1f)); + right32 = Word32And(right32, Int32Constant(0x1F)); } return ChangeUint32ToTagged(Unsigned(Word32Shr(left32, right32))); default: @@ -10426,7 +10365,7 @@ Node* CodeStubAssembler::IsDetachedBuffer(Node* buffer) { } CodeStubArguments::CodeStubArguments( - CodeStubAssembler* assembler, SloppyTNode<IntPtrT> argc, Node* fp, + CodeStubAssembler* assembler, Node* argc, Node* fp, CodeStubAssembler::ParameterMode param_mode, ReceiverMode receiver_mode) : assembler_(assembler), argc_mode_(param_mode), @@ -10463,7 +10402,7 @@ TNode<Object> CodeStubArguments::AtIndex( Node* index, CodeStubAssembler::ParameterMode mode) const { DCHECK_EQ(argc_mode_, mode); CSA_ASSERT(assembler_, - assembler_->UintPtrOrSmiLessThan(index, GetLength(), mode)); + assembler_->UintPtrOrSmiLessThan(index, GetLength(mode), mode)); return assembler_->UncheckedCast<Object>( assembler_->Load(MachineType::AnyTagged(), AtIndexPtr(index, mode))); } @@ -10529,7 +10468,9 @@ void CodeStubArguments::PopAndReturn(Node* value) { } else { pop_count = argc_; } - assembler_->PopAndReturn(pop_count, value); + + assembler_->PopAndReturn(assembler_->ParameterToWord(pop_count, argc_mode_), + value); } Node* CodeStubAssembler::IsFastElementsKind(Node* elements_kind) { @@ -10586,6 +10527,7 @@ Node* CodeStubAssembler::AllocateFunctionWithMapAndContext(Node* map, CSA_ASSERT(this, Word32BinaryNot(IsConstructorMap(map))); CSA_ASSERT(this, Word32BinaryNot(IsFunctionWithPrototypeSlotMap(map))); Node* const fun = Allocate(JSFunction::kSizeWithoutPrototype); + STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kPointerSize); StoreMapNoWriteBarrier(fun, map); StoreObjectFieldRoot(fun, JSObject::kPropertiesOrHashOffset, Heap::kEmptyFixedArrayRootIndex); @@ -10752,5 +10694,23 @@ void CodeStubAssembler::PerformStackCheck(Node* context) { BIND(&ok); } +void CodeStubAssembler::InitializeFunctionContext(Node* native_context, + Node* context, int slots) { + DCHECK_GE(slots, Context::MIN_CONTEXT_SLOTS); + StoreMapNoWriteBarrier(context, Heap::kFunctionContextMapRootIndex); + StoreObjectFieldNoWriteBarrier(context, FixedArray::kLengthOffset, + SmiConstant(slots)); + + Node* const empty_fn = + LoadContextElement(native_context, Context::CLOSURE_INDEX); + StoreContextElementNoWriteBarrier(context, Context::CLOSURE_INDEX, empty_fn); + StoreContextElementNoWriteBarrier(context, Context::PREVIOUS_INDEX, + UndefinedConstant()); + StoreContextElementNoWriteBarrier(context, Context::EXTENSION_INDEX, + TheHoleConstant()); + StoreContextElementNoWriteBarrier(context, Context::NATIVE_CONTEXT_INDEX, + native_context); +} + } // namespace internal } // namespace v8 |