Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Unified Diff: src/code-stub-assembler.cc

Issue 2744263002: [string] Refactor direct string conversions (Closed)
Patch Set: Tweaks Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/code-stub-assembler.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/code-stub-assembler.cc
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
index 53b9835ab46eb2334bbb526d346c290eeb5a05d5..52a64bc4e78511d1b31010b9a739d6b5ab37f76c 100644
--- a/src/code-stub-assembler.cc
+++ b/src/code-stub-assembler.cc
@@ -2904,6 +2904,22 @@ Node* CodeStubAssembler::IsSequentialStringInstanceType(Node* instance_type) {
Int32Constant(kSeqStringTag));
}
+Node* CodeStubAssembler::IsExternalStringInstanceType(Node* instance_type) {
+ CSA_ASSERT(this, IsStringInstanceType(instance_type));
+ return Word32Equal(
+ Word32And(instance_type, Int32Constant(kStringRepresentationMask)),
+ Int32Constant(kExternalStringTag));
+}
+
+Node* CodeStubAssembler::IsShortExternalStringInstanceType(
+ Node* instance_type) {
+ CSA_ASSERT(this, IsStringInstanceType(instance_type));
+ STATIC_ASSERT(kShortExternalStringTag != 0);
+ return Word32NotEqual(
+ Word32And(instance_type, Int32Constant(kShortExternalStringMask)),
+ Int32Constant(0));
+}
+
Node* CodeStubAssembler::IsJSReceiverInstanceType(Node* instance_type) {
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
return Int32GreaterThanOrEqual(instance_type,
@@ -3013,188 +3029,58 @@ Node* CodeStubAssembler::IsJSFunction(Node* object) {
Node* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index,
ParameterMode parameter_mode) {
CSA_ASSERT(this, IsString(string));
+
// Translate the {index} into a Word.
- index = ParameterToWord(index, parameter_mode);
+ Node* const int_index = ParameterToWord(index, parameter_mode);
- // We may need to loop in case of cons, thin, or sliced strings.
- Variable var_index(this, MachineType::PointerRepresentation(), index);
- Variable var_string(this, MachineRepresentation::kTagged, string);
Variable var_result(this, MachineRepresentation::kWord32);
- Variable* loop_vars[] = {&var_index, &var_string};
- Label done_loop(this, &var_result), loop(this, 2, loop_vars);
- Goto(&loop);
- Bind(&loop);
- {
- // Load the current {index}.
- index = var_index.value();
- // Load the current {string}.
- string = var_string.value();
+ Label out(this, &var_result), runtime_generic(this), runtime_external(this);
- // Load the instance type of the {string}.
- Node* string_instance_type = LoadInstanceType(string);
+ ToDirectStringAssembler to_direct(state(), string);
+ Node* const direct_string = to_direct.TryToDirect(&runtime_generic);
+ Node* const offset = IntPtrAdd(int_index, to_direct.offset());
+ Node* const instance_type = to_direct.instance_type();
- // Check if the {string} is a SeqString.
- Label if_stringissequential(this), if_stringisnotsequential(this);
- Branch(Word32Equal(Word32And(string_instance_type,
- Int32Constant(kStringRepresentationMask)),
- Int32Constant(kSeqStringTag)),
- &if_stringissequential, &if_stringisnotsequential);
+ Node* const string_data = to_direct.PointerToData(&runtime_external);
- Bind(&if_stringissequential);
- {
- // Check if the {string} is a TwoByteSeqString or a OneByteSeqString.
- Label if_stringistwobyte(this), if_stringisonebyte(this);
- Branch(Word32Equal(Word32And(string_instance_type,
- Int32Constant(kStringEncodingMask)),
- Int32Constant(kTwoByteStringTag)),
- &if_stringistwobyte, &if_stringisonebyte);
-
- Bind(&if_stringisonebyte);
- {
- var_result.Bind(
- Load(MachineType::Uint8(), string,
- IntPtrAdd(index, IntPtrConstant(SeqOneByteString::kHeaderSize -
- kHeapObjectTag))));
- Goto(&done_loop);
- }
-
- Bind(&if_stringistwobyte);
- {
- var_result.Bind(
- Load(MachineType::Uint16(), string,
- IntPtrAdd(WordShl(index, IntPtrConstant(1)),
- IntPtrConstant(SeqTwoByteString::kHeaderSize -
- kHeapObjectTag))));
- Goto(&done_loop);
- }
- }
-
- Bind(&if_stringisnotsequential);
- {
- // Check if the {string} is a ConsString.
- Label if_stringiscons(this), if_stringisnotcons(this);
- Branch(Word32Equal(Word32And(string_instance_type,
- Int32Constant(kStringRepresentationMask)),
- Int32Constant(kConsStringTag)),
- &if_stringiscons, &if_stringisnotcons);
-
- Bind(&if_stringiscons);
- {
- // Check whether the right hand side is the empty string (i.e. if
- // this is really a flat string in a cons string). If that is not
- // the case we flatten the string first.
- Label if_rhsisempty(this), if_rhsisnotempty(this, Label::kDeferred);
- Node* rhs = LoadObjectField(string, ConsString::kSecondOffset);
- Branch(WordEqual(rhs, EmptyStringConstant()), &if_rhsisempty,
- &if_rhsisnotempty);
-
- Bind(&if_rhsisempty);
- {
- // Just operate on the left hand side of the {string}.
- var_string.Bind(LoadObjectField(string, ConsString::kFirstOffset));
- Goto(&loop);
- }
-
- Bind(&if_rhsisnotempty);
- {
- // Flatten the {string} and lookup in the resulting string.
- var_string.Bind(CallRuntime(Runtime::kFlattenString,
- NoContextConstant(), string));
- Goto(&loop);
- }
- }
+ // Check if the {string} is a TwoByteSeqString or a OneByteSeqString.
+ Label if_stringistwobyte(this), if_stringisonebyte(this);
+ Branch(IsOneByteStringInstanceType(instance_type), &if_stringisonebyte,
+ &if_stringistwobyte);
- Bind(&if_stringisnotcons);
- {
- // Check if the {string} is an ExternalString.
- Label if_stringisexternal(this), if_stringisnotexternal(this);
- Branch(Word32Equal(Word32And(string_instance_type,
- Int32Constant(kStringRepresentationMask)),
- Int32Constant(kExternalStringTag)),
- &if_stringisexternal, &if_stringisnotexternal);
-
- Bind(&if_stringisexternal);
- {
- // Check if the {string} is a short external string.
- Label if_stringisnotshort(this),
- if_stringisshort(this, Label::kDeferred);
- Branch(Word32Equal(Word32And(string_instance_type,
- Int32Constant(kShortExternalStringMask)),
- Int32Constant(0)),
- &if_stringisnotshort, &if_stringisshort);
-
- Bind(&if_stringisnotshort);
- {
- // Load the actual resource data from the {string}.
- Node* string_resource_data =
- LoadObjectField(string, ExternalString::kResourceDataOffset,
- MachineType::Pointer());
-
- // Check if the {string} is a TwoByteExternalString or a
- // OneByteExternalString.
- Label if_stringistwobyte(this), if_stringisonebyte(this);
- Branch(Word32Equal(Word32And(string_instance_type,
- Int32Constant(kStringEncodingMask)),
- Int32Constant(kTwoByteStringTag)),
- &if_stringistwobyte, &if_stringisonebyte);
-
- Bind(&if_stringisonebyte);
- {
- var_result.Bind(
- Load(MachineType::Uint8(), string_resource_data, index));
- Goto(&done_loop);
- }
+ Bind(&if_stringisonebyte);
+ {
+ var_result.Bind(Load(MachineType::Uint8(), string_data, offset));
+ Goto(&out);
+ }
- Bind(&if_stringistwobyte);
- {
- var_result.Bind(Load(MachineType::Uint16(), string_resource_data,
- WordShl(index, IntPtrConstant(1))));
- Goto(&done_loop);
- }
- }
+ Bind(&if_stringistwobyte);
+ {
+ var_result.Bind(Load(MachineType::Uint16(), string_data,
+ WordShl(offset, IntPtrConstant(1))));
+ Goto(&out);
+ }
- Bind(&if_stringisshort);
- {
- // The {string} might be compressed, call the runtime.
- var_result.Bind(SmiToWord32(
- CallRuntime(Runtime::kExternalStringGetChar,
- NoContextConstant(), string, SmiTag(index))));
- Goto(&done_loop);
- }
- }
+ Bind(&runtime_generic);
+ {
+ Node* const smi_index = ParameterToTagged(index, parameter_mode);
+ Node* const result = CallRuntime(Runtime::kStringCharCodeAtRT,
+ NoContextConstant(), string, smi_index);
+ var_result.Bind(SmiToWord32(result));
+ Goto(&out);
+ }
- Bind(&if_stringisnotexternal);
- {
- Label if_stringissliced(this), if_stringisthin(this);
- Branch(
- Word32Equal(Word32And(string_instance_type,
- Int32Constant(kStringRepresentationMask)),
- Int32Constant(kSlicedStringTag)),
- &if_stringissliced, &if_stringisthin);
- Bind(&if_stringissliced);
- {
- // The {string} is a SlicedString, continue with its parent.
- Node* string_offset =
- LoadAndUntagObjectField(string, SlicedString::kOffsetOffset);
- Node* string_parent =
- LoadObjectField(string, SlicedString::kParentOffset);
- var_index.Bind(IntPtrAdd(index, string_offset));
- var_string.Bind(string_parent);
- Goto(&loop);
- }
- Bind(&if_stringisthin);
- {
- // The {string} is a ThinString, continue with its actual value.
- var_string.Bind(LoadObjectField(string, ThinString::kActualOffset));
- Goto(&loop);
- }
- }
- }
- }
+ Bind(&runtime_external);
+ {
+ Node* const result =
+ CallRuntime(Runtime::kExternalStringGetChar, NoContextConstant(),
+ direct_string, SmiTag(offset));
+ var_result.Bind(SmiToWord32(result));
+ Goto(&out);
}
- Bind(&done_loop);
+ Bind(&out);
return var_result.value();
}
@@ -3313,27 +3199,14 @@ Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context,
Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from,
Node* to) {
- Label end(this);
- Label runtime(this);
-
- Node* const int_zero = Int32Constant(0);
-
- // Int32 variables.
- Variable var_instance_type(this, MachineRepresentation::kWord32, int_zero);
- Variable var_representation(this, MachineRepresentation::kWord32, int_zero);
-
- Variable var_from(this, MachineRepresentation::kTagged, from); // Smi.
- Variable var_string(this, MachineRepresentation::kTagged, string); // String.
- Variable var_result(this, MachineRepresentation::kTagged); // String.
+ Variable var_result(this, MachineRepresentation::kTagged);
+ ToDirectStringAssembler to_direct(state(), string);
+ Label end(this), runtime(this);
// Make sure first argument is a string.
CSA_ASSERT(this, TaggedIsNotSmi(string));
CSA_ASSERT(this, IsString(string));
- // Load the instance type of the {string}.
- Node* const instance_type = LoadInstanceType(string);
- var_instance_type.Bind(instance_type);
-
// Make sure that both from and to are non-negative smis.
GotoIfNot(TaggedIsPositiveSmi(from), &runtime);
@@ -3356,132 +3229,56 @@ Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from,
// TODO(jgruber): Add an additional case for substring of length == 0?
// Deal with different string types: update the index if necessary
- // and put the underlying string into var_string.
-
- // If the string is not indirect, it can only be sequential or external.
- STATIC_ASSERT(kIsIndirectStringMask ==
- (kSlicedStringTag & kConsStringTag & kThinStringTag));
- STATIC_ASSERT(kIsIndirectStringMask != 0);
- Label underlying_unpacked(this);
- GotoIf(Word32Equal(
- Word32And(instance_type, Int32Constant(kIsIndirectStringMask)),
- Int32Constant(0)),
- &underlying_unpacked);
-
- // The subject string is a sliced, cons, or thin string.
-
- Label thin_string(this), thin_or_sliced(this);
- var_representation.Bind(
- Word32And(instance_type, Int32Constant(kStringRepresentationMask)));
- GotoIf(
- Word32NotEqual(var_representation.value(), Int32Constant(kConsStringTag)),
- &thin_or_sliced);
+ // and extract the underlying string.
- // Cons string. Check whether it is flat, then fetch first part.
- // Flat cons strings have an empty second part.
- {
- GotoIf(WordNotEqual(LoadObjectField(string, ConsString::kSecondOffset),
- EmptyStringConstant()),
- &runtime);
-
- Node* first_string_part = LoadObjectField(string, ConsString::kFirstOffset);
- var_string.Bind(first_string_part);
- var_instance_type.Bind(LoadInstanceType(first_string_part));
- var_representation.Bind(Word32And(
- var_instance_type.value(), Int32Constant(kStringRepresentationMask)));
-
- // The loaded first part might be a thin string.
- Branch(Word32Equal(Word32And(var_instance_type.value(),
- Int32Constant(kIsIndirectStringMask)),
- Int32Constant(0)),
- &underlying_unpacked, &thin_string);
- }
-
- Bind(&thin_or_sliced);
- {
- GotoIf(
- Word32Equal(var_representation.value(), Int32Constant(kThinStringTag)),
- &thin_string);
- // Otherwise it's a sliced string.
- // Fetch parent and correct start index by offset.
- Node* sliced_offset =
- LoadObjectField(var_string.value(), SlicedString::kOffsetOffset);
- var_from.Bind(SmiAdd(from, sliced_offset));
-
- Node* slice_parent = LoadObjectField(string, SlicedString::kParentOffset);
- var_string.Bind(slice_parent);
-
- Node* slice_parent_instance_type = LoadInstanceType(slice_parent);
- var_instance_type.Bind(slice_parent_instance_type);
-
- // The loaded parent might be a thin string.
- Branch(Word32Equal(Word32And(var_instance_type.value(),
- Int32Constant(kIsIndirectStringMask)),
- Int32Constant(0)),
- &underlying_unpacked, &thin_string);
- }
-
- Bind(&thin_string);
- {
- Node* actual_string =
- LoadObjectField(var_string.value(), ThinString::kActualOffset);
- var_string.Bind(actual_string);
- var_instance_type.Bind(LoadInstanceType(actual_string));
- Goto(&underlying_unpacked);
- }
+ Node* const direct_string = to_direct.TryToDirect(&runtime);
+ Node* const offset = SmiAdd(from, SmiTag(to_direct.offset()));
+ Node* const instance_type = to_direct.instance_type();
// The subject string can only be external or sequential string of either
// encoding at this point.
Label external_string(this);
- Bind(&underlying_unpacked);
{
if (FLAG_string_slices) {
- Label copy_routine(this);
+ Label next(this);
// Short slice. Copy instead of slicing.
GotoIf(SmiLessThan(substr_length,
SmiConstant(Smi::FromInt(SlicedString::kMinLength))),
- &copy_routine);
+ &next);
// Allocate new sliced string.
- Label two_byte_slice(this);
- STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
- STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
-
Counters* counters = isolate()->counters();
IncrementCounter(counters->sub_string_native(), 1);
- GotoIf(Word32Equal(Word32And(var_instance_type.value(),
- Int32Constant(kStringEncodingMask)),
- Int32Constant(0)),
- &two_byte_slice);
+ Label one_byte_slice(this), two_byte_slice(this);
+ Branch(IsOneByteStringInstanceType(to_direct.instance_type()),
+ &one_byte_slice, &two_byte_slice);
- var_result.Bind(AllocateSlicedOneByteString(
- substr_length, var_string.value(), var_from.value()));
- Goto(&end);
+ Bind(&one_byte_slice);
+ {
+ var_result.Bind(
+ AllocateSlicedOneByteString(substr_length, direct_string, offset));
+ Goto(&end);
+ }
Bind(&two_byte_slice);
+ {
+ var_result.Bind(
+ AllocateSlicedTwoByteString(substr_length, direct_string, offset));
+ Goto(&end);
+ }
- var_result.Bind(AllocateSlicedTwoByteString(
- substr_length, var_string.value(), var_from.value()));
- Goto(&end);
-
- Bind(&copy_routine);
+ Bind(&next);
}
// The subject string can only be external or sequential string of either
// encoding at this point.
- STATIC_ASSERT(kExternalStringTag != 0);
- STATIC_ASSERT(kSeqStringTag == 0);
- GotoIfNot(Word32Equal(Word32And(var_instance_type.value(),
- Int32Constant(kExternalStringTag)),
- Int32Constant(0)),
- &external_string);
+ GotoIf(to_direct.is_external(), &external_string);
var_result.Bind(AllocAndCopyStringCharacters(
- this, context, var_string.value(), var_instance_type.value(),
- var_from.value(), substr_length));
+ this, context, direct_string, instance_type, offset, substr_length));
Counters* counters = isolate()->counters();
IncrementCounter(counters->sub_string_native(), 1);
@@ -3492,12 +3289,11 @@ Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from,
// Handle external string.
Bind(&external_string);
{
- Node* const fake_sequential_string = TryDerefExternalString(
- var_string.value(), var_instance_type.value(), &runtime);
+ Node* const fake_sequential_string = to_direct.PointerToString(&runtime);
- var_result.Bind(AllocAndCopyStringCharacters(
- this, context, fake_sequential_string, var_instance_type.value(),
- var_from.value(), substr_length));
+ var_result.Bind(
+ AllocAndCopyStringCharacters(this, context, fake_sequential_string,
+ instance_type, offset, substr_length));
Counters* counters = isolate()->counters();
IncrementCounter(counters->sub_string_native(), 1);
@@ -3508,7 +3304,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(var_string.value(), var_from.value());
+ Node* char_code = StringCharCodeAt(string, from);
var_result.Bind(StringFromCharCode(char_code));
Goto(&end);
}
@@ -3542,45 +3338,30 @@ Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from,
return var_result.value();
}
-namespace {
-
-Node* IsExternalStringInstanceType(CodeStubAssembler* a,
- Node* const instance_type) {
- CSA_ASSERT(a, a->IsStringInstanceType(instance_type));
- return a->Word32Equal(
- a->Word32And(instance_type, a->Int32Constant(kStringRepresentationMask)),
- a->Int32Constant(kExternalStringTag));
-}
+ToDirectStringAssembler::ToDirectStringAssembler(
+ compiler::CodeAssemblerState* state, Node* string)
+ : CodeStubAssembler(state),
+ var_string_(this, MachineRepresentation::kTagged, string),
+ var_instance_type_(this, MachineRepresentation::kWord32),
+ var_offset_(this, MachineType::PointerRepresentation()),
+ var_is_external_(this, MachineRepresentation::kWord32) {
+ CSA_ASSERT(this, TaggedIsNotSmi(string));
+ CSA_ASSERT(this, IsString(string));
-Node* IsShortExternalStringInstanceType(CodeStubAssembler* a,
- Node* const instance_type) {
- CSA_ASSERT(a, a->IsStringInstanceType(instance_type));
- STATIC_ASSERT(kShortExternalStringTag != 0);
- return a->Word32NotEqual(
- a->Word32And(instance_type, a->Int32Constant(kShortExternalStringMask)),
- a->Int32Constant(0));
+ var_string_.Bind(string);
+ var_offset_.Bind(IntPtrConstant(0));
+ var_instance_type_.Bind(LoadInstanceType(string));
+ var_is_external_.Bind(Int32Constant(0));
}
-} // 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());
+Node* ToDirectStringAssembler::TryToDirect(Label* if_bailout) {
+ 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);
+ Label if_iscons(this);
+ Label if_isexternal(this);
+ Label if_issliced(this);
+ Label if_isthin(this);
+ Label out(this);
Goto(&dispatch);
@@ -3592,12 +3373,12 @@ void CodeStubAssembler::TryUnpackString(Variable* var_string,
kSlicedStringTag, kThinStringTag,
};
Label* labels[] = {
- &if_isdirect, &if_iscons, &if_isexternal, &if_issliced, &if_isthin,
+ &out, &if_iscons, &if_isexternal, &if_issliced, &if_isthin,
};
STATIC_ASSERT(arraysize(values) == arraysize(labels));
Node* const representation = Word32And(
- var_instance_type->value(), Int32Constant(kStringRepresentationMask));
+ var_instance_type_.value(), Int32Constant(kStringRepresentationMask));
Switch(representation, if_bailout, values, labels, arraysize(values));
}
@@ -3605,13 +3386,13 @@ void CodeStubAssembler::TryUnpackString(Variable* var_string,
// Flat cons strings have an empty second part.
Bind(&if_iscons);
{
- Node* const string = var_string->value();
+ 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));
+ var_string_.Bind(lhs);
+ var_instance_type_.Bind(LoadInstanceType(lhs));
Goto(&dispatch);
}
@@ -3619,14 +3400,14 @@ void CodeStubAssembler::TryUnpackString(Variable* var_string,
// Sliced string. Fetch parent and correct start index by offset.
Bind(&if_issliced);
{
- Node* const string = var_string->value();
+ Node* const string = var_string_.value();
Node* const sliced_offset =
- LoadObjectField(string, SlicedString::kOffsetOffset);
- var_offset->Bind(IntPtrAdd(var_offset->value(), SmiUntag(sliced_offset)));
+ LoadAndUntagObjectField(string, SlicedString::kOffsetOffset);
+ var_offset_.Bind(IntPtrAdd(var_offset_.value(), sliced_offset));
Node* const parent = LoadObjectField(string, SlicedString::kParentOffset);
- var_string->Bind(BitcastTaggedToWord(parent));
- var_instance_type->Bind(LoadInstanceType(parent));
+ var_string_.Bind(parent);
+ var_instance_type_.Bind(LoadInstanceType(parent));
Goto(&dispatch);
}
@@ -3634,36 +3415,65 @@ void CodeStubAssembler::TryUnpackString(Variable* var_string,
// Thin string. Fetch the actual string.
Bind(&if_isthin);
{
- Node* const string = var_string->value();
+ 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);
+ var_string_.Bind(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);
+ var_is_external_.Bind(Int32Constant(1));
+ Goto(&out);
- 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));
+ Bind(&out);
+ return var_string_.value();
+}
+
+Node* ToDirectStringAssembler::TryToSequential(StringPointerKind ptr_kind,
+ Label* if_bailout) {
+ CHECK(ptr_kind == PTR_TO_DATA || ptr_kind == PTR_TO_STRING);
+
+ Variable var_result(this, MachineType::PointerRepresentation());
+ Label out(this), if_issequential(this), if_isexternal(this);
+ Branch(is_external(), &if_isexternal, &if_issequential);
+
+ Bind(&if_issequential);
+ {
+ STATIC_ASSERT(SeqOneByteString::kHeaderSize ==
+ SeqTwoByteString::kHeaderSize);
+ Node* result = BitcastTaggedToWord(var_string_.value());
+ if (ptr_kind == PTR_TO_DATA) {
+ result = IntPtrAdd(result, IntPtrConstant(SeqOneByteString::kHeaderSize -
+ kHeapObjectTag));
+ }
+ var_result.Bind(result);
+ Goto(&out);
+ }
- var_string->Bind(faked_seq_string);
- var_instance_type->Bind(faked_seq_instance_type);
+ Bind(&if_isexternal);
+ {
+ GotoIf(IsShortExternalStringInstanceType(var_instance_type_.value()),
+ if_bailout);
- Goto(&if_isdirect);
+ Node* const string = var_string_.value();
+ Node* result = LoadObjectField(string, ExternalString::kResourceDataOffset,
+ MachineType::Pointer());
+ if (ptr_kind == PTR_TO_STRING) {
+ result = IntPtrSub(result, IntPtrConstant(SeqOneByteString::kHeaderSize -
+ kHeapObjectTag));
+ }
+ var_result.Bind(result);
+ Goto(&out);
}
- Bind(&if_isdirect);
+ Bind(&out);
+ return var_result.value();
}
Node* CodeStubAssembler::TryDerefExternalString(Node* const string,
@@ -3671,9 +3481,8 @@ Node* CodeStubAssembler::TryDerefExternalString(Node* const string,
Label* if_bailout) {
Label out(this);
- USE(IsExternalStringInstanceType);
- CSA_ASSERT(this, IsExternalStringInstanceType(this, instance_type));
- GotoIf(IsShortExternalStringInstanceType(this, instance_type), if_bailout);
+ CSA_ASSERT(this, IsExternalStringInstanceType(instance_type));
+ GotoIf(IsShortExternalStringInstanceType(instance_type), if_bailout);
// Move the pointer so that offset-wise, it looks like a sequential string.
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
« no previous file with comments | « src/code-stub-assembler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698