Revision: 23042
Author:   [email protected]
Date:     Mon Aug 11 14:00:58 2014 UTC
Log:      Tag all prototypes as proto, except those set using __proto__

BUG=
[email protected], [email protected]

Review URL: https://codereview.chromium.org/450303003
http://code.google.com/p/v8/source/detail?r=23042

Added:
 /branches/bleeding_edge/test/mjsunit/runtime-gen/internalsetprototype.js
Modified:
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/apinatives.js
 /branches/bleeding_edge/src/bootstrapper.cc
 /branches/bleeding_edge/src/factory.cc
 /branches/bleeding_edge/src/generator.js
 /branches/bleeding_edge/src/math.js
 /branches/bleeding_edge/src/objects-debug.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/runtime.h
 /branches/bleeding_edge/src/serialize.cc
 /branches/bleeding_edge/src/stub-cache.cc
 /branches/bleeding_edge/src/v8natives.js
 /branches/bleeding_edge/tools/generate-runtime-tests.py

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/runtime-gen/internalsetprototype.js Mon Aug 11 14:00:58 2014 UTC
@@ -0,0 +1,6 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
+// Flags: --allow-natives-syntax --harmony --harmony-proxies
+var _obj = new Object();
+var _prototype = new Object();
+%InternalSetPrototype(_obj, _prototype);
=======================================
--- /branches/bleeding_edge/src/api.cc  Thu Aug  7 08:55:49 2014 UTC
+++ /branches/bleeding_edge/src/api.cc  Mon Aug 11 14:00:58 2014 UTC
@@ -3204,8 +3204,8 @@
   // to propagate outside.
   TryCatch try_catch;
   EXCEPTION_PREAMBLE(isolate);
-  i::MaybeHandle<i::Object> result = i::JSObject::SetPrototype(
-      self, value_obj);
+  i::MaybeHandle<i::Object> result =
+      i::JSObject::SetPrototype(self, value_obj, false);
   has_pending_exception = result.is_null();
   EXCEPTION_BAILOUT_CHECK(isolate, false);
   return true;
=======================================
--- /branches/bleeding_edge/src/apinatives.js   Tue Jul 29 08:09:14 2014 UTC
+++ /branches/bleeding_edge/src/apinatives.js   Mon Aug 11 14:00:58 2014 UTC
@@ -68,7 +68,7 @@
         // internal ToBoolean doesn't handle that!
         if (typeof parent !== 'undefined') {
           var parent_fun = Instantiate(parent);
-          %SetPrototype(prototype, parent_fun.prototype);
+          %InternalSetPrototype(prototype, parent_fun.prototype);
         }
       }
       var fun = %CreateApiFunction(data, prototype);
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Fri Aug  8 11:42:59 2014 UTC
+++ /branches/bleeding_edge/src/bootstrapper.cc Mon Aug 11 14:00:58 2014 UTC
@@ -480,7 +480,8 @@
     Handle<JSFunction> object_fun = factory->NewFunction(object_name);
     Handle<Map> object_function_map =
         factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
-    JSFunction::SetInitialMap(object_fun, object_function_map);
+    JSFunction::SetInitialMap(object_fun, object_function_map,
+                              isolate->factory()->null_value());
     object_function_map->set_unused_property_fields(
         JSObject::kInitialGlobalObjectUnusedPropertiesCount);

@@ -490,6 +491,9 @@
     Handle<JSObject> prototype = factory->NewJSObject(
         isolate->object_function(),
         TENURED);
+    Handle<Map> map = Map::Copy(handle(prototype->map()));
+    map->set_is_prototype_map(true);
+    prototype->set_map(*map);

     native_context()->set_initial_object_prototype(*prototype);
// For bootstrapping set the array prototype to be the same as the object
@@ -507,6 +511,15 @@
   Handle<JSFunction> empty_function = factory->NewFunctionWithoutPrototype(
       empty_string, code);

