Index: src/code-stub-assembler.cc |
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc |
index 7062da63eef2a5b6d0c31972d276e683a23e5c18..1c8fc9f358649c0e76f3688132485796976fff95 100644 |
--- a/src/code-stub-assembler.cc |
+++ b/src/code-stub-assembler.cc |
@@ -3457,23 +3457,8 @@ Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from, |
// Handle external string. |
Bind(&external_string); |
{ |
- // Rule out short external strings. |
- STATIC_ASSERT(kShortExternalStringTag != 0); |
- GotoIf(Word32NotEqual(Word32And(var_instance_type.value(), |
- Int32Constant(kShortExternalStringMask)), |
- Int32Constant(0)), |
- &runtime); |
- |
- // Move the pointer so that offset-wise, it looks like a sequential string. |
- STATIC_ASSERT(SeqTwoByteString::kHeaderSize == |
- SeqOneByteString::kHeaderSize); |
- |
- Node* resource_data = |
- LoadObjectField(var_string.value(), ExternalString::kResourceDataOffset, |
- MachineType::Pointer()); |
- Node* const fake_sequential_string = IntPtrSub( |
- resource_data, |
- IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
+ Node* const fake_sequential_string = TryDerefExternalString( |
+ var_string.value(), var_instance_type.value(), &runtime); |
var_result.Bind(AllocAndCopyStringCharacters( |
this, context, fake_sequential_string, var_instance_type.value(), |
@@ -3522,6 +3507,48 @@ 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)); |
+} |
Camillo Bruni
2017/02/22 12:02:05
we can probably push those even on the CodeStubAss
jgruber
2017/02/22 12:06:07
Agreed, but atm it doesn't look like we'd save muc
|
+ |
+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)); |
+} |
+ |
+} // namespace |
+ |
+Node* CodeStubAssembler::TryDerefExternalString(Node* const string, |
+ Node* const instance_type, |
+ Label* if_bailout) { |
+ Label out(this); |
+ |
+ USE(IsExternalStringInstanceType); |
+ CSA_ASSERT(this, IsExternalStringInstanceType(this, instance_type)); |
+ GotoIf(IsShortExternalStringInstanceType(this, instance_type), if_bailout); |
+ |
+ // Move the pointer so that offset-wise, it looks like a sequential string. |
+ STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
+ |
+ Node* resource_data = LoadObjectField( |
+ string, ExternalString::kResourceDataOffset, MachineType::Pointer()); |
+ Node* const fake_sequential_string = |
+ IntPtrSub(resource_data, |
+ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
+ |
+ return fake_sequential_string; |
+} |
+ |
void CodeStubAssembler::MaybeDerefIndirectString(Variable* var_string, |
Node* instance_type, |
Variable* var_did_something) { |