| Index: src/code-stub-assembler.cc
|
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
|
| index 96b6d7ed2569492cf00f74d19c8d68b4cb040960..05305dfb8ef6073af3f1805d5843b289fd8158cc 100644
|
| --- a/src/code-stub-assembler.cc
|
| +++ b/src/code-stub-assembler.cc
|
| @@ -2890,6 +2890,20 @@ Node* CodeStubAssembler::IsStringInstanceType(Node* instance_type) {
|
| return Int32LessThan(instance_type, Int32Constant(FIRST_NONSTRING_TYPE));
|
| }
|
|
|
| +Node* CodeStubAssembler::IsOneByteStringInstanceType(Node* instance_type) {
|
| + CSA_ASSERT(this, IsStringInstanceType(instance_type));
|
| + return Word32Equal(
|
| + Word32And(instance_type, Int32Constant(kStringEncodingMask)),
|
| + Int32Constant(kOneByteStringTag));
|
| +}
|
| +
|
| +Node* CodeStubAssembler::IsSequentialStringInstanceType(Node* instance_type) {
|
| + CSA_ASSERT(this, IsStringInstanceType(instance_type));
|
| + return Word32Equal(
|
| + Word32And(instance_type, Int32Constant(kStringRepresentationMask)),
|
| + Int32Constant(kSeqStringTag));
|
| +}
|
| +
|
| Node* CodeStubAssembler::IsJSReceiverInstanceType(Node* instance_type) {
|
| STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
|
| return Int32GreaterThanOrEqual(instance_type,
|
| @@ -3255,18 +3269,16 @@ Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context,
|
| typedef CodeStubAssembler::Label Label;
|
| typedef CodeStubAssembler::Variable Variable;
|
|
|
| - Label end(a), two_byte_sequential(a);
|
| + Label end(a), one_byte_sequential(a), two_byte_sequential(a);
|
| Variable var_result(a, MachineRepresentation::kTagged);
|
|
|
| Node* const smi_zero = a->SmiConstant(Smi::kZero);
|
|
|
| - STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
|
| - a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type,
|
| - a->Int32Constant(kStringEncodingMask)),
|
| - a->Int32Constant(0)),
|
| - &two_byte_sequential);
|
| + a->Branch(a->IsOneByteStringInstanceType(from_instance_type),
|
| + &one_byte_sequential, &two_byte_sequential);
|
|
|
| // The subject string is a sequential one-byte string.
|
| + a->Bind(&one_byte_sequential);
|
| {
|
| Node* result =
|
| a->AllocateSeqOneByteString(context, a->SmiToWord(character_count));
|
| @@ -3551,6 +3563,109 @@ Node* IsShortExternalStringInstanceType(CodeStubAssembler* a,
|
|
|
| } // namespace
|
|
|
| +void CodeStubAssembler::TryUnpackString(Variable* var_string,
|
| + Variable* var_offset,
|
| + Variable* var_instance_type,
|
| + Label* if_bailout) {
|
| + DCHECK_EQ(var_string->rep(), MachineType::PointerRepresentation());
|
| + DCHECK_EQ(var_offset->rep(), MachineType::PointerRepresentation());
|
| + DCHECK_EQ(var_instance_type->rep(), MachineRepresentation::kWord32);
|
| + CSA_ASSERT(this, IsString(var_string->value()));
|
| +
|
| + Label out(this);
|
| +
|
| + VariableList vars({var_string, var_offset, var_instance_type}, zone());
|
| + Label dispatch(this, vars);
|
| + Label if_isdirect(this);
|
| + Label if_iscons(this, Label::kDeferred);
|
| + Label if_isexternal(this, Label::kDeferred);
|
| + Label if_issliced(this, Label::kDeferred);
|
| + Label if_isthin(this, Label::kDeferred);
|
| +
|
| + Goto(&dispatch);
|
| +
|
| + // Dispatch based on string representation.
|
| + Bind(&dispatch);
|
| + {
|
| + int32_t values[] = {
|
| + kSeqStringTag, kConsStringTag, kExternalStringTag,
|
| + kSlicedStringTag, kThinStringTag,
|
| + };
|
| + Label* labels[] = {
|
| + &if_isdirect, &if_iscons, &if_isexternal, &if_issliced, &if_isthin,
|
| + };
|
| + STATIC_ASSERT(arraysize(values) == arraysize(labels));
|
| +
|
| + Node* const representation = Word32And(
|
| + var_instance_type->value(), Int32Constant(kStringRepresentationMask));
|
| + Switch(representation, if_bailout, values, labels, arraysize(values));
|
| + }
|
| +
|
| + // Cons string. Check whether it is flat, then fetch first part.
|
| + // Flat cons strings have an empty second part.
|
| + Bind(&if_iscons);
|
| + {
|
| + Node* const string = var_string->value();
|
| + GotoIfNot(IsEmptyString(LoadObjectField(string, ConsString::kSecondOffset)),
|
| + if_bailout);
|
| +
|
| + Node* const lhs = LoadObjectField(string, ConsString::kFirstOffset);
|
| + var_string->Bind(BitcastTaggedToWord(lhs));
|
| + var_instance_type->Bind(LoadInstanceType(lhs));
|
| +
|
| + Goto(&dispatch);
|
| + }
|
| +
|
| + // Sliced string. Fetch parent and correct start index by offset.
|
| + Bind(&if_issliced);
|
| + {
|
| + Node* const string = var_string->value();
|
| + Node* const sliced_offset =
|
| + LoadObjectField(string, SlicedString::kOffsetOffset);
|
| + var_offset->Bind(IntPtrAdd(var_offset->value(), SmiUntag(sliced_offset)));
|
| +
|
| + Node* const parent = LoadObjectField(string, SlicedString::kParentOffset);
|
| + var_string->Bind(BitcastTaggedToWord(parent));
|
| + var_instance_type->Bind(LoadInstanceType(parent));
|
| +
|
| + Goto(&dispatch);
|
| + }
|
| +
|
| + // Thin string. Fetch the actual string.
|
| + Bind(&if_isthin);
|
| + {
|
| + Node* const string = var_string->value();
|
| + Node* const actual_string =
|
| + LoadObjectField(string, ThinString::kActualOffset);
|
| + Node* const actual_instance_type = LoadInstanceType(actual_string);
|
| +
|
| + var_string->Bind(BitcastTaggedToWord(actual_string));
|
| + var_instance_type->Bind(actual_instance_type);
|
| +
|
| + Goto(&dispatch);
|
| + }
|
| +
|
| + // External string.
|
| + Bind(&if_isexternal);
|
| + {
|
| + Node* const string = var_string->value();
|
| + Node* const faked_seq_string =
|
| + TryDerefExternalString(string, var_instance_type->value(), if_bailout);
|
| +
|
| + STATIC_ASSERT(kSeqStringTag == 0x0);
|
| + Node* const faked_seq_instance_type = Word32Xor(
|
| + var_instance_type->value(), Int32Constant(kExternalStringTag));
|
| + CSA_ASSERT(this, IsSequentialStringInstanceType(faked_seq_instance_type));
|
| +
|
| + var_string->Bind(faked_seq_string);
|
| + var_instance_type->Bind(faked_seq_instance_type);
|
| +
|
| + Goto(&if_isdirect);
|
| + }
|
| +
|
| + Bind(&if_isdirect);
|
| +}
|
| +
|
| Node* CodeStubAssembler::TryDerefExternalString(Node* const string,
|
| Node* const instance_type,
|
| Label* if_bailout) {
|
| @@ -5618,23 +5733,10 @@ void CodeStubAssembler::UpdateFeedback(Node* feedback, Node* feedback_vector,
|
| }
|
|
|
| Node* CodeStubAssembler::LoadReceiverMap(Node* receiver) {
|
| - Variable var_receiver_map(this, MachineRepresentation::kTagged);
|
| - Label load_smi_map(this, Label::kDeferred), load_receiver_map(this),
|
| - if_result(this);
|
| -
|
| - Branch(TaggedIsSmi(receiver), &load_smi_map, &load_receiver_map);
|
| - Bind(&load_smi_map);
|
| - {
|
| - var_receiver_map.Bind(LoadRoot(Heap::kHeapNumberMapRootIndex));
|
| - Goto(&if_result);
|
| - }
|
| - Bind(&load_receiver_map);
|
| - {
|
| - var_receiver_map.Bind(LoadMap(receiver));
|
| - Goto(&if_result);
|
| - }
|
| - Bind(&if_result);
|
| - return var_receiver_map.value();
|
| + return Select(TaggedIsSmi(receiver),
|
| + [=] { return LoadRoot(Heap::kHeapNumberMapRootIndex); },
|
| + [=] { return LoadMap(receiver); },
|
| + MachineRepresentation::kTagged);
|
| }
|
|
|
| Node* CodeStubAssembler::TryToIntptr(Node* key, Label* miss) {
|
|
|