Version 3.30.29 (based on e634bdb290cb3761b9335d1bf7ec016fb3ebdbd5)

Cr-Commit-Position: refs/heads/candidates@{#25075}
git-svn-id: https://v8.googlecode.com/svn/trunk@25075 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/compiler/ia32/instruction-selector-ia32.cc b/src/compiler/ia32/instruction-selector-ia32.cc
index f4358ea..1dd9c16 100644
--- a/src/compiler/ia32/instruction-selector-ia32.cc
+++ b/src/compiler/ia32/instruction-selector-ia32.cc
@@ -648,10 +648,9 @@
 
 void InstructionSelector::VisitInt32MulHigh(Node* node) {
   IA32OperandGenerator g(this);
-  InstructionOperand* temps[] = {g.TempRegister(eax)};
   Emit(kIA32ImulHigh, g.DefineAsFixed(node, edx),
-       g.UseFixed(node->InputAt(0), eax), g.UseUniqueRegister(node->InputAt(1)),
-       arraysize(temps), temps);
+       g.UseFixed(node->InputAt(0), eax),
+       g.UseUniqueRegister(node->InputAt(1)));
 }
 
 
@@ -679,11 +678,9 @@
 static inline void VisitMod(InstructionSelector* selector, Node* node,
                             ArchOpcode opcode) {
   IA32OperandGenerator g(selector);
-  InstructionOperand* temps[] = {g.TempRegister(eax), g.TempRegister(edx)};
-  size_t temp_count = arraysize(temps);
   selector->Emit(opcode, g.DefineAsFixed(node, edx),
                  g.UseFixed(node->InputAt(0), eax),
-                 g.UseUnique(node->InputAt(1)), temp_count, temps);
+                 g.UseUnique(node->InputAt(1)));
 }
 
 
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index 994a638..6b32258 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -252,7 +252,7 @@
         redo(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {}
 
   GenericGraphVisit::Control Post(Node* node) {
-    if (node->op()->ValueOutputCount() > 0 && !NodeProperties::IsTyped(node)) {
+    if (node->op()->ValueOutputCount() > 0) {
       Bounds bounds = TypeNode(node);
       NodeProperties::SetBounds(node, bounds);
       // Remember incompletely typed nodes for least fixpoint iteration.
@@ -291,33 +291,64 @@
 
 class Typer::WidenVisitor : public Typer::Visitor {
  public:
-  explicit WidenVisitor(Typer* typer) : Visitor(typer) {}
+  explicit WidenVisitor(Typer* typer)
+      : Visitor(typer),
+        local_zone_(zone()->isolate()),
+        enabled_(graph()->NodeCount(), true, &local_zone_),
+        queue_(&local_zone_) {}
 
-  GenericGraphVisit::Control Pre(Node* node) {
-    if (node->op()->ValueOutputCount() > 0) {
-      Bounds previous = BoundsOrNone(node);
-      Bounds current = TypeNode(node);
+  void Run(NodeSet* nodes) {
+    // Queue all the roots.
+    for (Node* node : *nodes) {
+      Queue(node);
+    }
 
-      // Speed up termination in the presence of range types:
-      current.upper = Weaken(current.upper, previous.upper);
-      current.lower = Weaken(current.lower, previous.lower);
+    while (!queue_.empty()) {
+      Node* node = queue_.front();
+      queue_.pop();
 
-      DCHECK(previous.lower->Is(current.lower));
-      DCHECK(previous.upper->Is(current.upper));
+      if (node->op()->ValueOutputCount() > 0) {
+        // Enable future queuing (and thus re-typing) of this node.
+        enabled_[node->id()] = true;
 
-      NodeProperties::SetBounds(node, current);
-      // Stop when nothing changed (but allow re-entry in case it does later).
-      return previous.Narrows(current) && current.Narrows(previous)
-                 ? GenericGraphVisit::DEFER
-                 : GenericGraphVisit::REENTER;
-    } else {
-      return GenericGraphVisit::SKIP;
+        // Compute the new type.
+        Bounds previous = BoundsOrNone(node);
+        Bounds current = TypeNode(node);
+
+        // Speed up termination in the presence of range types:
+        current.upper = Weaken(current.upper, previous.upper);
+        current.lower = Weaken(current.lower, previous.lower);
+
+        // Types should not get less precise.
+        DCHECK(previous.lower->Is(current.lower));
+        DCHECK(previous.upper->Is(current.upper));
+
+        NodeProperties::SetBounds(node, current);
+        // If something changed, push all uses into the queue.
+        if (!(previous.Narrows(current) && current.Narrows(previous))) {
+          for (Node* use : node->uses()) {
+            Queue(use);
+          }
+        }
+      }
+      // If there is no value output, we deliberately leave the node disabled
+      // for queuing - there is no need to type it.
     }
   }
 
-  GenericGraphVisit::Control Post(Node* node) {
-    return GenericGraphVisit::REENTER;
+  void Queue(Node* node) {
+    // If the node is enabled for queuing, push it to the queue and disable it
+    // (to avoid queuing it multiple times).
+    if (enabled_[node->id()]) {
+      queue_.push(node);
+      enabled_[node->id()] = false;
+    }
   }
+
+ private:
+  Zone local_zone_;
+  BoolVector enabled_;
+  ZoneQueue<Node*> queue_;
 };
 
 
@@ -326,9 +357,7 @@
   graph_->VisitNodeInputsFromEnd(&typing);
   // Find least fixpoint.
   WidenVisitor widen(this);
-  for (NodeSetIter it = typing.redo.begin(); it != typing.redo.end(); ++it) {
-    graph_->VisitNodeUsesFrom(*it, &widen);
-  }
+  widen.Run(&typing.redo);
 }
 
 
diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc
index f49f8bf..432b21c 100644
--- a/src/compiler/x64/instruction-selector-x64.cc
+++ b/src/compiler/x64/instruction-selector-x64.cc
@@ -420,10 +420,9 @@
 
 void InstructionSelector::VisitInt32MulHigh(Node* node) {
   X64OperandGenerator g(this);
-  InstructionOperand* temps[] = {g.TempRegister(rax)};
   Emit(kX64ImulHigh32, g.DefineAsFixed(node, rdx),
-       g.UseFixed(node->InputAt(0), rax), g.UseUniqueRegister(node->InputAt(1)),
-       arraysize(temps), temps);
+       g.UseFixed(node->InputAt(0), rax),
+       g.UseUniqueRegister(node->InputAt(1)));
 }
 
 
@@ -460,10 +459,9 @@
 static void VisitMod(InstructionSelector* selector, Node* node,
                      ArchOpcode opcode) {
   X64OperandGenerator g(selector);
-  InstructionOperand* temps[] = {g.TempRegister(rax), g.TempRegister(rdx)};
-  selector->Emit(
-      opcode, g.DefineAsFixed(node, rdx), g.UseFixed(node->InputAt(0), rax),
-      g.UseUniqueRegister(node->InputAt(1)), arraysize(temps), temps);
+  selector->Emit(opcode, g.DefineAsFixed(node, rdx),
+                 g.UseFixed(node->InputAt(0), rax),
+                 g.UseUniqueRegister(node->InputAt(1)));
 }
 
 
diff --git a/src/globals.h b/src/globals.h
index 03eb99e..4ea06b2 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -376,7 +376,6 @@
   CELL_SPACE,           // Only and all cell objects.
   PROPERTY_CELL_SPACE,  // Only and all global property cell objects.
   LO_SPACE,             // Promoted large objects.
-  INVALID_SPACE,        // Only used in AllocationResult to signal success.
 
   FIRST_SPACE = NEW_SPACE,
   LAST_SPACE = LO_SPACE,
diff --git a/src/heap/heap-inl.h b/src/heap/heap-inl.h
index 9e3421e..48e928d 100644
--- a/src/heap/heap-inl.h
+++ b/src/heap/heap-inl.h
@@ -458,8 +458,6 @@
     case PROPERTY_CELL_SPACE:
     case LO_SPACE:
       return false;
-    case INVALID_SPACE:
-      break;
   }
   UNREACHABLE();
   return false;
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index 93e00d2..5c8cd45 100644
--- a/src/heap/heap.cc
+++ b/src/heap/heap.cc
@@ -4545,8 +4545,6 @@
       return property_cell_space_->Contains(addr);
     case LO_SPACE:
       return lo_space_->SlowContains(addr);
-    case INVALID_SPACE:
-      break;
   }
   UNREACHABLE();
   return false;
diff --git a/src/heap/spaces.h b/src/heap/spaces.h
index 1944464..ef294b2 100644
--- a/src/heap/spaces.h
+++ b/src/heap/spaces.h
@@ -1614,16 +1614,19 @@
  public:
   // Implicit constructor from Object*.
   AllocationResult(Object* object)  // NOLINT
-      : object_(object),
-        retry_space_(INVALID_SPACE) {}
+      : object_(object) {
+    // AllocationResults can't return Smis, which are used to represent
+    // failure and the space to retry in.
+    CHECK(!object->IsSmi());
+  }
 
-  AllocationResult() : object_(NULL), retry_space_(INVALID_SPACE) {}
+  AllocationResult() : object_(Smi::FromInt(NEW_SPACE)) {}
 
   static inline AllocationResult Retry(AllocationSpace space = NEW_SPACE) {
     return AllocationResult(space);
   }
 
-  inline bool IsRetry() { return retry_space_ != INVALID_SPACE; }
+  inline bool IsRetry() { return object_->IsSmi(); }
 
   template <typename T>
   bool To(T** obj) {
@@ -1639,18 +1642,20 @@
 
   AllocationSpace RetrySpace() {
     DCHECK(IsRetry());
-    return retry_space_;
+    return static_cast<AllocationSpace>(Smi::cast(object_)->value());
   }
 
  private:
   explicit AllocationResult(AllocationSpace space)
-      : object_(NULL), retry_space_(space) {}
+      : object_(Smi::FromInt(static_cast<int>(space))) {}
 
   Object* object_;
-  AllocationSpace retry_space_;
 };
 
 
+STATIC_ASSERT(sizeof(AllocationResult) == kPointerSize);
+
+
 class PagedSpace : public Space {
  public:
   // Creates a space with a maximum capacity, and an id.
diff --git a/src/serialize.cc b/src/serialize.cc
index df62adb..6347943 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -1903,7 +1903,7 @@
     }
   }
   UNREACHABLE();
-  return INVALID_SPACE;
+  return FIRST_SPACE;
 }
 
 
diff --git a/src/serialize.h b/src/serialize.h
index 9c56118..d7a6c7f 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -296,7 +296,7 @@
 
   // No reservation for large object space necessary.
   static const int kNumberOfPreallocatedSpaces = LO_SPACE;
-  static const int kNumberOfSpaces = INVALID_SPACE;
+  static const int kNumberOfSpaces = LAST_SPACE + 1;
 
  protected:
   // Where the pointed-to object can be found:
diff --git a/src/third_party/fdlibm/fdlibm.js b/src/third_party/fdlibm/fdlibm.js
index 08c6f5e..b52f1de 100644
--- a/src/third_party/fdlibm/fdlibm.js
+++ b/src/third_party/fdlibm/fdlibm.js
@@ -267,7 +267,7 @@
       }
     }
   }
