Revision: 14982
Author:   [email protected]
Date:     Thu Jun  6 07:21:35 2013
Log:      Initialized representations of computed values to None.

[email protected]

Review URL: https://chromiumcodereview.appspot.com/14721009
http://code.google.com/p/v8/source/detail?r=14982

Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/bootstrapper.cc
 /branches/bleeding_edge/src/flag-definitions.h
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/heap.h
 /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/parser.cc
 /branches/bleeding_edge/src/property-details.h
 /branches/bleeding_edge/src/property.h
 /branches/bleeding_edge/test/mjsunit/track-fields.js

=======================================
--- /branches/bleeding_edge/include/v8.h        Thu Jun  6 06:16:52 2013
+++ /branches/bleeding_edge/include/v8.h        Thu Jun  6 07:21:35 2013
@@ -5283,7 +5283,7 @@
   static const int kNullValueRootIndex = 7;
   static const int kTrueValueRootIndex = 8;
   static const int kFalseValueRootIndex = 9;
-  static const int kEmptyStringRootIndex = 129;
+  static const int kEmptyStringRootIndex = 130;

   static const int kNodeClassIdOffset = 1 * kApiPointerSize;
   static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Wed Jun  5 03:43:18 2013
+++ /branches/bleeding_edge/src/bootstrapper.cc Thu Jun  6 07:21:35 2013
@@ -1086,11 +1086,13 @@
     CHECK_NOT_EMPTY_HANDLE(isolate,
                            JSObject::SetLocalPropertyIgnoreAttributes(
                                result, factory->length_string(),
-                               factory->undefined_value(), DONT_ENUM));
+                               factory->undefined_value(), DONT_ENUM,
+                               Object::FORCE_TAGGED));
     CHECK_NOT_EMPTY_HANDLE(isolate,
                            JSObject::SetLocalPropertyIgnoreAttributes(
                                result, factory->callee_string(),
-                               factory->undefined_value(), DONT_ENUM));
+                               factory->undefined_value(), DONT_ENUM,
+                               Object::FORCE_TAGGED));

 #ifdef DEBUG
     LookupResult lookup(isolate);
=======================================
--- /branches/bleeding_edge/src/flag-definitions.h      Tue Jun  4 09:41:24 2013
+++ /branches/bleeding_edge/src/flag-definitions.h      Thu Jun  6 07:21:35 2013
@@ -199,8 +199,10 @@
 DEFINE_bool(track_fields, true, "track fields with only smi values")
 DEFINE_bool(track_double_fields, true, "track fields with double values")
DEFINE_bool(track_heap_object_fields, true, "track fields with heap values") +DEFINE_bool(track_computed_fields, true, "track computed boilerplate fields")
 DEFINE_implication(track_double_fields, track_fields)
 DEFINE_implication(track_heap_object_fields, track_fields)
+DEFINE_implication(track_computed_fields, track_fields)

 // Flags for data representation optimizations
DEFINE_bool(unbox_double_arrays, true, "automatically unbox arrays of doubles")
=======================================
--- /branches/bleeding_edge/src/heap.cc Thu Jun  6 05:24:05 2013
+++ /branches/bleeding_edge/src/heap.cc Thu Jun  6 07:21:35 2013
@@ -2845,6 +2845,13 @@
   }
   set_the_hole_value(Oddball::cast(obj));

