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:
parent
d97fe8d4df
commit
df57747fc4
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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) {
|
||||
|
@ -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")
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user