+  // Allocate the function map first and then patch the prototype later
+  Handle<Map> empty_function_map =
+      CreateFunctionMap(FUNCTION_WITHOUT_PROTOTYPE);
+  DCHECK(!empty_function_map->is_dictionary_map());
+  empty_function_map->set_prototype(
+      native_context()->object_function()->prototype());
+  empty_function_map->set_is_prototype_map(true);
+  empty_function->set_map(*empty_function_map);
+
   // --- E m p t y ---
   Handle<String> source = factory->NewStringFromStaticAscii("() {}");
   Handle<Script> script = factory->NewScript(source);
@@ -521,13 +534,6 @@
   native_context()->sloppy_function_without_prototype_map()->
       set_prototype(*empty_function);
   sloppy_function_map_writable_prototype_->set_prototype(*empty_function);
-
-  // Allocate the function map first and then patch the prototype later
-  Handle<Map> empty_function_map =
-      CreateFunctionMap(FUNCTION_WITHOUT_PROTOTYPE);
-  empty_function_map->set_prototype(
-      native_context()->object_function()->prototype());
-  empty_function->set_map(*empty_function_map);
   return empty_function;
 }

@@ -1082,6 +1088,7 @@
     proto->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
                                  Smi::FromInt(0),
                                  SKIP_WRITE_BARRIER);  // It's a Smi.
+    proto_map->set_is_prototype_map(true);
     initial_map->set_prototype(*proto);
     factory->SetRegExpIrregexpData(Handle<JSRegExp>::cast(proto),
JSRegExp::IRREGEXP, factory->empty_string(),
@@ -1204,13 +1211,13 @@
     }

     map->set_function_with_prototype(true);
-    map->set_prototype(native_context()->object_function()->prototype());
     map->set_pre_allocated_property_fields(2);
     map->set_inobject_properties(2);
     native_context()->set_sloppy_arguments_map(*map);

     DCHECK(!function->has_initial_map());
-    JSFunction::SetInitialMap(function, map);
+    JSFunction::SetInitialMap(function, map,
+                              isolate->initial_object_prototype());

     DCHECK(map->inobject_properties() > Heap::kArgumentsCalleeIndex);
     DCHECK(map->inobject_properties() > Heap::kArgumentsLengthIndex);
@@ -1334,7 +1341,8 @@
       JS_TYPED_ARRAY_TYPE,
       JSTypedArray::kSizeWithInternalFields,
       elements_kind);
-  JSFunction::SetInitialMap(result, initial_map);
+  JSFunction::SetInitialMap(result, initial_map,
+                            handle(initial_map->prototype(), isolate()));
   *fun = result;

ElementsKind external_kind = GetNextTransitionElementsKind(elements_kind);
@@ -1652,7 +1660,7 @@
   Handle<Map> original_map(array_function->initial_map());
   Handle<Map> initial_map = Map::Copy(original_map);
   initial_map->set_elements_kind(elements_kind);
-  JSFunction::SetInitialMap(array_function, initial_map);
+  JSFunction::SetInitialMap(array_function, initial_map, prototype);

   // Make "length" magic on instances.
   Map::EnsureDescriptorSlack(initial_map, 1);
=======================================
--- /branches/bleeding_edge/src/factory.cc      Thu Aug  7 16:14:22 2014 UTC
+++ /branches/bleeding_edge/src/factory.cc      Mon Aug 11 14:00:58 2014 UTC
@@ -1289,8 +1289,8 @@
     prototype = NewFunctionPrototype(function);
   }

-  initial_map->set_prototype(*prototype);
-  JSFunction::SetInitialMap(function, initial_map);
+  JSFunction::SetInitialMap(function, initial_map,
+                            Handle<JSReceiver>::cast(prototype));

   return function;
 }
@@ -1321,6 +1321,7 @@
     new_map = handle(object_function->initial_map());
   }

