| 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_DEOPT_INSTRUCTIONS_H_ | 5 #ifndef VM_DEOPT_INSTRUCTIONS_H_ |
| 6 #define VM_DEOPT_INSTRUCTIONS_H_ | 6 #define VM_DEOPT_INSTRUCTIONS_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
| 10 #include "vm/code_generator.h" | 10 #include "vm/code_generator.h" |
| 11 #include "vm/deferred_objects.h" |
| 11 #include "vm/growable_array.h" | 12 #include "vm/growable_array.h" |
| 12 #include "vm/object.h" | 13 #include "vm/object.h" |
| 13 | 14 |
| 14 namespace dart { | 15 namespace dart { |
| 15 | 16 |
| 16 class Location; | 17 class Location; |
| 17 class Value; | 18 class Value; |
| 18 class MaterializeObjectInstr; | 19 class MaterializeObjectInstr; |
| 19 | 20 |
| 20 // Holds all data relevant for execution of deoptimization instructions. | 21 // Holds all data relevant for execution of deoptimization instructions. |
| 21 class DeoptimizationContext : public ValueObject { | 22 class DeoptContext { |
| 22 public: | 23 public: |
| 23 // 'to_frame_start' points to the fixed size portion of the frame under sp. | |
| 24 // 'num_args' is 0 if there are no arguments or if there are optional | 24 // 'num_args' is 0 if there are no arguments or if there are optional |
| 25 // arguments. | 25 // arguments. |
| 26 DeoptimizationContext(intptr_t* to_frame_start, | 26 DeoptContext(const Array& object_table, |
| 27 intptr_t to_frame_size, | 27 intptr_t num_args, |
| 28 const Array& object_table, | 28 DeoptReasonId deopt_reason); |
| 29 intptr_t num_args, | |
| 30 DeoptReasonId deopt_reason); | |
| 31 | 29 |
| 32 intptr_t* GetFromFrameAddressAt(intptr_t index) const { | 30 virtual ~DeoptContext(); |
| 33 ASSERT((0 <= index) && (index < from_frame_size_)); | 31 |
| 34 return &from_frame_[index]; | 32 // Sets the sources (frame and registers) for this deoptimization. |
| 33 // |
| 34 // if 'frame_is_copy' is true, DeoptContext will delete the frame |
| 35 // when it is done. |
| 36 void SetSourceArgs(intptr_t* frame_start, |
| 37 intptr_t frame_size, |
| 38 fpu_register_t* fpu_registers, |
| 39 intptr_t* cpu_registers, |
| 40 bool frame_is_copy); |
| 41 |
| 42 // Sets the destination fraem for this deoptimization. |
| 43 // |
| 44 // 'frame_start' oints to the fixed size portion of the frame under |
| 45 // sp. |
| 46 // |
| 47 // DeoptContext does not claim ownership of the frame memory. |
| 48 void SetDestArgs(intptr_t* frame_start, intptr_t frame_size); |
| 49 |
| 50 intptr_t* GetSourceFrameAddressAt(intptr_t index) const { |
| 51 ASSERT(source_frame_ != NULL); |
| 52 ASSERT((0 <= index) && (index < source_frame_size_)); |
| 53 return &source_frame_[index]; |
| 35 } | 54 } |
| 36 | 55 |
| 37 intptr_t* GetToFrameAddressAt(intptr_t index) const { | 56 intptr_t* GetDestFrameAddressAt(intptr_t index) const { |
| 38 ASSERT((0 <= index) && (index < to_frame_size_)); | 57 ASSERT(dest_frame_ != NULL); |
| 39 return &to_frame_[index]; | 58 ASSERT((0 <= index) && (index < dest_frame_size_)); |
| 59 return &dest_frame_[index]; |
| 40 } | 60 } |
| 41 | 61 |
| 42 intptr_t GetFromFp() const; | 62 intptr_t GetSourceFp() const; |
| 43 intptr_t GetFromPp() const; | 63 intptr_t GetSourcePp() const; |
| 44 intptr_t GetFromPc() const; | 64 intptr_t GetSourcePc() const; |
| 45 | 65 |
| 46 intptr_t GetCallerFp() const; | 66 intptr_t GetCallerFp() const; |
| 47 void SetCallerFp(intptr_t callers_fp); | 67 void SetCallerFp(intptr_t callers_fp); |
| 48 | 68 |
| 49 RawObject* ObjectAt(intptr_t index) const { | 69 RawObject* ObjectAt(intptr_t index) const { |
| 50 return object_table_.At(index); | 70 const Array& object_table = Array::Handle(object_table_); |
| 71 return object_table.At(index); |
| 51 } | 72 } |
| 52 | 73 |
| 53 intptr_t RegisterValue(Register reg) const { | 74 intptr_t RegisterValue(Register reg) const { |
| 54 return registers_copy_[reg]; | 75 return cpu_registers_[reg]; |
| 55 } | 76 } |
| 56 | 77 |
| 57 double FpuRegisterValue(FpuRegister reg) const { | 78 double FpuRegisterValue(FpuRegister reg) const { |
| 58 return *reinterpret_cast<double*>(&fpu_registers_copy_[reg]); | 79 return *reinterpret_cast<double*>(&fpu_registers_[reg]); |
| 59 } | 80 } |
| 60 | 81 |
| 61 int64_t FpuRegisterValueAsInt64(FpuRegister reg) const { | 82 int64_t FpuRegisterValueAsInt64(FpuRegister reg) const { |
| 62 return *reinterpret_cast<int64_t*>(&fpu_registers_copy_[reg]); | 83 return *reinterpret_cast<int64_t*>(&fpu_registers_[reg]); |
| 63 } | 84 } |
| 64 | 85 |
| 65 simd128_value_t FpuRegisterValueAsSimd128(FpuRegister reg) const { | 86 simd128_value_t FpuRegisterValueAsSimd128(FpuRegister reg) const { |
| 66 const float* address = reinterpret_cast<float*>(&fpu_registers_copy_[reg]); | 87 const float* address = reinterpret_cast<float*>(&fpu_registers_[reg]); |
| 67 return simd128_value_t().readFrom(address); | 88 return simd128_value_t().readFrom(address); |
| 68 } | 89 } |
| 69 | 90 |
| 70 Isolate* isolate() const { return isolate_; } | 91 Isolate* isolate() const { return isolate_; } |
| 71 | 92 |
| 72 intptr_t from_frame_size() const { return from_frame_size_; } | 93 intptr_t source_frame_size() const { return source_frame_size_; } |
| 73 | 94 |
| 74 DeoptReasonId deopt_reason() const { return deopt_reason_; } | 95 DeoptReasonId deopt_reason() const { return deopt_reason_; } |
| 75 | 96 |
| 97 void VisitObjectPointers(ObjectPointerVisitor* visitor); |
| 98 |
| 99 void PrepareForDeferredMaterialization(intptr_t count) { |
| 100 if (count > 0) { |
| 101 deferred_objects_ = new DeferredObject*[count]; |
| 102 deferred_objects_count_ = count; |
| 103 } |
| 104 } |
| 105 |
| 106 DeferredObject* GetDeferredObject(intptr_t idx) const { |
| 107 return deferred_objects_[idx]; |
| 108 } |
| 109 |
| 110 // Sets the materialized value for some deferred object. |
| 111 // |
| 112 // Claims ownership of the memory for 'object'. |
| 113 void SetDeferredObjectAt(intptr_t idx, DeferredObject* object) { |
| 114 deferred_objects_[idx] = object; |
| 115 } |
| 116 |
| 117 intptr_t DeferredObjectsCount() const { |
| 118 return deferred_objects_count_; |
| 119 } |
| 120 |
| 121 void DeferMaterializedObjectRef(intptr_t idx, intptr_t* slot) { |
| 122 deferred_object_refs_ = new DeferredObjectRef( |
| 123 idx, |
| 124 reinterpret_cast<RawInstance**>(slot), |
| 125 deferred_object_refs_); |
| 126 } |
| 127 |
| 128 void DeferDoubleMaterialization(double value, RawDouble** slot) { |
| 129 deferred_boxes_ = new DeferredDouble( |
| 130 value, |
| 131 reinterpret_cast<RawInstance**>(slot), |
| 132 deferred_boxes_); |
| 133 } |
| 134 |
| 135 void DeferMintMaterialization(int64_t value, RawMint** slot) { |
| 136 deferred_boxes_ = new DeferredMint( |
| 137 value, |
| 138 reinterpret_cast<RawInstance**>(slot), |
| 139 deferred_boxes_); |
| 140 } |
| 141 |
| 142 void DeferFloat32x4Materialization(simd128_value_t value, |
| 143 RawFloat32x4** slot) { |
| 144 deferred_boxes_ = new DeferredFloat32x4( |
| 145 value, |
| 146 reinterpret_cast<RawInstance**>(slot), |
| 147 deferred_boxes_); |
| 148 } |
| 149 |
| 150 void DeferUint32x4Materialization(simd128_value_t value, |
| 151 RawUint32x4** slot) { |
| 152 deferred_boxes_ = new DeferredUint32x4( |
| 153 value, |
| 154 reinterpret_cast<RawInstance**>(slot), |
| 155 deferred_boxes_); |
| 156 } |
| 157 |
| 158 // Materializes all deferred objects. Returns the total number of |
| 159 // artificial arguments used during deoptimization. |
| 160 intptr_t MaterializeDeferredObjects(); |
| 161 |
| 76 private: | 162 private: |
| 77 const Array& object_table_; | 163 RawArray* object_table_; |
| 78 intptr_t* to_frame_; | 164 intptr_t* dest_frame_; |
| 79 const intptr_t to_frame_size_; | 165 intptr_t dest_frame_size_; |
| 80 intptr_t* from_frame_; | 166 bool source_frame_is_copy_; |
| 81 intptr_t from_frame_size_; | 167 intptr_t* source_frame_; |
| 82 intptr_t* registers_copy_; | 168 intptr_t source_frame_size_; |
| 83 fpu_register_t* fpu_registers_copy_; | 169 intptr_t* cpu_registers_; |
| 170 fpu_register_t* fpu_registers_; |
| 84 const intptr_t num_args_; | 171 const intptr_t num_args_; |
| 85 const DeoptReasonId deopt_reason_; | 172 const DeoptReasonId deopt_reason_; |
| 86 intptr_t caller_fp_; | 173 intptr_t caller_fp_; |
| 87 Isolate* isolate_; | 174 Isolate* isolate_; |
| 88 | 175 |
| 89 DISALLOW_COPY_AND_ASSIGN(DeoptimizationContext); | 176 DeferredSlot* deferred_boxes_; |
| 177 DeferredSlot* deferred_object_refs_; |
| 178 |
| 179 intptr_t deferred_objects_count_; |
| 180 DeferredObject** deferred_objects_; |
| 181 |
| 182 DISALLOW_COPY_AND_ASSIGN(DeoptContext); |
| 90 }; | 183 }; |
| 91 | 184 |
| 92 | 185 |
| 93 | 186 |
| 94 // Represents one deopt instruction, e.g, setup return address, store object, | 187 // Represents one deopt instruction, e.g, setup return address, store object, |
| 95 // store register, etc. The target is defined by instruction's position in | 188 // store register, etc. The target is defined by instruction's position in |
| 96 // the deopt-info array. | 189 // the deopt-info array. |
| 97 class DeoptInstr : public ZoneAllocated { | 190 class DeoptInstr : public ZoneAllocated { |
| 98 public: | 191 public: |
| 99 enum Kind { | 192 enum Kind { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 112 kPcMarker, | 205 kPcMarker, |
| 113 kPp, | 206 kPp, |
| 114 kCallerFp, | 207 kCallerFp, |
| 115 kCallerPp, | 208 kCallerPp, |
| 116 kCallerPc, | 209 kCallerPc, |
| 117 kSuffix, | 210 kSuffix, |
| 118 kMaterializedObjectRef, | 211 kMaterializedObjectRef, |
| 119 kMaterializeObject | 212 kMaterializeObject |
| 120 }; | 213 }; |
| 121 | 214 |
| 122 static DeoptInstr* Create(intptr_t kind_as_int, intptr_t from_index); | 215 static DeoptInstr* Create(intptr_t kind_as_int, intptr_t source_index); |
| 123 | 216 |
| 124 DeoptInstr() {} | 217 DeoptInstr() {} |
| 125 virtual ~DeoptInstr() {} | 218 virtual ~DeoptInstr() {} |
| 126 | 219 |
| 127 virtual const char* ToCString() const = 0; | 220 virtual const char* ToCString() const = 0; |
| 128 | 221 |
| 129 virtual void Execute(DeoptimizationContext* deopt_context, | 222 virtual void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) = 0; |
| 130 intptr_t* to_addr) = 0; | |
| 131 | 223 |
| 132 virtual DeoptInstr::Kind kind() const = 0; | 224 virtual DeoptInstr::Kind kind() const = 0; |
| 133 | 225 |
| 134 bool Equals(const DeoptInstr& other) const { | 226 bool Equals(const DeoptInstr& other) const { |
| 135 return (kind() == other.kind()) && (from_index() == other.from_index()); | 227 return (kind() == other.kind()) && (source_index() == other.source_index()); |
| 136 } | 228 } |
| 137 | 229 |
| 138 // Decode the payload of a suffix command. Return the suffix length and | 230 // Decode the payload of a suffix command. Return the suffix length and |
| 139 // set the output parameter info_number to the index of the shared suffix. | 231 // set the output parameter info_number to the index of the shared suffix. |
| 140 static intptr_t DecodeSuffix(intptr_t from_index, intptr_t* info_number); | 232 static intptr_t DecodeSuffix(intptr_t source_index, intptr_t* info_number); |
| 141 | 233 |
| 142 // Get the function and return address which is encoded in this | 234 // Get the function and return address which is encoded in this |
| 143 // kRetAfterAddress deopt instruction. | 235 // kRetAfterAddress deopt instruction. |
| 144 static uword GetRetAddress(DeoptInstr* instr, | 236 static uword GetRetAddress(DeoptInstr* instr, |
| 145 const Array& object_table, | 237 const Array& object_table, |
| 146 Function* func); | 238 Function* func); |
| 147 | 239 |
| 148 // Return number of initialized fields in the object that will be | 240 // Return number of initialized fields in the object that will be |
| 149 // materialized by kMaterializeObject instruction. | 241 // materialized by kMaterializeObject instruction. |
| 150 static intptr_t GetFieldCount(DeoptInstr* instr) { | 242 static intptr_t GetFieldCount(DeoptInstr* instr) { |
| 151 ASSERT(instr->kind() == DeoptInstr::kMaterializeObject); | 243 ASSERT(instr->kind() == DeoptInstr::kMaterializeObject); |
| 152 return instr->from_index(); | 244 return instr->source_index(); |
| 153 } | 245 } |
| 154 | 246 |
| 155 protected: | 247 protected: |
| 156 friend class DeoptInfoBuilder; | 248 friend class DeoptInfoBuilder; |
| 157 | 249 |
| 158 virtual intptr_t from_index() const = 0; | 250 virtual intptr_t source_index() const = 0; |
| 159 | 251 |
| 160 private: | 252 private: |
| 161 DISALLOW_COPY_AND_ASSIGN(DeoptInstr); | 253 DISALLOW_COPY_AND_ASSIGN(DeoptInstr); |
| 162 }; | 254 }; |
| 163 | 255 |
| 164 | 256 |
| 165 // Builds a deoptimization info table, one DeoptInfo at a time. Call AddXXX | 257 // Builds a deoptimization info table, one DeoptInfo at a time. Call AddXXX |
| 166 // methods in the order of their target, starting wih deoptimized code | 258 // methods in the order of their target, starting wih deoptimized code |
| 167 // continuation pc and ending with the first argument of the deoptimized | 259 // continuation pc and ending with the first argument of the deoptimized |
| 168 // code. Call CreateDeoptInfo to write the accumulated instructions into | 260 // code. Call CreateDeoptInfo to write the accumulated instructions into |
| 169 // the heap and reset the builder's internal state for the next DeoptInfo. | 261 // the heap and reset the builder's internal state for the next DeoptInfo. |
| 170 class DeoptInfoBuilder : public ValueObject { | 262 class DeoptInfoBuilder : public ValueObject { |
| 171 public: | 263 public: |
| 172 explicit DeoptInfoBuilder(const intptr_t num_args); | 264 explicit DeoptInfoBuilder(const intptr_t num_args); |
| 173 | 265 |
| 174 // 'object_table' holds all objects referred to by DeoptInstr in | 266 // 'object_table' holds all objects referred to by DeoptInstr in |
| 175 // all DeoptInfo instances for a single Code object. | 267 // all DeoptInfo instances for a single Code object. |
| 176 const GrowableObjectArray& object_table() { return object_table_; } | 268 const GrowableObjectArray& object_table() { return object_table_; } |
| 177 | 269 |
| 178 // Return address before instruction. | 270 // Return address before instruction. |
| 179 void AddReturnAddress(const Function& function, | 271 void AddReturnAddress(const Function& function, |
| 180 intptr_t deopt_id, | 272 intptr_t deopt_id, |
| 181 intptr_t to_index); | 273 intptr_t dest_index); |
| 182 | 274 |
| 183 // Copy from optimized frame to unoptimized. | 275 // Copy from optimized frame to unoptimized. |
| 184 void AddCopy(Value* value, const Location& from_loc, intptr_t to_index); | 276 void AddCopy(Value* value, const Location& source_loc, intptr_t dest_index); |
| 185 void AddPcMarker(const Function& function, intptr_t to_index); | 277 void AddPcMarker(const Function& function, intptr_t dest_index); |
| 186 void AddPp(const Function& function, intptr_t to_index); | 278 void AddPp(const Function& function, intptr_t dest_index); |
| 187 void AddCallerFp(intptr_t to_index); | 279 void AddCallerFp(intptr_t dest_index); |
| 188 void AddCallerPp(intptr_t to_index); | 280 void AddCallerPp(intptr_t dest_index); |
| 189 void AddCallerPc(intptr_t to_index); | 281 void AddCallerPc(intptr_t dest_index); |
| 190 | 282 |
| 191 // Add object to be materialized. Emit kMaterializeObject instruction. | 283 // Add object to be materialized. Emit kMaterializeObject instruction. |
| 192 void AddMaterialization(MaterializeObjectInstr* mat); | 284 void AddMaterialization(MaterializeObjectInstr* mat); |
| 193 | 285 |
| 194 // For every materialized object emit instructions describing data required | 286 // For every materialized object emit instructions describing data required |
| 195 // for materialization: class of the instance to allocate and field-value | 287 // for materialization: class of the instance to allocate and field-value |
| 196 // pairs for initialization. | 288 // pairs for initialization. |
| 197 // Emitted instructions are expected to follow fixed size section of frame | 289 // Emitted instructions are expected to follow fixed size section of frame |
| 198 // emitted first. This way they become a part of the bottom-most deoptimized | 290 // emitted first. This way they become a part of the bottom-most deoptimized |
| 199 // frame and are discoverable by GC. | 291 // frame and are discoverable by GC. |
| 200 // At deoptimization they will be removed by the stub at the very end: | 292 // At deoptimization they will be removed by the stub at the very end: |
| 201 // after they were used to materialize objects. | 293 // after they were used to materialize objects. |
| 202 // Returns the index of the next stack slot. Used for verification. | 294 // Returns the index of the next stack slot. Used for verification. |
| 203 intptr_t EmitMaterializationArguments(intptr_t to_index); | 295 intptr_t EmitMaterializationArguments(intptr_t dest_index); |
| 204 | 296 |
| 205 RawDeoptInfo* CreateDeoptInfo(const Array& deopt_table); | 297 RawDeoptInfo* CreateDeoptInfo(const Array& deopt_table); |
| 206 | 298 |
| 207 // Mark the actual start of the frame description after all materialization | 299 // Mark the actual start of the frame description after all materialization |
| 208 // instructions were emitted. Used for verification purposes. | 300 // instructions were emitted. Used for verification purposes. |
| 209 void MarkFrameStart() { | 301 void MarkFrameStart() { |
| 210 ASSERT(frame_start_ == -1); | 302 ASSERT(frame_start_ == -1); |
| 211 frame_start_ = instructions_.length(); | 303 frame_start_ = instructions_.length(); |
| 212 } | 304 } |
| 213 | 305 |
| 214 private: | 306 private: |
| 215 class TrieNode; | 307 class TrieNode; |
| 216 | 308 |
| 217 intptr_t FindOrAddObjectInTable(const Object& obj) const; | 309 intptr_t FindOrAddObjectInTable(const Object& obj) const; |
| 218 intptr_t FindMaterialization(MaterializeObjectInstr* mat) const; | 310 intptr_t FindMaterialization(MaterializeObjectInstr* mat) const; |
| 219 intptr_t CalculateStackIndex(const Location& from_loc) const; | 311 intptr_t CalculateStackIndex(const Location& source_loc) const; |
| 220 | 312 |
| 221 intptr_t FrameSize() const { | 313 intptr_t FrameSize() const { |
| 222 return instructions_.length() - frame_start_; | 314 return instructions_.length() - frame_start_; |
| 223 } | 315 } |
| 224 | 316 |
| 225 void AddConstant(const Object& obj, intptr_t to_index); | 317 void AddConstant(const Object& obj, intptr_t dest_index); |
| 226 | 318 |
| 227 GrowableArray<DeoptInstr*> instructions_; | 319 GrowableArray<DeoptInstr*> instructions_; |
| 228 const GrowableObjectArray& object_table_; | 320 const GrowableObjectArray& object_table_; |
| 229 const intptr_t num_args_; | 321 const intptr_t num_args_; |
| 230 | 322 |
| 231 // Used to compress entries by sharing suffixes. | 323 // Used to compress entries by sharing suffixes. |
| 232 TrieNode* trie_root_; | 324 TrieNode* trie_root_; |
| 233 intptr_t current_info_number_; | 325 intptr_t current_info_number_; |
| 234 | 326 |
| 235 intptr_t frame_start_; | 327 intptr_t frame_start_; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 266 DeoptInfo* info, | 358 DeoptInfo* info, |
| 267 Smi* reason); | 359 Smi* reason); |
| 268 | 360 |
| 269 private: | 361 private: |
| 270 static const intptr_t kEntrySize = 3; | 362 static const intptr_t kEntrySize = 3; |
| 271 }; | 363 }; |
| 272 | 364 |
| 273 } // namespace dart | 365 } // namespace dart |
| 274 | 366 |
| 275 #endif // VM_DEOPT_INSTRUCTIONS_H_ | 367 #endif // VM_DEOPT_INSTRUCTIONS_H_ |
| OLD | NEW |