Porting r10023 and r10054 to x64 (pointer cache for external strings).
Review URL: http://codereview.chromium.org/8662009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10058 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
67c3cc41e2
commit
198e33560b
@ -94,23 +94,6 @@ class ElementsTransitionGenerator : public AllStatic {
|
||||
DISALLOW_COPY_AND_ASSIGN(ElementsTransitionGenerator);
|
||||
};
|
||||
|
||||
|
||||
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,
|
||||
Factory* factory,
|
||||
Register string,
|
||||
Register index,
|
||||
Register result,
|
||||
Label* call_runtime);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(StringCharLoadGenerator);
|
||||
};
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
#endif // V8_CODEGEN_H_
|
||||
|
@ -579,7 +579,7 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
__ movzx_b(result, Operand(result, index, times_1, 0));
|
||||
__ jmp(&done);
|
||||
|
||||
// Handle conses.
|
||||
// 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
|
||||
@ -594,11 +594,9 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
__ mov(result, FieldOperand(string, HeapObject::kMapOffset));
|
||||
__ movzx_b(result, FieldOperand(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.
|
||||
// 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).
|
||||
__ bind(&check_sequential);
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ test(result, Immediate(kStringRepresentationMask));
|
||||
|
@ -72,6 +72,22 @@ class CodeGenerator {
|
||||
};
|
||||
|
||||
|
||||
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,
|
||||
Factory* factory,
|
||||
Register string,
|
||||
Register index,
|
||||
Register result,
|
||||
Label* call_runtime);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(StringCharLoadGenerator);
|
||||
};
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
#endif // V8_IA32_CODEGEN_IA32_H_
|
||||
|
@ -4157,70 +4157,11 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
|
||||
__ SmiCompare(index_, FieldOperand(object_, String::kLengthOffset));
|
||||
__ j(above_equal, index_out_of_range_);
|
||||
|
||||
// We need special handling for non-flat strings.
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ testb(result_, Immediate(kStringRepresentationMask));
|
||||
__ j(zero, &flat_string);
|
||||
|
||||
// Handle non-flat strings.
|
||||
__ and_(result_, Immediate(kStringRepresentationMask));
|
||||
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
|
||||
STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
|
||||
__ cmpb(result_, Immediate(kExternalStringTag));
|
||||
__ j(greater, &sliced_string);
|
||||
__ j(equal, &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;
|
||||
__ CompareRoot(FieldOperand(object_, ConsString::kSecondOffset),
|
||||
Heap::kEmptyStringRootIndex);
|
||||
__ j(not_equal, &call_runtime_);
|
||||
// Get the first of the two parts.
|
||||
__ movq(object_, FieldOperand(object_, ConsString::kFirstOffset));
|
||||
__ jmp(&assure_seq_string, Label::kNear);
|
||||
|
||||
// SlicedString, unpack and add offset.
|
||||
__ bind(&sliced_string);
|
||||
__ addq(index_, FieldOperand(object_, SlicedString::kOffsetOffset));
|
||||
__ movq(object_, FieldOperand(object_, SlicedString::kParentOffset));
|
||||
|
||||
// Assure that we are dealing with a sequential string. Go to runtime if not.
|
||||
// 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(&assure_seq_string);
|
||||
__ movq(result_, FieldOperand(object_, HeapObject::kMapOffset));
|
||||
__ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ testb(result_, Immediate(kStringRepresentationMask));
|
||||
__ j(not_zero, &call_runtime_);
|
||||
|
||||
// Check for 1-byte or 2-byte string.
|
||||
__ bind(&flat_string);
|
||||
STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
|
||||
STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
|
||||
__ SmiToInteger32(index_, index_);
|
||||
__ testb(result_, Immediate(kStringEncodingMask));
|
||||
__ j(not_zero, &ascii_string);
|
||||
|
||||
// 2-byte string.
|
||||
// Load the 2-byte character code into the result register.
|
||||
__ movzxwl(result_, FieldOperand(object_,
|
||||
index_, times_2,
|
||||
SeqTwoByteString::kHeaderSize));
|
||||
__ jmp(&got_char_code);
|
||||
StringCharLoadGenerator::Generate(
|
||||
masm, object_, index_, result_, &call_runtime_);
|
||||
|
||||
// ASCII string.
|
||||
// Load the byte into the result register.
|
||||
__ bind(&ascii_string);
|
||||
__ movzxbl(result_, FieldOperand(object_,
|
||||
index_, times_1,
|
||||
SeqAsciiString::kHeaderSize));
|
||||
__ bind(&got_char_code);
|
||||
__ Integer32ToSmi(result_, result_);
|
||||
__ bind(&exit_);
|
||||
}
|
||||
@ -4270,6 +4211,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
__ bind(&call_runtime_);
|
||||
call_helper.BeforeCall(masm);
|
||||
__ push(object_);
|
||||
__ Integer32ToSmi(index_, index_);
|
||||
__ push(index_);
|
||||
__ CallRuntime(Runtime::kStringCharCodeAt, 2);
|
||||
if (!result_.is(rax)) {
|
||||
|
@ -367,6 +367,108 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
|
||||
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
||||
}
|
||||
|
||||
|
||||
void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
Register string,
|
||||
Register index,
|
||||
Register result,
|
||||
Label* call_runtime) {
|
||||
// Fetch the instance type of the receiver into result register.
|
||||
__ movq(result, FieldOperand(string, HeapObject::kMapOffset));
|
||||
__ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
|
||||
|
||||
// We need special handling for indirect strings.
|
||||
Label check_sequential;
|
||||
__ testb(result, Immediate(kIsIndirectStringMask));
|
||||
__ j(zero, &check_sequential);
|
||||
|
||||
// Dispatch on the indirect string shape: slice or cons.
|
||||
Label cons_string;
|
||||
__ testb(result, Immediate(kSlicedNotConsMask));
|
||||
__ j(zero, &cons_string, Label::kNear);
|
||||
|
||||
// Handle slices.
|
||||
Label indirect_string_loaded;
|
||||
__ SmiToInteger32(result, FieldOperand(string, SlicedString::kOffsetOffset));
|
||||
__ addq(index, result);
|
||||
__ 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
|
||||
// the case we would rather go to the runtime system now to flatten
|
||||
// the string.
|
||||
__ bind(&cons_string);
|
||||
__ CompareRoot(FieldOperand(string, ConsString::kSecondOffset),
|
||||
Heap::kEmptyStringRootIndex);
|
||||
__ j(not_equal, call_runtime);
|
||||
__ movq(string, FieldOperand(string, ConsString::kFirstOffset));
|
||||
|
||||
__ bind(&indirect_string_loaded);
|
||||
__ movq(result, FieldOperand(string, HeapObject::kMapOffset));
|
||||
__ movzxbl(result, FieldOperand(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).
|
||||
__ bind(&check_sequential);
|
||||
STATIC_ASSERT(kSeqStringTag == 0);
|
||||
__ testb(result, Immediate(kStringRepresentationMask));
|
||||
__ j(not_zero, &external_string);
|
||||
|
||||
// Dispatch on the encoding: ASCII or two-byte.
|
||||
Label ascii_string;
|
||||
STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
|
||||
STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
|
||||
__ testb(result, Immediate(kStringEncodingMask));
|
||||
__ j(not_zero, &ascii_string, Label::kNear);
|
||||
|
||||
// Two-byte string.
|
||||
// Load the two-byte character code into the result register.
|
||||
STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
|
||||
__ movzxwl(result, FieldOperand(string,
|
||||
index,
|
||||
times_2,
|
||||
SeqTwoByteString::kHeaderSize));
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// ASCII string.
|
||||
// Load the byte into the result register.
|
||||
__ bind(&ascii_string);
|
||||
__ movzxbl(result, FieldOperand(string,
|
||||
index,
|
||||
times_1,
|
||||
SeqAsciiString::kHeaderSize));
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -69,6 +69,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_X64_CODEGEN_X64_H_
|
||||
|
@ -3306,84 +3306,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.
|
||||
__ movq(result, FieldOperand(string, HeapObject::kMapOffset));
|
||||
__ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
|
||||
|
||||
// We need special handling for indirect strings.
|
||||
Label check_sequential;
|
||||
__ testb(result, Immediate(kIsIndirectStringMask));
|
||||
__ j(zero, &check_sequential, Label::kNear);
|
||||
|
||||
// Dispatch on the indirect string shape: slice or cons.
|
||||
Label cons_string;
|
||||
__ testb(result, Immediate(kSlicedNotConsMask));
|
||||
__ j(zero, &cons_string, Label::kNear);
|
||||
|
||||
// Handle slices.
|
||||
Label indirect_string_loaded;
|
||||
__ SmiToInteger32(result, FieldOperand(string, SlicedString::kOffsetOffset));
|
||||
__ addq(index, result);
|
||||
__ movq(string, FieldOperand(string, SlicedString::kParentOffset));
|
||||
__ jmp(&indirect_string_loaded, Label::kNear);
|
||||
|
||||
// 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);
|
||||
__ CompareRoot(FieldOperand(string, ConsString::kSecondOffset),
|
||||
Heap::kEmptyStringRootIndex);
|
||||
__ j(not_equal, deferred->entry());
|
||||
__ movq(string, FieldOperand(string, ConsString::kFirstOffset));
|
||||
|
||||
__ bind(&indirect_string_loaded);
|
||||
__ movq(result, FieldOperand(string, HeapObject::kMapOffset));
|
||||
__ movzxbl(result, FieldOperand(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);
|
||||
__ testb(result, Immediate(kStringRepresentationMask));
|
||||
__ j(not_zero, deferred->entry());
|
||||
|
||||
// Dispatch on the encoding: ASCII or two-byte.
|
||||
Label ascii_string;
|
||||
STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
|
||||
STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
|
||||
__ testb(result, Immediate(kStringEncodingMask));
|
||||
__ j(not_zero, &ascii_string, Label::kNear);
|
||||
|
||||
// Two-byte string.
|
||||
// Load the two-byte character code into the result register.
|
||||
Label done;
|
||||
STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
|
||||
__ movzxwl(result, FieldOperand(string,
|
||||
index,
|
||||
times_2,
|
||||
SeqTwoByteString::kHeaderSize));
|
||||
__ jmp(&done, Label::kNear);
|
||||
|
||||
// ASCII string.
|
||||
// Load the byte into the result register.
|
||||
__ bind(&ascii_string);
|
||||
__ movzxbl(result, FieldOperand(string,
|
||||
index,
|
||||
times_1,
|
||||
SeqAsciiString::kHeaderSize));
|
||||
__ bind(&done);
|
||||
StringCharLoadGenerator::Generate(masm(),
|
||||
ToRegister(instr->string()),
|
||||
ToRegister(instr->index()),
|
||||
ToRegister(instr->result()),
|
||||
deferred->entry());
|
||||
__ bind(deferred->exit());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user