-  if (ix >= 0x3fe59429) {  // |x| > .6744
+  if (ix >= 0x3fe59428) {  // |x| > .6744
     if (x < 0) {
       x = -x;
       y = -y;
diff --git a/src/version.cc b/src/version.cc
index 3be87c9..2f8ab0d 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     30
-#define BUILD_NUMBER      28
+#define BUILD_NUMBER      29
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc
index d647a31..54d516e 100644
--- a/test/cctest/test-alloc.cc
+++ b/test/cctest/test-alloc.cc
@@ -86,7 +86,7 @@
       Builtins::kIllegal)).ToObjectChecked();
 
   // Return success.
-  return Smi::FromInt(42);
+  return heap->true_value();
 }
 
 
@@ -100,7 +100,7 @@
   v8::Handle<v8::Context> env = v8::Context::New(CcTest::isolate());
   env->Enter();
   Handle<Object> o = Test();
-  CHECK(o->IsSmi() && Smi::cast(*o)->value() == 42);
+  CHECK(o->IsTrue());
   env->Exit();
 }
 
@@ -162,7 +162,7 @@
   // Call the accessor through JavaScript.
   v8::Handle<v8::Value> result = v8::Script::Compile(
       v8::String::NewFromUtf8(CcTest::isolate(), "(new Foo).get"))->Run();
