Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 #include "vm/deopt_instructions.h" | |
| 6 | |
| 7 #include "vm/intermediate_language.h" | |
| 8 #include "vm/locations.h" | |
| 9 #include "vm/parser.h" | |
| 10 | |
| 11 namespace dart { | |
| 12 | |
| 13 // Deoptimization instruction moving value from optimized frame at | |
| 14 // 'from_index'. 'from_index' represents the local count >= 0, first | |
|
siva
2012/08/04 01:21:50
'from_index' to specified slots in the unoptimized
srdjan
2012/08/06 20:09:05
Done.
| |
| 15 // argument being 0. | |
| 16 class DeoptStackSlotInstr : public DeoptInstr { | |
| 17 public: | |
| 18 explicit DeoptStackSlotInstr(intptr_t from_index) | |
| 19 : stack_slot_index_(from_index) { | |
| 20 ASSERT(stack_slot_index_ >= 0); | |
| 21 } | |
| 22 | |
| 23 virtual intptr_t from_index() const { return stack_slot_index_; } | |
| 24 virtual DeoptInstr::Kind kind() const { return kStackSlot; } | |
| 25 | |
| 26 virtual const char* ToCString() const { | |
| 27 intptr_t len = OS::SNPrint(NULL, 0, "s%d", stack_slot_index_); | |
| 28 char* chars = reinterpret_cast<char*>( | |
| 29 Isolate::Current()->current_zone()->Allocate(len + 1)); | |
| 30 OS::SNPrint(chars, len + 1, "s%d", stack_slot_index_); | |
| 31 return chars; | |
| 32 } | |
| 33 | |
| 34 private: | |
| 35 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | |
| 36 | |
| 37 DISALLOW_COPY_AND_ASSIGN(DeoptStackSlotInstr); | |
| 38 }; | |
| 39 | |
| 40 | |
| 41 // Deoptimization instruction creating return address using function and | |
| 42 // deopt-id stored at 'object_table_index'. | |
| 43 class DeoptRetAddrInstr : public DeoptInstr { | |
| 44 public: | |
| 45 explicit DeoptRetAddrInstr(intptr_t object_table_index) | |
| 46 : object_table_index_(object_table_index) { | |
| 47 ASSERT(object_table_index >= 0); | |
| 48 } | |
| 49 | |
| 50 virtual intptr_t from_index() const { return object_table_index_; } | |
| 51 virtual DeoptInstr::Kind kind() const { return kReturnAddress; } | |
| 52 | |
| 53 virtual const char* ToCString() const { | |
| 54 intptr_t len = OS::SNPrint(NULL, 0, "ret oti:%d", object_table_index_); | |
| 55 char* chars = reinterpret_cast<char*>( | |
| 56 Isolate::Current()->current_zone()->Allocate(len + 1)); | |
| 57 OS::SNPrint(chars, len + 1, "ret oti:%d", object_table_index_); | |
| 58 return chars; | |
| 59 } | |
| 60 | |
| 61 private: | |
| 62 const intptr_t object_table_index_; | |
| 63 | |
| 64 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddrInstr); | |
| 65 }; | |
| 66 | |
| 67 | |
| 68 // Deoptimization instruction moving a constant stored at 'object_table_index'. | |
| 69 class DeoptConstantInstr : public DeoptInstr { | |
| 70 public: | |
| 71 explicit DeoptConstantInstr(intptr_t object_table_index) | |
| 72 : object_table_index_(object_table_index) { | |
| 73 ASSERT(object_table_index >= 0); | |
| 74 } | |
| 75 | |
| 76 virtual intptr_t from_index() const { return object_table_index_; } | |
| 77 virtual DeoptInstr::Kind kind() const { return kConstant; } | |
| 78 | |
| 79 virtual const char* ToCString() const { | |
| 80 intptr_t len = OS::SNPrint(NULL, 0, "const oti:%d", object_table_index_); | |
| 81 char* chars = reinterpret_cast<char*>( | |
| 82 Isolate::Current()->current_zone()->Allocate(len + 1)); | |
| 83 OS::SNPrint(chars, len + 1, "const oti:%d", object_table_index_); | |
| 84 return chars; | |
| 85 } | |
| 86 | |
| 87 private: | |
| 88 const intptr_t object_table_index_; | |
| 89 | |
| 90 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); | |
| 91 }; | |
| 92 | |
| 93 | |
| 94 // Deoptimization instruction moving a register. | |
| 95 class DeoptRegisterInstr: public DeoptInstr { | |
| 96 public: | |
| 97 explicit DeoptRegisterInstr(intptr_t reg_as_int) | |
| 98 : reg_(static_cast<Register>(reg_as_int)) {} | |
| 99 | |
| 100 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | |
| 101 virtual DeoptInstr::Kind kind() const { return kRegister; } | |
| 102 | |
| 103 virtual const char* ToCString() const { | |
| 104 return Assembler::RegisterName(reg_); | |
| 105 } | |
| 106 | |
| 107 private: | |
| 108 const Register reg_; | |
| 109 | |
| 110 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); | |
| 111 }; | |
| 112 | |
| 113 | |
| 114 // Deoptimization instruction creating a PC marker for the code of | |
| 115 // function at 'object_table_index'. | |
| 116 class DeoptPcMarkerInstr : public DeoptInstr { | |
| 117 public: | |
| 118 explicit DeoptPcMarkerInstr(intptr_t object_table_index) | |
| 119 : object_table_index_(object_table_index) { | |
| 120 ASSERT(object_table_index >= 0); | |
| 121 } | |
| 122 | |
| 123 virtual intptr_t from_index() const { return object_table_index_; } | |
| 124 virtual DeoptInstr::Kind kind() const { return kPcMarker; } | |
| 125 | |
| 126 virtual const char* ToCString() const { | |
| 127 intptr_t len = OS::SNPrint(NULL, 0, "pcmark oti:%d", object_table_index_); | |
| 128 char* chars = reinterpret_cast<char*>( | |
| 129 Isolate::Current()->current_zone()->Allocate(len + 1)); | |
| 130 OS::SNPrint(chars, len + 1, "pcmark oti:%d", object_table_index_); | |
| 131 return chars; | |
| 132 } | |
| 133 | |
| 134 private: | |
| 135 intptr_t object_table_index_; | |
| 136 | |
| 137 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); | |
| 138 }; | |
| 139 | |
| 140 | |
| 141 // Deoptimization instruction copying the caller saved FP from optimized frame. | |
| 142 class DeoptCallerFpInstr : public DeoptInstr { | |
| 143 public: | |
| 144 DeoptCallerFpInstr() {} | |
| 145 | |
| 146 virtual intptr_t from_index() const { return 0; } | |
| 147 virtual DeoptInstr::Kind kind() const { return kCallerFp; } | |
| 148 | |
| 149 virtual const char* ToCString() const { return "callerfp"; } | |
| 150 | |
| 151 private: | |
| 152 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); | |
| 153 }; | |
| 154 | |
| 155 | |
| 156 // Deoptimization instruction copying the caller return address from optimzied | |
| 157 // frame. | |
| 158 class DeoptCallerPcInstr : public DeoptInstr { | |
| 159 public: | |
| 160 DeoptCallerPcInstr() {} | |
| 161 | |
| 162 virtual intptr_t from_index() const { return 0; } | |
| 163 virtual DeoptInstr::Kind kind() const { return kCallerFp; } | |
| 164 | |
| 165 virtual const char* ToCString() const { return "callerpc"; } | |
| 166 | |
| 167 private: | |
| 168 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); | |
| 169 }; | |
| 170 | |
| 171 | |
| 172 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { | |
| 173 Kind kind = static_cast<Kind>(kind_as_int); | |
| 174 switch (kind) { | |
| 175 case kStackSlot: return new DeoptStackSlotInstr(from_index); | |
| 176 case kReturnAddress: return new DeoptRetAddrInstr(from_index); | |
| 177 case kConstant: return new DeoptConstantInstr(from_index); | |
| 178 case kRegister: return new DeoptRegisterInstr(from_index); | |
| 179 case kPcMarker: return new DeoptPcMarkerInstr(from_index); | |
| 180 case kCallerFp: return new DeoptCallerFpInstr(); | |
| 181 case kCallerPc: return new DeoptCallerPcInstr(); | |
| 182 } | |
| 183 UNREACHABLE(); | |
| 184 return NULL; | |
| 185 } | |
| 186 | |
| 187 | |
| 188 intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const { | |
| 189 for (intptr_t i = 0; i < object_table_->length(); i++) { | |
| 190 if ((*object_table_)[i]->raw() == obj.raw()) { | |
| 191 return i; | |
| 192 } | |
| 193 } | |
| 194 // Add object. | |
| 195 const intptr_t result = object_table_->length(); | |
| 196 object_table_->Add(&obj); | |
|
siva
2012/08/04 01:21:50
Need to assert obj is a Zone handle because you ar
srdjan
2012/08/06 20:09:05
Discussed and switched to GrowableObjectAray.
| |
| 197 return result; | |
| 198 } | |
| 199 | |
| 200 | |
| 201 // Will be neeeded for inlined functions, currently trivial. | |
| 202 void DeoptInfoBuilder::AddReturnAddress(const Function& function, | |
| 203 intptr_t deopt_id) { | |
| 204 const intptr_t object_table_index = object_table_->length(); | |
| 205 object_table_->Add(&function); | |
| 206 object_table_->Add(&Smi::ZoneHandle(Smi::New(deopt_id))); | |
| 207 instructions_.Add(new DeoptRetAddrInstr(object_table_index)); | |
| 208 } | |
| 209 | |
| 210 | |
| 211 void DeoptInfoBuilder::AddPcMarker(const Function& function) { | |
| 212 // Function object was already added by AddReturnAddress, find it. | |
| 213 intptr_t from_index = FindOrAddObjectInTable(function); | |
| 214 instructions_.Add(new DeoptPcMarkerInstr(from_index)); | |
| 215 } | |
| 216 | |
| 217 | |
| 218 void DeoptInfoBuilder::AddCopy(const Location& loc, const Value& value) { | |
|
siva
2012/08/04 01:21:50
The "to index" is implicit and you have made a com
srdjan
2012/08/06 20:09:05
Done.
| |
| 219 DeoptInstr* deopt_instr = NULL; | |
| 220 if (loc.IsConstant()) { | |
| 221 const intptr_t object_table_index = FindOrAddObjectInTable(loc.constant()); | |
| 222 deopt_instr = new DeoptConstantInstr(object_table_index); | |
| 223 } else if (loc.IsRegister()) { | |
| 224 deopt_instr = new DeoptRegisterInstr(loc.reg()); | |
| 225 } else if (loc.IsStackSlot()) { | |
| 226 deopt_instr = new DeoptStackSlotInstr(loc.stack_index() + num_args_); | |
| 227 } else if (loc.IsInvalid()) { | |
| 228 ASSERT(value.IsConstant()); | |
| 229 const Object& obj = value.AsConstant()->value(); | |
| 230 const intptr_t object_table_index = FindOrAddObjectInTable(obj); | |
| 231 deopt_instr = new DeoptConstantInstr(object_table_index); | |
| 232 } else { | |
| 233 UNREACHABLE(); | |
| 234 } | |
| 235 | |
| 236 instructions_.Add(deopt_instr); | |
| 237 } | |
| 238 | |
| 239 | |
| 240 void DeoptInfoBuilder::AddCallerFp() { | |
| 241 instructions_.Add(new DeoptCallerFpInstr()); | |
| 242 } | |
| 243 | |
| 244 | |
| 245 void DeoptInfoBuilder::AddCallerPc() { | |
| 246 instructions_.Add(new DeoptCallerPcInstr()); | |
| 247 } | |
| 248 | |
| 249 | |
| 250 RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo() { | |
| 251 const intptr_t len = instructions_.length(); | |
| 252 const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(len)); | |
| 253 for (intptr_t i = 0; i < len; i++) { | |
| 254 DeoptInstr* instr = instructions_[i]; | |
| 255 deopt_info.SetAt(i, instr->kind(), instr->from_index()); | |
| 256 } | |
| 257 return deopt_info.raw(); | |
| 258 } | |
| 259 | |
| 260 } // namespace dart | |
| OLD | NEW |