+  { MaybeObject* maybe_obj = CreateOddball("uninitialized",
+                                           Smi::FromInt(-1),
+                                           Oddball::kUninitialized);
+    if (!maybe_obj->ToObject(&obj)) return false;
+  }
+  set_uninitialized_value(Oddball::cast(obj));
+
   { MaybeObject* maybe_obj = CreateOddball("arguments_marker",
                                            Smi::FromInt(-4),
                                            Oddball::kArgumentMarker);
=======================================
--- /branches/bleeding_edge/src/heap.h  Thu Jun  6 05:24:05 2013
+++ /branches/bleeding_edge/src/heap.h  Thu Jun  6 07:21:35 2013
@@ -59,6 +59,7 @@
V(Oddball, null_value, NullValue) \ V(Oddball, true_value, TrueValue) \ V(Oddball, false_value, FalseValue) \ + V(Oddball, uninitialized_value, UninitializedValue) \ V(Map, global_property_cell_map, GlobalPropertyCellMap) \ V(Map, shared_function_info_map, SharedFunctionInfoMap) \ V(Map, meta_map, MetaMap) \
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc        Tue May 21 10:21:27 2013
+++ /branches/bleeding_edge/src/objects-debug.cc        Thu Jun  6 07:21:35 2013
@@ -312,8 +312,9 @@
         Representation r = descriptors->GetDetails(i).representation();
         int field = descriptors->GetFieldIndex(i);
         Object* value = RawFastPropertyAt(field);
+        if (r.IsDouble()) ASSERT(value->IsHeapNumber());
+        if (value->IsUninitialized()) continue;
         if (r.IsSmi()) ASSERT(value->IsSmi());
-        if (r.IsDouble()) ASSERT(value->IsHeapNumber());
         if (r.IsHeapObject()) ASSERT(value->IsHeapObject());
       }
     }
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Wed Jun  5 01:43:25 2013
+++ /branches/bleeding_edge/src/objects-inl.h   Thu Jun  6 07:21:35 2013
@@ -292,6 +292,9 @@
                                            PretenureFlag tenure) {
   if (!FLAG_track_double_fields) return this;
   if (!representation.IsDouble()) return this;
+  if (IsUninitialized()) {
+    return heap->AllocateHeapNumber(0, tenure);
+  }
   return heap->AllocateHeapNumber(Number(), tenure);
 }

@@ -528,6 +531,11 @@
 bool MaybeObject::IsTheHole() {
   return !IsFailure() && ToObjectUnchecked()->IsTheHole();
 }
