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