-  CHECK_EQ(42, result->Int32Value());
+  CHECK_EQ(true, result->BooleanValue());
   env->Exit();
 }
 
diff --git a/test/mjsunit/compiler/regress-register-allocator2.js b/test/mjsunit/compiler/regress-register-allocator2.js
new file mode 100644
index 0000000..06e0c49
--- /dev/null
+++ b/test/mjsunit/compiler/regress-register-allocator2.js
@@ -0,0 +1,17 @@
+// Copyright 2014 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.
+
+function f() {
+  var x = 0;
+  var y = 0;
+  x ^= undefined;
+  assertEquals(x /= 1);
+  assertEquals(NaN, y %= 1);
+  assertEquals(y = 1);
+  f();
+  y = -2;
+  assertEquals(x >>= 1);
+  assertEquals(0, ((y+(y+(y+((y^(x%5))+y)))+(y+y))>>y)+y);
+}
+try { f(); } catch (e) {}
diff --git a/test/mjsunit/sin-cos.js b/test/mjsunit/sin-cos.js
index 71fae20..fb6f858 100644
--- a/test/mjsunit/sin-cos.js
+++ b/test/mjsunit/sin-cos.js
@@ -227,6 +227,8 @@
 assertEquals(0.8211418015898941, Math.tan(11/16));
 assertEquals(-0.8211418015898941, Math.tan(-11/16));
 assertEquals(0.41421356237309503, Math.tan(Math.PI / 8));
