Revision: 14565
Author: [email protected]
Date: Tue May 7 03:32:23 2013
Log: Fix polymorphic to monomorphic load to take representation into
account.
Review URL: https://chromiumcodereview.appspot.com/14966005
http://code.google.com/p/v8/source/detail?r=14565
Modified:
/branches/bleeding_edge/src/code-stubs-hydrogen.cc
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/hydrogen.h
/branches/bleeding_edge/src/property-details.h
/branches/bleeding_edge/test/mjsunit/track-fields.js
=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Fri May 3 05:21:16
2013
+++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue May 7 03:32:23
2013
@@ -413,7 +413,7 @@
template<>
HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() {
Representation representation = casted_stub()->representation();
- HInstruction* load = AddInstruction(new(zone()) HLoadNamedField(
+ HInstruction* load = AddInstruction(DoBuildLoadNamedField(
GetParameter(0), casted_stub()->is_inobject(),
representation, casted_stub()->offset()));
return load;
@@ -428,7 +428,7 @@
template<>
HValue* CodeStubGraphBuilder<KeyedLoadFieldStub>::BuildCodeStub() {
Representation representation = casted_stub()->representation();
- HInstruction* load = AddInstruction(new(zone()) HLoadNamedField(
+ HInstruction* load = AddInstruction(DoBuildLoadNamedField(
GetParameter(0), casted_stub()->is_inobject(),
representation, casted_stub()->offset()));
return load;
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Fri May 3 06:39:11 2013
+++ /branches/bleeding_edge/src/hydrogen.cc Tue May 7 03:32:23 2013
@@ -7131,22 +7131,31 @@
HValue* object,
SmallMapList* types,
Handle<String> name) {
- int count = 0;
- int previous_field_offset = 0;
- bool previous_field_is_in_object = false;
- bool is_monomorphic_field = true;
if (HandlePolymorphicArrayLengthLoad(expr, object, types, name))
return;
- Handle<Map> map;
- LookupResult lookup(isolate());
- for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism;
++i) {
- map = types->at(i);
- if (ComputeLoadStoreField(map, name, &lookup, false)) {
+ AddInstruction(new(zone()) HCheckNonSmi(object));
+
+ // Use monomorphic load if property lookup results in the same field
index
+ // for all maps. Requires special map check on the set of all handled
maps.
+ HInstruction* instr = NULL;
+ if (types->length() > 0 && types->length() <= kMaxLoadPolymorphism) {
+ LookupResult lookup(isolate());
+ int previous_field_offset = 0;
+ bool previous_field_is_in_object = false;
+ Representation representation = Representation::None();
+ int count;
+ for (count = 0; count < types->length(); ++count) {
+ Handle<Map> map = types->at(count);
+ if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
+
int index = ComputeLoadStoreFieldIndex(map, &lookup);
+ Representation new_representation =
+ ComputeLoadStoreRepresentation(map, &lookup);
bool is_in_object = index < 0;
int offset = index * kPointerSize;
+
if (index < 0) {
// Negative property indices are in-object properties, indexed
// from the end of the fixed part of the object.
@@ -7154,31 +7163,33 @@
} else {
offset += FixedArray::kHeaderSize;
}
+
if (count == 0) {
previous_field_offset = offset;
previous_field_is_in_object = is_in_object;
- } else if (is_monomorphic_field) {
- is_monomorphic_field = (offset == previous_field_offset) &&
- (is_in_object ==
previous_field_is_in_object);
+ representation = new_representation;
+ } else if (offset != previous_field_offset ||
+ is_in_object != previous_field_is_in_object ||
+ (FLAG_track_fields &&
+ !representation.IsCompatibleForLoad(new_representation)))
{
+ break;
}
- ++count;
+
+ representation = representation.generalize(new_representation);
+ }
+
+ if (count == types->length()) {
+ AddInstruction(HCheckMaps::New(object, types, zone()));
+ instr = DoBuildLoadNamedField(
+ object, previous_field_is_in_object,
+ representation, previous_field_offset);
}
}
- // Use monomorphic load if property lookup results in the same field
index
- // for all maps. Requires special map check on the set of all handled
maps.
- AddInstruction(new(zone()) HCheckNonSmi(object));
- HInstruction* instr;
- if (count == types->length() && is_monomorphic_field) {
- AddInstruction(HCheckMaps::New(object, types, zone()));
- instr = BuildLoadNamedField(object, map, &lookup);
- } else {
+ if (instr == NULL) {
HValue* context = environment()->LookupContext();
- instr = new(zone()) HLoadNamedFieldPolymorphic(context,
- object,
- types,
- name,
- zone());
+ instr = new(zone()) HLoadNamedFieldPolymorphic(
+ context, object, types, name, zone());
}
instr->set_position(expr->position());
@@ -7735,18 +7746,25 @@
HValue* object,
Handle<Map> map,
LookupResult* lookup) {
- Representation representation = lookup->representation();
int index = lookup->GetLocalFieldIndexFromMap(*map);
- if (index < 0) {
- // Negative property indices are in-object properties, indexed
- // from the end of the fixed part of the object.
- int offset = (index * kPointerSize) + map->instance_size();
- return new(zone()) HLoadNamedField(object, true, representation,
offset);
- } else {
- // Non-negative property indices are in the properties array.
- int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
- return new(zone()) HLoadNamedField(object, false, representation,
offset);
- }
+ // Negative property indices are in-object properties, indexed from the
end of
+ // the fixed part of the object. Non-negative property indices are in the
+ // properties array.
+ int inobject = index < 0;
+ Representation representation = lookup->representation();
+ int offset = inobject
+ ? index * kPointerSize + map->instance_size()
+ : index * kPointerSize + FixedArray::kHeaderSize;
+ return DoBuildLoadNamedField(object, inobject, representation, offset);
+}
+
+
+HLoadNamedField* HGraphBuilder::DoBuildLoadNamedField(
+ HValue* object,
+ bool inobject,
+ Representation representation,
+ int offset) {
+ return new(zone()) HLoadNamedField(object, inobject, representation,
offset);
}
=======================================
--- /branches/bleeding_edge/src/hydrogen.h Fri May 3 05:21:16 2013
+++ /branches/bleeding_edge/src/hydrogen.h Tue May 7 03:32:23 2013
@@ -982,6 +982,11 @@
HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
// Building common constructs
+ HLoadNamedField* DoBuildLoadNamedField(HValue* object,
+ bool inobject,
+ Representation representation,
+ int offset);
+
HInstruction* BuildExternalArrayElementAccess(
HValue* external_elements,
HValue* checked_key,
=======================================
--- /branches/bleeding_edge/src/property-details.h Thu May 2 08:41:02 2013
+++ /branches/bleeding_edge/src/property-details.h Tue May 7 03:32:23 2013
@@ -102,6 +102,11 @@
bool Equals(const Representation& other) const {
return kind_ == other.kind_;
}
+
+ bool IsCompatibleForLoad(const Representation& other) const {
+ return (IsDouble() && other.IsDouble()) ||
+ (!IsDouble() && !other.IsDouble());
+ }
bool is_more_general_than(const Representation& other) const {
ASSERT(kind_ != kExternal);
=======================================
--- /branches/bleeding_edge/test/mjsunit/track-fields.js Fri Apr 26
08:30:41 2013
+++ /branches/bleeding_edge/test/mjsunit/track-fields.js Tue May 7
03:32:23 2013
@@ -99,3 +99,22 @@
// Smi, double, object.
o6.c = {};
assertTrue(%HaveSameMap(o6, o7));
+
+function poly_load(o, b) {
+ var v = o.field;
+ if (b) {
+ return v + 10;
+ }
+ return o;
+}
+
+var of1 = {a:0};
+of1.field = {};
+var of2 = {b:0};
+of2.field = 10;
+
+poly_load(of1, false);
+poly_load(of1, false);
+poly_load(of2, true);
+%OptimizeFunctionOnNextCall(poly_load);
+assertEquals("[object Object]10", poly_load(of1, true));
--
--
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.