Index: src/code-stub-assembler.cc |
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc |
index 80c4c77bf6f034f21cd12a2b7d90788aa2fec7d4..64a1ed6b2b9dc4c995909b952ba4d3728e3d7c19 100644 |
--- a/src/code-stub-assembler.cc |
+++ b/src/code-stub-assembler.cc |
@@ -2429,6 +2429,251 @@ Node* CodeStubAssembler::StringFromCharCode(Node* code) { |
return var_result.value(); |
} |
+Node* CodeStubAssembler::StringFromCodePointAt(Node* string, Node* length, |
Benedikt Meurer
2016/09/22 03:48:23
I'd prefer to have a helper method StringFromCodeP
caitp
2016/09/22 13:26:21
The main reason I've put this in CodeStubAssembler
Benedikt Meurer
2016/09/23 03:46:24
I'd be fine with __ if it improves readability (an
caitp
2016/09/23 10:14:28
Acknowledged, but maybe that will be a cleanup fol
|
+ Node* index) { |
+ Label return_result(this); |
+ Variable var_result(this, MachineRepresentation::kTagged); |
+ var_result.Bind(UndefinedConstant()); |
+ |
+ Node* string_instance_type = LoadInstanceType(string); |
+ |
+ Label if_stringissequential(this), if_stringisexternal(this); |
+ Branch(Word32Equal(Word32And(string_instance_type, |
+ Int32Constant(kStringRepresentationMask)), |
+ Int32Constant(kSeqStringTag)), |
+ &if_stringissequential, &if_stringisexternal); |
+ |
+ Bind(&if_stringissequential); |
+ { |
+ Label if_stringisonebyte(this), if_stringistwobyte(this); |
+ Branch(Word32Equal(Word32And(string_instance_type, |
+ Int32Constant(kStringEncodingMask)), |
+ Int32Constant(kOneByteStringTag)), |
+ &if_stringisonebyte, &if_stringistwobyte); |
+ |
+ Bind(&if_stringisonebyte); |
+ { |
+ Node* ch = |
+ Load(MachineType::Uint8(), string, |
+ IntPtrAdd(index, IntPtrConstant(SeqOneByteString::kHeaderSize - |
+ kHeapObjectTag))); |
+ Node* result = AllocateSeqOneByteString(1); |
+ StoreNoWriteBarrier( |
+ MachineRepresentation::kWord8, result, |
+ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), ch); |
+ var_result.Bind(result); |
+ Goto(&return_result); |
+ } |
+ |
+ Bind(&if_stringistwobyte); |
+ { |
+ Node* lead = Load(MachineType::Uint16(), string, |
+ IntPtrAdd(WordShl(index, IntPtrConstant(1)), |
+ IntPtrConstant(SeqTwoByteString::kHeaderSize - |
+ kHeapObjectTag))); |
+ Node* next_pos = Int32Add(index, Int32Constant(1)); |
+ |
+ Label if_issinglecodeunit(this), if_isdoublecodeunit(this); |
+ GotoIf(Int32GreaterThanOrEqual(next_pos, length), &if_issinglecodeunit); |
+ GotoIf(Int32LessThan(lead, Int32Constant(0xD800)), &if_issinglecodeunit); |
+ BranchIf(Int32LessThan(lead, Int32Constant(0xDC00)), &if_isdoublecodeunit, |
+ &if_issinglecodeunit); |
+ |
+ Bind(&if_isdoublecodeunit); |
+ { |
+ Node* trail = |
+ Load(MachineType::Uint16(), string, |
+ IntPtrAdd(WordShl(next_pos, IntPtrConstant(1)), |
+ IntPtrConstant(SeqTwoByteString::kHeaderSize - |
+ kHeapObjectTag))); |
+ GotoIf(Int32LessThan(trail, Int32Constant(0xDC00)), |
+ &if_issinglecodeunit); |
+ GotoIf(Int32GreaterThan(trail, Int32Constant(0xDFFF)), |
+ &if_issinglecodeunit); |
+ |
+ Node* result = AllocateSeqTwoByteString(2); |
+#if defined(V8_TARGET_LITTLE_ENDIAN) |
+ Node* ch = Word32Or(WordShl(trail, Int32Constant(16)), lead); |
+#else |
+ Node* ch = Word32Or(WordShl(lead, Int32Constant(16)), trail); |
+#endif |
+ StoreNoWriteBarrier( |
+ MachineRepresentation::kWord32, result, |
+ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), ch); |
+ var_result.Bind(result); |
+ Goto(&return_result); |
+ } |
+ |
+ Bind(&if_issinglecodeunit); |
+ { |
+ Node* result = AllocateSeqTwoByteString(1); |
+ StoreNoWriteBarrier( |
+ MachineRepresentation::kWord16, result, |
+ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), |
+ lead); |
+ var_result.Bind(result); |
+ Goto(&return_result); |
+ } |
+ } |
+ } |
+ |
+ Bind(&if_stringisexternal); |
+ { |
+ Assert(Word32Equal(Word32And(string_instance_type, |
+ Int32Constant(kStringRepresentationMask)), |
+ Int32Constant(kExternalStringTag))); |
+ Label if_stringisshort(this), if_stringisnotshort(this); |
+ |
+ Branch(Word32Equal(Word32And(string_instance_type, |
+ Int32Constant(kShortExternalStringMask)), |
+ Int32Constant(0)), |
+ &if_stringisshort, &if_stringisnotshort); |
+ |
+ Bind(&if_stringisshort); |
+ { |
+ // Load the actual resource data from the {string}. |
+ Node* string_resource_data = LoadObjectField( |
+ string, ExternalString::kResourceDataOffset, MachineType::Pointer()); |
+ |
+ Label if_stringistwobyte(this), if_stringisonebyte(this); |
+ Branch(Word32Equal(Word32And(string_instance_type, |
+ Int32Constant(kStringEncodingMask)), |
+ Int32Constant(kTwoByteStringTag)), |
+ &if_stringistwobyte, &if_stringisonebyte); |
+ |
+ Bind(&if_stringisonebyte); |
+ { |
+ Node* ch = Load(MachineType::Uint8(), string_resource_data, index); |
+ Node* result = AllocateSeqOneByteString(1); |
+ StoreNoWriteBarrier( |
+ MachineRepresentation::kWord8, result, |
+ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), ch); |
+ var_result.Bind(result); |
+ Goto(&return_result); |
+ } |
+ |
+ Bind(&if_stringistwobyte); |
+ { |
+ Label if_issinglecodeunit(this), if_isdoublecodeunit(this); |
+ Node* lead = Load(MachineType::Uint16(), string_resource_data, |
+ WordShl(index, IntPtrConstant(1))); |
+ Node* next_pos = Int32Add(index, Int32Constant(1)); |
+ |
+ GotoIf(Int32GreaterThanOrEqual(next_pos, length), &if_issinglecodeunit); |
+ GotoIf(Int32LessThan(lead, Int32Constant(0xD800)), |
+ &if_issinglecodeunit); |
+ Branch(Int32LessThan(lead, Int32Constant(0xDC00)), &if_isdoublecodeunit, |
+ &if_issinglecodeunit); |
+ |
+ Bind(&if_isdoublecodeunit); |
+ { |
+ Node* trail = |
+ Load(MachineType::Uint16(), string, |
+ IntPtrAdd(WordShl(next_pos, IntPtrConstant(1)), |
+ IntPtrConstant(SeqTwoByteString::kHeaderSize - |
+ kHeapObjectTag))); |
+ GotoIf(Int32LessThan(trail, Int32Constant(0xDC00)), |
+ &if_issinglecodeunit); |
+ GotoIf(Int32GreaterThan(trail, Int32Constant(0xDFFF)), |
+ &if_issinglecodeunit); |
+ |
+ Node* result = AllocateSeqTwoByteString(2); |
+#if defined(V8_TARGET_LITTLE_ENDIAN) |
+ Node* ch = Word32Or(WordShl(trail, Int32Constant(16)), lead); |
+#else |
+ Node* ch = Word32Or(WordShl(lead, Int32Constant(16)), trail); |
+#endif |
+ StoreNoWriteBarrier( |
+ MachineRepresentation::kWord32, result, |
+ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), |
+ ch); |
+ var_result.Bind(result); |
+ Goto(&return_result); |
+ } |
+ |
+ Bind(&if_issinglecodeunit); |
+ { |
+ Node* result = AllocateSeqTwoByteString(1); |
+ StoreNoWriteBarrier( |
+ MachineRepresentation::kWord16, result, |
+ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), |
+ lead); |
+ var_result.Bind(result); |
+ Goto(&return_result); |
+ } |
+ } |
+ } |
+ |
+ Bind(&if_stringisnotshort); |
+ { |
+ Label if_issinglecodeunit(this), if_isdoublecodeunit(this); |
+ Node* lead = |
+ SmiToWord32(CallRuntime(Runtime::kExternalStringGetChar, |
+ NoContextConstant(), string, SmiTag(index))); |
+ Node* next_pos = Int32Add(index, Int32Constant(1)); |
+ |
+ GotoIf(Int32GreaterThanOrEqual(next_pos, length), &if_issinglecodeunit); |
+ GotoIf(Int32LessThan(lead, Int32Constant(0xD800)), &if_issinglecodeunit); |
+ Branch(Int32GreaterThan(lead, Int32Constant(0xDBFF)), |
+ &if_issinglecodeunit, &if_isdoublecodeunit); |
+ |
+ Bind(&if_isdoublecodeunit); |
+ { |
+ Node* trail = SmiToWord32(CallRuntime(Runtime::kExternalStringGetChar, |
+ NoContextConstant(), string, |
+ SmiTag(next_pos))); |
+ GotoIf(Int32LessThan(trail, Int32Constant(0xDC00)), |
+ &if_issinglecodeunit); |
+ GotoIf(Int32GreaterThan(trail, Int32Constant(0xDFFF)), |
+ &if_issinglecodeunit); |
+ Node* result = AllocateSeqTwoByteString(2); |
+#if defined(V8_TARGET_LITTLE_ENDIAN) |
+ Node* ch = Word32Or(WordShl(trail, Int32Constant(16)), lead); |
+#else |
+ Node* ch = Word32Or(WordShl(lead, Int32Constant(16)), trail); |
+#endif |
+ StoreNoWriteBarrier( |
+ MachineRepresentation::kWord32, result, |
+ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), ch); |
+ var_result.Bind(result); |
+ Goto(&return_result); |
+ } |
+ |
+ Bind(&if_issinglecodeunit); |
+ { |
+ Label if_isonebyte(this), if_istwobyte(this); |
+ Branch(Int32LessThan(lead, Int32Constant(0x100)), &if_isonebyte, |
+ &if_istwobyte); |
+ |
+ Bind(&if_isonebyte); |
+ { |
+ Node* result = AllocateSeqOneByteString(1); |
+ StoreNoWriteBarrier( |
+ MachineRepresentation::kWord8, result, |
+ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), |
+ lead); |
+ var_result.Bind(result); |
+ Goto(&return_result); |
+ } |
+ |
+ Bind(&if_istwobyte); |
+ { |
+ Node* result = AllocateSeqTwoByteString(1); |
+ StoreNoWriteBarrier( |
+ MachineRepresentation::kWord8, result, |
+ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), |
+ lead); |
+ var_result.Bind(result); |
+ Goto(&return_result); |
+ } |
+ } |
+ } |
+ } |
+ |
+ Bind(&return_result); |
+ return var_result.value(); |
+} |
+ |
Node* CodeStubAssembler::StringToNumber(Node* context, Node* input) { |
Label runtime(this, Label::kDeferred); |
Label end(this); |