+
+
+bool MaybeObject::IsUninitialized() {
+  return !IsFailure() && ToObjectUnchecked()->IsUninitialized();
+}


 Failure* Failure::cast(MaybeObject* obj) {
@@ -843,6 +851,11 @@
 bool Object::IsTheHole() {
   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
 }
+
+
+bool Object::IsUninitialized() {
+ return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUninitialized;
+}


 bool Object::IsTrue() {
@@ -1541,7 +1554,7 @@
   // Converting any field to the most specific type will cause the
// GeneralizeFieldRepresentation algorithm to create the most general existing
   // transition that matches the object. This achieves what is needed.
-  return GeneralizeFieldRepresentation(0, Representation::Smi());
+  return GeneralizeFieldRepresentation(0, Representation::None());
 }


@@ -2366,7 +2379,6 @@
   // Range check.
   ASSERT(descriptor_number < number_of_descriptors());

-  ASSERT(!desc->GetDetails().representation().IsNone());
   NoIncrementalWriteBarrierSet(this,
                                ToKeyIndex(descriptor_number),
                                desc->GetKey());
@@ -2382,7 +2394,6 @@
 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
   // Range check.
   ASSERT(descriptor_number < number_of_descriptors());
-  ASSERT(!desc->GetDetails().representation().IsNone());

   set(ToKeyIndex(descriptor_number), desc->GetKey());
   set(ToValueIndex(descriptor_number), desc->GetValue());
@@ -3617,6 +3628,9 @@
   int descriptor = LastAdded();
   for (int i = 0; i <= descriptor; i++) {
     PropertyDetails details = instance_descriptors()->GetDetails(i);
+    if (FLAG_track_fields && details.representation().IsNone()) {
+      return true;
+    }
     if (FLAG_track_fields && details.representation().IsSmi()) {
       return true;
     }
=======================================
--- /branches/bleeding_edge/src/objects.cc      Thu Jun  6 06:16:52 2013
+++ /branches/bleeding_edge/src/objects.cc      Thu Jun  6 07:21:35 2013
@@ -1817,7 +1817,8 @@
 MaybeObject* JSObject::AddFastProperty(Name* name,
                                        Object* value,
                                        PropertyAttributes attributes,
-                                       StoreFromKeyed store_mode) {
+                                       StoreFromKeyed store_mode,
+                                       ValueType value_type) {
   ASSERT(!IsJSGlobalProxy());
   ASSERT(DescriptorArray::kNotFound ==
          map()->instance_descriptors()->Search(
@@ -1843,8 +1844,8 @@
   int index = map()->NextFreePropertyIndex();

   // Allocate new instance descriptors with (name, index) added
-  Representation representation = IsJSContextExtensionObject()
-      ? Representation::Tagged() : value->OptimalRepresentation();
+  if (IsJSContextExtensionObject()) value_type = FORCE_TAGGED;
+  Representation representation = value->OptimalRepresentation(value_type);

   FieldDescriptor new_field(name, index, attributes, representation);

@@ -1961,7 +1962,8 @@
                                    PropertyAttributes attributes,
                                    StrictModeFlag strict_mode,
                                    JSReceiver::StoreFromKeyed store_mode,
- ExtensibilityCheck extensibility_check) {
+                                   ExtensibilityCheck extensibility_check,
+                                   ValueType value_type) {
   ASSERT(!IsJSGlobalProxy());
   Map* map_of_this = map();
   Heap* heap = GetHeap();
@@ -1988,7 +1990,8 @@
                                              JSFunction::cast(value),
                                              attributes);
       } else {
-        result = AddFastProperty(name, value, attributes, store_mode);
+        result = AddFastProperty(
+            name, value, attributes, store_mode, value_type);
       }
     } else {
       // Normalize the object to prevent very large instance descriptors.
@@ -2272,7 +2275,7 @@
     int limit = NumberOfOwnDescriptors();
     for (int i = 0; i < limit; i++) {
       if (new_desc->GetDetails(i).representation().IsDouble() &&
-          old_desc->GetDetails(i).representation().IsSmi()) {
+          !old_desc->GetDetails(i).representation().IsDouble()) {
         return true;
       }
     }
@@ -2343,8 +2346,9 @@
         ? old_descriptors->GetValue(i)
         : RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
     if (FLAG_track_double_fields &&
-        old_details.representation().IsSmi() &&
+        !old_details.representation().IsDouble() &&
         details.representation().IsDouble()) {
+      if (old_details.representation().IsNone()) value = Smi::FromInt(0);
       // Objects must be allocated in the old object space, since the
       // overall number of HeapNumbers needed for the conversion might
       // exceed the capacity of new space, and we would fail repeatedly
@@ -2397,7 +2401,7 @@
   MaybeObject* maybe_new_map =
       map()->GeneralizeRepresentation(modify_index, new_representation);
   if (!maybe_new_map->To(&new_map)) return maybe_new_map;
-  ASSERT(map() != new_map || new_map->FindRootMap()->is_deprecated());
+  if (map() == new_map) return this;

   return MigrateToMap(new_map);
 }
@@ -2574,10 +2578,21 @@
   Representation old_representation =
       old_descriptors->GetDetails(modify_index).representation();

-  if (old_representation.IsNone()) {
-    UNREACHABLE();
+  // It's fine to transition from None to anything but double without any
+ // modification to the object, because the default uninitialized value for
+  // representation None can be overwritten by both smi and tagged values.
+  // Doubles, however, would require a box allocation.
+  if (old_representation.IsNone() &&
+      !new_representation.IsNone() &&
+      !new_representation.IsDouble()) {
+    if (FLAG_trace_generalization) {
+      PrintF("initializing representation %i: %p -> %s\n",
+             modify_index,
+             static_cast<void*>(this),
+             new_representation.Mnemonic());
+    }
     old_descriptors->SetRepresentation(modify_index, new_representation);
-    return this;
+    return old_map;
   }

   int descriptors = old_map->NumberOfOwnDescriptors();
@@ -2603,7 +2618,7 @@
         updated_descriptors->GetDetails(modify_index).representation();
     if (new_representation.fits_into(updated_representation)) {
       if (FLAG_trace_generalization &&
-          !(modify_index == 0 && new_representation.IsSmi())) {
+          !(modify_index == 0 && new_representation.IsNone())) {
PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
         PrintF("migrating to existing map %p(%s) -> %p(%s)\n",
                static_cast<void*>(this),
@@ -2641,7 +2656,7 @@
       old_descriptors->GetKey(descriptor), new_descriptors);

   if (FLAG_trace_generalization &&
-      !(modify_index == 0 && new_representation.IsSmi())) {
+      !(modify_index == 0 && new_representation.IsNone())) {
     PrintF("migrating to new map %i: %p(%s) -> %p(%s) (%i steps)\n",
            modify_index,
            static_cast<void*>(this),
@@ -3933,10 +3948,12 @@
     Handle<JSObject> object,
     Handle<Name> key,
     Handle<Object> value,
-    PropertyAttributes attributes) {
+    PropertyAttributes attributes,
+    ValueType value_type) {
   CALL_HEAP_FUNCTION(
     object->GetIsolate(),
-    object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes),
+    object->SetLocalPropertyIgnoreAttributes(
+        *key, *value, attributes, value_type),
     Object);
 }

@@ -3944,7 +3961,8 @@
 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
     Name* name_raw,
     Object* value_raw,
-    PropertyAttributes attributes) {
+    PropertyAttributes attributes,
+    ValueType value_type) {
   // Make sure that the top context does not change when doing callbacks or
   // interceptor calls.
   AssertNoContextChange ncc;
@@ -3970,13 +3988,16 @@
     return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes(
         name_raw,
         value_raw,
-        attributes);
+        attributes,
+        value_type);
   }

   // Check for accessor in prototype chain removed here in clone.
   if (!lookup.IsFound()) {
     // Neither properties nor transitions found.
-    return AddProperty(name_raw, value_raw, attributes, kNonStrictMode);
+    return AddProperty(
+        name_raw, value_raw, attributes, kNonStrictMode,
+        MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, value_type);
   }

   // From this point on everything needs to be handlified.
@@ -4003,9 +4024,11 @@
     }
     case FIELD: {
       Representation representation = lookup.representation();
-      if (!value->FitsRepresentation(representation)) {
+      Representation value_representation =
+          value->OptimalRepresentation(value_type);
+      if (!value_representation.fits_into(representation)) {
         MaybeObject* maybe_failure = self->GeneralizeFieldRepresentation(
-            lookup.GetDescriptorIndex(), value->OptimalRepresentation());
+            lookup.GetDescriptorIndex(), value_representation);
         if (maybe_failure->IsFailure()) return maybe_failure;
         DescriptorArray* desc = self->map()->instance_descriptors();
         int descriptor = lookup.GetDescriptorIndex();
@@ -4046,9 +4069,11 @@
       if (details.type() == FIELD) {
         if (attributes == details.attributes()) {
           Representation representation = details.representation();
-          if (!value->FitsRepresentation(representation)) {
+          Representation value_representation =
+              value->OptimalRepresentation(value_type);
+          if (!value_representation.fits_into(representation)) {
MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
-                descriptor, value->OptimalRepresentation());
+                descriptor, value_representation);
             if (!maybe_map->To(&transition_map)) return maybe_map;
             Object* back = transition_map->GetBackPointer();
             if (back->IsMap()) {
=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Jun  6 06:28:22 2013
+++ /branches/bleeding_edge/src/objects.h       Thu Jun  6 07:21:35 2013
@@ -869,6 +869,7 @@
   inline bool IsOutOfMemory();
   inline bool IsException();
   INLINE(bool IsTheHole());
+  INLINE(bool IsUninitialized());
   inline bool ToObject(Object** obj) {
     if (IsFailure()) return false;
     *obj = reinterpret_cast<Object*>(this);
@@ -1046,6 +1047,7 @@
   INLINE(bool IsUndefined());
   INLINE(bool IsNull());
   INLINE(bool IsTheHole());  // Shadows MaybeObject's implementation.
+  INLINE(bool IsUninitialized());
   INLINE(bool IsTrue());
   INLINE(bool IsFalse());
   inline bool IsArgumentsMarker();
@@ -1060,16 +1062,24 @@
   bool ToInt32(int32_t* value);
   bool ToUint32(uint32_t* value);

-  inline Representation OptimalRepresentation() {
-    if (FLAG_track_fields && IsSmi()) {
+  // Indicates whether OptimalRepresentation can do its work, or whether it
+  // always has to return Representation::Tagged().
+  enum ValueType {
+    OPTIMAL_REPRESENTATION,
+    FORCE_TAGGED
+  };
+
+  inline Representation OptimalRepresentation(
+      ValueType type = OPTIMAL_REPRESENTATION) {
+    if (!FLAG_track_fields) return Representation::Tagged();
+    if (type == FORCE_TAGGED) return Representation::Tagged();
+    if (IsSmi()) {
       return Representation::Smi();
     } else if (FLAG_track_double_fields && IsHeapNumber()) {
       return Representation::Double();
-    } else if (FLAG_track_heap_object_fields && !IsUndefined()) {
- // Don't track undefined as heapobject because it's also used as temporary - // value for computed fields that may turn out to be Smi. That combination
-      // will go tagged, so go tagged immediately.
-      // TODO(verwaest): Change once we track computed boilerplate fields.
+    } else if (FLAG_track_computed_fields && IsUninitialized()) {
+      return Representation::None();
+    } else if (FLAG_track_heap_object_fields) {
       ASSERT(IsHeapObject());
       return Representation::HeapObject();
     } else {
@@ -1078,7 +1088,9 @@
   }

   inline bool FitsRepresentation(Representation representation) {
-    if (FLAG_track_fields && representation.IsSmi()) {
+    if (FLAG_track_fields && representation.IsNone()) {
+      return false;
+    } else if (FLAG_track_fields && representation.IsSmi()) {
       return IsSmi();
     } else if (FLAG_track_double_fields && representation.IsDouble()) {
       return IsNumber();
@@ -1827,7 +1839,8 @@
       Handle<JSObject> object,
       Handle<Name> key,
       Handle<Object> value,
-      PropertyAttributes attributes);
+      PropertyAttributes attributes,
+      ValueType value_type = OPTIMAL_REPRESENTATION);

   static inline Handle<String> ExpectedTransitionKey(Handle<Map> map);
   static inline Handle<Map> ExpectedTransitionTarget(Handle<Map> map);
@@ -1854,7 +1867,8 @@
   MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes(
       Name* key,
       Object* value,
-      PropertyAttributes attributes);
+      PropertyAttributes attributes,
+      ValueType value_type = OPTIMAL_REPRESENTATION);

   // Retrieve a value in a normalized object given a lookup result.
   // Handles the special representation of JS global objects.
@@ -2216,7 +2230,8 @@
       Name* name,
       Object* value,
       PropertyAttributes attributes,
-      StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
+      StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED,
+      ValueType value_type = OPTIMAL_REPRESENTATION);

   // Add a property to a slow-case object.
   MUST_USE_RESULT MaybeObject* AddSlowProperty(Name* name,
@@ -2230,7 +2245,8 @@
       PropertyAttributes attributes,
       StrictModeFlag strict_mode,
       StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED,
- ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK);
+      ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK,
+      ValueType value_type = OPTIMAL_REPRESENTATION);

   // Convert the object to use the canonical dictionary
// representation. If the object is expected to have additional properties
@@ -8483,7 +8499,8 @@
   static const byte kNull = 3;
   static const byte kArgumentMarker = 4;
   static const byte kUndefined = 5;
-  static const byte kOther = 6;
+  static const byte kUninitialized = 6;
+  static const byte kOther = 7;

   typedef FixedBodyDescriptor<kToStringOffset,
                               kToNumberOffset + kPointerSize,
=======================================
--- /branches/bleeding_edge/src/parser.cc       Thu Jun  6 06:28:22 2013
+++ /branches/bleeding_edge/src/parser.cc       Thu Jun  6 07:21:35 2013
@@ -3593,7 +3593,7 @@
     Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
     if (boilerplate_value->IsTheHole()) {
       is_holey = true;
-    } else if (boilerplate_value->IsUndefined()) {
+    } else if (boilerplate_value->IsUninitialized()) {
       is_simple = false;
       JSObject::SetOwnElement(
           array, i, handle(Smi::FromInt(0), isolate()), kNonStrictMode);
@@ -3693,7 +3693,7 @@
   if (CompileTimeValue::IsCompileTimeValue(expression)) {
     return CompileTimeValue::GetValue(expression);
   }
-  return isolate()->factory()->undefined_value();
+  return isolate()->factory()->uninitialized_value();
 }

 // Validation per 11.1.5 Object Initialiser
@@ -3804,13 +3804,17 @@
     Handle<Object> key = property->key()->handle();
     Handle<Object> value = GetBoilerplateValue(property->value());

-    // Ensure objects with doubles are always treated as nested objects.
+ // Ensure objects that may, at any point in time, contain fields with double + // representation are always treated as nested objects. This is true for
+    // computed fields (value is undefined), and smi and double literals
+    // (value->IsNumber()).
     // TODO(verwaest): Remove once we can store them inline.
-    if (FLAG_track_double_fields && value->IsNumber()) {
+    if (FLAG_track_double_fields &&
+        (value->IsNumber() || value->IsUninitialized())) {
       *may_store_doubles = true;
     }

-    is_simple_acc = is_simple_acc && !value->IsUndefined();
+    is_simple_acc = is_simple_acc && !value->IsUninitialized();

     // Keep track of the number of elements in the object literal and
     // the largest element index.  If the largest element index is
=======================================
--- /branches/bleeding_edge/src/property-details.h      Fri May 31 12:11:09 2013
+++ /branches/bleeding_edge/src/property-details.h      Thu Jun  6 07:21:35 2013
@@ -113,7 +113,7 @@
   bool is_more_general_than(const Representation& other) const {
     ASSERT(kind_ != kExternal);
     ASSERT(other.kind_ != kExternal);
-    if (IsHeapObject()) return other.IsDouble();
+    if (IsHeapObject()) return other.IsDouble() || other.IsNone();
     return kind_ > other.kind_;
   }

@@ -213,6 +213,7 @@
   }

   Representation representation() {
+    ASSERT(type() != NORMAL);
     return DecodeRepresentation(RepresentationField::decode(value_));
   }

=======================================
--- /branches/bleeding_edge/src/property.h      Fri May 31 12:11:09 2013
+++ /branches/bleeding_edge/src/property.h      Thu Jun  6 07:21:35 2013
@@ -203,6 +203,8 @@
   }

   bool CanHoldValue(Handle<Object> value) {
+    if (IsNormal()) return true;
+    ASSERT(!IsTransition());
     return value->FitsRepresentation(details_.representation());
   }

=======================================
--- /branches/bleeding_edge/test/mjsunit/track-fields.js Wed May 22 03:46:33 2013 +++ /branches/bleeding_edge/test/mjsunit/track-fields.js Thu Jun 6 07:21:35 2013
@@ -325,3 +325,83 @@
 df3.second_function = some_function2;
 df1.first_double = 10;
 read_first_double(df1);
+
+// Test boilerplates with computed values.
+function none_boilerplate(a) {
+  return {"a_none":a};
+}
+%OptimizeFunctionOnNextCall(none_boilerplate);
+var none_double1 = none_boilerplate(1.7);
+var none_double2 = none_boilerplate(1.9);
+assertTrue(%HaveSameMap(none_double1, none_double2));
+assertEquals(1.7, none_double1.a_none);
+assertEquals(1.9, none_double2.a_none);
+none_double2.a_none = 3.5;
+var none_double1 = none_boilerplate(1.7);
+var none_double2 = none_boilerplate(3.5);
+
+function none_to_smi(a) {
+  return {"a_smi":a};
+}
+
+var none_smi1 = none_to_smi(1);
+var none_smi2 = none_to_smi(2);
+%OptimizeFunctionOnNextCall(none_to_smi);
+var none_smi3 = none_to_smi(3);
+assertTrue(%HaveSameMap(none_smi1, none_smi2));
+assertTrue(%HaveSameMap(none_smi1, none_smi3));
+assertEquals(1, none_smi1.a_smi);
+assertEquals(2, none_smi2.a_smi);
+assertEquals(3, none_smi3.a_smi);
+
+function none_to_double(a) {
+  return {"a_double":a};
+}
+
+var none_to_double1 = none_to_double(1.5);
+var none_to_double2 = none_to_double(2.8);
+%OptimizeFunctionOnNextCall(none_to_double);
+var none_to_double3 = none_to_double(3.7);
+assertTrue(%HaveSameMap(none_to_double1, none_to_double2));
+assertTrue(%HaveSameMap(none_to_double1, none_to_double3));
+assertEquals(1.5, none_to_double1.a_double);
+assertEquals(2.8, none_to_double2.a_double);
+assertEquals(3.7, none_to_double3.a_double);
+
+function none_to_object(a) {
+  return {"an_object":a};
+}
+
+var none_to_object1 = none_to_object(true);
+var none_to_object2 = none_to_object(false);
+%OptimizeFunctionOnNextCall(none_to_object);
+var none_to_object3 = none_to_object(3.7);
+assertTrue(%HaveSameMap(none_to_object1, none_to_object2));
+assertTrue(%HaveSameMap(none_to_object1, none_to_object3));
+assertEquals(true, none_to_object1.an_object);
+assertEquals(false, none_to_object2.an_object);
+assertEquals(3.7, none_to_object3.an_object);
+
+function double_to_object(a) {
+  var o = {"d_to_h":1.8};
+  o.d_to_h = a;
+  return o;
+}
+
+var dh1 = double_to_object(true);
+var dh2 = double_to_object(false);
+assertTrue(%HaveSameMap(dh1, dh2));
+assertEquals(true, dh1.d_to_h);
+assertEquals(false, dh2.d_to_h);
+
+function smi_to_object(a) {
+  var o = {"s_to_t":18};
+  o.s_to_t = a;
+  return o;
+}
+
+var st1 = smi_to_object(true);
+var st2 = smi_to_object(false);
+assertTrue(%HaveSameMap(st1, st2));
+assertEquals(true, st1.s_to_t);
+assertEquals(false, st2.s_to_t);

--
--
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/groups/opt_out.


Reply via email to