Porting r10023 and r10054 to arm (pointer cache for external strings).
Review URL: http://codereview.chromium.org/8682010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10059 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
198e33560b
commit
304d49cd17
@ -5107,74 +5107,14 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
|
||||
__ cmp(ip, Operand(index_));
|
||||
__ b(ls, index_out_of_range_);
|
||||
|
||||
// We need special handling for non-flat strings.
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ tst(result_, Operand(kStringRepresentationMask));
|
||||
__ b(eq, &flat_string);
|
||||
__ mov(index_, Operand(index_, ASR, kSmiTagSize));
|
||||
|
||||
// Handle non-flat strings.
|
||||
__ and_(result_, result_, Operand(kStringRepresentationMask));
|
||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
||||
__ cmp(result_, Operand(kExternalStringTag));
|
||||
__ b(gt, &sliced_string);
|
||||
__ b(eq, &call_runtime_);
|
||||
StringCharLoadGenerator::Generate(masm,
|
||||
object_,
|
||||
index_,
|
||||
result_,
|
||||
&call_runtime_);
|
||||
|
||||
// ConsString.
|
||||
// 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 would rather go to the runtime system now to flatten
|
||||
// the string.
|
||||
Label assure_seq_string;
|
||||
__ ldr(result_, FieldMemOperand(object_, ConsString::kSecondOffset));
|
||||
__ LoadRoot(ip, Heap::kEmptyStringRootIndex);
|
||||
__ cmp(result_, Operand(ip));
|
||||
__ b(ne, &call_runtime_);
|
||||
// Get the first of the two parts.
|
||||
__ ldr(object_, FieldMemOperand(object_, ConsString::kFirstOffset));
|
||||
__ jmp(&assure_seq_string);
|
||||
|
||||
// SlicedString, unpack and add offset.
|
||||
__ bind(&sliced_string);
|
||||
__ ldr(result_, FieldMemOperand(object_, SlicedString::kOffsetOffset));
|
||||
__ add(index_, index_, result_);
|
||||
__ ldr(object_, FieldMemOperand(object_, SlicedString::kParentOffset));
|
||||
|
||||
// Assure that we are dealing with a sequential string. Go to runtime if not.
|
||||
__ bind(&assure_seq_string);
|
||||
__ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
|
||||
__ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
|
||||
// Check that parent is not an external string. Go to runtime otherwise.
|
||||
// Note that if the original string is a cons or slice with an external
|
||||
// string as underlying string, we pass that unpacked underlying string with
|
||||
// the adjusted index to the runtime function.
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ tst(result_, Operand(kStringRepresentationMask));
|
||||
__ b(ne, &call_runtime_);
|
||||
|
||||
// Check for 1-byte or 2-byte string.
|
||||
__ bind(&flat_string);
|
||||
STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
|
||||
STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
|
||||
__ tst(result_, Operand(kStringEncodingMask));
|
||||
__ b(ne, &ascii_string);
|
||||
|
||||
// 2-byte string.
|
||||
// Load the 2-byte character code into the result register. We can
|
||||
// add without shifting since the smi tag size is the log2 of the
|
||||
// number of bytes in a two-byte character.
|
||||
STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1 && kSmiShiftSize == 0);
|
||||
__ add(index_, object_, Operand(index_));
|
||||
__ ldrh(result_, FieldMemOperand(index_, SeqTwoByteString::kHeaderSize));
|
||||
__ jmp(&got_char_code);
|
||||
|
||||
// ASCII string.
|
||||
// Load the byte into the result register.
|
||||
__ bind(&ascii_string);
|
||||
__ add(index_, object_, Operand(index_, LSR, kSmiTagSize));
|
||||
__ ldrb(result_, FieldMemOperand(index_, SeqAsciiString::kHeaderSize));
|
||||
|
||||
__ bind(&got_char_code);
|
||||
__ mov(result_, Operand(result_, LSL, kSmiTagSize));
|
||||
__ bind(&exit_);
|
||||
}
|
||||
@ -5221,6 +5161,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
// is too complex (e.g., when the string needs to be flattened).
|
||||
__ bind(&call_runtime_);
|
||||
call_helper.BeforeCall(masm);
|
||||
__ mov(index_, Operand(index_, LSL, kSmiTagSize));
|
||||
__ Push(object_, index_);
|
||||
__ CallRuntime(Runtime::kStringCharCodeAt, 2);
|
||||
__ Move(result_, r0);
|
||||
|
@ -302,6 +302,94 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
|
||||
__ pop(lr);
|
||||
}
|
||||
|
||||
|
||||
void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
Register string,
|
||||
Register index,
|
||||
Register result,
|
||||
Label* call_runtime) {
|
||||
// Fetch the instance type of the receiver into result register.
|
||||
__ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset));
|
||||
__ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
|
||||
|
||||
// We need special handling for indirect strings.
|
||||
Label check_sequential;
|
||||
__ tst(result, Operand(kIsIndirectStringMask));
|
||||
__ b(eq, &check_sequential);
|
||||
|
||||
// Dispatch on the indirect string shape: slice or cons.
|
||||
Label cons_string;
|
||||
__ tst(result, Operand(kSlicedNotConsMask));
|
||||
__ b(eq, &cons_string);
|
||||
|
||||
// Handle slices.
|
||||
Label indirect_string_loaded;
|
||||
__ ldr(result, FieldMemOperand(string, SlicedString::kOffsetOffset));
|
||||
__ add(index, index, Operand(result, ASR, kSmiTagSize));
|
||||
__ ldr(string, FieldMemOperand(string, SlicedString::kParentOffset));
|
||||
__ jmp(&indirect_string_loaded);
|
||||
|
||||
// Handle cons strings.
|
||||
// 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 would rather go to the runtime system now to flatten
|
||||
// the string.
|
||||
__ bind(&cons_string);
|
||||
__ ldr(result, FieldMemOperand(string, ConsString::kSecondOffset));
|
||||
__ LoadRoot(ip, Heap::kEmptyStringRootIndex);
|
||||
__ cmp(result, ip);
|
||||
__ b(ne, call_runtime);
|
||||
// Get the first of the two strings and load its instance type.
|
||||
__ ldr(string, FieldMemOperand(string, ConsString::kFirstOffset));
|
||||
|
||||
__ bind(&indirect_string_loaded);
|
||||
__ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset));
|
||||
__ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
|
||||
|
||||
// Distinguish sequential and external strings. Only these two string
|
||||
// representations can reach here (slices and flat cons strings have been
|
||||
// reduced to the underlying sequential or external string).
|
||||
Label external_string, check_encoding;
|
||||
__ bind(&check_sequential);
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ tst(result, Operand(kStringRepresentationMask));
|
||||
__ b(ne, &external_string);
|
||||
|
||||
// Prepare sequential strings
|
||||
STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize);
|
||||
__ add(string,
|
||||
string,
|
||||
Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||
__ jmp(&check_encoding);
|
||||
|
||||
// Handle external strings.
|
||||
__ bind(&external_string);
|
||||
if (FLAG_debug_code) {
|
||||
// Assert that we do not have a cons or slice (indirect strings) here.
|
||||
// Sequential strings have already been ruled out.
|
||||
__ tst(result, Operand(kIsIndirectStringMask));
|
||||
__ Assert(eq, "external string expected, but not found");
|
||||
}
|
||||
// Rule out short external strings.
|
||||
STATIC_CHECK(kShortExternalStringTag != 0);
|
||||
__ tst(result, Operand(kShortExternalStringMask));
|
||||
__ b(ne, call_runtime);
|
||||
__ ldr(string, FieldMemOperand(string, ExternalString::kResourceDataOffset));
|
||||
|
||||
Label ascii, done;
|
||||
__ bind(&check_encoding);
|
||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||
__ tst(result, Operand(kStringEncodingMask));
|
||||
__ b(ne, &ascii);
|
||||
// Two-byte string.
|
||||
__ ldrh(result, MemOperand(string, index, LSL, 1));
|
||||
__ jmp(&done);
|
||||
__ bind(&ascii);
|
||||
// Ascii string.
|
||||
__ ldrb(result, MemOperand(string, index));
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -73,6 +73,21 @@ class CodeGenerator: public AstVisitor {
|
||||
};
|
||||
|
||||
|
||||
class StringCharLoadGenerator : public AllStatic {
|
||||
public:
|
||||
// Generates the code for handling different string types and loading the
|
||||
// indexed character into |result|. We expect |index| as untagged input and
|
||||
// |result| as untagged output.
|
||||
static void Generate(MacroAssembler* masm,
|
||||
Register string,
|
||||
Register index,
|
||||
Register result,
|
||||
Label* call_runtime);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(StringCharLoadGenerator);
|
||||
};
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
#endif // V8_ARM_CODEGEN_ARM_H_
|
||||
|
@ -3592,86 +3592,14 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
|
||||
LStringCharCodeAt* instr_;
|
||||
};
|
||||
|
||||
Register string = ToRegister(instr->string());
|
||||
Register index = ToRegister(instr->index());
|
||||
Register result = ToRegister(instr->result());
|
||||
|
||||
DeferredStringCharCodeAt* deferred =
|
||||
new DeferredStringCharCodeAt(this, instr);
|
||||
|
||||
// Fetch the instance type of the receiver into result register.
|
||||
__ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset));
|
||||
__ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
|
||||
|
||||
// We need special handling for indirect strings.
|
||||
Label check_sequential;
|
||||
__ tst(result, Operand(kIsIndirectStringMask));
|
||||
__ b(eq, &check_sequential);
|
||||
|
||||
// Dispatch on the indirect string shape: slice or cons.
|
||||
Label cons_string;
|
||||
__ tst(result, Operand(kSlicedNotConsMask));
|
||||
__ b(eq, &cons_string);
|
||||
|
||||
// Handle slices.
|
||||
Label indirect_string_loaded;
|
||||
__ ldr(result, FieldMemOperand(string, SlicedString::kOffsetOffset));
|
||||
__ add(index, index, Operand(result, ASR, kSmiTagSize));
|
||||
__ ldr(string, FieldMemOperand(string, SlicedString::kParentOffset));
|
||||
__ jmp(&indirect_string_loaded);
|
||||
|
||||
// Handle conses.
|
||||
// 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 would rather go to the runtime system now to flatten
|
||||
// the string.
|
||||
__ bind(&cons_string);
|
||||
__ ldr(result, FieldMemOperand(string, ConsString::kSecondOffset));
|
||||
__ LoadRoot(ip, Heap::kEmptyStringRootIndex);
|
||||
__ cmp(result, ip);
|
||||
__ b(ne, deferred->entry());
|
||||
// Get the first of the two strings and load its instance type.
|
||||
__ ldr(string, FieldMemOperand(string, ConsString::kFirstOffset));
|
||||
|
||||
__ bind(&indirect_string_loaded);
|
||||
__ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset));
|
||||
__ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
|
||||
|
||||
// Check whether the string is sequential. The only non-sequential
|
||||
// shapes we support have just been unwrapped above.
|
||||
// Note that if the original string is a cons or slice with an external
|
||||
// string as underlying string, we pass that unpacked underlying string with
|
||||
// the adjusted index to the runtime function.
|
||||
__ bind(&check_sequential);
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ tst(result, Operand(kStringRepresentationMask));
|
||||
__ b(ne, deferred->entry());
|
||||
|
||||
// Dispatch on the encoding: ASCII or two-byte.
|
||||
Label ascii_string;
|
||||
STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
|
||||
STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
|
||||
__ tst(result, Operand(kStringEncodingMask));
|
||||
__ b(ne, &ascii_string);
|
||||
|
||||
// Two-byte string.
|
||||
// Load the two-byte character code into the result register.
|
||||
Label done;
|
||||
__ add(result,
|
||||
string,
|
||||
Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
||||
__ ldrh(result, MemOperand(result, index, LSL, 1));
|
||||
__ jmp(&done);
|
||||
|
||||
// ASCII string.
|
||||
// Load the byte into the result register.
|
||||
__ bind(&ascii_string);
|
||||
__ add(result,
|
||||
string,
|
||||
Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
|
||||
__ ldrb(result, MemOperand(result, index));
|
||||
|
||||
__ bind(&done);
|
||||
StringCharLoadGenerator::Generate(masm(),
|
||||
ToRegister(instr->string()),
|
||||
ToRegister(instr->index()),
|
||||
ToRegister(instr->result()),
|
||||
deferred->entry());
|
||||
__ bind(deferred->exit());
|
||||
}
|
||||
|
||||
|
@ -538,12 +538,12 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
// We need special handling for indirect strings.
|
||||
Label check_sequential;
|
||||
__ test(result, Immediate(kIsIndirectStringMask));
|
||||
__ j(zero, &check_sequential);
|
||||
__ j(zero, &check_sequential, Label::kNear);
|
||||
|
||||
// Dispatch on the indirect string shape: slice or cons.
|
||||
Label cons_string;
|
||||
__ test(result, Immediate(kSlicedNotConsMask));
|
||||
__ j(zero, &cons_string);
|
||||
__ j(zero, &cons_string, Label::kNear);
|
||||
|
||||
// Handle slices.
|
||||
Label indirect_string_loaded;
|
||||
@ -551,33 +551,7 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
__ SmiUntag(result);
|
||||
__ add(index, result);
|
||||
__ mov(string, FieldOperand(string, SlicedString::kParentOffset));
|
||||
__ jmp(&indirect_string_loaded);
|
||||
|
||||
// Handle external strings.
|
||||
Label external_string, ascii_external, done;
|
||||
__ bind(&external_string);
|
||||
if (FLAG_debug_code) {
|
||||
// Assert that we do not have a cons or slice (indirect strings) here.
|
||||
// Sequential strings have already been ruled out.
|
||||
__ test(result, Immediate(kIsIndirectStringMask));
|
||||
__ Assert(zero, "external string expected, but not found");
|
||||
}
|
||||
// Rule out short external strings.
|
||||
STATIC_CHECK(kShortExternalStringTag != 0);
|
||||
__ test_b(result, kShortExternalStringMask);
|
||||
__ j(not_zero, call_runtime);
|
||||
// Check encoding.
|
||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||
__ test_b(result, kStringEncodingMask);
|
||||
__ mov(result, FieldOperand(string, ExternalString::kResourceDataOffset));
|
||||
__ j(not_equal, &ascii_external, Label::kNear);
|
||||
// Two-byte string.
|
||||
__ movzx_w(result, Operand(result, index, times_2, 0));
|
||||
__ jmp(&done);
|
||||
__ bind(&ascii_external);
|
||||
// Ascii string.
|
||||
__ movzx_b(result, Operand(result, index, times_1, 0));
|
||||
__ jmp(&done);
|
||||
__ jmp(&indirect_string_loaded, Label::kNear);
|
||||
|
||||
// Handle cons strings.
|
||||
// Check whether the right hand side is the empty string (i.e. if
|
||||
@ -597,21 +571,47 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
// Distinguish sequential and external strings. Only these two string
|
||||
// representations can reach here (slices and flat cons strings have been
|
||||
// reduced to the underlying sequential or external string).
|
||||
Label seq_string;
|
||||
__ bind(&check_sequential);
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ test(result, Immediate(kStringRepresentationMask));
|
||||
__ j(not_zero, &external_string);
|
||||
__ j(zero, &seq_string, Label::kNear);
|
||||
|
||||
// Handle external strings.
|
||||
Label ascii_external, done;
|
||||
if (FLAG_debug_code) {
|
||||
// Assert that we do not have a cons or slice (indirect strings) here.
|
||||
// Sequential strings have already been ruled out.
|
||||
__ test(result, Immediate(kIsIndirectStringMask));
|
||||
__ Assert(zero, "external string expected, but not found");
|
||||
}
|
||||
// Rule out short external strings.
|
||||
STATIC_CHECK(kShortExternalStringTag != 0);
|
||||
__ test_b(result, kShortExternalStringMask);
|
||||
__ j(not_zero, call_runtime);
|
||||
// Check encoding.
|
||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||
__ test_b(result, kStringEncodingMask);
|
||||
__ mov(result, FieldOperand(string, ExternalString::kResourceDataOffset));
|
||||
__ j(not_equal, &ascii_external, Label::kNear);
|
||||
// Two-byte string.
|
||||
__ movzx_w(result, Operand(result, index, times_2, 0));
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&ascii_external);
|
||||
// Ascii string.
|
||||
__ movzx_b(result, Operand(result, index, times_1, 0));
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// Dispatch on the encoding: ASCII or two-byte.
|
||||
Label ascii_string;
|
||||
Label ascii;
|
||||
__ bind(&seq_string);
|
||||
STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
|
||||
STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
|
||||
__ test(result, Immediate(kStringEncodingMask));
|
||||
__ j(not_zero, &ascii_string, Label::kNear);
|
||||
__ j(not_zero, &ascii, Label::kNear);
|
||||
|
||||
// Two-byte string.
|
||||
// Load the two-byte character code into the result register.
|
||||
STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
|
||||
__ movzx_w(result, FieldOperand(string,
|
||||
index,
|
||||
times_2,
|
||||
@ -620,7 +620,7 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
|
||||
// Ascii string.
|
||||
// Load the byte into the result register.
|
||||
__ bind(&ascii_string);
|
||||
__ bind(&ascii);
|
||||
__ movzx_b(result, FieldOperand(string,
|
||||
index,
|
||||
times_1,
|
||||
|
@ -380,7 +380,7 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
// We need special handling for indirect strings.
|
||||
Label check_sequential;
|
||||
__ testb(result, Immediate(kIsIndirectStringMask));
|
||||
__ j(zero, &check_sequential);
|
||||
__ j(zero, &check_sequential, Label::kNear);
|
||||
|
||||
// Dispatch on the indirect string shape: slice or cons.
|
||||
Label cons_string;
|
||||
@ -394,32 +394,6 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
__ movq(string, FieldOperand(string, SlicedString::kParentOffset));
|
||||
__ jmp(&indirect_string_loaded, Label::kNear);
|
||||
|
||||
// Handle external strings.
|
||||
Label external_string, ascii_external, done;
|
||||
__ bind(&external_string);
|
||||
if (FLAG_debug_code) {
|
||||
// Assert that we do not have a cons or slice (indirect strings) here.
|
||||
// Sequential strings have already been ruled out.
|
||||
__ testb(result, Immediate(kIsIndirectStringMask));
|
||||
__ Assert(zero, "external string expected, but not found");
|
||||
}
|
||||
// Rule out short external strings.
|
||||
STATIC_CHECK(kShortExternalStringTag != 0);
|
||||
__ testb(result, Immediate(kShortExternalStringTag));
|
||||
__ j(not_zero, call_runtime);
|
||||
// Check encoding.
|
||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||
__ testb(result, Immediate(kStringEncodingMask));
|
||||
__ movq(result, FieldOperand(string, ExternalString::kResourceDataOffset));
|
||||
__ j(not_equal, &ascii_external, Label::kNear);
|
||||
// Two-byte string.
|
||||
__ movzxwl(result, Operand(result, index, times_2, 0));
|
||||
__ jmp(&done);
|
||||
__ bind(&ascii_external);
|
||||
// Ascii string.
|
||||
__ movzxbl(result, Operand(result, index, times_1, 0));
|
||||
__ jmp(&done);
|
||||
|
||||
// Handle cons strings.
|
||||
// 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
|
||||
@ -438,17 +412,44 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
// Distinguish sequential and external strings. Only these two string
|
||||
// representations can reach here (slices and flat cons strings have been
|
||||
// reduced to the underlying sequential or external string).
|
||||
Label seq_string;
|
||||
__ bind(&check_sequential);
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ testb(result, Immediate(kStringRepresentationMask));
|
||||
__ j(not_zero, &external_string);
|
||||
__ j(zero, &seq_string, Label::kNear);
|
||||
|
||||
// Handle external strings.
|
||||
Label ascii_external, done;
|
||||
if (FLAG_debug_code) {
|
||||
// Assert that we do not have a cons or slice (indirect strings) here.
|
||||
// Sequential strings have already been ruled out.
|
||||
__ testb(result, Immediate(kIsIndirectStringMask));
|
||||
__ Assert(zero, "external string expected, but not found");
|
||||
}
|
||||
// Rule out short external strings.
|
||||
STATIC_CHECK(kShortExternalStringTag != 0);
|
||||
__ testb(result, Immediate(kShortExternalStringTag));
|
||||
__ j(not_zero, call_runtime);
|
||||
// Check encoding.
|
||||
STATIC_ASSERT(kTwoByteStringTag == 0);
|
||||
__ testb(result, Immediate(kStringEncodingMask));
|
||||
__ movq(result, FieldOperand(string, ExternalString::kResourceDataOffset));
|
||||
__ j(not_equal, &ascii_external, Label::kNear);
|
||||
// Two-byte string.
|
||||
__ movzxwl(result, Operand(result, index, times_2, 0));
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&ascii_external);
|
||||
// Ascii string.
|
||||
__ movzxbl(result, Operand(result, index, times_1, 0));
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// Dispatch on the encoding: ASCII or two-byte.
|
||||
Label ascii_string;
|
||||
Label ascii;
|
||||
__ bind(&seq_string);
|
||||
STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
|
||||
STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
|
||||
__ testb(result, Immediate(kStringEncodingMask));
|
||||
__ j(not_zero, &ascii_string, Label::kNear);
|
||||
__ j(not_zero, &ascii, Label::kNear);
|
||||
|
||||
// Two-byte string.
|
||||
// Load the two-byte character code into the result register.
|
||||
@ -461,7 +462,7 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
|
||||
// ASCII string.
|
||||
// Load the byte into the result register.
|
||||
__ bind(&ascii_string);
|
||||
__ bind(&ascii);
|
||||
__ movzxbl(result, FieldOperand(string,
|
||||
index,
|
||||
times_1,
|
||||
|
Loading…
Reference in New Issue
Block a user