| Index: runtime/vm/intermediate_language.h
|
| diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
|
| index c7771ee81d3dddf11335b5425dce8aaeb796db14..2cdead96f248642af7a494791734941cf5fdd131 100644
|
| --- a/runtime/vm/intermediate_language.h
|
| +++ b/runtime/vm/intermediate_language.h
|
| @@ -142,6 +142,8 @@ class CompileType : public ValueObject {
|
| return *this;
|
| }
|
|
|
| + bool is_nullable() const { return is_nullable_; }
|
| +
|
| // Return type such that concrete value's type in runtime is guaranteed to
|
| // be subtype of it.
|
| const AbstractType* ToAbstractType();
|
| @@ -176,6 +178,14 @@ class CompileType : public ValueObject {
|
| // abstract type. The pair is assumed to be coherent.
|
| static CompileType Create(intptr_t cid, const AbstractType& type);
|
|
|
| + CompileType CopyNonNullable() const {
|
| + return CompileType(kNonNullable, cid_, type_);
|
| + }
|
| +
|
| + static CompileType CreateNullable(bool is_nullable, intptr_t cid) {
|
| + return CompileType(is_nullable, cid, NULL);
|
| + }
|
| +
|
| // Create a new CompileType representing given abstract type. By default
|
| // values as assumed to be nullable.
|
| static CompileType FromAbstractType(const AbstractType& type,
|
| @@ -481,6 +491,7 @@ class EmbeddedArray<T, 0> {
|
| M(Constraint) \
|
| M(StringFromCharCode) \
|
| M(InvokeMathCFunction) \
|
| + M(GuardField) \
|
|
|
|
|
| #define FORWARD_DECLARATION(type) class type##Instr;
|
| @@ -730,6 +741,7 @@ FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
|
| friend class UnaryMintOpInstr;
|
| friend class MathSqrtInstr;
|
| friend class CheckClassInstr;
|
| + friend class GuardFieldInstr;
|
| friend class CheckSmiInstr;
|
| friend class CheckArrayBoundInstr;
|
| friend class CheckEitherNonSmiInstr;
|
| @@ -740,6 +752,7 @@ FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
|
| friend class FlowGraphOptimizer;
|
| friend class LoadIndexedInstr;
|
| friend class StoreIndexedInstr;
|
| + friend class StoreInstanceFieldInstr;
|
|
|
| virtual void RawSetInputAt(intptr_t i, Value* value) = 0;
|
|
|
| @@ -2755,12 +2768,20 @@ class StoreInstanceFieldInstr : public TemplateDefinition<2> {
|
| StoreInstanceFieldInstr(const Field& field,
|
| Value* instance,
|
| Value* value,
|
| - StoreBarrierType emit_store_barrier)
|
| - : field_(field), emit_store_barrier_(emit_store_barrier) {
|
| + StoreBarrierType emit_store_barrier,
|
| + bool emit_field_guard = true)
|
| + : field_(field),
|
| + emit_store_barrier_(emit_store_barrier),
|
| + emit_field_guard_(emit_field_guard) {
|
| SetInputAt(0, instance);
|
| SetInputAt(1, value);
|
| }
|
|
|
| + void SetDeoptId(intptr_t deopt_id) {
|
| + ASSERT(CanDeoptimize());
|
| + deopt_id_ = deopt_id;
|
| + }
|
| +
|
| DECLARE_INSTRUCTION(StoreInstanceField)
|
| virtual CompileType* ComputeInitialType() const;
|
|
|
| @@ -2775,18 +2796,60 @@ class StoreInstanceFieldInstr : public TemplateDefinition<2> {
|
|
|
| virtual void PrintOperandsTo(BufferFormatter* f) const;
|
|
|
| - virtual bool CanDeoptimize() const { return false; }
|
| + virtual bool CanDeoptimize() const { return emit_field_guard_; }
|
|
|
| virtual bool HasSideEffect() const { return true; }
|
|
|
| + void detach_field_guard() { emit_field_guard_ = false; }
|
| +
|
| + bool should_emit_field_guard() const { return emit_field_guard_; }
|
| +
|
| private:
|
| const Field& field_;
|
| const StoreBarrierType emit_store_barrier_;
|
| + bool emit_field_guard_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(StoreInstanceFieldInstr);
|
| };
|
|
|
|
|
| +class GuardFieldInstr : public TemplateInstruction<1> {
|
| + public:
|
| + GuardFieldInstr(Value* value,
|
| + const Field& field,
|
| + intptr_t deopt_id)
|
| + : field_(field) {
|
| + deopt_id_ = deopt_id;
|
| + SetInputAt(0, value);
|
| + }
|
| +
|
| + DECLARE_INSTRUCTION(GuardField)
|
| +
|
| + virtual intptr_t ArgumentCount() const { return 0; }
|
| +
|
| + virtual bool CanDeoptimize() const { return env() != NULL; }
|
| +
|
| + virtual bool HasSideEffect() const { return false; }
|
| +
|
| + virtual bool AttributesEqual(Instruction* other) const;
|
| +
|
| + virtual bool AffectedBySideEffect() const;
|
| +
|
| + Value* value() const { return inputs_[0]; }
|
| +
|
| + virtual Instruction* Canonicalize(FlowGraphOptimizer* optimizer);
|
| +
|
| + virtual void PrintOperandsTo(BufferFormatter* f) const;
|
| +
|
| + const Field& field() const { return field_; }
|
| +
|
| + private:
|
| + const Field& field_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(GuardFieldInstr);
|
| +};
|
| +
|
| +
|
| class LoadStaticFieldInstr : public TemplateDefinition<0> {
|
| public:
|
| explicit LoadStaticFieldInstr(const Field& field) : field_(field) {}
|
| @@ -3180,7 +3243,9 @@ class LoadFieldInstr : public TemplateDefinition<1> {
|
| type_(type),
|
| result_cid_(kDynamicCid),
|
| immutable_(immutable),
|
| - recognized_kind_(MethodRecognizer::kUnknown) {
|
| + recognized_kind_(MethodRecognizer::kUnknown),
|
| + field_name_(NULL),
|
| + field_(NULL) {
|
| ASSERT(type.IsZoneHandle()); // May be null if field is not an instance.
|
| SetInputAt(0, value);
|
| }
|
| @@ -3221,6 +3286,12 @@ class LoadFieldInstr : public TemplateDefinition<1> {
|
|
|
| static bool IsFixedLengthArrayCid(intptr_t cid);
|
|
|
| + void set_field_name(const char* name) { field_name_ = name; }
|
| + const char* field_name() const { return field_name_; }
|
| +
|
| + Field* field() const { return field_; }
|
| + void set_field(Field* field) { field_ = field; }
|
| +
|
| private:
|
| const intptr_t offset_in_bytes_;
|
| const AbstractType& type_;
|
| @@ -3229,6 +3300,9 @@ class LoadFieldInstr : public TemplateDefinition<1> {
|
|
|
| MethodRecognizer::Kind recognized_kind_;
|
|
|
| + const char* field_name_;
|
| + Field* field_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(LoadFieldInstr);
|
| };
|
|
|
| @@ -4213,9 +4287,15 @@ class CheckClassInstr : public TemplateInstruction<1> {
|
|
|
| virtual void PrintOperandsTo(BufferFormatter* f) const;
|
|
|
| + void set_null_check(bool flag) { null_check_ = flag; }
|
| +
|
| + bool null_check() const { return null_check_; }
|
| +
|
| private:
|
| const ICData& unary_checks_;
|
|
|
| + bool null_check_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(CheckClassInstr);
|
| };
|
|
|
|
|