+  DCHECK(!new_map->is_prototype_map());
   Handle<JSObject> prototype = NewJSObjectFromMap(new_map);

   if (!function->shared()->is_generator()) {
=======================================
--- /branches/bleeding_edge/src/generator.js    Mon Jul 14 14:05:30 2014 UTC
+++ /branches/bleeding_edge/src/generator.js    Mon Aug 11 14:00:58 2014 UTC
@@ -67,11 +67,11 @@
       GeneratorObjectIterator, DONT_ENUM | DONT_DELETE | READ_ONLY);
   %AddNamedProperty(GeneratorObjectPrototype, "constructor",
       GeneratorFunctionPrototype, DONT_ENUM | DONT_DELETE | READ_ONLY);
-  %SetPrototype(GeneratorFunctionPrototype, $Function.prototype);
+  %InternalSetPrototype(GeneratorFunctionPrototype, $Function.prototype);
%SetCode(GeneratorFunctionPrototype, GeneratorFunctionPrototypeConstructor);
   %AddNamedProperty(GeneratorFunctionPrototype, "constructor",
       GeneratorFunction, DONT_ENUM | DONT_DELETE | READ_ONLY);
-  %SetPrototype(GeneratorFunction, $Function);
+  %InternalSetPrototype(GeneratorFunction, $Function);
   %SetCode(GeneratorFunction, GeneratorFunctionConstructor);
 }

=======================================
--- /branches/bleeding_edge/src/math.js Wed Aug  6 11:39:39 2014 UTC
+++ /branches/bleeding_edge/src/math.js Mon Aug 11 14:00:58 2014 UTC
@@ -372,7 +372,7 @@
 function SetUpMath() {
   %CheckIsBootstrapping();

-  %SetPrototype($Math, $Object.prototype);
+  %InternalSetPrototype($Math, $Object.prototype);
   %AddNamedProperty(global, "Math", $Math, DONT_ENUM);
   %FunctionSetInstanceClassName(MathConstructor, 'Math');

=======================================
--- /branches/bleeding_edge/src/objects-debug.cc Thu Aug 7 12:21:01 2014 UTC +++ /branches/bleeding_edge/src/objects-debug.cc Mon Aug 11 14:00:58 2014 UTC
@@ -308,9 +308,9 @@
 }


