Reviewers: Toon Verwaest,

Message:
PTAL. This is split out from https://codereview.chromium.org/908213002/.

Description:
Handlify Map::SetPrototype()

Please review this at https://codereview.chromium.org/1005393004/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+56, -42 lines):
  M src/bootstrapper.cc
  M src/factory.cc
  M src/objects.h
  M src/objects.cc
  M src/runtime/runtime-classes.cc
  M src/runtime/runtime-debug.cc
  M test/cctest/test-heap.cc


Index: src/bootstrapper.cc
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 963336a79ca68a9036e3c11b9b0d3e5eff39b0b1..814009118d545c8ad0d62a09d281da54a90b36c9 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -329,7 +329,7 @@ static void SetObjectPrototype(Handle<JSObject> object, Handle<Object> proto) {
   // object.__proto__ = proto;
   Handle<Map> old_map = Handle<Map>(object->map());
   Handle<Map> new_map = Map::Copy(old_map, "SetObjectPrototype");
-  new_map->SetPrototype(proto, FAST_PROTOTYPE);
+  Map::SetPrototype(new_map, proto, FAST_PROTOTYPE);
   JSObject::MigrateToMap(object, new_map);
 }

@@ -509,7 +509,7 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
   Handle<Map> empty_function_map =
       CreateSloppyFunctionMap(FUNCTION_WITHOUT_PROTOTYPE);
   DCHECK(!empty_function_map->is_dictionary_map());
-  empty_function_map->SetPrototype(object_function_prototype);
+  Map::SetPrototype(empty_function_map, object_function_prototype);
   empty_function_map->set_is_prototype_map(true);
   empty_function->set_map(*empty_function_map);

@@ -523,10 +523,13 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
   empty_function->shared()->DontAdaptArguments();

   // Set prototypes for the function maps.
-  native_context()->sloppy_function_map()->SetPrototype(empty_function);
-  native_context()->sloppy_function_without_prototype_map()->SetPrototype(
-      empty_function);
-  sloppy_function_map_writable_prototype_->SetPrototype(empty_function);
+  Handle<Map> sloppy_function_map(native_context()->sloppy_function_map(),
+                                  isolate);
+  Handle<Map> sloppy_function_without_prototype_map(
+      native_context()->sloppy_function_without_prototype_map(), isolate);
+  Map::SetPrototype(sloppy_function_map, empty_function);
+  Map::SetPrototype(sloppy_function_without_prototype_map, empty_function);
+ Map::SetPrototype(sloppy_function_map_writable_prototype_, empty_function);
   return empty_function;
 }

@@ -654,7 +657,7 @@ Handle<Map> Genesis::CreateStrictFunctionMap(
   Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
   SetStrictFunctionInstanceDescriptor(map, function_mode);
map->set_function_with_prototype(IsFunctionModeWithPrototype(function_mode));
-  map->SetPrototype(empty_function);
+  Map::SetPrototype(map, empty_function);
   return map;
 }

@@ -664,7 +667,7 @@ Handle<Map> Genesis::CreateStrongFunctionMap(
   Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
   SetStrongFunctionInstanceDescriptor(map);
   map->set_function_with_prototype(is_constructor);
-  map->SetPrototype(empty_function);
+  Map::SetPrototype(map, empty_function);
   map->set_is_extensible(is_constructor);
   // TODO(rossberg): mark strong
   return map;
@@ -1124,7 +1127,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
                                  Smi::FromInt(0),
                                  SKIP_WRITE_BARRIER);  // It's a Smi.
     proto_map->set_is_prototype_map(true);
-    initial_map->SetPrototype(proto);
+    Map::SetPrototype(initial_map, proto);
     factory->SetRegExpIrregexpData(Handle<JSRegExp>::cast(proto),
JSRegExp::IRREGEXP, factory->empty_string(),
                                    JSRegExp::Flags(0), 0);
@@ -1313,7 +1316,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
     map->set_function_with_prototype(true);
     DCHECK_EQ(native_context()->object_function()->prototype(),
               *isolate->initial_object_prototype());
