| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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 #include "vm/code_descriptors.h" | 5 #include "vm/code_descriptors.h" |
| 6 | 6 |
| 7 #include "vm/log.h" | 7 #include "vm/log.h" |
| 8 | 8 |
| 9 namespace dart { | 9 namespace dart { |
| 10 | 10 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 Zone* zone = Thread::Current()->zone(); | 121 Zone* zone = Thread::Current()->zone(); |
| 122 return zone->Realloc<uint8_t>(ptr, old_size, new_size); | 122 return zone->Realloc<uint8_t>(ptr, old_size, new_size); |
| 123 } | 123 } |
| 124 | 124 |
| 125 | 125 |
| 126 const TokenPosition CodeSourceMapBuilder::kInitialPosition = | 126 const TokenPosition CodeSourceMapBuilder::kInitialPosition = |
| 127 TokenPosition::kDartCodePrologue; | 127 TokenPosition::kDartCodePrologue; |
| 128 | 128 |
| 129 | 129 |
| 130 CodeSourceMapBuilder::CodeSourceMapBuilder( | 130 CodeSourceMapBuilder::CodeSourceMapBuilder( |
| 131 bool stack_traces_only, |
| 131 const GrowableArray<intptr_t>& caller_inline_id, | 132 const GrowableArray<intptr_t>& caller_inline_id, |
| 132 const GrowableArray<TokenPosition>& inline_id_to_token_pos, | 133 const GrowableArray<TokenPosition>& inline_id_to_token_pos, |
| 133 const GrowableArray<const Function*>& inline_id_to_function) | 134 const GrowableArray<const Function*>& inline_id_to_function) |
| 134 : pc_offset_(0), | 135 : buffered_pc_offset_(0), |
| 135 advance_pc_peephole_(0), | 136 buffered_inline_id_stack_(), |
| 136 inline_id_stack_(), | 137 buffered_token_pos_stack_(), |
| 137 token_pos_stack_(), | 138 written_pc_offset_(0), |
| 139 written_inline_id_stack_(), |
| 140 written_token_pos_stack_(), |
| 138 caller_inline_id_(caller_inline_id), | 141 caller_inline_id_(caller_inline_id), |
| 139 inline_id_to_token_pos_(inline_id_to_token_pos), | 142 inline_id_to_token_pos_(inline_id_to_token_pos), |
| 140 inline_id_to_function_(inline_id_to_function), | 143 inline_id_to_function_(inline_id_to_function), |
| 141 buffer_(NULL), | 144 buffer_(NULL), |
| 142 stream_(&buffer_, zone_allocator, 64) { | 145 stream_(&buffer_, zone_allocator, 64), |
| 143 inline_id_stack_.Add(0); | 146 stack_traces_only_(stack_traces_only) { |
| 144 token_pos_stack_.Add(TokenPosition::kDartCodePrologue); | 147 buffered_inline_id_stack_.Add(0); |
| 148 buffered_token_pos_stack_.Add(kInitialPosition); |
| 149 written_inline_id_stack_.Add(0); |
| 150 written_token_pos_stack_.Add(kInitialPosition); |
| 151 } |
| 152 |
| 153 |
| 154 void CodeSourceMapBuilder::FlushBuffer() { |
| 155 FlushBufferStack(); |
| 156 FlushBufferPosition(); |
| 157 FlushBufferPC(); |
| 158 } |
| 159 |
| 160 |
| 161 void CodeSourceMapBuilder::FlushBufferStack() { |
| 162 for (intptr_t i = buffered_inline_id_stack_.length() - 1; i >= 0; i--) { |
| 163 intptr_t buffered_id = buffered_inline_id_stack_[i]; |
| 164 if (i < written_inline_id_stack_.length()) { |
| 165 intptr_t written_id = written_inline_id_stack_[i]; |
| 166 if (buffered_id == written_id) { |
| 167 // i is the top-most position where the buffered and written stack |
| 168 // match. |
| 169 while (written_inline_id_stack_.length() > i + 1) { |
| 170 WritePop(); |
| 171 } |
| 172 for (intptr_t j = i + 1; j < buffered_inline_id_stack_.length(); j++) { |
| 173 TokenPosition buffered_pos = buffered_token_pos_stack_[j - 1]; |
| 174 TokenPosition written_pos = written_token_pos_stack_[j - 1]; |
| 175 if (buffered_pos != written_pos) { |
| 176 WriteChangePosition(buffered_pos); |
| 177 } |
| 178 WritePush(buffered_inline_id_stack_[j]); |
| 179 } |
| 180 return; |
| 181 } |
| 182 } |
| 183 } |
| 184 UNREACHABLE(); |
| 185 } |
| 186 |
| 187 |
| 188 void CodeSourceMapBuilder::FlushBufferPosition() { |
| 189 ASSERT(buffered_token_pos_stack_.length() == |
| 190 written_token_pos_stack_.length()); |
| 191 |
| 192 intptr_t top = buffered_token_pos_stack_.length() - 1; |
| 193 TokenPosition buffered_pos = buffered_token_pos_stack_[top]; |
| 194 TokenPosition written_pos = written_token_pos_stack_[top]; |
| 195 if (buffered_pos != written_pos) { |
| 196 WriteChangePosition(buffered_pos); |
| 197 } |
| 198 } |
| 199 |
| 200 |
| 201 void CodeSourceMapBuilder::FlushBufferPC() { |
| 202 if (buffered_pc_offset_ != written_pc_offset_) { |
| 203 WriteAdvancePC(buffered_pc_offset_ - written_pc_offset_); |
| 204 } |
| 145 } | 205 } |
| 146 | 206 |
| 147 | 207 |
| 148 void CodeSourceMapBuilder::StartInliningInterval(int32_t pc_offset, | 208 void CodeSourceMapBuilder::StartInliningInterval(int32_t pc_offset, |
| 149 intptr_t inline_id) { | 209 intptr_t inline_id) { |
| 150 if (inline_id_stack_.Last() == inline_id) { | 210 if (buffered_inline_id_stack_.Last() == inline_id) { |
| 151 // No change in function stack. | 211 // No change in function stack. |
| 152 return; | 212 return; |
| 153 } | 213 } |
| 154 if (inline_id == -1) { | 214 if (inline_id == -1) { |
| 155 // Basic blocking missing an inline_id. | 215 // Basic blocking missing an inline_id. |
| 156 return; | 216 return; |
| 157 } | 217 } |
| 158 | 218 |
| 219 if (!stack_traces_only_) { |
| 220 FlushBuffer(); |
| 221 } |
| 222 |
| 159 // Find a minimal set of pops and pushes to bring us to the new function | 223 // Find a minimal set of pops and pushes to bring us to the new function |
| 160 // stack. | 224 // stack. |
| 161 | 225 |
| 162 // Pop to a common ancestor. | 226 // Pop to a common ancestor. |
| 163 intptr_t common_parent = inline_id; | 227 intptr_t common_parent = inline_id; |
| 164 while (!IsOnStack(common_parent)) { | 228 while (!IsOnBufferedStack(common_parent)) { |
| 165 common_parent = caller_inline_id_[common_parent]; | 229 common_parent = caller_inline_id_[common_parent]; |
| 166 } | 230 } |
| 167 while (inline_id_stack_.Last() != common_parent) { | 231 while (buffered_inline_id_stack_.Last() != common_parent) { |
| 168 EmitPop(); | 232 BufferPop(); |
| 169 inline_id_stack_.RemoveLast(); | |
| 170 token_pos_stack_.RemoveLast(); | |
| 171 } | 233 } |
| 172 | 234 |
| 173 // Push to the new top-of-stack function. | 235 // Push to the new top-of-stack function. |
| 174 GrowableArray<intptr_t> to_push; | 236 GrowableArray<intptr_t> to_push; |
| 175 intptr_t id = inline_id; | 237 intptr_t id = inline_id; |
| 176 while (id != common_parent) { | 238 while (id != common_parent) { |
| 177 to_push.Add(id); | 239 to_push.Add(id); |
| 178 id = caller_inline_id_[id]; | 240 id = caller_inline_id_[id]; |
| 179 } | 241 } |
| 180 for (intptr_t i = to_push.length() - 1; i >= 0; i--) { | 242 for (intptr_t i = to_push.length() - 1; i >= 0; i--) { |
| 181 intptr_t push_id = to_push[i]; | 243 intptr_t callee_id = to_push[i]; |
| 182 TokenPosition call_token; | 244 TokenPosition call_token; |
| 183 if (push_id != 0) { | 245 if (callee_id != 0) { |
| 184 // TODO(rmacnak): Should make this array line up with the others. | 246 // TODO(rmacnak): Should make this array line up with the others. |
| 185 call_token = inline_id_to_token_pos_[push_id - 1]; | 247 call_token = inline_id_to_token_pos_[callee_id - 1]; |
| 248 } else { |
| 249 UNREACHABLE(); |
| 186 } | 250 } |
| 187 | 251 |
| 188 // Report caller as at the position of the call. | 252 // Report caller as at the position of the call. |
| 189 if (call_token != token_pos_stack_.Last()) { | 253 BufferChangePosition(call_token); |
| 190 EmitPosition(call_token); | |
| 191 token_pos_stack_[token_pos_stack_.length() - 1] = call_token; | |
| 192 } | |
| 193 | 254 |
| 194 // Push the callee. | 255 BufferPush(callee_id); |
| 195 EmitPush(push_id); | |
| 196 inline_id_stack_.Add(push_id); | |
| 197 token_pos_stack_.Add(TokenPosition::kDartCodePrologue); | |
| 198 } | 256 } |
| 199 } | 257 } |
| 200 | 258 |
| 201 | 259 |
| 202 void CodeSourceMapBuilder::BeginCodeSourceRange(int32_t pc_offset) {} | 260 void CodeSourceMapBuilder::BeginCodeSourceRange(int32_t pc_offset) {} |
| 203 | 261 |
| 204 | 262 |
| 205 void CodeSourceMapBuilder::EndCodeSourceRange(int32_t pc_offset, | 263 void CodeSourceMapBuilder::EndCodeSourceRange(int32_t pc_offset, |
| 206 TokenPosition pos) { | 264 TokenPosition pos) { |
| 207 if (pc_offset == pc_offset_) { | 265 if (pc_offset == buffered_pc_offset_) { |
| 208 return; // Empty intermediate instruction. | 266 return; // Empty intermediate instruction. |
| 209 } | 267 } |
| 210 if (pos != token_pos_stack_.Last()) { | 268 if (pos != buffered_token_pos_stack_.Last()) { |
| 211 EmitPosition(pos); | 269 if (!stack_traces_only_) { |
| 212 token_pos_stack_[token_pos_stack_.length() - 1] = pos; | 270 FlushBuffer(); |
| 271 } |
| 272 BufferChangePosition(pos); |
| 213 } | 273 } |
| 214 EmitAdvancePC(pc_offset - pc_offset_); | 274 BufferAdvancePC(pc_offset - buffered_pc_offset_); |
| 215 pc_offset_ = pc_offset; | |
| 216 } | 275 } |
| 217 | 276 |
| 218 | 277 |
| 278 void CodeSourceMapBuilder::NoteDescriptor(RawPcDescriptors::Kind kind, |
| 279 int32_t pc_offset, |
| 280 TokenPosition pos) { |
| 281 const uint8_t kCanThrow = |
| 282 RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall | |
| 283 RawPcDescriptors::kRuntimeCall | RawPcDescriptors::kOther; |
| 284 if (stack_traces_only_ && ((kind & kCanThrow) != 0)) { |
| 285 BufferChangePosition(pos); |
| 286 BufferAdvancePC(pc_offset - buffered_pc_offset_); |
| 287 FlushBuffer(); |
| 288 } |
| 289 } |
| 290 |
| 291 |
| 219 RawArray* CodeSourceMapBuilder::InliningIdToFunction() { | 292 RawArray* CodeSourceMapBuilder::InliningIdToFunction() { |
| 220 if (inline_id_to_function_.length() <= 1) { | 293 if (inline_id_to_function_.length() <= 1) { |
| 221 // Not optimizing, or optimizing and nothing inlined. | 294 // Not optimizing, or optimizing and nothing inlined. |
| 222 return Object::empty_array().raw(); | 295 return Object::empty_array().raw(); |
| 223 } | 296 } |
| 224 const Array& res = | 297 const Array& res = |
| 225 Array::Handle(Array::New(inline_id_to_function_.length(), Heap::kOld)); | 298 Array::Handle(Array::New(inline_id_to_function_.length(), Heap::kOld)); |
| 226 for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) { | 299 for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) { |
| 227 res.SetAt(i, *inline_id_to_function_[i]); | 300 res.SetAt(i, *inline_id_to_function_[i]); |
| 228 } | 301 } |
| 229 return res.raw(); | 302 return res.raw(); |
| 230 } | 303 } |
| 231 | 304 |
| 232 | 305 |
| 233 RawCodeSourceMap* CodeSourceMapBuilder::Finalize() { | 306 RawCodeSourceMap* CodeSourceMapBuilder::Finalize() { |
| 234 FlushPeephole(); | 307 if (!stack_traces_only_) { |
| 308 FlushBuffer(); |
| 309 } |
| 235 intptr_t length = stream_.bytes_written(); | 310 intptr_t length = stream_.bytes_written(); |
| 236 const CodeSourceMap& map = CodeSourceMap::Handle(CodeSourceMap::New(length)); | 311 const CodeSourceMap& map = CodeSourceMap::Handle(CodeSourceMap::New(length)); |
| 237 NoSafepointScope no_safepoint; | 312 NoSafepointScope no_safepoint; |
| 238 memmove(map.Data(), buffer_, length); | 313 memmove(map.Data(), buffer_, length); |
| 239 return map.raw(); | 314 return map.raw(); |
| 240 } | 315 } |
| 241 | 316 |
| 242 | 317 |
| 243 void CodeSourceMapReader::GetInlinedFunctionsAt( | 318 void CodeSourceMapReader::GetInlinedFunctionsAt( |
| 244 int32_t pc_offset, | 319 int32_t pc_offset, |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 break; | 523 break; |
| 449 } | 524 } |
| 450 default: | 525 default: |
| 451 UNREACHABLE(); | 526 UNREACHABLE(); |
| 452 } | 527 } |
| 453 } | 528 } |
| 454 THR_Print("}\n"); | 529 THR_Print("}\n"); |
| 455 } | 530 } |
| 456 | 531 |
| 457 } // namespace dart | 532 } // namespace dart |
| OLD | NEW |