[es6] Fix RegExp built-in subclassing.
1) The Map::CopyInitialMap() did not set descriptor's array if
the source initial map had one.
2) Subclasses are temporarily disallowed to have more in-object
properties than the parent class (for GC reasons).
BUG=v8:3101, v8:3330, v8:4531
LOG=N
Review URL: https://codereview.chromium.org/1431593003
Cr-Commit-Position: refs/heads/master@{#31743}
diff --git a/src/objects.cc b/src/objects.cc
index 12404df..ecd31f7 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -8221,6 +8221,19 @@
result->SetInObjectProperties(in_object_properties);
result->set_unused_property_fields(unused_property_fields);
+ int number_of_own_descriptors = map->NumberOfOwnDescriptors();
+ if (number_of_own_descriptors > 0) {
+ DCHECK(map->owns_descriptors());
+ // The copy will use the same descriptors array, but it's not the owner.
+ result->UpdateDescriptors(map->instance_descriptors(),
+ map->layout_descriptor());
+ result->set_owns_descriptors(false);
+ result->SetNumberOfOwnDescriptors(number_of_own_descriptors);
+
+ DCHECK_EQ(result->NumberOfFields(),
+ in_object_properties - unused_property_fields);
+ }
+
return result;
}
@@ -11904,17 +11917,25 @@
// Finally link initial map and constructor function if the original
// constructor is actually a subclass constructor.
if (IsSubclassConstructor(original_constructor->shared()->kind())) {
+// TODO(ishell): v8:4531, allow ES6 built-ins subclasses to have
+// in-object properties.
+#if 0
InstanceType instance_type = constructor_initial_map->instance_type();
int internal_fields =
JSObject::GetInternalFieldCount(*constructor_initial_map);
+ int pre_allocated = constructor_initial_map->GetInObjectProperties() -
+ constructor_initial_map->unused_property_fields();
int instance_size;
int in_object_properties;
original_constructor->CalculateInstanceSizeForDerivedClass(
instance_type, internal_fields, &instance_size, &in_object_properties);
+ int unused_property_fields = in_object_properties - pre_allocated;
Handle<Map> map =
Map::CopyInitialMap(constructor_initial_map, instance_size,
- in_object_properties, in_object_properties);
+ in_object_properties, unused_property_fields);
+#endif
+ Handle<Map> map = Map::CopyInitialMap(constructor_initial_map);
JSFunction::SetInitialMap(original_constructor, map, prototype);
map->SetConstructor(*constructor);
diff --git a/test/mjsunit/es6/classes-subclass-builtins.js b/test/mjsunit/es6/classes-subclass-builtins.js
index 175d0dc..5404863 100644
--- a/test/mjsunit/es6/classes-subclass-builtins.js
+++ b/test/mjsunit/es6/classes-subclass-builtins.js
@@ -23,6 +23,7 @@
assertTrue(%IsConstructCall());
super(...args);
this.a = 42;
+ this.d = 4.2;
}
}
@@ -34,6 +35,7 @@
checkPrototypeChain(o, [A, Boolean]);
assertTrue(o.valueOf());
assertEquals(42, o.a);
+ assertEquals(4.2, o.d);
var o1 = new A(false);
assertTrue(%HaveSameMap(o, o1));
@@ -46,6 +48,7 @@
assertTrue(%IsConstructCall());
super(...args);
this.a = 42;
+ this.d = 4.2;
}
}
@@ -63,6 +66,7 @@
assertEquals("message", o.message);
assertEquals(error.name + ": message", o.toString());
assertEquals(42, o.a);
+ assertEquals(4.2, o.d);
var o1 = new A("achtung!");
assertTrue(%HaveSameMap(o, o1));
@@ -86,6 +90,7 @@
assertTrue(%IsConstructCall());
super(...args);
this.a = 42;
+ this.d = 4.2;
}
}
@@ -97,6 +102,7 @@
checkPrototypeChain(o, [A, Number, Object]);
assertEquals(153, o.valueOf());
assertEquals(42, o.a);
+ assertEquals(4.2, o.d);
var o1 = new A(312);
assertTrue(%HaveSameMap(o, o1));
@@ -109,6 +115,7 @@
assertTrue(%IsConstructCall());
super(...args);
this.a = 42;
+ this.d = 4.2;
}
}
@@ -120,6 +127,7 @@
checkPrototypeChain(o, [A, Date, Object]);
assertEquals(1234567890, o.getTime());
assertEquals(42, o.a);
+ assertEquals(4.2, o.d);
var o1 = new A(2015, 10, 29);
assertEquals(2015, o1.getFullYear());
@@ -135,6 +143,7 @@
assertTrue(%IsConstructCall());
super(...args);
this.a = 42;
+ this.d = 4.2;
}
}
@@ -147,6 +156,7 @@
assertEquals("foo", o.valueOf());
assertEquals(42, o.a);
+ assertEquals(4.2, o.d);
var o1 = new A("bar");
assertTrue(%HaveSameMap(o, o1));
@@ -159,17 +169,25 @@
assertTrue(%IsConstructCall());
super(...args);
this.a = 42;
+ this.d = 4.2;
}
}
- var o = new A("o..h");
+ var o = new A("o(..)h", "g");
assertTrue(o instanceof Object);
assertTrue(o instanceof RegExp);
assertTrue(o instanceof A);
assertEquals("object", typeof o);
checkPrototypeChain(o, [A, RegExp, Object]);
assertTrue(o.test("ouch"));
+ assertArrayEquals(["ouch", "uc"], o.exec("boom! ouch! bam!"));
+ assertEquals("o(..)h", o.source);
+ assertTrue(o.global);
+ assertFalse(o.ignoreCase);
+ assertFalse(o.multiline);
+ assertEquals(10, o.lastIndex);
assertEquals(42, o.a);
+ assertEquals(4.2, o.d);
var o1 = new A(7);
assertTrue(%HaveSameMap(o, o1));
@@ -182,6 +200,7 @@
assertTrue(%IsConstructCall());
super(...args);
this.a = 42;
+ this.d = 4.2;
}
}
@@ -200,6 +219,7 @@
checkPrototypeChain(o, [A, array, Object]);
assertEquals(10, o.length);
assertEquals(42, o.a);
+ assertEquals(4.2, o.d);
var o1 = new A(7);
assertTrue(%HaveSameMap(o, o1));
@@ -226,6 +246,7 @@
assertTrue(%IsConstructCall());
super(...args);
this.a = 42;
+ this.d = 4.2;
}
}
@@ -238,6 +259,7 @@
assertEquals(16, o.byteLength);
assertEquals(42, o.a);
+ assertEquals(4.2, o.d);
var o1 = new A("bar");
assertTrue(%HaveSameMap(o, o1));
@@ -278,6 +300,7 @@
assertTrue(%IsConstructCall());
super(...args);
this.a = 42;
+ this.d = 4.2;
}
}
@@ -293,6 +316,7 @@
assertEquals(0xcafebabe, o.getUint32(0, false));
assertEquals(0xbebafeca, o.getUint32(0, true));
assertEquals(42, o.a);
+ assertEquals(4.2, o.d);
var o1 = new A(buffer);
assertTrue(%HaveSameMap(o, o1));