+// crbug/427468
+assertEquals(0.7993357819992383, Math.tan(0.6743358));
 
 // Tests for Math.sin.
 assertEquals(0.479425538604203, Math.sin(0.5));
diff --git a/tools/push-to-trunk/auto_push.py b/tools/push-to-trunk/auto_push.py
index cec1489..b0f1b26 100755
--- a/tools/push-to-trunk/auto_push.py
+++ b/tools/push-to-trunk/auto_push.py
@@ -118,6 +118,8 @@
       args.extend(["--svn-config", self._options.svn_config])
     if self._options.vc_interface:
       args.extend(["--vc-interface", self._options.vc_interface])
+    if self._options.work_dir:
+      args.extend(["--work-dir", self._options.work_dir])
 
     # TODO(machenbach): Update the script before calling it.
     if self._options.push:
diff --git a/tools/push-to-trunk/auto_roll.py b/tools/push-to-trunk/auto_roll.py
index 2cca070..00f45e0 100755
--- a/tools/push-to-trunk/auto_roll.py
+++ b/tools/push-to-trunk/auto_roll.py
@@ -99,6 +99,8 @@
             "--sheriff", "--googlers-mapping", self._options.googlers_mapping])
       if self._options.dry_run:
         args.extend(["--dry-run"])
+      if self._options.work_dir:
+        args.extend(["--work-dir", self._options.work_dir])
       self._side_effect_handler.Call(chromium_roll.ChromiumRoll().Run, args)
 
 
diff --git a/tools/push-to-trunk/common_includes.py b/tools/push-to-trunk/common_includes.py
index a555500..e95d555 100644
--- a/tools/push-to-trunk/common_includes.py
+++ b/tools/push-to-trunk/common_includes.py
@@ -48,7 +48,7 @@
 VERSION_FILE = os.path.join("src", "version.cc")
 
 # V8 base directory.