-void Map::SharedMapVerify() {
+void Map::DictionaryMapVerify() {
   MapVerify();
-  CHECK(is_shared());
+  CHECK(is_dictionary_map());
   CHECK(instance_descriptors()->IsEmpty());
   CHECK_EQ(0, pre_allocated_property_fields());
   CHECK_EQ(0, unused_property_fields());
@@ -1012,7 +1012,7 @@
     for (int i = 0; i < length(); i++) {
       Object* e = FixedArray::get(i);
       if (e->IsMap()) {
-        Map::cast(e)->SharedMapVerify();
+        Map::cast(e)->DictionaryMapVerify();
       } else {
         CHECK(e->IsUndefined());
       }
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Thu Aug  7 16:14:22 2014 UTC
+++ /branches/bleeding_edge/src/objects-inl.h   Mon Aug 11 14:00:58 2014 UTC
@@ -2206,7 +2206,8 @@


 void FixedArray::set(int index, Object* value) {
-  DCHECK(map() != GetHeap()->fixed_cow_array_map());
+  DCHECK_NE(GetHeap()->fixed_cow_array_map(), map());
+  DCHECK_EQ(FIXED_ARRAY_TYPE, map()->instance_type());
   DCHECK(index >= 0 && index < this->length());
   int offset = kHeaderSize + index * kPointerSize;
   WRITE_FIELD(this, offset, value);
@@ -4460,15 +4461,6 @@
 }


-void Map::set_is_shared(bool value) {
-  set_bit_field3(IsShared::update(bit_field3(), value));
-}
-
-
-bool Map::is_shared() {
-  return IsShared::decode(bit_field3()); }
-
-
 void Map::set_dictionary_map(bool value) {
   uint32_t new_bit_field3 = DictionaryMap::update(bit_field3(), value);
   new_bit_field3 = IsUnstable::update(new_bit_field3, value);
@@ -4486,8 +4478,8 @@
 }


-void Map::set_owns_descriptors(bool is_shared) {
-  set_bit_field3(OwnsDescriptors::update(bit_field3(), is_shared));
+void Map::set_owns_descriptors(bool owns_descriptors) {
+  set_bit_field3(OwnsDescriptors::update(bit_field3(), owns_descriptors));
 }


=======================================
--- /branches/bleeding_edge/src/objects.cc      Mon Aug 11 12:26:17 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc      Mon Aug 11 14:00:58 2014 UTC
@@ -3470,7 +3470,7 @@
   bool allow_store_transition =
// Only remember the map transition if there is not an already existing
       // non-matching element transition.
-      !map->IsUndefined() && !map->is_shared() &&
+      !map->IsUndefined() && !map->is_dictionary_map() &&
       IsTransitionElementsKind(from_kind);

   // Only store fast element maps in ascending generality.
@@ -4440,6 +4440,8 @@

 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
                                          PropertyNormalizationMode mode) {
+  // Only use the cache once it is initialized.
+  if (!IsNormalizedMapCache(this)) return MaybeHandle<Map>();
   DisallowHeapAllocation no_gc;
   Object* value = FixedArray::get(GetIndex(fast_map));
   if (!value->IsMap() ||
@@ -4452,6 +4454,8 @@

 void NormalizedMapCache::Set(Handle<Map> fast_map,
                              Handle<Map> normalized_map) {
+  // Only use the cache once it is initialized.
+  if (!IsNormalizedMapCache(this)) return;
   DisallowHeapAllocation no_gc;
   DCHECK(normalized_map->is_dictionary_map());
   FixedArray::set(GetIndex(fast_map), *normalized_map);
@@ -6981,17 +6985,14 @@
   Handle<Map> new_map;
   if (cache->Get(fast_map, mode).ToHandle(&new_map)) {
 #ifdef VERIFY_HEAP
-    if (FLAG_verify_heap) {
-      new_map->SharedMapVerify();
-    }
+    if (FLAG_verify_heap) new_map->DictionaryMapVerify();
 #endif
 #ifdef ENABLE_SLOW_DCHECKS
     if (FLAG_enable_slow_asserts) {
// The cached map should match newly created normalized map bit-by-bit,
       // except for the code cache, which can contain some ics which can be
       // applied to the shared map.
-      Handle<Map> fresh = Map::CopyNormalized(
-          fast_map, mode, SHARED_NORMALIZED_MAP);
+      Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);

       DCHECK(memcmp(fresh->address(),
                     new_map->address(),
@@ -7005,7 +7006,7 @@
     }
 #endif
   } else {
-    new_map = Map::CopyNormalized(fast_map, mode, SHARED_NORMALIZED_MAP);
+    new_map = Map::CopyNormalized(fast_map, mode);
     cache->Set(fast_map, new_map);
     isolate->counters()->normalized_maps()->Increment();
   }
@@ -7015,8 +7016,7 @@


 Handle<Map> Map::CopyNormalized(Handle<Map> map,
-                                PropertyNormalizationMode mode,
-                                NormalizedMapSharingMode sharing) {
+                                PropertyNormalizationMode mode) {
   int new_instance_size = map->instance_size();
   if (mode == CLEAR_INOBJECT_PROPERTIES) {
     new_instance_size -= map->inobject_properties() * kPointerSize;
@@ -7028,14 +7028,11 @@
     result->set_inobject_properties(map->inobject_properties());
   }

-  result->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
   result->set_dictionary_map(true);
   result->set_migration_target(false);

 #ifdef VERIFY_HEAP
-  if (FLAG_verify_heap && result->is_shared()) {
-    result->SharedMapVerify();
-  }
+  if (FLAG_verify_heap) result->DictionaryMapVerify();
 #endif

   return result;
@@ -7051,7 +7048,6 @@

   result->set_pre_allocated_property_fields(
       map->pre_allocated_property_fields());
-  result->set_is_shared(false);
   result->ClearCodeCache(map->GetHeap());
   map->NotifyLeafMapLayoutChange();
   return result;
@@ -9812,20 +9808,29 @@
 }


-void JSObject::OptimizeAsPrototype(Handle<JSObject> object) {
+void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
+                                   PrototypeOptimizationMode mode) {
   if (object->IsGlobalObject()) return;
-
-  // Make sure prototypes are fast objects and their maps have the bit set
-  // so they remain fast.
+  if (object->IsJSGlobalProxy()) return;
+  if (mode == FAST_PROTOTYPE && !object->map()->is_prototype_map()) {
+    // First normalize to ensure all JSFunctions are CONSTANT.
+    JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0);
+  }
   if (!object->HasFastProperties()) {
-    MigrateSlowToFast(object, 0);
+    JSObject::MigrateSlowToFast(object, 0);
+  }
+  if (mode == FAST_PROTOTYPE && object->HasFastProperties() &&
+      !object->map()->is_prototype_map()) {
+    Handle<Map> new_map = Map::Copy(handle(object->map()));
+    JSObject::MigrateToMap(object, new_map);
+    object->map()->set_is_prototype_map(true);
   }
 }


 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
   if (!object->map()->is_prototype_map()) return;
-  OptimizeAsPrototype(object);
+  OptimizeAsPrototype(object, FAST_PROTOTYPE);
 }


@@ -9876,20 +9881,29 @@
     if (function->IsInobjectSlackTrackingInProgress()) {
       function->CompleteInobjectSlackTracking();
     }
+
     Handle<Map> initial_map(function->initial_map(), isolate);
-    Handle<Map> new_map = Map::Copy(initial_map);
-    new_map->set_prototype(*value);
+
+    if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
+        initial_map->instance_type() == JS_OBJECT_TYPE) {
+ // Put the value in the initial map field until an initial map is needed. + // At that point, a new initial map is created and the prototype is put
+      // into the initial map where it belongs.
+      function->set_prototype_or_initial_map(*value);
+    } else {
+      Handle<Map> new_map = Map::Copy(initial_map);
+      JSFunction::SetInitialMap(function, new_map, value);

-    // If the function is used as the global Array function, cache the
-    // initial map (and transitioned versions) in the native context.
-    Context* native_context = function->context()->native_context();
- Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX);
-    if (array_function->IsJSFunction() &&
-        *function == JSFunction::cast(array_function)) {
-      CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
+      // If the function is used as the global Array function, cache the
+      // initial map (and transitioned versions) in the native context.
+      Context* native_context = function->context()->native_context();
+      Object* array_function =
+          native_context->get(Context::ARRAY_FUNCTION_INDEX);
+      if (array_function->IsJSFunction() &&
+          *function == JSFunction::cast(array_function)) {
+        CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
+      }
     }
-
-    JSFunction::SetInitialMap(function, new_map);

     // Deoptimize all code that embeds the previous initial map.
     initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
@@ -9956,27 +9970,13 @@
 }


-void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map) {
-  if (map->prototype()->IsJSObject()) {
-    Handle<JSObject> js_proto = handle(JSObject::cast(map->prototype()));
-    if (!js_proto->map()->is_prototype_map() &&
-        !js_proto->map()->IsGlobalObjectMap() &&
-        !js_proto->map()->IsJSGlobalProxyMap()) {
-      // Normalize and turn fast again to make all functions CONSTANT
-      // properties.
-      if (!js_proto->GetIsolate()->bootstrapper()->IsActive()) {
- JSObject::NormalizeProperties(js_proto, KEEP_INOBJECT_PROPERTIES, 0);
-      }
-      if (!js_proto->HasFastProperties()) {
-        JSObject::MigrateSlowToFast(js_proto, 0);
-      }
-      if (js_proto->HasFastProperties()) {
-        Handle<Map> new_map = Map::Copy(handle(js_proto->map()));
-        JSObject::MigrateToMap(js_proto, new_map);
-        js_proto->map()->set_is_prototype_map(true);
-      }
-    }
+void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
+                               Handle<Object> prototype) {
+  if (prototype->IsJSObject()) {
+    Handle<JSObject> js_proto = Handle<JSObject>::cast(prototype);
+    JSObject::OptimizeAsPrototype(js_proto, FAST_PROTOTYPE);
   }
+  map->set_prototype(*prototype);
   function->set_prototype_or_initial_map(*map);
   map->set_constructor(*function);
 }
@@ -10011,11 +10011,10 @@
   }
   map->set_inobject_properties(in_object_properties);
   map->set_unused_property_fields(in_object_properties);
-  map->set_prototype(*prototype);
   DCHECK(map->has_fast_object_elements());

   // Finally link initial map and constructor function.
-  JSFunction::SetInitialMap(function, map);
+ JSFunction::SetInitialMap(function, map, Handle<JSReceiver>::cast(prototype));

   if (!function->shared()->is_generator()) {
     function->StartInobjectSlackTracking();
@@ -11796,7 +11795,7 @@
// Don't cache prototype transition if this map is either shared, or a map of
   // a prototype.
   if (map->is_prototype_map()) return map;
-  if (map->is_shared() || !FLAG_cache_prototype_transitions) return map;
+ if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map;

   const int step = kProtoTransitionElementsPerEntry;
   const int header = kProtoTransitionHeaderSize;
@@ -12119,7 +12118,7 @@

 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
                                            Handle<Object> value,
-                                           bool skip_hidden_prototypes) {
+                                           bool from_javascript) {
 #ifdef DEBUG
   int size = object->Size();
 #endif
@@ -12164,7 +12163,7 @@
       object->map()->DictionaryElementsInPrototypeChainOnly();
   Handle<JSObject> real_receiver = object;

-  if (skip_hidden_prototypes) {
+  if (from_javascript) {
     // Find the first object in the chain whose prototype object is not
     // hidden and set the new prototype on that object.
     PrototypeIterator iter(isolate, real_receiver);
@@ -12182,7 +12181,9 @@
   if (map->prototype() == *value) return value;

   if (value->IsJSObject()) {
-    JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
+    PrototypeOptimizationMode mode =
+        from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
+    JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value), mode);
   }

   Handle<Map> new_map = Map::TransitionToPrototype(map, value);
=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Aug  7 16:14:22 2014 UTC
+++ /branches/bleeding_edge/src/objects.h       Mon Aug 11 14:00:58 2014 UTC
@@ -247,12 +247,12 @@
 };


-// NormalizedMapSharingMode is used to specify whether a map may be shared
-// by different objects with normalized properties.
-enum NormalizedMapSharingMode {
-  UNIQUE_NORMALIZED_MAP,
-  SHARED_NORMALIZED_MAP
-};
+// Indicates how aggressively the prototype should be optimized. FAST_PROTOTYPE +// will give the fastest result by tailoring the map to the prototype, but that +// will cause polymorphism with other objects. REGULAR_PROTOTYPE is to be used
+// (at least for now) when dynamically modifying the prototype chain of an
+// object using __proto__ or Object.setPrototypeOf.
+enum PrototypeOptimizationMode { REGULAR_PROTOTYPE, FAST_PROTOTYPE };


 // Indicates whether transitions can be added to a source map or not.
@@ -2196,7 +2196,8 @@
                                     Handle<Object> value,
                                     PropertyDetails details);

-  static void OptimizeAsPrototype(Handle<JSObject> object);
+  static void OptimizeAsPrototype(Handle<JSObject> object,
+                                  PrototypeOptimizationMode mode);
   static void ReoptimizeIfPrototype(Handle<JSObject> object);

   // Retrieve interceptors.
@@ -2475,9 +2476,7 @@

// Set the object's prototype (only JSReceiver and null are allowed values).
   MUST_USE_RESULT static MaybeHandle<Object> SetPrototype(
-      Handle<JSObject> object,
-      Handle<Object> value,
-      bool skip_hidden_prototypes = false);
+      Handle<JSObject> object, Handle<Object> value, bool from_javascript);

   // Initializes the body after properties slot, properties slot is
   // initialized by set_properties.  Fill the pre-allocated fields with
