Reviewers: Toon Verwaest,
Message:
PTAL
Description:
Fixed mutable heap numbers leak in JSON parser.
BUG=chromium:423687
LOG=N
Please review this at https://codereview.chromium.org/669403002/
Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files (+57, -20 lines):
M src/json-parser.h
A + test/mjsunit/regress/regress-crbug-423687.js
Index: src/json-parser.h
diff --git a/src/json-parser.h b/src/json-parser.h
index
d3148c9e21ed295fb8d8bace1924eb080be2e680..fdbdfca2d9c420f0e8760a9fb6bfacc66cdd28c2
100644
--- a/src/json-parser.h
+++ b/src/json-parser.h
@@ -182,6 +182,9 @@ class JsonParser BASE_EMBEDDED {
private:
Zone* zone() { return &zone_; }
+ void CommitStateToJsonObject(Handle<JSObject> json_object, Handle<Map>
map,
+ ZoneList<Handle<Object> >* properties);
+
Handle<String> source_;
int source_length_;
Handle<SeqOneByteString> seq_source_;
@@ -410,13 +413,7 @@ Handle<Object>
JsonParser<seq_one_byte>::ParseJsonObject() {
}
// Commit the intermediate state to the object and stop
transitioning.
- JSObject::AllocateStorageForMap(json_object, map);
- int length = properties.length();
- for (int i = 0; i < length; i++) {
- Handle<Object> value = properties[i];
- FieldIndex index = FieldIndex::ForPropertyIndex(*map, i);
- json_object->FastPropertyAtPut(index, *value);
- }
+ CommitStateToJsonObject(json_object, map, &properties);
} else {
key = ParseJsonInternalizedString();
if (key.is_null() || c0_ != ':') return
ReportUnexpectedCharacter();
@@ -434,19 +431,60 @@ Handle<Object>
JsonParser<seq_one_byte>::ParseJsonObject() {
// If we transitioned until the very end, transition the map now.
if (transitioning) {
- JSObject::AllocateStorageForMap(json_object, map);
- int length = properties.length();
- for (int i = 0; i < length; i++) {
- Handle<Object> value = properties[i];
- FieldIndex index = FieldIndex::ForPropertyIndex(*map, i);
- json_object->FastPropertyAtPut(index, *value);
- }
+ CommitStateToJsonObject(json_object, map, &properties);
}
}
AdvanceSkipWhitespace();
return scope.CloseAndEscape(json_object);
}
+
+template <bool seq_one_byte>
+void JsonParser<seq_one_byte>::CommitStateToJsonObject(
+ Handle<JSObject> json_object, Handle<Map> map,
+ ZoneList<Handle<Object> >* properties) {
+ JSObject::AllocateStorageForMap(json_object, map);
+
+ DisallowHeapAllocation no_gc;
+ Factory* factory = isolate()->factory();
+ // If the |json_object|'s map is exactly the same as |map| then the
+ // |properties| values correspond to the |map| and nothing more has to be
+ // done. But if the |json_object|'s map is different then we have to
+ // iterate descriptors to ensure that properties still correspond to the
+ // map.
+ bool slow_case = json_object->map() != *map;
+ DescriptorArray* descriptors = NULL;
+ int descriptor = 0;
+ if (slow_case) {
+ descriptors = json_object->map()->instance_descriptors();
+ }
+
+ int length = properties->length();
+ DCHECK(json_object->map()->NumberOfFields() == length);
+ for (int i = 0; i < length; i++) {
+ Handle<Object> value = (*properties)[i];
+ if (slow_case) {
+ // Skip non-field descriptors.
+ Representation representation;
+ for (;; descriptor++) {
+ PropertyDetails details = descriptors->GetDetails(descriptor);
+ if (details.type() == FIELD) {
+ representation = details.representation();
+ break;
+ }
+ }
+ // Turn mutable heap numbers into immutable if the field
representation
+ // is not double.
+ if (value->IsMutableHeapNumber() && !representation.IsDouble()) {
+ HeapNumber::cast(*value)->set_map(*factory->heap_number_map());
+ }
+ }
+ FieldIndex index = FieldIndex::ForPropertyIndex(*map, i);
+ json_object->FastPropertyAtPut(index, *value);
+ }
+}
+
+
// Parse a JSON array. Position must be right at '['.
template <bool seq_one_byte>
Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
Index: test/mjsunit/regress/regress-crbug-423687.js
diff --git a/test/mjsunit/regress/regress-355486.js
b/test/mjsunit/regress/regress-crbug-423687.js
similarity index 57%
copy from test/mjsunit/regress/regress-355486.js
copy to test/mjsunit/regress/regress-crbug-423687.js
index
55362a13416335b72bfa1ff92bc29f7a04edbd65..9284e69d3710fb05d23ef3f3f7a7ec21a3f2ea5e
100644
--- a/test/mjsunit/regress/regress-355486.js
+++ b/test/mjsunit/regress/regress-crbug-423687.js
@@ -4,10 +4,9 @@
// Flags: --allow-natives-syntax
-function f() { var v = arguments[0]; }
-function g() { f(); }
+var json = '{"a":{"c":2.1,"d":0},"b":{"c":7,"1024":8}}';
+var data = JSON.parse(json);
-g();
-g();
-%OptimizeFunctionOnNextCall(g);
-g();
+// %DebugPrint(data.b);
+// %DebugPrint(data.b.c);
+data.b.c++;
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.