| Index: runtime/vm/code_descriptors.h | 
| diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h | 
| index d2faea285dbd8e28de593501d405c68887eff905..cde1cfce8e1ddb9ea3611d9eadb089f6e884bb20 100644 | 
| --- a/runtime/vm/code_descriptors.h | 
| +++ b/runtime/vm/code_descriptors.h | 
| @@ -10,6 +10,7 @@ | 
| #include "vm/globals.h" | 
| #include "vm/growable_array.h" | 
| #include "vm/object.h" | 
| +#include "vm/log.h" | 
|  | 
| namespace dart { | 
|  | 
| @@ -139,9 +140,20 @@ class ExceptionHandlerList : public ZoneAllocated { | 
| }; | 
|  | 
|  | 
| +// A CodeSourceMap maps from pc offsets to a stack of inlined functions and | 
| +// their positions. This is encoded as a little bytecode that pushes and pops | 
| +// functions and changes the top function's position as the PC advances. | 
| +// Decoding happens by running this bytecode until we reach the desired PC. | 
| +// | 
| +// The implementation keeps track of two sets of state: one written to the byte | 
| +// stream and one that is buffered. On the JIT, this buffering effectively gives | 
| +// us a peephole optimization that merges adjacent advance PC bytecodes. On AOT, | 
| +// this allows to skip encoding our position until we reach a PC where we might | 
| +// throw. | 
| class CodeSourceMapBuilder : public ZoneAllocated { | 
| public: | 
| CodeSourceMapBuilder( | 
| +      bool stack_traces_only, | 
| const GrowableArray<intptr_t>& caller_inline_id, | 
| const GrowableArray<TokenPosition>& inline_id_to_token_pos, | 
| const GrowableArray<const Function*>& inline_id_to_function); | 
| @@ -159,47 +171,67 @@ class CodeSourceMapBuilder : public ZoneAllocated { | 
| void StartInliningInterval(int32_t pc_offset, intptr_t inline_id); | 
| void BeginCodeSourceRange(int32_t pc_offset); | 
| void EndCodeSourceRange(int32_t pc_offset, TokenPosition pos); | 
| +  void NoteDescriptor(RawPcDescriptors::Kind kind, | 
| +                      int32_t pc_offset, | 
| +                      TokenPosition pos); | 
|  | 
| RawArray* InliningIdToFunction(); | 
| RawCodeSourceMap* Finalize(); | 
|  | 
| private: | 
| -  void EmitPosition(TokenPosition pos) { | 
| -    FlushPeephole(); | 
| +  void BufferChangePosition(TokenPosition pos) { | 
| +    buffered_token_pos_stack_.Last() = pos; | 
| +  } | 
| +  void WriteChangePosition(TokenPosition pos) { | 
| stream_.Write<uint8_t>(kChangePosition); | 
| stream_.Write<int32_t>(static_cast<int32_t>(pos.value())); | 
| +    written_token_pos_stack_.Last() = pos; | 
| } | 
| -  void EmitAdvancePC(int32_t distance) { advance_pc_peephole_ += distance; } | 
| -  void FlushPeephole() { | 
| -    if (advance_pc_peephole_ != 0) { | 
| -      stream_.Write<uint8_t>(kAdvancePC); | 
| -      stream_.Write<int32_t>(advance_pc_peephole_); | 
| -      advance_pc_peephole_ = 0; | 
| -    } | 
| +  void BufferAdvancePC(int32_t distance) { buffered_pc_offset_ += distance; } | 
| +  void WriteAdvancePC(int32_t distance) { | 
| +    stream_.Write<uint8_t>(kAdvancePC); | 
| +    stream_.Write<int32_t>(distance); | 
| +    written_pc_offset_ += distance; | 
| +  } | 
| +  void BufferPush(intptr_t inline_id) { | 
| +    buffered_inline_id_stack_.Add(inline_id); | 
| +    buffered_token_pos_stack_.Add(kInitialPosition); | 
| } | 
| -  void EmitPush(intptr_t inline_id) { | 
| -    FlushPeephole(); | 
| +  void WritePush(intptr_t inline_id) { | 
| stream_.Write<uint8_t>(kPushFunction); | 
| stream_.Write<int32_t>(inline_id); | 
| +    written_inline_id_stack_.Add(inline_id); | 
| +    written_token_pos_stack_.Add(kInitialPosition); | 
| } | 
| -  void EmitPop() { | 
| -    FlushPeephole(); | 
| +  void BufferPop() { | 
| +    buffered_inline_id_stack_.RemoveLast(); | 
| +    buffered_token_pos_stack_.RemoveLast(); | 
| +  } | 
| +  void WritePop() { | 
| stream_.Write<uint8_t>(kPopFunction); | 
| +    written_inline_id_stack_.RemoveLast(); | 
| +    written_token_pos_stack_.RemoveLast(); | 
| } | 
|  | 
| -  bool IsOnStack(intptr_t inline_id) { | 
| -    for (intptr_t i = 0; i < inline_id_stack_.length(); i++) { | 
| -      if (inline_id_stack_[i] == inline_id) { | 
| -        return true; | 
| -      } | 
| +  void FlushBuffer(); | 
| +  void FlushBufferStack(); | 
| +  void FlushBufferPosition(); | 
| +  void FlushBufferPC(); | 
| + | 
| +  bool IsOnBufferedStack(intptr_t inline_id) { | 
| +    for (intptr_t i = 0; i < buffered_inline_id_stack_.length(); i++) { | 
| +      if (buffered_inline_id_stack_[i] == inline_id) return true; | 
| } | 
| return false; | 
| } | 
|  | 
| -  intptr_t pc_offset_; | 
| -  intptr_t advance_pc_peephole_; | 
| -  GrowableArray<intptr_t> inline_id_stack_; | 
| -  GrowableArray<TokenPosition> token_pos_stack_; | 
| +  intptr_t buffered_pc_offset_; | 
| +  GrowableArray<intptr_t> buffered_inline_id_stack_; | 
| +  GrowableArray<TokenPosition> buffered_token_pos_stack_; | 
| + | 
| +  intptr_t written_pc_offset_; | 
| +  GrowableArray<intptr_t> written_inline_id_stack_; | 
| +  GrowableArray<TokenPosition> written_token_pos_stack_; | 
|  | 
| const GrowableArray<intptr_t>& caller_inline_id_; | 
| const GrowableArray<TokenPosition>& inline_id_to_token_pos_; | 
| @@ -208,6 +240,8 @@ class CodeSourceMapBuilder : public ZoneAllocated { | 
| uint8_t* buffer_; | 
| WriteStream stream_; | 
|  | 
| +  const bool stack_traces_only_; | 
| + | 
| DISALLOW_COPY_AND_ASSIGN(CodeSourceMapBuilder); | 
| }; | 
|  | 
|  |