Commit 9e1a7e2e authored by yangguo@chromium.org's avatar yangguo@chromium.org

Unify code for fast and slow path of JSON.stringify.

R=verwaest@chromium.org
BUG=

Review URL: https://chromiumcodereview.appspot.com/12690017

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14023 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 53adf3b1
......@@ -220,6 +220,7 @@ namespace internal {
V(undefined_string, "undefined") \
V(value_of_string, "valueOf") \
V(stack_string, "stack") \
V(toJSON_string, "toJSON") \
V(InitializeVarGlobal_string, "InitializeVarGlobal") \
V(InitializeConstGlobal_string, "InitializeConstGlobal") \
V(KeyedLoadElementMonomorphic_string, \
......
......@@ -41,6 +41,9 @@ class BasicJsonStringifier BASE_EMBEDDED {
MaybeObject* Stringify(Handle<Object> object);
INLINE(static MaybeObject* StringifyString(Isolate* isolate,
Handle<String> object));
private:
static const int kInitialPartLength = 32;
static const int kMaxPartLength = 16 * 1024;
......@@ -84,6 +87,11 @@ class BasicJsonStringifier BASE_EMBEDDED {
bool deferred_comma,
bool deferred_key);
template <typename StringType>
INLINE(static MaybeObject* StringifyString_(Isolate* isolate,
Handle<String> string,
Handle<String> result));
// Entry point to serialize the object.
INLINE(Result SerializeObject(Handle<Object> obj)) {
return Serialize_<false>(obj, false, factory_->empty_string());
......@@ -135,7 +143,7 @@ class BasicJsonStringifier BASE_EMBEDDED {
void SerializeString(Handle<String> object);
template <typename SrcChar, typename DestChar>
INLINE(void SerializeStringUnchecked_(const SrcChar* src,
INLINE(static int SerializeStringUnchecked_(const SrcChar* src,
DestChar* dest,
int length));
......@@ -143,10 +151,10 @@ class BasicJsonStringifier BASE_EMBEDDED {
INLINE(void SerializeString_(Handle<String> string));
template <typename Char>
INLINE(bool DoNotEscape(Char c));
INLINE(static bool DoNotEscape(Char c));
template <typename Char>
INLINE(Vector<const Char> GetCharVector(Handle<String> string));
INLINE(static Vector<const Char> GetCharVector(Handle<String> string));
Result StackPush(Handle<Object> object);
void StackPop();
......@@ -244,15 +252,15 @@ const char* const BasicJsonStringifier::JsonEscapeTable =
"\370\0 \371\0 \372\0 \373\0 "
"\374\0 \375\0 \376\0 \377\0 ";
BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate)
: isolate_(isolate), current_index_(0), is_ascii_(true) {
factory_ = isolate_->factory();
accumulator_store_ = Handle<JSValue>::cast(
factory_->ToObject(factory_->empty_string()));
part_length_ = kInitialPartLength;
current_part_ = factory_->NewRawOneByteString(kInitialPartLength);
tojson_string_ =
factory_->InternalizeOneByteString(STATIC_ASCII_VECTOR("toJSON"));
current_part_ = factory_->NewRawOneByteString(part_length_);
tojson_string_ = factory_->toJSON_string();
stack_ = factory_->NewJSArray(8);
}
......@@ -275,6 +283,57 @@ MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) {
}
MaybeObject* BasicJsonStringifier::StringifyString(Isolate* isolate,
Handle<String> object) {
static const int kJsonQuoteWorstCaseBlowup = 6;
static const int kSpaceForQuotes = 2;
int worst_case_length =
object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes;
if (worst_case_length > 32 * KB) { // Slow path if too large.
BasicJsonStringifier stringifier(isolate);
return stringifier.Stringify(object);
}
object = FlattenGetString(object);
if (object->IsSeqOneByteString()) {
return StringifyString_<SeqOneByteString>(
isolate,
object,
isolate->factory()->NewRawOneByteString(worst_case_length));
} else {
return StringifyString_<SeqTwoByteString>(
isolate,
object,
isolate->factory()->NewRawTwoByteString(worst_case_length));
}
}
template <typename StringType>
MaybeObject* BasicJsonStringifier::StringifyString_(Isolate* isolate,
Handle<String> string,
Handle<String> result) {
AssertNoAllocation no_allocation;
int final_size = 0;
StringType* dest = StringType::cast(*result);
dest->Set(final_size++, '\"');
final_size += SerializeStringUnchecked_(StringType::cast(*string)->GetChars(),
dest->GetChars() + 1,
string->length());
dest->Set(final_size++, '\"');
if (isolate->heap()->InNewSpace(*result)) {
// In new space, simply lower the allocation top to fit the actual size.
isolate->heap()->new_space()->ShrinkStringAtAllocationBoundary<StringType>(
*result, final_size);
return *result;
} else {
// Not in new space, need to fill the wasted space with filler objects.
return SeqString::cast(*result)->Truncate(final_size);
}
}
template <bool is_ascii, typename Char>
void BasicJsonStringifier::Append_(Char c) {
if (is_ascii) {
......@@ -667,10 +726,9 @@ void BasicJsonStringifier::ChangeEncoding() {
template <typename SrcChar, typename DestChar>
void BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src,
int BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src,
DestChar* dest,
int length) {
dest += current_index_;
DestChar* dest_start = dest;
// Assert that uc16 character is not truncated down to 8 bit.
......@@ -688,7 +746,7 @@ void BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src,
}
}
current_index_ += static_cast<int>(dest - dest_start);
return static_cast<int>(dest - dest_start);
}
......@@ -705,14 +763,14 @@ void BasicJsonStringifier::SerializeString_(Handle<String> string) {
AssertNoAllocation no_allocation;
Vector<const Char> vector = GetCharVector<Char>(string);
if (is_ascii) {
SerializeStringUnchecked_(
current_index_ += SerializeStringUnchecked_(
vector.start(),
SeqOneByteString::cast(*current_part_)->GetChars(),
SeqOneByteString::cast(*current_part_)->GetChars() + current_index_,
length);
} else {
SerializeStringUnchecked_(
current_index_ += SerializeStringUnchecked_(
vector.start(),
SeqTwoByteString::cast(*current_part_)->GetChars(),
SeqTwoByteString::cast(*current_part_)->GetChars() + current_index_,
length);
}
} else {
......
This diff is collapsed.
......@@ -195,8 +195,6 @@ namespace internal {
F(ParseJson, 1, 1) \
F(BasicJSONStringify, 1, 1) \
F(QuoteJSONString, 1, 1) \
F(QuoteJSONStringComma, 1, 1) \
F(QuoteJSONStringArray, 1, 1) \
\
/* Strings */ \
F(StringCharCodeAt, 2, 1) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment