[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));