-    map->SetPrototype(isolate->initial_object_prototype());
+    Map::SetPrototype(map, isolate->initial_object_prototype());
     map->set_pre_allocated_property_fields(1);
     map->set_inobject_properties(1);

@@ -2035,7 +2038,7 @@ bool Genesis::InstallNatives() {
     // maps in the native context.
     Handle<Map> generator_function_map =
Map::Copy(sloppy_function_map_writable_prototype_, "GeneratorFunction");
-    generator_function_map->SetPrototype(generator_function_prototype);
+ Map::SetPrototype(generator_function_map, generator_function_prototype);
     native_context()->set_sloppy_generator_function_map(
         *generator_function_map);

@@ -2068,20 +2071,23 @@ bool Genesis::InstallNatives() {
     Handle<Map> strict_generator_function_map =
         Map::Copy(strict_function_map, "StrictGeneratorFunction");
     // "arguments" and "caller" already poisoned.
- strict_generator_function_map->SetPrototype(generator_function_prototype);
+    Map::SetPrototype(strict_generator_function_map,
+                      generator_function_prototype);
     native_context()->set_strict_generator_function_map(
         *strict_generator_function_map);

Handle<Map> strong_function_map(native_context()->strong_function_map());
     Handle<Map> strong_generator_function_map =
         Map::Copy(strong_function_map, "StrongGeneratorFunction");
- strong_generator_function_map->SetPrototype(generator_function_prototype);
+    Map::SetPrototype(strong_generator_function_map,
+                      generator_function_prototype);
     native_context()->set_strong_generator_function_map(
         *strong_generator_function_map);

Handle<JSFunction> object_function(native_context()->object_function());
     Handle<Map> generator_object_prototype_map = Map::Create(isolate(), 0);
- generator_object_prototype_map->SetPrototype(generator_object_prototype);
+    Map::SetPrototype(generator_object_prototype_map,
+                      generator_object_prototype);
     native_context()->set_generator_object_prototype_map(
         *generator_object_prototype_map);
   }
@@ -2183,7 +2189,7 @@ bool Genesis::InstallNatives() {

     // Set prototype on map.
     initial_map->set_non_instance_prototype(false);
-    initial_map->SetPrototype(array_prototype);
+    Map::SetPrototype(initial_map, array_prototype);

// Update map with length accessor from Array and add "index" and "input".
     Map::EnsureDescriptorSlack(initial_map, 3);
Index: src/factory.cc
diff --git a/src/factory.cc b/src/factory.cc
index 59f9d68727b8d0bb84adf1f0ca429b85e99a84fe..b940f80531c9f424f43afc4ecb250d339a7fdff3 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -1869,7 +1869,7 @@ Handle<JSProxy> Factory::NewJSProxy(Handle<Object> handler, // TODO(rossberg): Once we optimize proxies, think about a scheme to share
   // maps. Will probably depend on the identity of the handler object, too.
   Handle<Map> map = NewMap(JS_PROXY_TYPE, JSProxy::kSize);
-  map->SetPrototype(prototype);
+  Map::SetPrototype(map, prototype);

   // Allocate the proxy object.
   Handle<JSProxy> result = New<JSProxy>(map, NEW_SPACE);
@@ -1888,7 +1888,7 @@ Handle<JSProxy> Factory::NewJSFunctionProxy(Handle<Object> handler, // TODO(rossberg): Once we optimize proxies, think about a scheme to share
   // maps. Will probably depend on the identity of the handler object, too.
   Handle<Map> map = NewMap(JS_FUNCTION_PROXY_TYPE, JSFunctionProxy::kSize);
-  map->SetPrototype(prototype);
+  Map::SetPrototype(map, prototype);

   // Allocate the proxy object.
   Handle<JSFunctionProxy> result = New<JSFunctionProxy>(map, NEW_SPACE);
@@ -1913,7 +1913,8 @@ void Factory::ReinitializeJSProxy(Handle<JSProxy> proxy, InstanceType type, int size_difference = proxy->map()->instance_size() - map->instance_size();
   DCHECK(size_difference >= 0);

- map->SetPrototype(handle(proxy->map()->prototype(), proxy->GetIsolate()));
+  Handle<Object> prototype(proxy->map()->prototype(), isolate());
+  Map::SetPrototype(map, prototype);

   // Allocate the backing storage for the properties.
   int prop_size = map->InitialPropertiesLength();
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index b885a17b239e6234036a7a3bc33697e5f48d337a..359cf60c761033194a9ed852f73adea33eafd432 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -6799,9 +6799,11 @@ Object* JSObject::SlowReverseLookup(Object* value) {


 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
-  Handle<Map> result = map->GetIsolate()->factory()->NewMap(
-      map->instance_type(), instance_size);
-  result->SetPrototype(handle(map->prototype(), map->GetIsolate()));
+  Isolate* isolate = map->GetIsolate();
+  Handle<Map> result =
+      isolate->factory()->NewMap(map->instance_type(), instance_size);
+  Handle<Object> prototype(map->prototype(), isolate);
+  Map::SetPrototype(result, prototype);
   result->set_constructor_or_backpointer(map->GetConstructor());
   result->set_bit_field(map->bit_field());
   result->set_bit_field2(map->bit_field2());
@@ -6996,7 +6998,7 @@ void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
     TransitionArray::Insert(parent, name, child, flag);
     if (child->prototype()->IsJSObject()) {
       Handle<JSObject> proto(JSObject::cast(child->prototype()));
-      if (!child->ShouldRegisterAsPrototypeUser(proto)) {
+      if (!ShouldRegisterAsPrototypeUser(child, proto)) {
         JSObject::UnregisterPrototypeUser(proto, child);
       }
     }
@@ -9958,29 +9960,32 @@ void JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype,
 }


-void Map::SetPrototype(Handle<Object> prototype,
+// static
+void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
                        PrototypeOptimizationMode proto_mode) {
-  if (this->prototype()->IsJSObject() && FLAG_track_prototype_users) {
-    Handle<JSObject> old_prototype(JSObject::cast(this->prototype()));
-    JSObject::UnregisterPrototypeUser(old_prototype, handle(this));
+  if (map->prototype()->IsJSObject() && FLAG_track_prototype_users) {
+    Handle<JSObject> old_prototype(JSObject::cast(map->prototype()));
+    JSObject::UnregisterPrototypeUser(old_prototype, map);
   }
   if (prototype->IsJSObject()) {
     Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
-    if (ShouldRegisterAsPrototypeUser(prototype_jsobj)) {
-      JSObject::RegisterPrototypeUser(prototype_jsobj, handle(this));
+    if (ShouldRegisterAsPrototypeUser(map, prototype_jsobj)) {
+      JSObject::RegisterPrototypeUser(prototype_jsobj, map);
     }
     JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
   }
   WriteBarrierMode wb_mode =
       prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
-  set_prototype(*prototype, wb_mode);
+  map->set_prototype(*prototype, wb_mode);
 }


-bool Map::ShouldRegisterAsPrototypeUser(Handle<JSObject> prototype) {
+// static
+bool Map::ShouldRegisterAsPrototypeUser(Handle<Map> map,
+                                        Handle<JSObject> prototype) {
   if (!FLAG_track_prototype_users) return false;
-  if (this->is_prototype_map()) return true;
-  Object* back = GetBackPointer();
+  if (map->is_prototype_map()) return true;
+  Object* back = map->GetBackPointer();
   if (!back->IsMap()) return true;
   if (Map::cast(back)->prototype() != *prototype) return true;
   return false;
@@ -10133,7 +10138,7 @@ bool JSFunction::RemovePrototype() {
void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
                                Handle<Object> prototype) {
   if (map->prototype() != *prototype) {
-    map->SetPrototype(prototype, FAST_PROTOTYPE);
+    Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
   }
   function->set_prototype_or_initial_map(*map);
   map->SetConstructor(*function);
@@ -12244,7 +12249,7 @@ Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
   if (new_map.is_null()) {
     new_map = Copy(map, "TransitionToPrototype");
     TransitionArray::PutPrototypeTransition(map, prototype, new_map);
-    new_map->SetPrototype(prototype, mode);
+    Map::SetPrototype(new_map, prototype, mode);
   }
   return new_map;
 }
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index 2fe600d5236e0cc0c898649e8ce520096db431b0..ed0bda149c98a8af9908294f9b3dfbfaa08d88e1 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -6042,9 +6042,11 @@ class Map: public HeapObject {
   // [prototype]: implicit prototype object.
   DECL_ACCESSORS(prototype, Object)
   // TODO(jkummerow): make set_prototype private.
-  void SetPrototype(Handle<Object> prototype,
-                    PrototypeOptimizationMode proto_mode = FAST_PROTOTYPE);
-  bool ShouldRegisterAsPrototypeUser(Handle<JSObject> prototype);
+  static void SetPrototype(
+      Handle<Map> map, Handle<Object> prototype,
+      PrototypeOptimizationMode proto_mode = FAST_PROTOTYPE);
+  static bool ShouldRegisterAsPrototypeUser(Handle<Map> map,
+                                            Handle<JSObject> prototype);
   bool CanUseOptimizationsBasedOnPrototypeRegistry();

   // [constructor]: points back to the function responsible for this map.
@@ -6338,8 +6340,8 @@ class Map: public HeapObject {
       kPrototypeOffset + kPointerSize;
// When there is only one transition, it is stored directly in this field;
   // otherwise a transition array is used.
- // For prototype maps, this slot is used to store a pointer to the prototype
-  // object using this map.
+ // For prototype maps, this slot is used to store this map's PrototypeInfo
+  // struct.
   static const int kTransitionsOrPrototypeInfoOffset =
       kConstructorOrBackPointerOffset + kPointerSize;
   static const int kDescriptorsOffset =
Index: src/runtime/runtime-classes.cc
diff --git a/src/runtime/runtime-classes.cc b/src/runtime/runtime-classes.cc
index 67d7e6939a634213440744b054796355d6e3bd44..9059870c7ab344544952d61fd953982af96e1313 100644
--- a/src/runtime/runtime-classes.cc
+++ b/src/runtime/runtime-classes.cc
@@ -140,7 +140,7 @@ RUNTIME_FUNCTION(Runtime_DefineClass) {

   Handle<Map> map =
       isolate->factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
-  map->SetPrototype(prototype_parent);
+  Map::SetPrototype(map, prototype_parent);
   map->SetConstructor(*constructor);
   Handle<JSObject> prototype = isolate->factory()->NewJSObjectFromMap(map);

Index: src/runtime/runtime-debug.cc
diff --git a/src/runtime/runtime-debug.cc b/src/runtime/runtime-debug.cc
index a7bca97a964553977010b2211b4cb71fd531dcf4..5cd65e00faffaf25570700c674b354b3f6e284b1 100644
--- a/src/runtime/runtime-debug.cc
+++ b/src/runtime/runtime-debug.cc
@@ -2171,7 +2171,7 @@ static Handle<JSObject> NewJSObjectWithNullProto(Isolate* isolate) {
       isolate->factory()->NewJSObject(isolate->object_function());
   Handle<Map> new_map =
       Map::Copy(Handle<Map>(result->map()), "ObjectWithNullProto");
-  new_map->SetPrototype(isolate->factory()->null_value());
+  Map::SetPrototype(new_map, isolate->factory()->null_value());
   JSObject::MigrateToMap(result, new_map);
   return result;
 }
Index: test/cctest/test-heap.cc
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index ca3ec7b07ab416f3385702ed480b4f08add3de0f..fff65eba0ac1054e2db5b9b2320b73db3825d19f 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -5072,7 +5072,7 @@ void CheckMapRetainingFor(int n) {
         CompileRun("(function () { return {x : 10}; })();");
     Handle<JSObject> proto =
         v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(result));
-    map->set_prototype(*proto);
+    Map::SetPrototype(map, proto);
     heap->AddRetainedMap(map);
     weak_cell = inner_scope.CloseAndEscape(Map::WeakCellForMap(map));
   }


--
--
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.

Reply via email to