| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ | 5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ |
| 6 #define VM_INTERMEDIATE_LANGUAGE_H_ | 6 #define VM_INTERMEDIATE_LANGUAGE_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/ast.h" | 9 #include "vm/ast.h" |
| 10 #include "vm/growable_array.h" | 10 #include "vm/growable_array.h" |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 cid_(other.cid_), | 135 cid_(other.cid_), |
| 136 type_(other.type_) { } | 136 type_(other.type_) { } |
| 137 | 137 |
| 138 CompileType& operator=(const CompileType& other) { | 138 CompileType& operator=(const CompileType& other) { |
| 139 is_nullable_ = other.is_nullable_; | 139 is_nullable_ = other.is_nullable_; |
| 140 cid_ = other.cid_; | 140 cid_ = other.cid_; |
| 141 type_ = other.type_; | 141 type_ = other.type_; |
| 142 return *this; | 142 return *this; |
| 143 } | 143 } |
| 144 | 144 |
| 145 bool is_nullable() const { return is_nullable_; } |
| 146 |
| 145 // Return type such that concrete value's type in runtime is guaranteed to | 147 // Return type such that concrete value's type in runtime is guaranteed to |
| 146 // be subtype of it. | 148 // be subtype of it. |
| 147 const AbstractType* ToAbstractType(); | 149 const AbstractType* ToAbstractType(); |
| 148 | 150 |
| 149 // Return class id such that it is either kDynamicCid or in runtime | 151 // Return class id such that it is either kDynamicCid or in runtime |
| 150 // value is guaranteed to have an equal class id. | 152 // value is guaranteed to have an equal class id. |
| 151 intptr_t ToCid(); | 153 intptr_t ToCid(); |
| 152 | 154 |
| 153 // Return class id such that it is either kDynamicCid or in runtime | 155 // Return class id such that it is either kDynamicCid or in runtime |
| 154 // value is guaranteed to be either null or have an equal class id. | 156 // value is guaranteed to be either null or have an equal class id. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 169 bool IsAssignableTo(const AbstractType& type) { | 171 bool IsAssignableTo(const AbstractType& type) { |
| 170 bool is_instance; | 172 bool is_instance; |
| 171 return CanComputeIsInstanceOf(type, kNullable, &is_instance) && | 173 return CanComputeIsInstanceOf(type, kNullable, &is_instance) && |
| 172 is_instance; | 174 is_instance; |
| 173 } | 175 } |
| 174 | 176 |
| 175 // Create a new CompileType representing given combination of class id and | 177 // Create a new CompileType representing given combination of class id and |
| 176 // abstract type. The pair is assumed to be coherent. | 178 // abstract type. The pair is assumed to be coherent. |
| 177 static CompileType Create(intptr_t cid, const AbstractType& type); | 179 static CompileType Create(intptr_t cid, const AbstractType& type); |
| 178 | 180 |
| 181 CompileType CopyNonNullable() const { |
| 182 return CompileType(kNonNullable, cid_, type_); |
| 183 } |
| 184 |
| 185 static CompileType CreateNullable(bool is_nullable, intptr_t cid) { |
| 186 return CompileType(is_nullable, cid, NULL); |
| 187 } |
| 188 |
| 179 // Create a new CompileType representing given abstract type. By default | 189 // Create a new CompileType representing given abstract type. By default |
| 180 // values as assumed to be nullable. | 190 // values as assumed to be nullable. |
| 181 static CompileType FromAbstractType(const AbstractType& type, | 191 static CompileType FromAbstractType(const AbstractType& type, |
| 182 bool is_nullable = kNullable); | 192 bool is_nullable = kNullable); |
| 183 | 193 |
| 184 // Create a new CompileType representing an value with the given class id. | 194 // Create a new CompileType representing an value with the given class id. |
| 185 // Resulting CompileType is nullable only if cid is kDynamicCid or kNullCid. | 195 // Resulting CompileType is nullable only if cid is kDynamicCid or kNullCid. |
| 186 static CompileType FromCid(intptr_t cid); | 196 static CompileType FromCid(intptr_t cid); |
| 187 | 197 |
| 188 // Create None CompileType. It is the bottom of the lattice and is used to | 198 // Create None CompileType. It is the bottom of the lattice and is used to |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 M(BoxDouble) \ | 484 M(BoxDouble) \ |
| 475 M(UnboxInteger) \ | 485 M(UnboxInteger) \ |
| 476 M(BoxInteger) \ | 486 M(BoxInteger) \ |
| 477 M(BinaryMintOp) \ | 487 M(BinaryMintOp) \ |
| 478 M(ShiftMintOp) \ | 488 M(ShiftMintOp) \ |
| 479 M(UnaryMintOp) \ | 489 M(UnaryMintOp) \ |
| 480 M(CheckArrayBound) \ | 490 M(CheckArrayBound) \ |
| 481 M(Constraint) \ | 491 M(Constraint) \ |
| 482 M(StringFromCharCode) \ | 492 M(StringFromCharCode) \ |
| 483 M(InvokeMathCFunction) \ | 493 M(InvokeMathCFunction) \ |
| 494 M(GuardField) \ |
| 484 | 495 |
| 485 | 496 |
| 486 #define FORWARD_DECLARATION(type) class type##Instr; | 497 #define FORWARD_DECLARATION(type) class type##Instr; |
| 487 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION) | 498 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION) |
| 488 #undef FORWARD_DECLARATION | 499 #undef FORWARD_DECLARATION |
| 489 | 500 |
| 490 | 501 |
| 491 // Functions required in all concrete instruction classes. | 502 // Functions required in all concrete instruction classes. |
| 492 #define DECLARE_INSTRUCTION(type) \ | 503 #define DECLARE_INSTRUCTION(type) \ |
| 493 virtual Tag tag() const { return k##type; } \ | 504 virtual Tag tag() const { return k##type; } \ |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 723 friend class UnboxIntegerInstr; | 734 friend class UnboxIntegerInstr; |
| 724 friend class UnboxDoubleInstr; | 735 friend class UnboxDoubleInstr; |
| 725 friend class BinaryDoubleOpInstr; | 736 friend class BinaryDoubleOpInstr; |
| 726 friend class BinaryMintOpInstr; | 737 friend class BinaryMintOpInstr; |
| 727 friend class BinarySmiOpInstr; | 738 friend class BinarySmiOpInstr; |
| 728 friend class UnarySmiOpInstr; | 739 friend class UnarySmiOpInstr; |
| 729 friend class ShiftMintOpInstr; | 740 friend class ShiftMintOpInstr; |
| 730 friend class UnaryMintOpInstr; | 741 friend class UnaryMintOpInstr; |
| 731 friend class MathSqrtInstr; | 742 friend class MathSqrtInstr; |
| 732 friend class CheckClassInstr; | 743 friend class CheckClassInstr; |
| 744 friend class GuardFieldInstr; |
| 733 friend class CheckSmiInstr; | 745 friend class CheckSmiInstr; |
| 734 friend class CheckArrayBoundInstr; | 746 friend class CheckArrayBoundInstr; |
| 735 friend class CheckEitherNonSmiInstr; | 747 friend class CheckEitherNonSmiInstr; |
| 736 friend class LICM; | 748 friend class LICM; |
| 737 friend class DoubleToSmiInstr; | 749 friend class DoubleToSmiInstr; |
| 738 friend class DoubleToDoubleInstr; | 750 friend class DoubleToDoubleInstr; |
| 739 friend class InvokeMathCFunctionInstr; | 751 friend class InvokeMathCFunctionInstr; |
| 740 friend class FlowGraphOptimizer; | 752 friend class FlowGraphOptimizer; |
| 741 friend class LoadIndexedInstr; | 753 friend class LoadIndexedInstr; |
| 742 friend class StoreIndexedInstr; | 754 friend class StoreIndexedInstr; |
| 755 friend class StoreInstanceFieldInstr; |
| 743 | 756 |
| 744 virtual void RawSetInputAt(intptr_t i, Value* value) = 0; | 757 virtual void RawSetInputAt(intptr_t i, Value* value) = 0; |
| 745 | 758 |
| 746 intptr_t deopt_id_; | 759 intptr_t deopt_id_; |
| 747 intptr_t lifetime_position_; // Position used by register allocator. | 760 intptr_t lifetime_position_; // Position used by register allocator. |
| 748 Instruction* previous_; | 761 Instruction* previous_; |
| 749 Instruction* next_; | 762 Instruction* next_; |
| 750 Environment* env_; | 763 Environment* env_; |
| 751 intptr_t expr_id_; | 764 intptr_t expr_id_; |
| 752 | 765 |
| (...skipping 1995 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2748 kNoStoreBarrier, | 2761 kNoStoreBarrier, |
| 2749 kEmitStoreBarrier | 2762 kEmitStoreBarrier |
| 2750 }; | 2763 }; |
| 2751 | 2764 |
| 2752 | 2765 |
| 2753 class StoreInstanceFieldInstr : public TemplateDefinition<2> { | 2766 class StoreInstanceFieldInstr : public TemplateDefinition<2> { |
| 2754 public: | 2767 public: |
| 2755 StoreInstanceFieldInstr(const Field& field, | 2768 StoreInstanceFieldInstr(const Field& field, |
| 2756 Value* instance, | 2769 Value* instance, |
| 2757 Value* value, | 2770 Value* value, |
| 2758 StoreBarrierType emit_store_barrier) | 2771 StoreBarrierType emit_store_barrier, |
| 2759 : field_(field), emit_store_barrier_(emit_store_barrier) { | 2772 bool emit_field_guard = true) |
| 2773 : field_(field), |
| 2774 emit_store_barrier_(emit_store_barrier), |
| 2775 emit_field_guard_(emit_field_guard) { |
| 2760 SetInputAt(0, instance); | 2776 SetInputAt(0, instance); |
| 2761 SetInputAt(1, value); | 2777 SetInputAt(1, value); |
| 2762 } | 2778 } |
| 2763 | 2779 |
| 2780 void SetDeoptId(intptr_t deopt_id) { |
| 2781 ASSERT(CanDeoptimize()); |
| 2782 deopt_id_ = deopt_id; |
| 2783 } |
| 2784 |
| 2764 DECLARE_INSTRUCTION(StoreInstanceField) | 2785 DECLARE_INSTRUCTION(StoreInstanceField) |
| 2765 virtual CompileType* ComputeInitialType() const; | 2786 virtual CompileType* ComputeInitialType() const; |
| 2766 | 2787 |
| 2767 const Field& field() const { return field_; } | 2788 const Field& field() const { return field_; } |
| 2768 | 2789 |
| 2769 Value* instance() const { return inputs_[0]; } | 2790 Value* instance() const { return inputs_[0]; } |
| 2770 Value* value() const { return inputs_[1]; } | 2791 Value* value() const { return inputs_[1]; } |
| 2771 bool ShouldEmitStoreBarrier() const { | 2792 bool ShouldEmitStoreBarrier() const { |
| 2772 return value()->NeedsStoreBuffer() | 2793 return value()->NeedsStoreBuffer() |
| 2773 && (emit_store_barrier_ == kEmitStoreBarrier); | 2794 && (emit_store_barrier_ == kEmitStoreBarrier); |
| 2774 } | 2795 } |
| 2775 | 2796 |
| 2776 virtual void PrintOperandsTo(BufferFormatter* f) const; | 2797 virtual void PrintOperandsTo(BufferFormatter* f) const; |
| 2777 | 2798 |
| 2778 virtual bool CanDeoptimize() const { return false; } | 2799 virtual bool CanDeoptimize() const { return emit_field_guard_; } |
| 2779 | 2800 |
| 2780 virtual bool HasSideEffect() const { return true; } | 2801 virtual bool HasSideEffect() const { return true; } |
| 2781 | 2802 |
| 2803 void detach_field_guard() { emit_field_guard_ = false; } |
| 2804 |
| 2805 bool should_emit_field_guard() const { return emit_field_guard_; } |
| 2806 |
| 2782 private: | 2807 private: |
| 2783 const Field& field_; | 2808 const Field& field_; |
| 2784 const StoreBarrierType emit_store_barrier_; | 2809 const StoreBarrierType emit_store_barrier_; |
| 2810 bool emit_field_guard_; |
| 2785 | 2811 |
| 2786 DISALLOW_COPY_AND_ASSIGN(StoreInstanceFieldInstr); | 2812 DISALLOW_COPY_AND_ASSIGN(StoreInstanceFieldInstr); |
| 2787 }; | 2813 }; |
| 2788 | 2814 |
| 2789 | 2815 |
| 2816 class GuardFieldInstr : public TemplateInstruction<1> { |
| 2817 public: |
| 2818 GuardFieldInstr(Value* value, |
| 2819 const Field& field, |
| 2820 intptr_t deopt_id) |
| 2821 : field_(field) { |
| 2822 deopt_id_ = deopt_id; |
| 2823 SetInputAt(0, value); |
| 2824 } |
| 2825 |
| 2826 DECLARE_INSTRUCTION(GuardField) |
| 2827 |
| 2828 virtual intptr_t ArgumentCount() const { return 0; } |
| 2829 |
| 2830 virtual bool CanDeoptimize() const { return env() != NULL; } |
| 2831 |
| 2832 virtual bool HasSideEffect() const { return false; } |
| 2833 |
| 2834 virtual bool AttributesEqual(Instruction* other) const; |
| 2835 |
| 2836 virtual bool AffectedBySideEffect() const; |
| 2837 |
| 2838 Value* value() const { return inputs_[0]; } |
| 2839 |
| 2840 virtual Instruction* Canonicalize(FlowGraphOptimizer* optimizer); |
| 2841 |
| 2842 virtual void PrintOperandsTo(BufferFormatter* f) const; |
| 2843 |
| 2844 const Field& field() const { return field_; } |
| 2845 |
| 2846 private: |
| 2847 const Field& field_; |
| 2848 |
| 2849 DISALLOW_COPY_AND_ASSIGN(GuardFieldInstr); |
| 2850 }; |
| 2851 |
| 2852 |
| 2790 class LoadStaticFieldInstr : public TemplateDefinition<0> { | 2853 class LoadStaticFieldInstr : public TemplateDefinition<0> { |
| 2791 public: | 2854 public: |
| 2792 explicit LoadStaticFieldInstr(const Field& field) : field_(field) {} | 2855 explicit LoadStaticFieldInstr(const Field& field) : field_(field) {} |
| 2793 | 2856 |
| 2794 DECLARE_INSTRUCTION(LoadStaticField); | 2857 DECLARE_INSTRUCTION(LoadStaticField); |
| 2795 virtual CompileType ComputeType() const; | 2858 virtual CompileType ComputeType() const; |
| 2796 | 2859 |
| 2797 const Field& field() const { return field_; } | 2860 const Field& field() const { return field_; } |
| 2798 | 2861 |
| 2799 virtual void PrintOperandsTo(BufferFormatter* f) const; | 2862 virtual void PrintOperandsTo(BufferFormatter* f) const; |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3173 class LoadFieldInstr : public TemplateDefinition<1> { | 3236 class LoadFieldInstr : public TemplateDefinition<1> { |
| 3174 public: | 3237 public: |
| 3175 LoadFieldInstr(Value* value, | 3238 LoadFieldInstr(Value* value, |
| 3176 intptr_t offset_in_bytes, | 3239 intptr_t offset_in_bytes, |
| 3177 const AbstractType& type, | 3240 const AbstractType& type, |
| 3178 bool immutable = false) | 3241 bool immutable = false) |
| 3179 : offset_in_bytes_(offset_in_bytes), | 3242 : offset_in_bytes_(offset_in_bytes), |
| 3180 type_(type), | 3243 type_(type), |
| 3181 result_cid_(kDynamicCid), | 3244 result_cid_(kDynamicCid), |
| 3182 immutable_(immutable), | 3245 immutable_(immutable), |
| 3183 recognized_kind_(MethodRecognizer::kUnknown) { | 3246 recognized_kind_(MethodRecognizer::kUnknown), |
| 3247 field_name_(NULL), |
| 3248 field_(NULL) { |
| 3184 ASSERT(type.IsZoneHandle()); // May be null if field is not an instance. | 3249 ASSERT(type.IsZoneHandle()); // May be null if field is not an instance. |
| 3185 SetInputAt(0, value); | 3250 SetInputAt(0, value); |
| 3186 } | 3251 } |
| 3187 | 3252 |
| 3188 DECLARE_INSTRUCTION(LoadField) | 3253 DECLARE_INSTRUCTION(LoadField) |
| 3189 virtual CompileType ComputeType() const; | 3254 virtual CompileType ComputeType() const; |
| 3190 | 3255 |
| 3191 Value* value() const { return inputs_[0]; } | 3256 Value* value() const { return inputs_[0]; } |
| 3192 intptr_t offset_in_bytes() const { return offset_in_bytes_; } | 3257 intptr_t offset_in_bytes() const { return offset_in_bytes_; } |
| 3193 const AbstractType& type() const { return type_; } | 3258 const AbstractType& type() const { return type_; } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3214 } | 3279 } |
| 3215 | 3280 |
| 3216 bool IsImmutableLengthLoad() const; | 3281 bool IsImmutableLengthLoad() const; |
| 3217 | 3282 |
| 3218 virtual Definition* Canonicalize(FlowGraphOptimizer* optimizer); | 3283 virtual Definition* Canonicalize(FlowGraphOptimizer* optimizer); |
| 3219 | 3284 |
| 3220 static MethodRecognizer::Kind RecognizedKindFromArrayCid(intptr_t cid); | 3285 static MethodRecognizer::Kind RecognizedKindFromArrayCid(intptr_t cid); |
| 3221 | 3286 |
| 3222 static bool IsFixedLengthArrayCid(intptr_t cid); | 3287 static bool IsFixedLengthArrayCid(intptr_t cid); |
| 3223 | 3288 |
| 3289 void set_field_name(const char* name) { field_name_ = name; } |
| 3290 const char* field_name() const { return field_name_; } |
| 3291 |
| 3292 Field* field() const { return field_; } |
| 3293 void set_field(Field* field) { field_ = field; } |
| 3294 |
| 3224 private: | 3295 private: |
| 3225 const intptr_t offset_in_bytes_; | 3296 const intptr_t offset_in_bytes_; |
| 3226 const AbstractType& type_; | 3297 const AbstractType& type_; |
| 3227 intptr_t result_cid_; | 3298 intptr_t result_cid_; |
| 3228 const bool immutable_; | 3299 const bool immutable_; |
| 3229 | 3300 |
| 3230 MethodRecognizer::Kind recognized_kind_; | 3301 MethodRecognizer::Kind recognized_kind_; |
| 3231 | 3302 |
| 3303 const char* field_name_; |
| 3304 Field* field_; |
| 3305 |
| 3232 DISALLOW_COPY_AND_ASSIGN(LoadFieldInstr); | 3306 DISALLOW_COPY_AND_ASSIGN(LoadFieldInstr); |
| 3233 }; | 3307 }; |
| 3234 | 3308 |
| 3235 | 3309 |
| 3236 class StoreVMFieldInstr : public TemplateDefinition<2> { | 3310 class StoreVMFieldInstr : public TemplateDefinition<2> { |
| 3237 public: | 3311 public: |
| 3238 StoreVMFieldInstr(Value* dest, | 3312 StoreVMFieldInstr(Value* dest, |
| 3239 intptr_t offset_in_bytes, | 3313 intptr_t offset_in_bytes, |
| 3240 Value* value, | 3314 Value* value, |
| 3241 const AbstractType& type) | 3315 const AbstractType& type) |
| (...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4206 virtual bool AffectedBySideEffect() const; | 4280 virtual bool AffectedBySideEffect() const; |
| 4207 | 4281 |
| 4208 Value* value() const { return inputs_[0]; } | 4282 Value* value() const { return inputs_[0]; } |
| 4209 | 4283 |
| 4210 const ICData& unary_checks() const { return unary_checks_; } | 4284 const ICData& unary_checks() const { return unary_checks_; } |
| 4211 | 4285 |
| 4212 virtual Instruction* Canonicalize(FlowGraphOptimizer* optimizer); | 4286 virtual Instruction* Canonicalize(FlowGraphOptimizer* optimizer); |
| 4213 | 4287 |
| 4214 virtual void PrintOperandsTo(BufferFormatter* f) const; | 4288 virtual void PrintOperandsTo(BufferFormatter* f) const; |
| 4215 | 4289 |
| 4290 void set_null_check(bool flag) { null_check_ = flag; } |
| 4291 |
| 4292 bool null_check() const { return null_check_; } |
| 4293 |
| 4216 private: | 4294 private: |
| 4217 const ICData& unary_checks_; | 4295 const ICData& unary_checks_; |
| 4218 | 4296 |
| 4297 bool null_check_; |
| 4298 |
| 4219 DISALLOW_COPY_AND_ASSIGN(CheckClassInstr); | 4299 DISALLOW_COPY_AND_ASSIGN(CheckClassInstr); |
| 4220 }; | 4300 }; |
| 4221 | 4301 |
| 4222 | 4302 |
| 4223 class CheckSmiInstr : public TemplateInstruction<1> { | 4303 class CheckSmiInstr : public TemplateInstruction<1> { |
| 4224 public: | 4304 public: |
| 4225 CheckSmiInstr(Value* value, intptr_t original_deopt_id) { | 4305 CheckSmiInstr(Value* value, intptr_t original_deopt_id) { |
| 4226 ASSERT(original_deopt_id != Isolate::kNoDeoptId); | 4306 ASSERT(original_deopt_id != Isolate::kNoDeoptId); |
| 4227 SetInputAt(0, value); | 4307 SetInputAt(0, value); |
| 4228 deopt_id_ = original_deopt_id; | 4308 deopt_id_ = original_deopt_id; |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4514 ForwardInstructionIterator* current_iterator_; | 4594 ForwardInstructionIterator* current_iterator_; |
| 4515 | 4595 |
| 4516 private: | 4596 private: |
| 4517 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); | 4597 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); |
| 4518 }; | 4598 }; |
| 4519 | 4599 |
| 4520 | 4600 |
| 4521 } // namespace dart | 4601 } // namespace dart |
| 4522 | 4602 |
| 4523 #endif // VM_INTERMEDIATE_LANGUAGE_H_ | 4603 #endif // VM_INTERMEDIATE_LANGUAGE_H_ |
| OLD | NEW |