Merge V8 5.3.332.45.  DO NOT MERGE

Test: Manual

FPIIM-449

Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/tools/turbolizer/code-view.js b/tools/turbolizer/code-view.js
new file mode 100644
index 0000000..aa106d3
--- /dev/null
+++ b/tools/turbolizer/code-view.js
@@ -0,0 +1,177 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var CodeView = function(divID, PR, sourceText, sourcePosition, broker) {
+  "use strict";
+  var view = this;
+
+  view.divElement = document.getElementById(divID);
+  view.broker = broker;
+  view.codeSelection = null;
+  view.allSpans = [];
+
+  var selectionHandler = {
+    clear: function() {
+      broker.clear(selectionHandler);
+    },
+    select: function(items, selected) {
+      var handler = this;
+      var divElement = view.divElement;
+      var broker = view.broker;
+      for (let span of items) {
+        if (selected) {
+          span.classList.add("selected");
+        } else {
+          span.classList.remove("selected");
+        }
+      }
+      var ranges = [];
+      for (var span of items) {
+        ranges.push([span.start, span.end, null]);
+      }
+      broker.select(selectionHandler, ranges, selected);
+    },
+    selectionDifference: function(span1, inclusive1, span2, inclusive2) {
+      var pos1 = span1.start;
+      var pos2 = span2.start;
+      var result = [];
+      var lineListDiv = view.divElement.firstChild.firstChild.childNodes;
+      for (var i=0; i < lineListDiv.length; i++) {
+        var currentLineElement = lineListDiv[i];
+        var spans = currentLineElement.childNodes;
+        for (var j=0; j < spans.length; ++j) {
+          var currentSpan = spans[j];
+          if (currentSpan.start > pos1 || (inclusive1 && currentSpan.start == pos1)) {
+            if (currentSpan.start < pos2 || (inclusive2 && currentSpan.start == pos2)) {
+              result.push(currentSpan);
+            }
+          }
+        }
+      }
+      return result;
+    },
+    brokeredSelect: function(ranges, selected) {
+      var firstSelect = view.codeSelection.isEmpty();
+      for (var range of ranges) {
+        var start = range[0];
+        var end = range[1];
+        var lower = 0;
+        var upper = view.allSpans.length;
+        if (upper > 0) {
+          while ((upper - lower) > 1) {
+            var middle = Math.floor((upper + lower) / 2);
+            var lineStart = view.allSpans[middle].start;
+            if (lineStart < start) {
+              lower = middle;
+            } else if (lineStart > start) {
+              upper = middle;
+            } else {
+              lower = middle;
+              break;
+            }
+          }
+          var currentSpan = view.allSpans[lower];
+          var currentLineElement = currentSpan.parentNode;
+          if ((currentSpan.start <= start && start < currentSpan.end) ||
+              (currentSpan.start <= end && end < currentSpan.end)) {
+            if (firstSelect) {
+              makeContainerPosVisible(view.divElement, currentLineElement.offsetTop);
+              firstSelect = false;
+            }
+            view.codeSelection.select(currentSpan, selected);
+          }
+        }
+      }
+    },
+    brokeredClear: function() {
+      view.codeSelection.clear();
+    },
+  };
+
+  view.codeSelection = new Selection(selectionHandler);
+  broker.addSelectionHandler(selectionHandler);
+
+  var mouseDown = false;
+
+  this.handleSpanMouseDown = function(e) {
+    e.stopPropagation();
+    if (!e.shiftKey) {
+      view.codeSelection.clear();
+    }
+    view.codeSelection.select(this, true);
+    mouseDown = true;
+  }
+
+  this.handleSpanMouseMove = function(e) {
+    if (mouseDown) {
+      view.codeSelection.extendTo(this);
+    }
+  }
+
+  this.handleCodeMouseDown = function(e) {
+    view.codeSelection.clear();
+  }
+
+  document.addEventListener('mouseup', function(e){
+    mouseDown = false;
+  }, false);
+
+  this.initializeCode(sourceText, sourcePosition);
+}
+
+CodeView.prototype.initializeCode = function(sourceText, sourcePosition) {
+  var view = this;
+  if (sourceText == "") {
+    var newHtml = "<pre class=\"prettyprint\"</pre>";
+    view.divElement.innerHTML = newHtml;
+  } else {
+    var newHtml = "<pre class=\"prettyprint linenums\">"
+      + sourceText + "</pre>";
+    view.divElement.innerHTML = newHtml;
+    try {
+      // Wrap in try to work when offline.
+      PR.prettyPrint();
+    } catch (e) {
+    }
+
+    view.divElement.onmousedown = this.handleCodeMouseDown;
+
+    var base = sourcePosition;
+    var current = 0;
+    var lineListDiv = view.divElement.firstChild.firstChild.childNodes;
+    for (i=0; i < lineListDiv.length; i++) {
+      var currentLineElement = lineListDiv[i];
+      currentLineElement.id = "li" + i;
+      var pos = base + current;
+      currentLineElement.pos = pos;
+      var spans = currentLineElement.childNodes;
+      for (j=0; j < spans.length; ++j) {
+        var currentSpan = spans[j];
+        if (currentSpan.nodeType == 1) {
+          currentSpan.start = pos;
+          currentSpan.end = pos + currentSpan.textContent.length;
+          currentSpan.onmousedown = this.handleSpanMouseDown;
+          currentSpan.onmousemove = this.handleSpanMouseMove;
+          view.allSpans.push(currentSpan);
+        }
+        current += currentSpan.textContent.length;
+        pos = base + current;
+      }
+      while ((current < sourceText.length) && (
+        sourceText[current] == '\n' ||
+          sourceText[current] == '\r')) {
+        ++current;
+      }
+    }
+  }
+
+  this.resizeToParent();
+}
+
+CodeView.prototype.resizeToParent = function() {
+  var view = this;
+  var documentElement = document.documentElement;
+  var y = view.divElement.parentNode.clientHeight || documentElement.clientHeight;
+  view.divElement.style.height = y + "px";
+}