@@ -6125,15 +6124,16 @@
   class NumberOfOwnDescriptorsBits: public BitField<int,
       kDescriptorIndexBitCount, kDescriptorIndexBitCount> {};  // NOLINT
   STATIC_ASSERT(kDescriptorIndexBitCount + kDescriptorIndexBitCount == 20);
-  class IsShared:                   public BitField<bool, 20,  1> {};
-  class DictionaryMap:              public BitField<bool, 21,  1> {};
-  class OwnsDescriptors:            public BitField<bool, 22,  1> {};
-  class HasInstanceCallHandler:     public BitField<bool, 23,  1> {};
-  class Deprecated:                 public BitField<bool, 24,  1> {};
-  class IsFrozen:                   public BitField<bool, 25,  1> {};
-  class IsUnstable:                 public BitField<bool, 26,  1> {};
-  class IsMigrationTarget:          public BitField<bool, 27,  1> {};
-  class DoneInobjectSlackTracking:  public BitField<bool, 28,  1> {};
+  class DictionaryMap : public BitField<bool, 20, 1> {};
+  class OwnsDescriptors : public BitField<bool, 21, 1> {};
+  class HasInstanceCallHandler : public BitField<bool, 22, 1> {};
+  class Deprecated : public BitField<bool, 23, 1> {};
+  class IsFrozen : public BitField<bool, 24, 1> {};
+  class IsUnstable : public BitField<bool, 25, 1> {};
+  class IsMigrationTarget : public BitField<bool, 26, 1> {};
+  class DoneInobjectSlackTracking : public BitField<bool, 27, 1> {};
+  // Bit 28 is free.
+
   // Keep this bit field at the very end for better code in
   // Builtins::kJSConstructStubGeneric stub.
   class ConstructionCount:          public BitField<int, 29, 3> {};
