Track heap objects.

R=danno@chromium.org

Review URL: https://chromiumcodereview.appspot.com/14996004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14625 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
verwaest@chromium.org 2013-05-10 17:17:50 +00:00
parent d97fe8d4df
commit df57747fc4
16 changed files with 103 additions and 19 deletions

View File

@ -2334,7 +2334,9 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp);
if (FLAG_track_fields && instr->field_representation().IsSmi()) {
if ((FLAG_track_fields && instr->field_representation().IsSmi()) ||
(FLAG_track_heap_object_fields &&
instr->field_representation().IsHeapObject())) {
return AssignEnvironment(result);
}
return result;

View File

@ -4229,6 +4229,12 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
if (!instr->hydrogen()->value()->range()->IsInSmiRange()) {
DeoptimizeIf(vs, instr->environment());
}
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
Register value = ToRegister(instr->value());
if (!instr->hydrogen()->value()->type().IsHeapObject()) {
__ tst(value, Operand(kSmiTagMask));
DeoptimizeIf(eq, instr->environment());
}
} else if (FLAG_track_double_fields && representation.IsDouble()) {
ASSERT(transition.is_null());
ASSERT(instr->is_in_object());

View File

@ -516,6 +516,8 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm,
if (FLAG_track_fields && representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_restore_name);
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_restore_name);
} else if (FLAG_track_double_fields && representation.IsDouble()) {
Label do_store, heap_number;
__ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex);
@ -685,6 +687,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
ASSERT(!representation.IsNone());
if (FLAG_track_fields && representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label);
} else if (FLAG_track_double_fields && representation.IsDouble()) {
// Load the double storage.
if (index < 0) {

View File

@ -195,7 +195,9 @@ DEFINE_bool(clever_optimizations,
DEFINE_bool(pretenure_literals, true, "allocate literals in old space")
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_implication(track_double_fields, track_fields)
DEFINE_implication(track_heap_object_fields, track_fields)
// Flags for data representation optimizations
DEFINE_bool(unbox_double_arrays, true, "automatically unbox arrays of doubles")

View File

@ -5218,6 +5218,10 @@ class HLoadNamedField: public HTemplateInstruction<2> {
set_representation(Representation::Tagged());
} else if (FLAG_track_double_fields && field_representation.IsDouble()) {
set_representation(field_representation);
} else if (FLAG_track_heap_object_fields &&
field_representation.IsHeapObject()) {
set_type(HType::NonPrimitive());
set_representation(Representation::Tagged());
} else {
set_representation(Representation::Tagged());
}

View File

@ -4239,6 +4239,19 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
DeoptimizeIf(overflow, instr->environment());
}
}
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
if (instr->value()->IsConstantOperand()) {
LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
if (IsInteger32(operand_value)) {
DeoptimizeIf(no_condition, instr->environment());
}
} else {
if (!instr->hydrogen()->value()->type().IsHeapObject()) {
Register value = ToRegister(instr->value());
__ test(value, Immediate(kSmiTagMask));
DeoptimizeIf(zero, instr->environment());
}
}
} else if (FLAG_track_double_fields && representation.IsDouble()) {
ASSERT(transition.is_null());
ASSERT(instr->is_in_object());

View File

@ -2458,7 +2458,9 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
LStoreNamedField* result =
new(zone()) LStoreNamedField(obj, val, temp, temp_map);
if (FLAG_track_fields && instr->field_representation().IsSmi()) {
if ((FLAG_track_fields && instr->field_representation().IsSmi()) ||
(FLAG_track_heap_object_fields &&
instr->field_representation().IsHeapObject())) {
return AssignEnvironment(result);
}
return result;

View File

@ -826,6 +826,8 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm,
if (FLAG_track_fields && representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_restore_name);
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_restore_name);
} else if (FLAG_track_double_fields && representation.IsDouble()) {
Label do_store, heap_number;
__ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow);
@ -996,6 +998,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
ASSERT(!representation.IsNone());
if (FLAG_track_fields && representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label);
} else if (FLAG_track_double_fields && representation.IsDouble()) {
// Load the double storage.
if (index < 0) {

View File

@ -3608,6 +3608,10 @@ bool Map::CanBeDeprecated() {
if (FLAG_track_double_fields && details.representation().IsDouble()) {
return true;
}
if (FLAG_track_heap_object_fields &&
details.representation().IsHeapObject()) {
return true;
}
}
return false;
}

View File

@ -2137,6 +2137,7 @@ const char* Representation::Mnemonic() const {
case kSmi: return "s";
case kDouble: return "d";
case kInteger32: return "i";
case kHeapObject: return "h";
case kExternal: return "x";
default:
UNREACHABLE();
@ -2499,10 +2500,10 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
Representation new_representation) {
Map* old_map = this;
DescriptorArray* old_descriptors = old_map->instance_descriptors();
Representation old_reprepresentation =
Representation old_representation =
old_descriptors->GetDetails(modify_index).representation();
if (old_reprepresentation.IsNone()) {
if (old_representation.IsNone()) {
UNREACHABLE();
old_descriptors->SetRepresentation(modify_index, new_representation);
return this;
@ -2528,9 +2529,14 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
Representation updated_representation =
updated_descriptors->GetDetails(modify_index).representation();
if (new_representation.fits_into(updated_representation)) {
if (FLAG_trace_generalization) {
PrintF("migrating to existing map %p -> %p\n",
static_cast<void*>(this), static_cast<void*>(updated));
if (FLAG_trace_generalization &&
!(modify_index == 0 && new_representation.IsSmi())) {
PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
PrintF("migrating to existing map %p(%s) -> %p(%s)\n",
static_cast<void*>(this),
old_details.representation().Mnemonic(),
static_cast<void*>(updated),
updated_representation.Mnemonic());
}
return updated;
}
@ -2541,10 +2547,13 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
verbatim, valid, descriptors, old_descriptors);
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
old_reprepresentation =
old_representation =
new_descriptors->GetDetails(modify_index).representation();
new_representation = new_representation.generalize(old_reprepresentation);
new_descriptors->SetRepresentation(modify_index, new_representation);
Representation updated_representation =
new_representation.generalize(old_representation);
if (!updated_representation.Equals(old_representation)) {
new_descriptors->SetRepresentation(modify_index, updated_representation);
}
Map* split_map = root_map->FindLastMatchMap(
verbatim, descriptors, new_descriptors);
@ -2558,10 +2567,14 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
split_map->DeprecateTarget(
old_descriptors->GetKey(descriptor), new_descriptors);
if (FLAG_trace_generalization) {
PrintF("migrating to new map %p -> %p (%i steps)\n",
if (FLAG_trace_generalization &&
!(modify_index == 0 && new_representation.IsSmi())) {
PrintF("migrating to new map %i: %p(%s) -> %p(%s) (%i steps)\n",
modify_index,
static_cast<void*>(this),
old_representation.Mnemonic(),
static_cast<void*>(new_descriptors),
updated_representation.Mnemonic(),
descriptors - descriptor);
}

View File

@ -1066,6 +1066,13 @@ class Object : public MaybeObject {
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.
ASSERT(IsHeapObject());
return Representation::HeapObject();
} else {
return Representation::Tagged();
}
@ -1076,6 +1083,8 @@ class Object : public MaybeObject {
return IsSmi();
} else if (FLAG_track_double_fields && representation.IsDouble()) {
return IsNumber();
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
return IsHeapObject();
}
return true;
}

View File

@ -83,6 +83,7 @@ class Representation {
kSmi,
kInteger32,
kDouble,
kHeapObject,
kTagged,
kExternal,
kNumRepresentations
@ -95,6 +96,7 @@ class Representation {
static Representation Smi() { return Representation(kSmi); }
static Representation Integer32() { return Representation(kInteger32); }
static Representation Double() { return Representation(kDouble); }
static Representation HeapObject() { return Representation(kHeapObject); }
static Representation External() { return Representation(kExternal); }
static Representation FromKind(Kind kind) { return Representation(kind); }
@ -111,6 +113,7 @@ class Representation {
bool is_more_general_than(const Representation& other) const {
ASSERT(kind_ != kExternal);
ASSERT(other.kind_ != kExternal);
if (IsHeapObject()) return other.IsDouble();
return kind_ > other.kind_;
}
@ -119,11 +122,9 @@ class Representation {
}
Representation generalize(Representation other) {
if (is_more_general_than(other)) {
return *this;
} else {
return other;
}
if (other.fits_into(*this)) return *this;
if (other.is_more_general_than(*this)) return other;
return Representation::Tagged();
}
Kind kind() const { return static_cast<Kind>(kind_); }
@ -132,6 +133,7 @@ class Representation {
bool IsSmi() const { return kind_ == kSmi; }
bool IsInteger32() const { return kind_ == kInteger32; }
bool IsDouble() const { return kind_ == kDouble; }
bool IsHeapObject() const { return kind_ == kHeapObject; }
bool IsExternal() const { return kind_ == kExternal; }
bool IsSpecialization() const {
return kind_ == kInteger32 || kind_ == kDouble;

View File

@ -3921,6 +3921,19 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
Register value = ToRegister(instr->value());
__ Integer32ToSmi(value, value);
}
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
if (instr->value()->IsConstantOperand()) {
LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
if (IsInteger32Constant(operand_value)) {
DeoptimizeIf(no_condition, instr->environment());
}
} else {
if (!instr->hydrogen()->value()->type().IsHeapObject()) {
Register value = ToRegister(instr->value());
Condition cc = masm()->CheckSmi(value);
DeoptimizeIf(cc, instr->environment());
}
}
} else if (FLAG_track_double_fields && representation.IsDouble()) {
ASSERT(transition.is_null());
ASSERT(instr->is_in_object());

View File

@ -2273,7 +2273,9 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
needs_write_barrier_for_map) ? TempRegister() : NULL;
LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp);
if (FLAG_track_fields && instr->field_representation().IsSmi()) {
if ((FLAG_track_fields && instr->field_representation().IsSmi()) ||
(FLAG_track_heap_object_fields &&
instr->field_representation().IsHeapObject())) {
return AssignEnvironment(result);
}
return result;

View File

@ -807,6 +807,8 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm,
if (FLAG_track_fields && representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_restore_name);
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_restore_name);
} else if (FLAG_track_double_fields && representation.IsDouble()) {
Label do_store, heap_number;
__ AllocateHeapNumber(storage_reg, scratch1, slow);
@ -953,6 +955,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
ASSERT(!representation.IsNone());
if (FLAG_track_fields && representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
__ JumpIfSmi(value_reg, miss_label);
} else if (FLAG_track_double_fields && representation.IsDouble()) {
// Load the double storage.
if (index < 0) {

View File

@ -129,7 +129,7 @@ if (support_smi_only_arrays) {
// upon can hoisted, too.
function testExactMapHoisting3(a) {
var object = new Object();
a.foo = 0;
a.foo = null;
a[0] = 0;
a[1] = 1;
var count = 3;