-DEFAULT_CWD = os.path.dirname(
+V8_BASE = os.path.dirname(
     os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 
@@ -408,7 +408,7 @@
     # is the case for all automated merge and push commits - also no title is
     # the prefix of another title).
     commit = None
-    for wait_interval in [3, 7, 15, 35, 35]:
+    for wait_interval in [3, 7, 15, 35, 45, 60]:
       self.step.Git("fetch")
       commit = self.step.GitLog(n=1, format="%H", grep=message, branch=remote)
       if commit:
@@ -470,7 +470,8 @@
     self.vc.InjectStep(self)
 
     # The testing configuration might set a different default cwd.
-    self.default_cwd = self._config.get("DEFAULT_CWD") or DEFAULT_CWD
+    self.default_cwd = (self._config.get("DEFAULT_CWD") or
+                        os.path.join(self._options.work_dir, "v8"))
 
     assert self._number >= 0
     assert self._config is not None
@@ -744,6 +745,19 @@
         cwd=self._options.svn)
 
 
+class BootstrapStep(Step):
+  MESSAGE = "Bootstapping v8 checkout."
+
+  def RunStep(self):
+    if os.path.realpath(self.default_cwd) == os.path.realpath(V8_BASE):
+      self.Die("Can't use v8 checkout with calling script as work checkout.")
+    # Directory containing the working v8 checkout.
+    if not os.path.exists(self._options.work_dir):
+      os.makedirs(self._options.work_dir)
+    if not os.path.exists(self.default_cwd):
+      self.Command("fetch", "v8", cwd=self._options.work_dir)
+
+
 class UploadStep(Step):
   MESSAGE = "Upload for code review."
 
@@ -859,6 +873,9 @@
     parser.add_argument("--vc-interface",
                         help=("Choose VC interface out of git_svn|"
                               "git_read_svn_write."))
+    parser.add_argument("--work-dir",
+                        help=("Location where to bootstrap a working v8 "
+                              "checkout."))
     self._PrepareOptions(parser)
 
     if args is None:  # pragma: no cover
@@ -898,6 +915,8 @@
 
     if not options.vc_interface:
       options.vc_interface = "git_read_svn_write"
+    if not options.work_dir:
+      options.work_dir = "/tmp/v8-release-scripts-work-dir"
     return options
 
   def RunSteps(self, step_classes, args=None):
@@ -910,7 +929,7 @@
       os.remove(state_file)
 
     steps = []
-    for (number, step_class) in enumerate(step_classes):
+    for (number, step_class) in enumerate([BootstrapStep] + step_classes):
       steps.append(MakeStep(step_class, number, self._state, self._config,
                             options, self._side_effect_handler))
     for step in steps[options.step:]:
diff --git a/tools/push-to-trunk/test_scripts.py b/tools/push-to-trunk/test_scripts.py
index d92c388..6eeb323 100644
--- a/tools/push-to-trunk/test_scripts.py
+++ b/tools/push-to-trunk/test_scripts.py
@@ -694,6 +694,21 @@
     commit_msg = """Line with "quotation marks"."""
     self._TestSquashCommits(change_log, commit_msg)
 
+  def testBootstrapper(self):
+    work_dir = self.MakeEmptyTempDirectory()
+    class FakeScript(ScriptsBase):
+      def _Steps(self):
+        return []
+
+    # Use the test configuration without the fake testing default work dir.
+    fake_config = dict(TEST_CONFIG)
+    del(fake_config["DEFAULT_CWD"])
+
+    self.Expect([
+      Cmd("fetch v8", "", cwd=work_dir),
+    ])
+    FakeScript(fake_config, self).Run(["--work-dir", work_dir])
+
   def _PushToTrunk(self, force=False, manual=False):
     TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
 
@@ -967,7 +982,8 @@
 
     args = ["-a", "author@chromium.org", "--revision", "push_hash",
             "--vc-interface", "git", "-f", "-r", "reviewer@chromium.org",
-            "--svn", svn_root, "--svn-config", "[CONFIG_DIR]"]
+            "--svn", svn_root, "--svn-config", "[CONFIG_DIR]",
+            "--work-dir", TEST_CONFIG["DEFAULT_CWD"]]
     PushToTrunk(TEST_CONFIG, self).Run(args)
 
     cl = FileToText(TEST_CONFIG["CHANGELOG_FILE"])
@@ -1318,7 +1334,7 @@
         lambda: MergeToBranch(TEST_CONFIG, self).Run(args))
 
     # Test that state recovery after restarting the script works.
-    args += ["-s", "3"]
+    args += ["-s", "4"]
     MergeToBranch(TEST_CONFIG, self).Run(args)
 
   def testMergeToBranchNewGit(self):
@@ -1459,7 +1475,7 @@
         lambda: MergeToBranch(TEST_CONFIG, self).Run(args))
 
     # Test that state recovery after restarting the script works.
-    args += ["-s", "3"]
+    args += ["-s", "4"]
     MergeToBranch(TEST_CONFIG, self).Run(args)
 
   def testReleases(self):