@@ -6335,12 +6335,6 @@
   // function that was used to instantiate the object).
   String* constructor_name();

- // Tells whether the map is shared between objects that may have different
-  // behavior. If true, the map should never be modified, instead a clone
-  // should be created and modified.
-  inline void set_is_shared(bool value);
-  inline bool is_shared();
-
   // Tells whether the map is used for JSObjects in dictionary mode (ie
// normalized objects, ie objects for which HasFastProperties returns false). // A map can never be used for both dictionary mode and fast mode JSObjects.
@@ -6460,7 +6454,7 @@
   }

   inline bool owns_descriptors();
-  inline void set_owns_descriptors(bool is_shared);
+  inline void set_owns_descriptors(bool owns_descriptors);
   inline bool has_instance_call_handler();
   inline void set_has_instance_call_handler();
   inline void freeze();
@@ -6649,7 +6643,7 @@
   DECLARE_VERIFIER(Map)

 #ifdef VERIFY_HEAP
-  void SharedMapVerify();
+  void DictionaryMapVerify();
   void VerifyOmittedMapChecks();
 #endif

@@ -6795,8 +6789,7 @@
                                            TransitionFlag flag);

   static Handle<Map> CopyNormalized(Handle<Map> map,
-                                    PropertyNormalizationMode mode,
-                                    NormalizedMapSharingMode sharing);
+                                    PropertyNormalizationMode mode);

   // Fires when the layout of an object with a leaf map changes.
   // This includes adding transitions to the leaf map or changing
