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.