Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(755)

Unified Diff: src/json-parser.h

Issue 13741010: Eagerly parse expected transitions in JSON. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add assert Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/objects.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/json-parser.h
diff --git a/src/json-parser.h b/src/json-parser.h
index ac34c59b23e096c52ac14e13977a55a492629ddf..74850cae253aab2cabcdc5a7138052e2cf0c84c5 100644
--- a/src/json-parser.h
+++ b/src/json-parser.h
@@ -102,9 +102,37 @@ class JsonParser BASE_EMBEDDED {
Handle<String> ParseJsonString() {
return ScanJsonString<false>();
}
+
+ bool ParseJsonString(Handle<String> expected) {
+ int length = expected->length();
+ if (source_->length() - position_ - 1 > length) {
+ AssertNoAllocation no_gc;
+ String::FlatContent content = expected->GetFlatContent();
+ if (content.IsAscii()) {
+ ASSERT_EQ('"', c0_);
+ const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1;
+ const uint8_t* expected_chars = content.ToOneByteVector().start();
+ for (int i = 0; i < length; i++) {
+ uint8_t c0 = input_chars[i];
+ if (c0 != expected_chars[i] ||
+ c0 == '"' || c0 < 0x20 || c0 == '\\') {
+ return false;
+ }
+ }
+ if (input_chars[length] == '"') {
+ position_ = position_ + length + 1;
+ AdvanceSkipWhitespace();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
Handle<String> ParseJsonInternalizedString() {
return ScanJsonString<true>();
}
+
template <bool is_internalized>
Handle<String> ScanJsonString();
// Creates a new string and copies prefix[start..end] into the beginning
@@ -294,8 +322,13 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
HandleScope scope(isolate());
Handle<JSObject> json_object =
factory()->NewJSObject(object_constructor(), pretenure_);
+ Handle<Map> map(json_object->map());
+ ZoneScope zone_scope(zone(), DELETE_ON_EXIT);
+ ZoneList<Handle<Object> > properties(8, zone());
ASSERT_EQ(c0_, '{');
+ bool transitioning = true;
+
AdvanceSkipWhitespace();
if (c0_ != '}') {
do {
@@ -339,24 +372,75 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
c0_ = '"';
#endif
- Handle<String> key = ParseJsonInternalizedString();
- if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
+ Handle<String> key;
+ Handle<Object> value;
+
+ // Try to follow existing transitions as long as possible. Once we stop
+ // transitioning, no transition can be found anymore.
+ if (transitioning) {
+ // First check whether there is a single expected transition. If so, try
+ // to parse it first.
+ bool follow_expected = false;
+ if (seq_ascii) {
+ key = JSObject::ExpectedTransitionKey(map);
+ follow_expected = !key.is_null() && ParseJsonString(key);
+ }
+ // If the expected transition hits, follow it.
+ if (follow_expected) {
+ map = JSObject::ExpectedTransitionTarget(map);
+ } else {
+ // If the expected transition failed, parse an internalized string and
+ // try to find a matching transition.
+ key = ParseJsonInternalizedString();
+ if (key.is_null()) return ReportUnexpectedCharacter();
+
+ Handle<Map> target = JSObject::FindTransitionToField(map, key);
+ // If a transition was found, follow it and continue.
+ if (!target.is_null()) {
+ map = target;
+ } else {
+ // If no transition was found, commit the intermediate state to the
+ // object and stop transitioning.
+ JSObject::TransitionToMap(json_object, map);
+ int length = properties.length();
+ for (int i = 0; i < length; i++) {
+ json_object->FastPropertyAtPut(i, *properties[i]);
+ }
+ transitioning = false;
+ }
+ }
+ if (c0_ != ':') return ReportUnexpectedCharacter();
- AdvanceSkipWhitespace();
- Handle<Object> value = ParseJsonValue();
- if (value.is_null()) return ReportUnexpectedCharacter();
+ AdvanceSkipWhitespace();
+ value = ParseJsonValue();
+ if (value.is_null()) return ReportUnexpectedCharacter();
- if (JSObject::TryTransitionToField(json_object, key)) {
- int index = json_object->LastAddedFieldIndex();
- json_object->FastPropertyAtPut(index, *value);
+ properties.Add(value, zone());
+ if (transitioning) continue;
} else {
- JSObject::SetLocalPropertyIgnoreAttributes(
- json_object, key, value, NONE);
+ key = ParseJsonInternalizedString();
+ if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
+
+ AdvanceSkipWhitespace();
+ value = ParseJsonValue();
+ if (value.is_null()) return ReportUnexpectedCharacter();
}
+
+ JSObject::SetLocalPropertyIgnoreAttributes(
+ json_object, key, value, NONE);
} while (MatchSkipWhiteSpace(','));
if (c0_ != '}') {
return ReportUnexpectedCharacter();
}
+
+ // If we transitioned until the very end, transition the map now.
+ if (transitioning) {
+ JSObject::TransitionToMap(json_object, map);
+ int length = properties.length();
+ for (int i = 0; i < length; i++) {
+ json_object->FastPropertyAtPut(i, *properties[i]);
+ }
+ }
}
AdvanceSkipWhitespace();
return scope.CloseAndEscape(json_object);
@@ -644,22 +728,32 @@ Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
uint32_t capacity = string_table->Capacity();
uint32_t entry = StringTable::FirstProbe(hash, capacity);
uint32_t count = 1;
+ Handle<String> result;
while (true) {
Object* element = string_table->KeyAt(entry);
if (element == isolate()->heap()->undefined_value()) {
// Lookup failure.
+ result = factory()->InternalizeOneByteString(
+ seq_source_, position_, length);
break;
}
if (element != isolate()->heap()->the_hole_value() &&
String::cast(element)->IsOneByteEqualTo(string_vector)) {
- // Lookup success, update the current position.
- position_ = position;
- // Advance past the last '"'.
- AdvanceSkipWhitespace();
- return Handle<String>(String::cast(element), isolate());
+ result = Handle<String>(String::cast(element), isolate());
+#ifdef DEBUG
+ uint32_t hash_field =
+ (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
+ ASSERT_EQ(static_cast<int>(result->Hash()),
+ static_cast<int>(hash_field >> String::kHashShift));
+#endif
+ break;
}
entry = StringTable::NextProbe(entry, count++, capacity);
}
+ position_ = position;
+ // Advance past the last '"'.
+ AdvanceSkipWhitespace();
+ return result;
}
int beg_pos = position_;
@@ -682,14 +776,10 @@ Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
}
} while (c0_ != '"');
int length = position_ - beg_pos;
- Handle<String> result;
- if (seq_ascii && is_internalized) {
- result = factory()->InternalizeOneByteString(seq_source_, beg_pos, length);
- } else {
- result = factory()->NewRawOneByteString(length, pretenure_);
- uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
- String::WriteToFlat(*source_, dest, beg_pos, position_);
- }
+ Handle<String> result = factory()->NewRawOneByteString(length, pretenure_);
+ uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
+ String::WriteToFlat(*source_, dest, beg_pos, position_);
+
ASSERT_EQ('"', c0_);
// Advance past the last '"'.
AdvanceSkipWhitespace();
« no previous file with comments | « no previous file | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698