@@ -7780,7 +7773,8 @@

   // The initial map for an object created by this constructor.
   inline Map* initial_map();
-  static void SetInitialMap(Handle<JSFunction> function, Handle<Map> map);
+  static void SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
+                            Handle<Object> prototype);
   inline bool has_initial_map();
   static void EnsureHasInitialMap(Handle<JSFunction> function);

=======================================
--- /branches/bleeding_edge/src/runtime.cc      Wed Aug  6 13:45:59 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc      Mon Aug 11 14:00:58 2014 UTC
@@ -1860,6 +1860,20 @@
   }
   return PrototypeIterator::GetCurrent(iter);
 }
+
+
+RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 2);
+  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
+  CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
+  DCHECK(!obj->IsAccessCheckNeeded());
+  DCHECK(!obj->map()->is_observed());
+  Handle<Object> result;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, result, JSObject::SetPrototype(obj, prototype, false));
+  return *result;
+}


 RUNTIME_FUNCTION(Runtime_SetPrototype) {
=======================================
--- /branches/bleeding_edge/src/runtime.h       Wed Aug  6 11:39:39 2014 UTC
+++ /branches/bleeding_edge/src/runtime.h       Mon Aug 11 14:00:58 2014 UTC
@@ -46,6 +46,7 @@
                                                             \
   F(GetPrototype, 1, 1)                                     \
   F(SetPrototype, 2, 1)                                     \
+  F(InternalSetPrototype, 2, 1)                             \
   F(IsInPrototypeChain, 2, 1)                               \
                                                             \
   F(GetOwnProperty, 2, 1)                                   \
=======================================
--- /branches/bleeding_edge/src/serialize.cc    Wed Aug  6 07:20:14 2014 UTC
+++ /branches/bleeding_edge/src/serialize.cc    Mon Aug 11 14:00:58 2014 UTC
@@ -1338,6 +1338,7 @@
     int skip) {
   CHECK(o->IsHeapObject());
   HeapObject* heap_object = HeapObject::cast(o);
+  DCHECK(!heap_object->IsJSFunction());

   int root_index;
if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
=======================================
--- /branches/bleeding_edge/src/stub-cache.cc   Wed Aug  6 13:18:36 2014 UTC
+++ /branches/bleeding_edge/src/stub-cache.cc   Mon Aug 11 14:00:58 2014 UTC
@@ -349,7 +349,7 @@
CompareNilICStub* stub) {
   Isolate* isolate = receiver_map->GetIsolate();
   Handle<String> name(isolate->heap()->empty_string());
-  if (!receiver_map->is_shared()) {
+  if (!receiver_map->is_dictionary_map()) {
     Handle<Code> cached_ic =
Find(name, receiver_map, Code::COMPARE_NIL_IC, stub->GetExtraICState());
     if (!cached_ic.is_null()) return cached_ic;
@@ -359,7 +359,7 @@
   pattern.Add(isolate->factory()->meta_map(), receiver_map);
   Handle<Code> ic = stub->GetCodeCopy(pattern);

-  if (!receiver_map->is_shared()) {
+  if (!receiver_map->is_dictionary_map()) {
     Map::UpdateCodeCache(receiver_map, name, ic);
   }

=======================================
--- /branches/bleeding_edge/src/v8natives.js    Fri Aug  8 13:39:13 2014 UTC
+++ /branches/bleeding_edge/src/v8natives.js    Mon Aug 11 14:00:58 2014 UTC
@@ -96,7 +96,7 @@
%AddNamedProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
     %SetNativeFlag(f);
   }
-  %SetPrototype(prototype, null);
+  %InternalSetPrototype(prototype, null);
   %ToFastProperties(prototype);
 }

@@ -1125,7 +1125,8 @@
   if (!IS_SPEC_OBJECT(proto) && proto !== null) {
     throw MakeTypeError("proto_object_or_null", [proto]);
   }
-  var obj = { __proto__: proto };
+  var obj = {};
+  %InternalSetPrototype(obj, proto);
   if (!IS_UNDEFINED(properties)) ObjectDefineProperties(obj, properties);
   return obj;
 }
=======================================
--- /branches/bleeding_edge/tools/generate-runtime-tests.py Fri Aug 8 11:42:59 2014 UTC +++ /branches/bleeding_edge/tools/generate-runtime-tests.py Mon Aug 11 14:00:58 2014 UTC
@@ -47,8 +47,8 @@
# that the parser doesn't bit-rot. Change the values as needed when you add, # remove or change runtime functions, but make sure we don't lose our ability
 # to parse them!
-EXPECTED_FUNCTION_COUNT = 427
-EXPECTED_FUZZABLE_COUNT = 330
+EXPECTED_FUNCTION_COUNT = 428
+EXPECTED_FUZZABLE_COUNT = 331
 EXPECTED_CCTEST_COUNT = 7
 EXPECTED_UNKNOWN_COUNT = 16
 EXPECTED_BUILTINS_COUNT = 809

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