Revision: 14474
Author: [email protected]
Date: Fri Apr 26 16:28:09 2013
Log: MIPS: Track storage types of instance variables.
Port r14464 (70300e97) and r14470 (65af80fc)
BUG=
Review URL: https://codereview.chromium.org/14305024
http://code.google.com/p/v8/source/detail?r=14474
Modified:
/branches/bleeding_edge/src/mips/lithium-codegen-mips.cc
/branches/bleeding_edge/src/mips/lithium-codegen-mips.h
/branches/bleeding_edge/src/mips/lithium-mips.cc
/branches/bleeding_edge/src/mips/lithium-mips.h
/branches/bleeding_edge/src/mips/macro-assembler-mips.cc
/branches/bleeding_edge/src/mips/macro-assembler-mips.h
/branches/bleeding_edge/src/mips/stub-cache-mips.cc
=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Fri Apr 26
16:26:52 2013
+++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Fri Apr 26
16:28:09 2013
@@ -91,6 +91,10 @@
prototype_maps_.at(i)->AddDependentCode(
DependentCode::kPrototypeCheckGroup, code);
}
+ for (int i = 0 ; i < transition_maps_.length(); i++) {
+ transition_maps_.at(i)->AddDependentCode(
+ DependentCode::kTransitionGroup, code);
+ }
}
@@ -2685,12 +2689,30 @@
void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
Register object = ToRegister(instr->object());
- Register result = ToRegister(instr->result());
+ if (!FLAG_track_double_fields) {
+ ASSERT(!instr->hydrogen()->representation().IsDouble());
+ }
+ Register temp = instr->hydrogen()->representation().IsDouble()
+ ? scratch0() : ToRegister(instr->result());
if (instr->hydrogen()->is_in_object()) {
- __ lw(result, FieldMemOperand(object, instr->hydrogen()->offset()));
+ __ lw(temp, FieldMemOperand(object, instr->hydrogen()->offset()));
} else {
- __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
- __ lw(result, FieldMemOperand(result, instr->hydrogen()->offset()));
+ __ lw(temp, FieldMemOperand(object, JSObject::kPropertiesOffset));
+ __ lw(temp, FieldMemOperand(temp, instr->hydrogen()->offset()));
+ }
+
+ if (instr->hydrogen()->representation().IsDouble()) {
+ Label load_from_heap_number, done;
+ DoubleRegister result = ToDoubleRegister(instr->result());
+ FPURegister flt_scratch = double_scratch0().low();
+ __ JumpIfNotSmi(temp, &load_from_heap_number);
+ __ SmiUntag(temp);
+ __ mtc1(temp, flt_scratch);
+ __ cvt_d_w(result, flt_scratch);
+ __ Branch(&done);
+ __ bind(&load_from_heap_number);
+ __ ldc1(result, FieldMemOperand(temp, HeapNumber::kValueOffset));
+ __ bind(&done);
}
}
@@ -3919,15 +3941,37 @@
void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
+ Representation representation = instr->representation();
+
Register object = ToRegister(instr->object());
Register value = ToRegister(instr->value());
+ ASSERT(!object.is(value));
Register scratch = scratch0();
int offset = instr->offset();
- ASSERT(!object.is(value));
+ if (FLAG_track_fields && representation.IsSmi()) {
+ __ SmiTagCheckOverflow(value, value, scratch);
+ if (!instr->hydrogen()->value()->range()->IsInSmiRange()) {
+ DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg));
+ }
+ } else if (FLAG_track_double_fields && representation.IsDouble() &&
+ !instr->hydrogen()->value()->type().IsSmi() &&
+ !instr->hydrogen()->value()->type().IsHeapNumber()) {
+ Label do_store;
+ __ JumpIfSmi(value, &do_store);
+ Handle<Map> map(isolate()->factory()->heap_number_map());
- if (!instr->transition().is_null()) {
- __ li(scratch, Operand(instr->transition()));
+ __ lw(scratch, FieldMemOperand(value, HeapObject::kMapOffset));
+ DoCheckMapCommon(scratch, map, REQUIRE_EXACT_MAP,
instr->environment());
+ __ bind(&do_store);
+ }
+
+ Handle<Map> transition = instr->transition();
+ if (!transition.is_null()) {
+ if (transition->CanBeDeprecated()) {
+ transition_maps_.Add(transition, info()->zone());
+ }
+ __ li(scratch, Operand(transition));
__ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
Register temp = ToRegister(instr->temp());
=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.h Tue Apr 23
17:58:48 2013
+++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.h Fri Apr 26
16:28:09 2013
@@ -56,6 +56,7 @@
deopt_jump_table_(4, info->zone()),
deoptimization_literals_(8, info->zone()),
prototype_maps_(0, info->zone()),
+ transition_maps_(0, info->zone()),
inlined_function_count_(0),
scope_(info->scope()),
status_(UNUSED),
@@ -416,6 +417,7 @@
ZoneList<JumpTableEntry> deopt_jump_table_;
ZoneList<Handle<Object> > deoptimization_literals_;
ZoneList<Handle<Map> > prototype_maps_;
+ ZoneList<Handle<Map> > transition_maps_;
int inlined_function_count_;
Scope* const scope_;
Status status_;
=======================================
--- /branches/bleeding_edge/src/mips/lithium-mips.cc Fri Apr 26 16:26:52
2013
+++ /branches/bleeding_edge/src/mips/lithium-mips.cc Fri Apr 26 16:28:09
2013
@@ -1993,8 +1993,8 @@
LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
- return DefineAsRegister(
- new(zone()) LLoadNamedField(UseRegisterAtStart(instr->object())));
+ LOperand* obj = UseRegisterAtStart(instr->object());
+ return DefineAsRegister(new(zone()) LLoadNamedField(obj));
}
@@ -2199,14 +2199,20 @@
: UseRegisterAtStart(instr->object());
}
- LOperand* val = needs_write_barrier
- ? UseTempRegister(instr->value())
- : UseRegister(instr->value());
+ LOperand* val =
+ needs_write_barrier ||
+ (FLAG_track_fields && instr->field_representation().IsSmi())
+ ? UseTempRegister(instr->value()) : UseRegister(instr->value());
// We need a temporary register for write barrier of the map field.
LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
- return new(zone()) LStoreNamedField(obj, val, temp);
+ LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp);
+ if ((FLAG_track_fields && instr->field_representation().IsSmi()) ||
+ (FLAG_track_double_fields &&
instr->field_representation().IsDouble())) {
+ return AssignEnvironment(result);
+ }
+ return result;
}
=======================================
--- /branches/bleeding_edge/src/mips/lithium-mips.h Fri Apr 26 16:26:52 2013
+++ /branches/bleeding_edge/src/mips/lithium-mips.h Fri Apr 26 16:28:09 2013
@@ -2089,6 +2089,9 @@
bool is_in_object() { return hydrogen()->is_in_object(); }
int offset() { return hydrogen()->offset(); }
Handle<Map> transition() const { return hydrogen()->transition(); }
+ Representation representation() const {
+ return hydrogen()->field_representation();
+ }
};
=======================================
--- /branches/bleeding_edge/src/mips/macro-assembler-mips.cc Wed Apr 24
16:12:53 2013
+++ /branches/bleeding_edge/src/mips/macro-assembler-mips.cc Fri Apr 26
16:28:09 2013
@@ -5133,6 +5133,18 @@
And(scratch, scratch, Operand(mask));
Branch(condition_met, cc, scratch, Operand(zero_reg));
}
+
+
+void MacroAssembler::CheckMapDeprecated(Handle<Map> map,
+ Register scratch,
+ Label* if_deprecated) {
+ if (map->CanBeDeprecated()) {
+ li(scratch, Operand(map));
+ lw(scratch, FieldMemOperand(scratch, Map::kBitField3Offset));
+ And(scratch, scratch, Operand(Smi::FromInt(Map::Deprecated::kMask)));
+ Branch(if_deprecated, ne, scratch, Operand(zero_reg));
+ }
+}
void MacroAssembler::JumpIfBlack(Register object,
=======================================
--- /branches/bleeding_edge/src/mips/macro-assembler-mips.h Tue Apr 23
17:58:48 2013
+++ /branches/bleeding_edge/src/mips/macro-assembler-mips.h Fri Apr 26
16:28:09 2013
@@ -325,6 +325,10 @@
Condition cc,
Label* condition_met);
+ void CheckMapDeprecated(Handle<Map> map,
+ Register scratch,
+ Label* if_deprecated);
+
// Check if object is in new space. Jumps if the object is not in new
space.
// The register scratch can be object itself, but it will be clobbered.
void JumpIfNotInNewSpace(Register object,
=======================================
--- /branches/bleeding_edge/src/mips/stub-cache-mips.cc Wed Apr 24 00:39:35
2013
+++ /branches/bleeding_edge/src/mips/stub-cache-mips.cc Fri Apr 26 16:28:09
2013
@@ -455,6 +455,25 @@
if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label);
}
+
+ int descriptor = transition->LastAdded();
+ DescriptorArray* descriptors = transition->instance_descriptors();
+ PropertyDetails details = descriptors->GetDetails(descriptor);
+ Representation representation = details.representation();
+ ASSERT(!representation.IsNone());
+
+ // Ensure no transitions to deprecated maps are followed.
+ __ CheckMapDeprecated(transition, scratch1, miss_label);
+
+ if (FLAG_track_fields && representation.IsSmi()) {
+ __ JumpIfNotSmi(value_reg, miss_label);
+ } else if (FLAG_track_double_fields && representation.IsDouble()) {
+ Label do_store;
+ __ JumpIfSmi(value_reg, &do_store);
+ __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex,
+ miss_label, DONT_DO_SMI_CHECK);
+ __ bind(&do_store);
+ }
// Check that we are allowed to write this.
if (object->GetPrototype()->IsJSObject()) {
@@ -537,18 +556,20 @@
int offset = object->map()->instance_size() + (index * kPointerSize);
__ sw(value_reg, FieldMemOperand(receiver_reg, offset));
- // Skip updating write barrier if storing a smi.
- __ JumpIfSmi(value_reg, &exit);
+ if (!FLAG_track_fields || !representation.IsSmi()) {
+ // Skip updating write barrier if storing a smi.
+ __ JumpIfSmi(value_reg, &exit);
- // Update the write barrier for the array address.
- // Pass the now unused name_reg as a scratch register.
- __ mov(name_reg, value_reg);
- __ RecordWriteField(receiver_reg,
- offset,
- name_reg,
- scratch1,
- kRAHasNotBeenSaved,
- kDontSaveFPRegs);
+ // Update the write barrier for the array address.
+ // Pass the now unused name_reg as a scratch register.
+ __ mov(name_reg, value_reg);
+ __ RecordWriteField(receiver_reg,
+ offset,
+ name_reg,
+ scratch1,
+ kRAHasNotBeenSaved,
+ kDontSaveFPRegs);
+ }
} else {
// Write to the properties array.
int offset = index * kPointerSize + FixedArray::kHeaderSize;
@@ -557,18 +578,20 @@
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
__ sw(value_reg, FieldMemOperand(scratch1, offset));
- // Skip updating write barrier if storing a smi.
- __ JumpIfSmi(value_reg, &exit);
+ if (!FLAG_track_fields || !representation.IsSmi()) {
+ // Skip updating write barrier if storing a smi.
+ __ JumpIfSmi(value_reg, &exit);
- // Update the write barrier for the array address.
- // Ok to clobber receiver_reg and name_reg, since we return.
- __ mov(name_reg, value_reg);
- __ RecordWriteField(scratch1,
- offset,
- name_reg,
- receiver_reg,
- kRAHasNotBeenSaved,
- kDontSaveFPRegs);
+ // Update the write barrier for the array address.
+ // Ok to clobber receiver_reg and name_reg, since we return.
+ __ mov(name_reg, value_reg);
+ __ RecordWriteField(scratch1,
+ offset,
+ name_reg,
+ receiver_reg,
+ kRAHasNotBeenSaved,
+ kDontSaveFPRegs);
+ }
}
// Return the value (register v0).
@@ -614,6 +637,18 @@
// face of a transition we can use the old map here because the size of
the
// object and the number of in-object properties is not going to change.
index -= object->map()->inobject_properties();
+
+ Representation representation = lookup->representation();
+ ASSERT(!representation.IsNone());
+ if (FLAG_track_fields && representation.IsSmi()) {
+ __ JumpIfNotSmi(value_reg, miss_label);
+ } else if (FLAG_track_double_fields && representation.IsDouble()) {
+ Label do_store;
+ __ JumpIfSmi(value_reg, &do_store);
+ __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex,
+ miss_label, DONT_DO_SMI_CHECK);
+ __ bind(&do_store);
+ }
// TODO(verwaest): Share this code as a code stub.
if (index < 0) {
@@ -621,18 +656,20 @@
int offset = object->map()->instance_size() + (index * kPointerSize);
__ sw(value_reg, FieldMemOperand(receiver_reg, offset));
- // Skip updating write barrier if storing a smi.
- __ JumpIfSmi(value_reg, &exit);
+ if (!FLAG_track_fields || !representation.IsSmi()) {
+ // Skip updating write barrier if storing a smi.
+ __ JumpIfSmi(value_reg, &exit);
- // Update the write barrier for the array address.
- // Pass the now unused name_reg as a scratch register.
- __ mov(name_reg, value_reg);
- __ RecordWriteField(receiver_reg,
- offset,
- name_reg,
- scratch1,
- kRAHasNotBeenSaved,
- kDontSaveFPRegs);
+ // Update the write barrier for the array address.
+ // Pass the now unused name_reg as a scratch register.
+ __ mov(name_reg, value_reg);
+ __ RecordWriteField(receiver_reg,
+ offset,
+ name_reg,
+ scratch1,
+ kRAHasNotBeenSaved,
+ kDontSaveFPRegs);
+ }
} else {
// Write to the properties array.
int offset = index * kPointerSize + FixedArray::kHeaderSize;
@@ -641,18 +678,20 @@
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
__ sw(value_reg, FieldMemOperand(scratch1, offset));
- // Skip updating write barrier if storing a smi.
- __ JumpIfSmi(value_reg, &exit);
+ if (!FLAG_track_fields || !representation.IsSmi()) {
+ // Skip updating write barrier if storing a smi.
+ __ JumpIfSmi(value_reg, &exit);
- // Update the write barrier for the array address.
- // Ok to clobber receiver_reg and name_reg, since we return.
- __ mov(name_reg, value_reg);
- __ RecordWriteField(scratch1,
- offset,
- name_reg,
- receiver_reg,
- kRAHasNotBeenSaved,
- kDontSaveFPRegs);
+ // Update the write barrier for the array address.
+ // Ok to clobber receiver_reg and name_reg, since we return.
+ __ mov(name_reg, value_reg);
+ __ RecordWriteField(scratch1,
+ offset,
+ name_reg,
+ receiver_reg,
+ kRAHasNotBeenSaved,
+ kDontSaveFPRegs);
+ }
}
// Return the value (register v0).
@@ -2935,18 +2974,24 @@
Register map_reg = scratch1();
int receiver_count = receiver_maps->length();
+ int number_of_handled_maps = 0;
__ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset));
for (int current = 0; current < receiver_count; ++current) {
- __ Jump(handlers->at(current), RelocInfo::CODE_TARGET,
- eq, map_reg, Operand(receiver_maps->at(current)));
+ Handle<Map> map = receiver_maps->at(current);
+ if (!map->is_deprecated()) {
+ number_of_handled_maps++;
+ __ Jump(handlers->at(current), RelocInfo::CODE_TARGET,
+ eq, map_reg, Operand(receiver_maps->at(current)));
+ }
}
+ ASSERT(number_of_handled_maps != 0);
__ bind(&miss);
TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
InlineCacheState state =
- receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC;
+ number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC;
return GetICCode(kind(), type, name, state);
}
--
--
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.