const char* reason) {
Representation r = representation();
if (new_rep.is_more_general_than(r)) {
- // When an HConstant is marked "not convertible to integer", then
- // never try to represent it as an integer.
- if (new_rep.IsInteger32() && !IsConvertibleToInteger()) {
- new_rep = Representation::Tagged();
- if (FLAG_trace_representation) {
- PrintF("Changing #%d %s representation %s -> %s because it's NCTI"
- " (%s want i)\n",
- id(), Mnemonic(), r.Mnemonic(), new_rep.Mnemonic(), reason);
- }
- } else {
- if (FLAG_trace_representation) {
- PrintF("Changing #%d %s representation %s -> %s based on %s\n",
- id(), Mnemonic(), r.Mnemonic(), new_rep.Mnemonic(), reason);
- }
+ if (FLAG_trace_representation) {
+ PrintF("Changing #%d %s representation %s -> %s based on %s\n",
+ id(), Mnemonic(), r.Mnemonic(), new_rep.Mnemonic(), reason);
}
ChangeRepresentation(new_rep);
AddDependantsToWorklist(h_infer);
int32_non_phi_uses() + int32_indirect_uses(),
double_non_phi_uses() + double_indirect_uses(),
tagged_non_phi_uses() + tagged_indirect_uses());
- if (!IsConvertibleToInteger()) stream->Add("_ncti");
PrintRangeTo(stream);
PrintTypeTo(stream);
stream->Add("]");
Representation HPhi::RepresentationFromInputs() {
- bool double_occurred = false;
- bool int32_occurred = false;
- bool smi_occurred = false;
+ Representation r = Representation::None();
for (int i = 0; i < OperandCount(); ++i) {
- HValue* value = OperandAt(i);
- if (value->IsUnknownOSRValue()) {
- HPhi* hint_value = HUnknownOSRValue::cast(value)->incoming_value();
- if (hint_value != NULL) {
- Representation hint = hint_value->representation();
- if (hint.IsTagged()) return hint;
- if (hint.IsDouble()) double_occurred = true;
- if (hint.IsInteger32()) int32_occurred = true;
- if (hint.IsSmi()) smi_occurred = true;
- }
- continue;
- }
- if (value->representation().IsDouble()) double_occurred = true;
- if (value->representation().IsInteger32()) int32_occurred = true;
- if (value->representation().IsSmi()) smi_occurred = true;
- if (value->representation().IsTagged()) {
- if (value->IsConstant()) {
- HConstant* constant = HConstant::cast(value);
- if (constant->IsConvertibleToInteger()) {
- int32_occurred = true;
- } else if (constant->HasNumberValue()) {
- double_occurred = true;
- } else {
- return Representation::Tagged();
- }
- } else {
- if (value->IsPhi() && !IsConvertibleToInteger()) {
- return Representation::Tagged();
- }
- }
- }
+ r = r.generalize(OperandAt(i)->KnownOptimalRepresentation());
}
-
- if (double_occurred) return Representation::Double();
- if (int32_occurred) return Representation::Integer32();
- if (smi_occurred) return Representation::Smi();
-
- return Representation::None();
+ return r;
}
}
virtual void AssumeRepresentation(Representation r);
- virtual bool IsConvertibleToInteger() const { return true; }
+ virtual Representation KnownOptimalRepresentation() {
+ Representation r = representation();
+ if (r.IsTagged()) {
+ HType t = type();
+ if (t.IsSmi()) return Representation::Smi();
+ if (t.IsHeapNumber()) return Representation::Double();
+ if (t.IsHeapObject()) return r;
+ return Representation::None();
+ }
+ return r;
+ }
HType type() const { return type_; }
void set_type(HType new_type) {
public:
explicit HMapEnumLength(HValue* value) : HUnaryOperation(value) {
set_type(HType::Smi());
- set_representation(Representation::Tagged());
+ set_representation(Representation::Smi());
SetFlag(kUseGVN);
SetGVNFlag(kDependsOnMaps);
}
HPhi(int merged_index, Zone* zone)
: inputs_(2, zone),
merged_index_(merged_index),
- phi_id_(-1),
- is_convertible_to_integer_(true) {
+ phi_id_(-1) {
for (int i = 0; i < Representation::kNumRepresentations; i++) {
non_phi_uses_[i] = 0;
indirect_uses_[i] = 0;
virtual Representation RequiredInputRepresentation(int index) {
return representation();
}
+ virtual Representation KnownOptimalRepresentation() {
+ return representation();
+ }
virtual HType CalculateInferredType();
virtual int OperandCount() { return inputs_.length(); }
virtual HValue* OperandAt(int index) const { return inputs_[index]; }
}
virtual Opcode opcode() const { return HValue::kPhi; }
- virtual bool IsConvertibleToInteger() const {
- return is_convertible_to_integer_;
- }
-
- void set_is_convertible_to_integer(bool b) {
- is_convertible_to_integer_ = b;
- }
-
- bool AllOperandsConvertibleToInteger() {
- for (int i = 0; i < OperandCount(); ++i) {
- if (!OperandAt(i)->IsConvertibleToInteger()) {
- if (FLAG_trace_representation) {
- HValue* input = OperandAt(i);
- PrintF("#%d %s: Input #%d %s at %d is NCTI\n",
- id(), Mnemonic(), input->id(), input->Mnemonic(), i);
- }
- return false;
- }
- }
- return true;
- }
-
void SimplifyConstantInputs();
// TODO(titzer): we can't eliminate the receiver for generating backtraces
int non_phi_uses_[Representation::kNumRepresentations];
int indirect_uses_[Representation::kNumRepresentations];
int phi_id_;
- bool is_convertible_to_integer_;
};
return Representation::None();
}
- virtual bool IsConvertibleToInteger() const {
- return has_int32_value_;
+ virtual Representation KnownOptimalRepresentation() {
+ if (HasSmiValue()) return Representation::Smi();
+ if (HasInteger32Value()) return Representation::Integer32();
+ if (HasNumberValue()) return Representation::Double();
+ return Representation::Tagged();
}
virtual bool EmitAtUses() { return !representation().IsDouble(); }
ASSERT(HasInteger32Value());
return int32_value_;
}
- bool HasSmiValue() const {
- return has_smi_value_;
- }
+ bool HasSmiValue() const { return has_smi_value_; }
bool HasDoubleValue() const { return has_double_value_; }
double DoubleValue() const {
ASSERT(HasDoubleValue());
return incoming_value_;
}
+ virtual Representation KnownOptimalRepresentation() {
+ if (incoming_value_ == NULL) return Representation::None();
+ return incoming_value_->KnownOptimalRepresentation();
+ }
+
DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
private:
}
// Use the phi reachability information from step 2 to
- // push information about values which can't be converted to integer
- // without deoptimization through the phi use-def chains, avoiding
- // unnecessary deoptimizations later.
- for (int i = 0; i < phi_count; ++i) {
- HPhi* phi = phi_list->at(i);
- bool cti = phi->AllOperandsConvertibleToInteger();
- if (cti) continue;
-
- for (BitVector::Iterator it(connected_phis.at(i));
- !it.Done();
- it.Advance()) {
- HPhi* phi = phi_list->at(it.Current());
- phi->set_is_convertible_to_integer(false);
- }
- }
-
- // Use the phi reachability information from step 2 to
// sum up the non-phi use counts of all connected phis.
for (int i = 0; i < phi_count; ++i) {
HPhi* phi = phi_list->at(i);
LInstruction* branch =
InstructionAt(cur_block->last_instruction_index());
if (branch->HasPointerMap()) {
- if (phi->representation().IsSmiOrTagged()) {
+ if (phi->representation().IsTagged() && !phi->type().IsSmi()) {
branch->pointer_map()->RecordPointer(phi_operand, zone());
} else if (!phi->representation().IsDouble()) {
branch->pointer_map()->RecordUntagged(phi_operand, zone());
bool LAllocator::HasTaggedValue(int virtual_register) const {
HValue* value = graph_->LookupValue(virtual_register);
if (value == NULL) return false;
- return value->representation().IsSmiOrTagged();
+ return value->representation().IsTagged() && !value->type().IsSmi();
}