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;
|
LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
|
||||||
|
|
||||||
LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp);
|
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 AssignEnvironment(result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -4229,6 +4229,12 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
|
|||||||
if (!instr->hydrogen()->value()->range()->IsInSmiRange()) {
|
if (!instr->hydrogen()->value()->range()->IsInSmiRange()) {
|
||||||
DeoptimizeIf(vs, instr->environment());
|
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()) {
|
} else if (FLAG_track_double_fields && representation.IsDouble()) {
|
||||||
ASSERT(transition.is_null());
|
ASSERT(transition.is_null());
|
||||||
ASSERT(instr->is_in_object());
|
ASSERT(instr->is_in_object());
|
||||||
|
@ -516,6 +516,8 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm,
|
|||||||
|
|
||||||
if (FLAG_track_fields && representation.IsSmi()) {
|
if (FLAG_track_fields && representation.IsSmi()) {
|
||||||
__ JumpIfNotSmi(value_reg, miss_restore_name);
|
__ 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()) {
|
} else if (FLAG_track_double_fields && representation.IsDouble()) {
|
||||||
Label do_store, heap_number;
|
Label do_store, heap_number;
|
||||||
__ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex);
|
__ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex);
|
||||||
@ -685,6 +687,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
|||||||
ASSERT(!representation.IsNone());
|
ASSERT(!representation.IsNone());
|
||||||
if (FLAG_track_fields && representation.IsSmi()) {
|
if (FLAG_track_fields && representation.IsSmi()) {
|
||||||
__ JumpIfNotSmi(value_reg, miss_label);
|
__ 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()) {
|
} else if (FLAG_track_double_fields && representation.IsDouble()) {
|
||||||
// Load the double storage.
|
// Load the double storage.
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
|
@ -195,7 +195,9 @@ DEFINE_bool(clever_optimizations,
|
|||||||
DEFINE_bool(pretenure_literals, true, "allocate literals in old space")
|
DEFINE_bool(pretenure_literals, true, "allocate literals in old space")
|
||||||
DEFINE_bool(track_fields, true, "track fields with only smi values")
|
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_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_double_fields, track_fields)
|
||||||
|
DEFINE_implication(track_heap_object_fields, track_fields)
|
||||||
|
|
||||||
// Flags for data representation optimizations
|
// Flags for data representation optimizations
|
||||||
DEFINE_bool(unbox_double_arrays, true, "automatically unbox arrays of doubles")
|
DEFINE_bool(unbox_double_arrays, true, "automatically unbox arrays of doubles")
|
||||||
|
@ -5218,6 +5218,10 @@ class HLoadNamedField: public HTemplateInstruction<2> {
|
|||||||
set_representation(Representation::Tagged());
|
set_representation(Representation::Tagged());
|
||||||
} else if (FLAG_track_double_fields && field_representation.IsDouble()) {
|
} else if (FLAG_track_double_fields && field_representation.IsDouble()) {
|
||||||
set_representation(field_representation);
|
set_representation(field_representation);
|
||||||
|
} else if (FLAG_track_heap_object_fields &&
|
||||||
|
field_representation.IsHeapObject()) {
|
||||||
|
set_type(HType::NonPrimitive());
|
||||||
|
set_representation(Representation::Tagged());
|
||||||
} else {
|
} else {
|
||||||
set_representation(Representation::Tagged());
|
set_representation(Representation::Tagged());
|
||||||
}
|
}
|
||||||
|
@ -4239,6 +4239,19 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
|
|||||||
DeoptimizeIf(overflow, instr->environment());
|
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()) {
|
} else if (FLAG_track_double_fields && representation.IsDouble()) {
|
||||||
ASSERT(transition.is_null());
|
ASSERT(transition.is_null());
|
||||||
ASSERT(instr->is_in_object());
|
ASSERT(instr->is_in_object());
|
||||||
|
@ -2458,7 +2458,9 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
|
|||||||
|
|
||||||
LStoreNamedField* result =
|
LStoreNamedField* result =
|
||||||
new(zone()) LStoreNamedField(obj, val, temp, temp_map);
|
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 AssignEnvironment(result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -826,6 +826,8 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm,
|
|||||||
|
|
||||||
if (FLAG_track_fields && representation.IsSmi()) {
|
if (FLAG_track_fields && representation.IsSmi()) {
|
||||||
__ JumpIfNotSmi(value_reg, miss_restore_name);
|
__ 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()) {
|
} else if (FLAG_track_double_fields && representation.IsDouble()) {
|
||||||
Label do_store, heap_number;
|
Label do_store, heap_number;
|
||||||
__ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow);
|
__ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow);
|
||||||
@ -996,6 +998,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
|||||||
ASSERT(!representation.IsNone());
|
ASSERT(!representation.IsNone());
|
||||||
if (FLAG_track_fields && representation.IsSmi()) {
|
if (FLAG_track_fields && representation.IsSmi()) {
|
||||||
__ JumpIfNotSmi(value_reg, miss_label);
|
__ 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()) {
|
} else if (FLAG_track_double_fields && representation.IsDouble()) {
|
||||||
// Load the double storage.
|
// Load the double storage.
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
|
@ -3608,6 +3608,10 @@ bool Map::CanBeDeprecated() {
|
|||||||
if (FLAG_track_double_fields && details.representation().IsDouble()) {
|
if (FLAG_track_double_fields && details.representation().IsDouble()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (FLAG_track_heap_object_fields &&
|
||||||
|
details.representation().IsHeapObject()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2137,6 +2137,7 @@ const char* Representation::Mnemonic() const {
|
|||||||
case kSmi: return "s";
|
case kSmi: return "s";
|
||||||
case kDouble: return "d";
|
case kDouble: return "d";
|
||||||
case kInteger32: return "i";
|
case kInteger32: return "i";
|
||||||
|
case kHeapObject: return "h";
|
||||||
case kExternal: return "x";
|
case kExternal: return "x";
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -2499,10 +2500,10 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
|
|||||||
Representation new_representation) {
|
Representation new_representation) {
|
||||||
Map* old_map = this;
|
Map* old_map = this;
|
||||||
DescriptorArray* old_descriptors = old_map->instance_descriptors();
|
DescriptorArray* old_descriptors = old_map->instance_descriptors();
|
||||||
Representation old_reprepresentation =
|
Representation old_representation =
|
||||||
old_descriptors->GetDetails(modify_index).representation();
|
old_descriptors->GetDetails(modify_index).representation();
|
||||||
|
|
||||||
if (old_reprepresentation.IsNone()) {
|
if (old_representation.IsNone()) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
old_descriptors->SetRepresentation(modify_index, new_representation);
|
old_descriptors->SetRepresentation(modify_index, new_representation);
|
||||||
return this;
|
return this;
|
||||||
@ -2528,9 +2529,14 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
|
|||||||
Representation updated_representation =
|
Representation updated_representation =
|
||||||
updated_descriptors->GetDetails(modify_index).representation();
|
updated_descriptors->GetDetails(modify_index).representation();
|
||||||
if (new_representation.fits_into(updated_representation)) {
|
if (new_representation.fits_into(updated_representation)) {
|
||||||
if (FLAG_trace_generalization) {
|
if (FLAG_trace_generalization &&
|
||||||
PrintF("migrating to existing map %p -> %p\n",
|
!(modify_index == 0 && new_representation.IsSmi())) {
|
||||||
static_cast<void*>(this), static_cast<void*>(updated));
|
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;
|
return updated;
|
||||||
}
|
}
|
||||||
@ -2541,10 +2547,13 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
|
|||||||
verbatim, valid, descriptors, old_descriptors);
|
verbatim, valid, descriptors, old_descriptors);
|
||||||
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
||||||
|
|
||||||
old_reprepresentation =
|
old_representation =
|
||||||
new_descriptors->GetDetails(modify_index).representation();
|
new_descriptors->GetDetails(modify_index).representation();
|
||||||
new_representation = new_representation.generalize(old_reprepresentation);
|
Representation updated_representation =
|
||||||
new_descriptors->SetRepresentation(modify_index, new_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(
|
Map* split_map = root_map->FindLastMatchMap(
|
||||||
verbatim, descriptors, new_descriptors);
|
verbatim, descriptors, new_descriptors);
|
||||||
@ -2558,10 +2567,14 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
|
|||||||
split_map->DeprecateTarget(
|
split_map->DeprecateTarget(
|
||||||
old_descriptors->GetKey(descriptor), new_descriptors);
|
old_descriptors->GetKey(descriptor), new_descriptors);
|
||||||
|
|
||||||
if (FLAG_trace_generalization) {
|
if (FLAG_trace_generalization &&
|
||||||
PrintF("migrating to new map %p -> %p (%i steps)\n",
|
!(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),
|
static_cast<void*>(this),
|
||||||
|
old_representation.Mnemonic(),
|
||||||
static_cast<void*>(new_descriptors),
|
static_cast<void*>(new_descriptors),
|
||||||
|
updated_representation.Mnemonic(),
|
||||||
descriptors - descriptor);
|
descriptors - descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1066,6 +1066,13 @@ class Object : public MaybeObject {
|
|||||||
return Representation::Smi();
|
return Representation::Smi();
|
||||||
} else if (FLAG_track_double_fields && IsHeapNumber()) {
|
} else if (FLAG_track_double_fields && IsHeapNumber()) {
|
||||||
return Representation::Double();
|
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 {
|
} else {
|
||||||
return Representation::Tagged();
|
return Representation::Tagged();
|
||||||
}
|
}
|
||||||
@ -1076,6 +1083,8 @@ class Object : public MaybeObject {
|
|||||||
return IsSmi();
|
return IsSmi();
|
||||||
} else if (FLAG_track_double_fields && representation.IsDouble()) {
|
} else if (FLAG_track_double_fields && representation.IsDouble()) {
|
||||||
return IsNumber();
|
return IsNumber();
|
||||||
|
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
|
||||||
|
return IsHeapObject();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,7 @@ class Representation {
|
|||||||
kSmi,
|
kSmi,
|
||||||
kInteger32,
|
kInteger32,
|
||||||
kDouble,
|
kDouble,
|
||||||
|
kHeapObject,
|
||||||
kTagged,
|
kTagged,
|
||||||
kExternal,
|
kExternal,
|
||||||
kNumRepresentations
|
kNumRepresentations
|
||||||
@ -95,6 +96,7 @@ class Representation {
|
|||||||
static Representation Smi() { return Representation(kSmi); }
|
static Representation Smi() { return Representation(kSmi); }
|
||||||
static Representation Integer32() { return Representation(kInteger32); }
|
static Representation Integer32() { return Representation(kInteger32); }
|
||||||
static Representation Double() { return Representation(kDouble); }
|
static Representation Double() { return Representation(kDouble); }
|
||||||
|
static Representation HeapObject() { return Representation(kHeapObject); }
|
||||||
static Representation External() { return Representation(kExternal); }
|
static Representation External() { return Representation(kExternal); }
|
||||||
|
|
||||||
static Representation FromKind(Kind kind) { return Representation(kind); }
|
static Representation FromKind(Kind kind) { return Representation(kind); }
|
||||||
@ -111,6 +113,7 @@ class Representation {
|
|||||||
bool is_more_general_than(const Representation& other) const {
|
bool is_more_general_than(const Representation& other) const {
|
||||||
ASSERT(kind_ != kExternal);
|
ASSERT(kind_ != kExternal);
|
||||||
ASSERT(other.kind_ != kExternal);
|
ASSERT(other.kind_ != kExternal);
|
||||||
|
if (IsHeapObject()) return other.IsDouble();
|
||||||
return kind_ > other.kind_;
|
return kind_ > other.kind_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,11 +122,9 @@ class Representation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Representation generalize(Representation other) {
|
Representation generalize(Representation other) {
|
||||||
if (is_more_general_than(other)) {
|
if (other.fits_into(*this)) return *this;
|
||||||
return *this;
|
if (other.is_more_general_than(*this)) return other;
|
||||||
} else {
|
return Representation::Tagged();
|
||||||
return other;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Kind kind() const { return static_cast<Kind>(kind_); }
|
Kind kind() const { return static_cast<Kind>(kind_); }
|
||||||
@ -132,6 +133,7 @@ class Representation {
|
|||||||
bool IsSmi() const { return kind_ == kSmi; }
|
bool IsSmi() const { return kind_ == kSmi; }
|
||||||
bool IsInteger32() const { return kind_ == kInteger32; }
|
bool IsInteger32() const { return kind_ == kInteger32; }
|
||||||
bool IsDouble() const { return kind_ == kDouble; }
|
bool IsDouble() const { return kind_ == kDouble; }
|
||||||
|
bool IsHeapObject() const { return kind_ == kHeapObject; }
|
||||||
bool IsExternal() const { return kind_ == kExternal; }
|
bool IsExternal() const { return kind_ == kExternal; }
|
||||||
bool IsSpecialization() const {
|
bool IsSpecialization() const {
|
||||||
return kind_ == kInteger32 || kind_ == kDouble;
|
return kind_ == kInteger32 || kind_ == kDouble;
|
||||||
|
@ -3921,6 +3921,19 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
|
|||||||
Register value = ToRegister(instr->value());
|
Register value = ToRegister(instr->value());
|
||||||
__ Integer32ToSmi(value, 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()) {
|
} else if (FLAG_track_double_fields && representation.IsDouble()) {
|
||||||
ASSERT(transition.is_null());
|
ASSERT(transition.is_null());
|
||||||
ASSERT(instr->is_in_object());
|
ASSERT(instr->is_in_object());
|
||||||
|
@ -2273,7 +2273,9 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
|
|||||||
needs_write_barrier_for_map) ? TempRegister() : NULL;
|
needs_write_barrier_for_map) ? TempRegister() : NULL;
|
||||||
|
|
||||||
LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp);
|
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 AssignEnvironment(result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -807,6 +807,8 @@ void StubCompiler::GenerateStoreTransition(MacroAssembler* masm,
|
|||||||
|
|
||||||
if (FLAG_track_fields && representation.IsSmi()) {
|
if (FLAG_track_fields && representation.IsSmi()) {
|
||||||
__ JumpIfNotSmi(value_reg, miss_restore_name);
|
__ 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()) {
|
} else if (FLAG_track_double_fields && representation.IsDouble()) {
|
||||||
Label do_store, heap_number;
|
Label do_store, heap_number;
|
||||||
__ AllocateHeapNumber(storage_reg, scratch1, slow);
|
__ AllocateHeapNumber(storage_reg, scratch1, slow);
|
||||||
@ -953,6 +955,8 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
|
|||||||
ASSERT(!representation.IsNone());
|
ASSERT(!representation.IsNone());
|
||||||
if (FLAG_track_fields && representation.IsSmi()) {
|
if (FLAG_track_fields && representation.IsSmi()) {
|
||||||
__ JumpIfNotSmi(value_reg, miss_label);
|
__ 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()) {
|
} else if (FLAG_track_double_fields && representation.IsDouble()) {
|
||||||
// Load the double storage.
|
// Load the double storage.
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
|
@ -129,7 +129,7 @@ if (support_smi_only_arrays) {
|
|||||||
// upon can hoisted, too.
|
// upon can hoisted, too.
|
||||||
function testExactMapHoisting3(a) {
|
function testExactMapHoisting3(a) {
|
||||||
var object = new Object();
|
var object = new Object();
|
||||||
a.foo = 0;
|
a.foo = null;
|
||||||
a[0] = 0;
|
a[0] = 0;
|
||||||
a[1] = 1;
|
a[1] = 1;
|
||||||
var count = 3;
|
var count = 3;
|
||||||
|
Loading…
Reference in New Issue
Block a user