Index: runtime/vm/intermediate_language.h |
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h |
index 61ed474da6b8b3409762ef04b32d86d5f80b420a..52f2c53ee47e7566bdde53aa5401f3323b96ff89 100644 |
--- a/runtime/vm/intermediate_language.h |
+++ b/runtime/vm/intermediate_language.h |
@@ -20,6 +20,7 @@ DECLARE_FLAG(bool, throw_on_javascript_int_overflow); |
class BitVector; |
class BlockEntryInstr; |
+class BoxIntNInstr; |
class BufferFormatter; |
class CatchBlockEntryInstr; |
class ComparisonInstr; |
@@ -35,6 +36,7 @@ class ParsedFunction; |
class Range; |
class RangeAnalysis; |
class RangeBoundary; |
+class UnboxIntNInstr; |
// CompileType describes type of the value produced by the definition. |
// |
@@ -468,10 +470,12 @@ class EmbeddedArray<T, 0> { |
M(AllocateUninitializedContext) \ |
M(CloneContext) \ |
M(BinarySmiOp) \ |
+ M(BinaryInt32Op) \ |
M(UnarySmiOp) \ |
M(UnaryDoubleOp) \ |
M(CheckStackOverflow) \ |
M(SmiToDouble) \ |
+ M(Int32ToDouble) \ |
M(DoubleToInteger) \ |
M(DoubleToSmi) \ |
M(DoubleToDouble) \ |
@@ -549,6 +553,8 @@ class EmbeddedArray<T, 0> { |
M(UnaryUint32Op) \ |
M(BoxUint32) \ |
M(UnboxUint32) \ |
+ M(BoxInt32) \ |
+ M(UnboxInt32) \ |
M(UnboxedIntConverter) \ |
@@ -603,6 +609,9 @@ class Instruction : public ZoneAllocated { |
bool IsDefinition() { return (AsDefinition() != NULL); } |
virtual Definition* AsDefinition() { return NULL; } |
+ virtual BoxIntNInstr* AsBoxIntN() { return NULL; } |
+ virtual UnboxIntNInstr* AsUnboxIntN() { return NULL; } |
+ |
virtual intptr_t token_pos() const { return Scanner::kNoSourcePos; } |
virtual intptr_t InputCount() const = 0; |
@@ -898,7 +907,11 @@ FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) |
friend class BinaryUint32OpInstr; |
friend class UnaryUint32OpInstr; |
friend class ShiftUint32OpInstr; |
+ friend class UnboxIntNInstr; |
+ friend class UnboxInt32Instr; |
friend class UnboxUint32Instr; |
+ friend class BinaryInt32OpInstr; |
+ friend class UnboxedIntConverterInstr; |
virtual void RawSetInputAt(intptr_t i, Value* value) = 0; |
@@ -1627,6 +1640,13 @@ class Definition : public Instruction { |
IsUnboxInteger(); |
} |
+ bool IsInt32Definition() { |
+ return IsBinaryInt32Op() || |
+ IsBoxInt32() || |
+ IsUnboxInt32() || |
+ IsUnboxedIntConverter(); |
+ } |
+ |
// Compute compile type for this definition. It is safe to use this |
// approximation even before type propagator was run (e.g. during graph |
// building). |
@@ -1657,6 +1677,8 @@ class Definition : public Instruction { |
return (input_use_list_ != NULL) || (env_use_list_ != NULL); |
} |
bool HasOnlyUse(Value* use) const; |
+ bool HasOnlyInputUse(Value* use) const; |
+ |
Value* input_use_list() const { return input_use_list_; } |
void set_input_use_list(Value* head) { input_use_list_ = head; } |
@@ -2415,10 +2437,11 @@ class ConstantInstr : public TemplateDefinition<0> { |
// for other unboxing instructions. |
class UnboxedConstantInstr : public ConstantInstr { |
public: |
- explicit UnboxedConstantInstr(const Object& value); |
+ explicit UnboxedConstantInstr(const Object& value, |
+ Representation representation); |
virtual Representation representation() const { |
- return kUnboxedDouble; |
+ return representation_; |
} |
// Either NULL or the address of the unboxed constant. |
@@ -2427,6 +2450,7 @@ class UnboxedConstantInstr : public ConstantInstr { |
DECLARE_INSTRUCTION(UnboxedConstant) |
private: |
+ const Representation representation_; |
uword constant_address_; // Either NULL or points to the untagged constant. |
DISALLOW_COPY_AND_ASSIGN(UnboxedConstantInstr); |
@@ -4665,6 +4689,8 @@ class BoxIntegerInstr : public TemplateDefinition<1> { |
virtual bool MayThrow() const { return false; } |
+ virtual Definition* Canonicalize(FlowGraph* flow_graph); |
+ |
private: |
bool is_smi_; |
@@ -4841,6 +4867,8 @@ class UnboxIntegerInstr : public TemplateDefinition<1> { |
virtual bool MayThrow() const { return false; } |
+ virtual Definition* Canonicalize(FlowGraph* flow_graph); |
+ |
private: |
DISALLOW_COPY_AND_ASSIGN(UnboxIntegerInstr); |
}; |
@@ -6876,6 +6904,12 @@ class BinarySmiOpInstr : public TemplateDefinition<2> { |
virtual bool MayThrow() const { return false; } |
+ virtual intptr_t DeoptimizationTarget() const { |
+ // Direct access since this instruction cannot deoptimize, and the deopt-id |
+ // was inherited from another instruction that could deoptimize. |
+ return deopt_id_; |
+ } |
+ |
private: |
const Token::Kind op_kind_; |
bool overflow_; |
@@ -6886,6 +6920,97 @@ class BinarySmiOpInstr : public TemplateDefinition<2> { |
}; |
+class BinaryInt32OpInstr : public TemplateDefinition<2> { |
+ public: |
+ BinaryInt32OpInstr(Token::Kind op_kind, |
+ Value* left, |
+ Value* right, |
+ intptr_t deopt_id) |
+ : op_kind_(op_kind), |
+ overflow_(true), |
+ is_truncating_(false) { |
+ SetInputAt(0, left); |
+ SetInputAt(1, right); |
+ // Override generated deopt-id. |
+ deopt_id_ = deopt_id; |
+ } |
+ |
+ static bool IsSupported(Token::Kind op, Value* left, Value* right) { |
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) |
srdjan
2014/08/27 16:17:13
You could move this into intermediate_language_xxx
Vyacheslav Egorov (Google)
2014/08/28 20:48:37
Agreed. However I did not for two reasons:
1) Thi
|
+ switch (op) { |
+ case Token::kADD: |
+ case Token::kSUB: |
+ case Token::kMUL: |
+ case Token::kBIT_AND: |
+ case Token::kBIT_OR: |
+ case Token::kBIT_XOR: |
+ return true; |
+ |
+ case Token::kSHL: |
+ case Token::kSHR: |
+ return right->BindsToConstant(); |
+ |
+ default: |
+ return false; |
+ } |
+#else |
+ return false; |
+#endif |
+ } |
+ |
+ Value* left() const { return inputs_[0]; } |
+ Value* right() const { return inputs_[1]; } |
+ |
+ Token::Kind op_kind() const { return op_kind_; } |
+ |
+ void set_overflow(bool overflow) { overflow_ = overflow; } |
+ |
+ void set_is_truncating(bool value) { is_truncating_ = value; } |
+ bool IsTruncating() const { return is_truncating_ || !overflow_; } |
+ |
+ void PrintTo(BufferFormatter* f) const; |
+ virtual void PrintOperandsTo(BufferFormatter* f) const; |
+ |
+ DECLARE_INSTRUCTION(BinaryInt32Op) |
+ virtual CompileType ComputeType() const; |
+ |
+ virtual bool CanDeoptimize() const; |
+ |
+ virtual bool AllowsCSE() const { return true; } |
+ virtual EffectSet Effects() const { return EffectSet::None(); } |
+ virtual EffectSet Dependencies() const { return EffectSet::None(); } |
+ virtual bool AttributesEqual(Instruction* other) const; |
+ |
+ virtual void InferRange(RangeAnalysis* analysis, Range* range); |
+ |
+ virtual Definition* Canonicalize(FlowGraph* flow_graph); |
+ |
+ virtual Representation representation() const { |
+ return kUnboxedInt32; |
+ } |
+ |
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
+ ASSERT(idx == 0 || idx == 1); |
srdjan
2014/08/27 16:17:13
parentheses
Vyacheslav Egorov (Google)
2014/08/28 20:48:37
Done.
|
+ return kUnboxedInt32; |
+ } |
+ |
+ virtual intptr_t DeoptimizationTarget() const { |
+ // Direct access since this instruction cannot deoptimize, and the deopt-id |
+ // was inherited from another instruction that could deoptimize. |
+ return deopt_id_; |
+ } |
+ |
+ virtual bool MayThrow() const { return false; } |
+ |
+ private: |
+ const Token::Kind op_kind_; |
+ bool overflow_; |
+ bool is_truncating_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(BinaryInt32OpInstr); |
+}; |
+ |
+ |
// Handles both Smi operations: BIT_OR and NEGATE. |
class UnarySmiOpInstr : public TemplateDefinition<1> { |
public: |
@@ -7006,6 +7131,7 @@ class CheckStackOverflowInstr : public TemplateInstruction<0> { |
}; |
+// TODO(vegorov): remove this instruction in favor of Int32ToDouble. |
class SmiToDoubleInstr : public TemplateDefinition<1> { |
public: |
SmiToDoubleInstr(Value* value, intptr_t token_pos) |
@@ -7041,6 +7167,40 @@ class SmiToDoubleInstr : public TemplateDefinition<1> { |
}; |
+class Int32ToDoubleInstr : public TemplateDefinition<1> { |
+ public: |
+ explicit Int32ToDoubleInstr(Value* value) { |
+ SetInputAt(0, value); |
+ } |
+ |
+ Value* value() const { return inputs_[0]; } |
+ |
+ DECLARE_INSTRUCTION(Int32ToDouble) |
+ virtual CompileType ComputeType() const; |
+ |
+ virtual Representation RequiredInputRepresentation(intptr_t index) const { |
+ ASSERT(index == 0); |
+ return kUnboxedInt32; |
+ } |
+ |
+ virtual Representation representation() const { |
+ return kUnboxedDouble; |
+ } |
+ |
+ virtual bool CanDeoptimize() const { return false; } |
+ |
+ virtual bool AllowsCSE() const { return true; } |
+ virtual EffectSet Effects() const { return EffectSet::None(); } |
+ virtual EffectSet Dependencies() const { return EffectSet::None(); } |
+ virtual bool AttributesEqual(Instruction* other) const { return true; } |
+ |
+ virtual bool MayThrow() const { return false; } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(Int32ToDoubleInstr); |
+}; |
+ |
+ |
class DoubleToIntegerInstr : public TemplateDefinition<1> { |
public: |
DoubleToIntegerInstr(Value* value, InstanceCallInstr* instance_call) |
@@ -7800,13 +7960,18 @@ class UnaryUint32OpInstr : public TemplateDefinition<1> { |
}; |
-class BoxUint32Instr : public TemplateDefinition<1> { |
+class BoxIntNInstr : public TemplateDefinition<1> { |
public: |
- explicit BoxUint32Instr(Value* value) { |
+ BoxIntNInstr(Representation representation, Value* value) |
+ : representation_(representation) { |
SetInputAt(0, value); |
} |
Value* value() const { return inputs_[0]; } |
+ virtual bool ValueFitsSmi() const; |
+ |
+ virtual CompileType ComputeType() const; |
+ virtual bool RecomputeType(); |
virtual bool CanDeoptimize() const { return false; } |
@@ -7816,69 +7981,148 @@ class BoxUint32Instr : public TemplateDefinition<1> { |
virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
ASSERT(idx == 0); |
- return kUnboxedUint32; |
+ return representation_; |
} |
- DECLARE_INSTRUCTION(BoxUint32) |
- virtual CompileType ComputeType() const; |
- |
virtual bool AllowsCSE() const { return true; } |
virtual EffectSet Effects() const { return EffectSet::None(); } |
virtual EffectSet Dependencies() const { return EffectSet::None(); } |
- virtual bool AttributesEqual(Instruction* other) const { return true; } |
+ virtual bool AttributesEqual(Instruction* other) const { |
+ return other->AsBoxIntN()->representation_ == representation_; |
+ } |
virtual bool MayThrow() const { return false; } |
+ virtual Definition* Canonicalize(FlowGraph* flow_graph); |
+ |
+ virtual BoxIntNInstr* AsBoxIntN() { return this; } |
+ |
+ private: |
+ const Representation representation_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(BoxIntNInstr); |
+}; |
+ |
+ |
+class BoxUint32Instr : public BoxIntNInstr { |
+ public: |
+ explicit BoxUint32Instr(Value* value) |
+ : BoxIntNInstr(kUnboxedUint32, value) { } |
+ |
+ DECLARE_INSTRUCTION(BoxUint32) |
+ |
private: |
DISALLOW_COPY_AND_ASSIGN(BoxUint32Instr); |
}; |
-class UnboxUint32Instr : public TemplateDefinition<1> { |
+class BoxInt32Instr : public BoxIntNInstr { |
+ public: |
+ explicit BoxInt32Instr(Value* value) |
+ : BoxIntNInstr(kUnboxedInt32, value) { } |
+ |
+ virtual void InferRange(RangeAnalysis* analysis, Range* range); |
+ |
+ DECLARE_INSTRUCTION(BoxInt32) |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(BoxInt32Instr); |
+}; |
+ |
+ |
+class UnboxIntNInstr : public TemplateDefinition<1> { |
public: |
- UnboxUint32Instr(Value* value, intptr_t deopt_id) { |
+ UnboxIntNInstr(Representation representation, |
+ Value* value, |
+ intptr_t deopt_id) |
+ : representation_(representation) { |
SetInputAt(0, value); |
deopt_id_ = deopt_id; |
} |
Value* value() const { return inputs_[0]; } |
- virtual bool CanDeoptimize() const { |
- return (value()->Type()->ToCid() != kSmiCid) |
- && (value()->Type()->ToCid() != kMintCid); |
- } |
- |
virtual Representation representation() const { |
- return kUnboxedUint32; |
+ return representation_; |
} |
- |
- DECLARE_INSTRUCTION(UnboxUint32) |
virtual CompileType ComputeType() const; |
virtual bool AllowsCSE() const { return true; } |
virtual EffectSet Effects() const { return EffectSet::None(); } |
virtual EffectSet Dependencies() const { return EffectSet::None(); } |
- virtual bool AttributesEqual(Instruction* other) const { return true; } |
+ virtual bool AttributesEqual(Instruction* other) const { |
+ return other->AsUnboxIntN()->representation_ == representation_; |
+ } |
virtual bool MayThrow() const { return false; } |
+ virtual Definition* Canonicalize(FlowGraph* flow_graph); |
+ |
+ virtual UnboxIntNInstr* AsUnboxIntN() { return this; } |
+ |
+ private: |
+ const Representation representation_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(UnboxIntNInstr); |
+}; |
+ |
+ |
+class UnboxUint32Instr : public UnboxIntNInstr { |
+ public: |
+ UnboxUint32Instr(Value* value, intptr_t deopt_id) |
+ : UnboxIntNInstr(kUnboxedUint32, value, deopt_id) { |
+ } |
+ |
+ virtual bool CanDeoptimize() const { |
+ return (value()->Type()->ToCid() != kSmiCid) |
+ && (value()->Type()->ToCid() != kMintCid); |
+ } |
+ |
+ DECLARE_INSTRUCTION(UnboxUint32) |
+ |
private: |
DISALLOW_COPY_AND_ASSIGN(UnboxUint32Instr); |
}; |
+class UnboxInt32Instr : public UnboxIntNInstr { |
+ public: |
+ UnboxInt32Instr(Value* value, intptr_t deopt_id) |
+ : UnboxIntNInstr(kUnboxedInt32, value, deopt_id) { |
+ } |
+ |
+ virtual bool CanDeoptimize() const; |
+ |
+ virtual void InferRange(RangeAnalysis* analysis, Range* range); |
+ |
+ virtual Definition* Canonicalize(FlowGraph* flow_graph); |
+ |
+ DECLARE_INSTRUCTION(UnboxInt32) |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(UnboxInt32Instr); |
+}; |
+ |
+ |
class UnboxedIntConverterInstr : public TemplateDefinition<1> { |
public: |
UnboxedIntConverterInstr(Representation from, |
Representation to, |
- Value* value) |
+ Value* value, |
+ intptr_t deopt_id) |
: from_representation_(from), |
to_representation_(to) { |
ASSERT(from != to); |
- ASSERT((from == kUnboxedMint) || (from == kUnboxedUint32)); |
- ASSERT((to == kUnboxedMint) || (to == kUnboxedUint32)); |
+ ASSERT((from == kUnboxedMint) || |
+ (from == kUnboxedUint32) || |
+ (from == kUnboxedInt32)); |
+ ASSERT((to == kUnboxedMint) || |
+ (to == kUnboxedUint32) || |
+ (to == kUnboxedInt32)); |
+ ASSERT((to != kUnboxedInt32) || (deopt_id != Isolate::kNoDeoptId)); |
SetInputAt(0, value); |
+ deopt_id_ = deopt_id; |
} |
Value* value() const { return inputs_[0]; } |
@@ -7886,7 +8130,9 @@ class UnboxedIntConverterInstr : public TemplateDefinition<1> { |
Representation from() const { return from_representation_; } |
Representation to() const { return to_representation_; } |
- virtual bool CanDeoptimize() const { return false; } |
+ Definition* Canonicalize(FlowGraph* flow_graph); |
+ |
+ virtual bool CanDeoptimize() const; |
virtual Representation representation() const { |
return to(); |
@@ -7907,6 +8153,10 @@ class UnboxedIntConverterInstr : public TemplateDefinition<1> { |
virtual bool MayThrow() const { return false; } |
+ virtual void InferRange(RangeAnalysis* analysis, Range* range); |
+ |
+ virtual void PrintOperandsTo(BufferFormatter* f) const; |
+ |
DECLARE_INSTRUCTION(UnboxedIntConverter); |
private: |
@@ -8143,6 +8393,16 @@ class FlowGraphVisitor : public ValueObject { |
}; |
+// Helper macros for platform ports. |
+#define DEFINE_UNIMPLEMENTED_INSTRUCTION(Name) \ |
+ LocationSummary* Name::MakeLocationSummary( \ |
+ Isolate* isolate, bool opt) const { \ |
+ UNIMPLEMENTED(); \ |
+ return NULL; \ |
+ } \ |
+ void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } |
+ |
+ |
} // namespace dart |
#endif // VM_INTERMEDIATE_LANGUAGE_H_ |