Revision: 23256
Author:   [email protected]
Date:     Thu Aug 21 07:23:04 2014 UTC
Log:      Version 3.29.11 (based on bleeding_edge revision r23252)

Refactor ParseObjectLiteral.

Support symbol-named properties in API (issue 3394).

Suppress test262 test that tests duplicate properties.

ES6: Duplicate properties are no longer an error (issue 3498).

Expose function CheckDebugBreak in the debugger api.

Remove RegExp.$input (issue 3486).

Performance and stability improvements on all platforms.
http://code.google.com/p/v8/source/detail?r=23256

Added:
 /trunk/src/compiler/js-inlining.cc
 /trunk/src/compiler/js-inlining.h
 /trunk/src/heap/gc-idle-time-handler.cc
 /trunk/src/heap/gc-idle-time-handler.h
 /trunk/test/cctest/compiler/test-run-inlining.cc
 /trunk/test/mjsunit/compiler/shift-shr.js
 /trunk/test/mjsunit/number-literal.js
 /trunk/test/mjsunit/regress/regress-crbug-405491.js
 /trunk/test/mjsunit/runtime-gen/createglobalprivateownsymbol.js
 /trunk/tools/cpu.sh
Deleted:
 /trunk/src/compiler-intrinsics.h
 /trunk/test/mjsunit/runtime-gen/createglobalprivatesymbol.js
 /trunk/test/mjsunit/runtime-gen/internalsetprototype.js
 /trunk/test/preparser/duplicate-property.pyt
Modified:
 /trunk/BUILD.gn
 /trunk/ChangeLog
 /trunk/include/v8-debug.h
 /trunk/include/v8.h
 /trunk/include/v8config.h
 /trunk/src/accessors.cc
 /trunk/src/accessors.h
 /trunk/src/api.cc
 /trunk/src/api.h
 /trunk/src/arguments.h
 /trunk/src/arm64/full-codegen-arm64.cc
 /trunk/src/arm64/lithium-codegen-arm64.cc
 /trunk/src/arm64/simulator-arm64.cc
 /trunk/src/array-iterator.js
 /trunk/src/assembler.h
 /trunk/src/base/bits.h
 /trunk/src/bootstrapper.cc
 /trunk/src/compiler/arm/instruction-selector-arm.cc
 /trunk/src/compiler/arm64/instruction-selector-arm64.cc
 /trunk/src/compiler/change-lowering.cc
 /trunk/src/compiler/change-lowering.h
 /trunk/src/compiler/generic-graph.h
 /trunk/src/compiler/generic-node.h
 /trunk/src/compiler/instruction-selector.cc
 /trunk/src/compiler/instruction-selector.h
 /trunk/src/compiler/js-context-specialization.cc
 /trunk/src/compiler/js-typed-lowering.cc
 /trunk/src/compiler/machine-type.cc
 /trunk/src/compiler/node-properties-inl.h
 /trunk/src/compiler/node-properties.h
 /trunk/src/compiler/pipeline.cc
 /trunk/src/compiler/scheduler.cc
 /trunk/src/compiler/scheduler.h
 /trunk/src/data-flow.cc
 /trunk/src/data-flow.h
 /trunk/src/elements.cc
 /trunk/src/elements.h
 /trunk/src/flag-definitions.h
 /trunk/src/frames.cc
 /trunk/src/heap/heap.cc
 /trunk/src/heap/heap.h
 /trunk/src/heap/mark-compact.cc
 /trunk/src/heap/mark-compact.h
 /trunk/src/heap/spaces.cc
 /trunk/src/heap-snapshot-generator.cc
 /trunk/src/hydrogen-instructions.cc
 /trunk/src/hydrogen-instructions.h
 /trunk/src/hydrogen.cc
 /trunk/src/ic.cc
 /trunk/src/lookup.h
 /trunk/src/macros.py
 /trunk/src/math.js
 /trunk/src/mips/simulator-mips.cc
 /trunk/src/mips64/simulator-mips64.cc
 /trunk/src/objects.cc
 /trunk/src/objects.h
 /trunk/src/parser.h
 /trunk/src/preparser.h
 /trunk/src/promise.js
 /trunk/src/property.cc
 /trunk/src/property.h
 /trunk/src/regexp.js
 /trunk/src/runtime.cc
 /trunk/src/runtime.h
 /trunk/src/serialize.cc
 /trunk/src/string-iterator.js
 /trunk/src/stub-cache.cc
 /trunk/src/version.cc
 /trunk/test/base-unittests/bits-unittest.cc
 /trunk/test/cctest/cctest.gyp
 /trunk/test/cctest/test-alloc.cc
 /trunk/test/cctest/test-api.cc
 /trunk/test/cctest/test-debug.cc
 /trunk/test/cctest/test-heap-profiler.cc
 /trunk/test/cctest/test-parsing.cc
 /trunk/test/compiler-unittests/arm64/instruction-selector-arm64-unittest.cc
 /trunk/test/compiler-unittests/change-lowering-unittest.cc
 /trunk/test/compiler-unittests/graph-unittest.cc
 /trunk/test/compiler-unittests/graph-unittest.h
 /trunk/test/compiler-unittests/instruction-selector-unittest.cc
 /trunk/test/compiler-unittests/instruction-selector-unittest.h
 /trunk/test/heap-unittests/heap-unittest.cc
 /trunk/test/mjsunit/es6/math-expm1.js
 /trunk/test/mjsunit/mjsunit.status
 /trunk/test/mjsunit/strict-mode.js
 /trunk/test/mjsunit/string-match.js
 /trunk/test/test262/test262.status
 /trunk/test/webkit/fast/js/Object-getOwnPropertyNames-expected.txt
 /trunk/test/webkit/object-literal-syntax-expected.txt
 /trunk/test/webkit/object-literal-syntax.js
 /trunk/third_party/fdlibm/LICENSE
 /trunk/third_party/fdlibm/fdlibm.cc
 /trunk/third_party/fdlibm/fdlibm.h
 /trunk/third_party/fdlibm/fdlibm.js
 /trunk/tools/generate-runtime-tests.py
 /trunk/tools/gyp/v8.gyp
 /trunk/tools/whitespace.txt

=======================================
--- /dev/null
+++ /trunk/src/compiler/js-inlining.cc  Thu Aug 21 07:23:04 2014 UTC
@@ -0,0 +1,329 @@
+// 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.
+
+#include "src/compiler/ast-graph-builder.h"
+#include "src/compiler/common-operator.h"
+#include "src/compiler/generic-node-inl.h"
+#include "src/compiler/graph-inl.h"
+#include "src/compiler/graph-visualizer.h"
+#include "src/compiler/js-inlining.h"
+#include "src/compiler/js-operator.h"
+#include "src/compiler/node-aux-data-inl.h"
+#include "src/compiler/node-matchers.h"
+#include "src/compiler/node-properties-inl.h"
+#include "src/compiler/simplified-operator.h"
+#include "src/compiler/typer.h"
+#include "src/parser.h"
+#include "src/rewriter.h"
+#include "src/scopes.h"
+
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class InlinerVisitor : public NullNodeVisitor {
+ public:
+  explicit InlinerVisitor(JSInliner* inliner) : inliner_(inliner) {}
+
+  GenericGraphVisit::Control Post(Node* node) {
+    switch (node->opcode()) {
+      case IrOpcode::kJSCallFunction:
+        inliner_->TryInlineCall(node);
+        break;
+      default:
+        break;
+    }
+    return GenericGraphVisit::CONTINUE;
+  }
+
+ private:
+  JSInliner* inliner_;
+};
+
+
+void JSInliner::Inline() {
+  InlinerVisitor visitor(this);
+  jsgraph_->graph()->VisitNodeInputsFromEnd(&visitor);
+}
+
+
+static void MoveWithDependencies(Graph* graph, Node* node, Node* old_block,
+                                 Node* new_block) {
+  if (OperatorProperties::HasControlInput(node->op())) {
+    // Check if we have left the old_block.
+    if (NodeProperties::GetControlInput(node) != old_block) return;
+    // If not, move this node to the new_block.
+    NodeProperties::ReplaceControlInput(node, new_block);
+  }
+  // Independent of whether a node has a control input or not,
+  // it might have a dependency that is pinned to old_block.
+ for (InputIter iter = node->inputs().begin(); iter != node->inputs().end();
+       ++iter) {
+    if (NodeProperties::IsControlEdge(iter.edge())) continue;
+    MoveWithDependencies(graph, *iter, old_block, new_block);
+  }
+}
+
+
+static void MoveAllControlNodes(Node* from, Node* to) {
+  for (UseIter iter = from->uses().begin(); iter != from->uses().end();) {
+    if (NodeProperties::IsControlEdge(iter.edge())) {
+      iter.UpdateToAndIncrement(to);
+    } else {
+      ++iter;
+    }
+  }
+}
+
+
+// TODO(sigurds) Find a home for this function and reuse it everywhere (esp. in
+// test cases, where similar code is currently duplicated).
+static void Parse(Handle<JSFunction> function, CompilationInfoWithZone* info) {
+  CHECK(Parser::Parse(info));
+  StrictMode strict_mode = info->function()->strict_mode();
+  info->SetStrictMode(strict_mode);
+  info->SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
+  CHECK(Rewriter::Rewrite(info));
+  CHECK(Scope::Analyze(info));
+  CHECK_NE(NULL, info->scope());
+ Handle<ScopeInfo> scope_info = ScopeInfo::Create(info->scope(), info->zone());
+  info->shared_info()->set_scope_info(*scope_info);
+}
+
+
+// A facade on a JSFunction's graph to facilitate inlining. It assumes the
+// that the function graph has only one return statement, and provides
+// {UnifyReturn} to convert a function graph to that end.
+// InlineAtCall will create some new nodes using {graph}'s builders (and hence
+// those nodes will live in {graph}'s zone.
+class Inlinee {
+ public:
+  explicit Inlinee(JSGraph* graph) : jsgraph_(graph) {}
+
+  Graph* graph() { return jsgraph_->graph(); }
+  JSGraph* jsgraph() { return jsgraph_; }
+
+  // Returns the last regular control node, that is
+  // the last control node before the end node.
+ Node* end_block() { return NodeProperties::GetControlInput(unique_return()); }
+
+  // Return the effect output of the graph,
+  // that is the effect input of the return statement of the inlinee.
+  Node* effect_output() {
+    return NodeProperties::GetEffectInput(unique_return());
+  }
+  // Return the value output of the graph,
+  // that is the value input of the return statement of the inlinee.
+  Node* value_output() {
+    return NodeProperties::GetValueInput(unique_return(), 0);
+  }
+  // Return the unique return statement of the graph.
+  Node* unique_return() {
+    Node* unique_return =
+        NodeProperties::GetControlInput(jsgraph_->graph()->end());
+    DCHECK_EQ(IrOpcode::kReturn, unique_return->opcode());
+    return unique_return;
+  }
+  // Inline this graph at {call}, use {jsgraph} and its zone to create
+  // any new nodes.
+  void InlineAtCall(JSGraph* jsgraph, Node* call);
+  // Ensure that only a single return reaches the end node.
+  void UnifyReturn();
+
+ private:
+  JSGraph* jsgraph_;
+};
+
+
+void Inlinee::UnifyReturn() {
+  Graph* graph = jsgraph_->graph();
+
+  Node* final_merge = NodeProperties::GetControlInput(graph->end(), 0);
+  if (final_merge->opcode() == IrOpcode::kReturn) {
+    // nothing to do
+    return;
+  }
+  DCHECK_EQ(IrOpcode::kMerge, final_merge->opcode());
+
+  int predecessors =
+      OperatorProperties::GetControlInputCount(final_merge->op());
+  Operator* op_phi = jsgraph_->common()->Phi(predecessors);
+  Operator* op_ephi = jsgraph_->common()->EffectPhi(predecessors);
+
+  NodeVector values(NodeVector::allocator_type(jsgraph_->zone()));
+  NodeVector effects(NodeVector::allocator_type(jsgraph_->zone()));
+  // Iterate over all control flow predecessors,
+  // which must be return statements.
+  InputIter iter = final_merge->inputs().begin();
+  while (iter != final_merge->inputs().end()) {
+    Node* input = *iter;
+    switch (input->opcode()) {
+      case IrOpcode::kReturn:
+        values.push_back(NodeProperties::GetValueInput(input, 0));
+        effects.push_back(NodeProperties::GetEffectInput(input));
+        iter.UpdateToAndIncrement(NodeProperties::GetControlInput(input));
+        input->RemoveAllInputs();
+        break;
+      default:
+        UNREACHABLE();
+        ++iter;
+        break;
+    }
+  }
+  values.push_back(final_merge);
+  effects.push_back(final_merge);
+  Node* phi =
+ graph->NewNode(op_phi, static_cast<int>(values.size()), &values.front());
+  Node* ephi = graph->NewNode(op_ephi, static_cast<int>(effects.size()),
+                              &effects.front());
+  Node* new_return =
+      graph->NewNode(jsgraph_->common()->Return(), phi, ephi, final_merge);
+  graph->end()->ReplaceInput(0, new_return);
+}
+
+
+void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
+  MachineOperatorBuilder machine(jsgraph->zone());
+
+  Node* control = NodeProperties::GetControlInput(call);
+  // Move all the nodes to the end block.
+  MoveAllControlNodes(control, end_block());
+  // Now move the ones the call depends on back up.
+  // We have to do this back-and-forth to treat the case where the call is
+  // pinned to the start block.
+  MoveWithDependencies(graph(), call, end_block(), control);
+
+  // The inlinee uses the context from the JSFunction object. This will
+ // also be the effect dependency for the inlinee as it produces an effect.
+  // TODO(sigurds) Use simplified load once it is ready.
+  Node* context = jsgraph->graph()->NewNode(
+      machine.Load(kMachAnyTagged), NodeProperties::GetValueInput(call, 0),
+      jsgraph->Int32Constant(JSFunction::kContextOffset - kHeapObjectTag),
+      NodeProperties::GetEffectInput(call));
+
+  // {inlinee_inputs} counts JSFunction, Receiver, arguments, context,
+  // but not effect, control.
+  int inlinee_inputs = graph()->start()->op()->OutputCount();
+  // Context is last argument.
+  int inlinee_context_index = inlinee_inputs - 1;
+  // {inliner_inputs} counts JSFunction, Receiver, arguments, but not
+  // context, effect, control.
+  int inliner_inputs = OperatorProperties::GetValueInputCount(call->op());
+  // Iterate over all uses of the start node.
+  UseIter iter = graph()->start()->uses().begin();
+  while (iter != graph()->start()->uses().end()) {
+    Node* use = *iter;
+    switch (use->opcode()) {
+      case IrOpcode::kParameter: {
+ int index = 1 + static_cast<Operator1<int>*>(use->op())->parameter();
+        if (index < inliner_inputs && index < inlinee_context_index) {
+          // There is an input from the call, and the index is a value
+          // projection but not the context, so rewire the input.
+          NodeProperties::ReplaceWithValue(*iter, call->InputAt(index));
+        } else if (index == inlinee_context_index) {
+ // This is the context projection, rewire it to the context from the
+          // JSFunction object.
+          NodeProperties::ReplaceWithValue(*iter, context);
+        } else if (index < inlinee_context_index) {
+          // Call has fewer arguments than required, fill with undefined.
+ NodeProperties::ReplaceWithValue(*iter, jsgraph->UndefinedConstant());
+        } else {
+          // We got too many arguments, discard for now.
+          // TODO(sigurds): Fix to treat arguments array correctly.
+        }
+        ++iter;
+        break;
+      }
+      default:
+        if (NodeProperties::IsEffectEdge(iter.edge())) {
+          iter.UpdateToAndIncrement(context);
+        } else if (NodeProperties::IsControlEdge(iter.edge())) {
+          iter.UpdateToAndIncrement(control);
+        } else {
+          UNREACHABLE();
+        }
+        break;
+    }
+  }
+
+  // Iterate over all uses of the call node.
+  iter = call->uses().begin();
+  while (iter != call->uses().end()) {
+    if (NodeProperties::IsEffectEdge(iter.edge())) {
+      iter.UpdateToAndIncrement(effect_output());
+    } else if (NodeProperties::IsControlEdge(iter.edge())) {
+      UNREACHABLE();
+    } else {
+      DCHECK(NodeProperties::IsValueEdge(iter.edge()));
+      iter.UpdateToAndIncrement(value_output());
+    }
+  }
+  call->RemoveAllInputs();
+  DCHECK_EQ(0, call->UseCount());
+  // TODO(sigurds) Remove this once we copy.
+  unique_return()->RemoveAllInputs();
+}
+
+
+void JSInliner::TryInlineCall(Node* node) {
+  DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
+
+  ValueMatcher<Handle<JSFunction> > match(node->InputAt(0));
+  if (!match.HasValue()) {
+    return;
+  }
+
+  Handle<JSFunction> function = match.Value();
+
+  if (function->shared()->native()) {
+    if (FLAG_trace_turbo_inlining) {
+      SmartArrayPointer<char> name =
+          function->shared()->DebugName()->ToCString();
+ PrintF("Not Inlining %s into %s because inlinee is native\n", name.get(),
+             info_->shared_info()->DebugName()->ToCString().get());
+    }
+    return;
+  }
+
+  CompilationInfoWithZone info(function);
+  Parse(function, &info);
+
+  if (info.scope()->arguments() != NULL) {
+    // For now do not inline functions that use their arguments array.
+ SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString();
+    if (FLAG_trace_turbo_inlining) {
+      PrintF(
+          "Not Inlining %s into %s because inlinee uses arguments "
+          "array\n",
+ name.get(), info_->shared_info()->DebugName()->ToCString().get());
+    }
+    return;
+  }
+
+  if (FLAG_trace_turbo_inlining) {
+ SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString();
+    PrintF("Inlining %s into %s\n", name.get(),
+           info_->shared_info()->DebugName()->ToCString().get());
+  }
+
+  Graph graph(info_->zone());
+  graph.SetNextNodeId(jsgraph_->graph()->NextNodeID());
+
+  Typer typer(info_->zone());
+  CommonOperatorBuilder common(info_->zone());
+  JSGraph jsgraph(&graph, &common, &typer);
+
+  AstGraphBuilder graph_builder(&info, &jsgraph);
+  graph_builder.CreateGraph();
+
+  Inlinee inlinee(&jsgraph);
+  inlinee.UnifyReturn();
+  inlinee.InlineAtCall(jsgraph_, node);
+
+  jsgraph_->graph()->SetNextNodeId(inlinee.graph()->NextNodeID());
+}
+}
+}
+}  // namespace v8::internal::compiler
=======================================
--- /dev/null
+++ /trunk/src/compiler/js-inlining.h   Thu Aug 21 07:23:04 2014 UTC
@@ -0,0 +1,34 @@
+// 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.
+
+#ifndef V8_COMPILER_JS_INLINING_H_
+#define V8_COMPILER_JS_INLINING_H_
+
+#include "src/compiler/js-graph.h"
+#include "src/v8.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class JSInliner {
+ public:
+  JSInliner(CompilationInfo* info, JSGraph* jsgraph)
+      : info_(info), jsgraph_(jsgraph) {}
+
+  void Inline();
+  void TryInlineCall(Node* node);
+
+ private:
+  friend class InlinerVisitor;
+  CompilationInfo* info_;
+  JSGraph* jsgraph_;
+
+  static void UnifyReturn(Graph* graph);
+};
+}
+}
+}  // namespace v8::internal::compiler
+
+#endif  // V8_COMPILER_JS_INLINING_H_
=======================================
--- /dev/null
+++ /trunk/src/heap/gc-idle-time-handler.cc     Thu Aug 21 07:23:04 2014 UTC
@@ -0,0 +1,36 @@
+// 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.
+
+#include "src/heap/gc-idle-time-handler.h"
+
+namespace v8 {
+namespace internal {
+
+
+const double GCIdleTimeHandler::kConservativeTimeRatio = 0.9;
+
+
+size_t GCIdleTimeHandler::EstimateMarkingStepSize(
+    size_t idle_time_in_ms, size_t marking_speed_in_bytes_per_ms) {
+  DCHECK(idle_time_in_ms > 0);
+
+  if (marking_speed_in_bytes_per_ms == 0) {
+    marking_speed_in_bytes_per_ms =
+        GCIdleTimeHandler::kInitialConservativeMarkingSpeed;
+  }
+
+ size_t marking_step_size = marking_speed_in_bytes_per_ms * idle_time_in_ms; + if (marking_step_size / marking_speed_in_bytes_per_ms != idle_time_in_ms) {
+    // In the case of an overflow we return maximum marking step size.
+    return GCIdleTimeHandler::kMaximumMarkingStepSize;
+  }
+
+  if (marking_step_size > kMaximumMarkingStepSize)
+    return kMaximumMarkingStepSize;
+
+  return static_cast<size_t>(marking_step_size *
+                             GCIdleTimeHandler::kConservativeTimeRatio);
+}
+}
+}
=======================================
--- /dev/null
+++ /trunk/src/heap/gc-idle-time-handler.h      Thu Aug 21 07:23:04 2014 UTC
@@ -0,0 +1,38 @@
+// 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.
+
+#ifndef V8_HEAP_GC_IDLE_TIME_HANDLER_H_
+#define V8_HEAP_GC_IDLE_TIME_HANDLER_H_
+
+#include "src/globals.h"
+
+namespace v8 {
+namespace internal {
+
+// The idle time handler makes decisions about which garbage collection
+// operations are executing during IdleNotification.
+class GCIdleTimeHandler {
+ public:
+  static size_t EstimateMarkingStepSize(size_t idle_time_in_ms,
+ size_t marking_speed_in_bytes_per_ms);
+
+ // If we haven't recorded any incremental marking events yet, we carefully
+  // mark with a conservative lower bound for the marking speed.
+  static const size_t kInitialConservativeMarkingSpeed = 100 * KB;
+
+  // Maximum marking step size returned by EstimateMarkingStepSize.
+  static const size_t kMaximumMarkingStepSize = 700 * MB;
+
+  // We have to make sure that we finish the IdleNotification before
+  // idle_time_in_ms. Hence, we conservatively prune our workload estimate.
+  static const double kConservativeTimeRatio;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GCIdleTimeHandler);
+};
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_HEAP_GC_IDLE_TIME_HANDLER_H_
=======================================
--- /dev/null
+++ /trunk/test/cctest/compiler/test-run-inlining.cc Thu Aug 21 07:23:04 2014 UTC
@@ -0,0 +1,184 @@
+// 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.
+
+#include "src/v8.h"
+
+#include "test/cctest/compiler/function-tester.h"
+
+#if V8_TURBOFAN_TARGET
+
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+
+// TODO(sigurds) At the moment we do not write optimization frames when
+// inlining, thus the reported stack depth changes depending on inlining.
+// AssertStackDepth checks the stack depth actually changes as a simple way
+// to ensure that inlining actually occurs.
+// Once inlining creates optimization frames, all these unit tests need to
+// check that the optimization frame is there.
+
+
+static void AssertStackDepth(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::HandleScope scope(args.GetIsolate());
+ v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
+      args.GetIsolate(), 10, v8::StackTrace::kDetailed);
+  CHECK_EQ(args[0]->ToInt32()->Value(), stackTrace->GetFrameCount());
+}
+
+
+static void InstallAssertStackDepthHelper(v8::Isolate* isolate) {
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::FunctionTemplate> t =
+      v8::FunctionTemplate::New(isolate, AssertStackDepth);
+  context->Global()->Set(v8_str("AssertStackDepth"), t->GetFunction());
+}
+
+
+TEST(SimpleInlining) {
+  FLAG_turbo_inlining = true;
+  FunctionTester T(
+      "(function(){"
+      "function foo(s) { AssertStackDepth(1); return s; };"
+      "function bar(s, t) { return foo(s); };"
+      "return bar;})();");
+
+  InstallAssertStackDepthHelper(CcTest::isolate());
+  T.CheckCall(T.Val(1), T.Val(1), T.Val(2));
+}
+
+
+TEST(SimpleInliningContext) {
+  FLAG_turbo_inlining = true;
+  FunctionTester T(
+      "(function () {"
+      "function foo(s) { AssertStackDepth(1); var x = 12; return s + x; };"
+      "function bar(s, t) { return foo(s); };"
+      "return bar;"
+      "})();");
+
+  InstallAssertStackDepthHelper(CcTest::isolate());
+  T.CheckCall(T.Val(13), T.Val(1), T.Val(2));
+}
+
+
+TEST(CaptureContext) {
+  FLAG_turbo_inlining = true;
+  FunctionTester T(
+      "var f = (function () {"
+      "var x = 42;"
+      "function bar(s) { return x + s; };"
+      "return (function (s) { return bar(s); });"
+      "})();"
+      "(function (s) { return f(s)})");
+
+  InstallAssertStackDepthHelper(CcTest::isolate());
+  T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined());
+}
+
+
+// TODO(sigurds) For now we do not inline any native functions. If we do at
+// some point, change this test.
+TEST(DontInlineEval) {
+  FLAG_turbo_inlining = true;
+  FunctionTester T(
+      "var x = 42;"
+      "(function () {"
+      "function bar(s, t) { return eval(\"AssertStackDepth(2); x\") };"
+      "return bar;"
+      "})();");
+
+  InstallAssertStackDepthHelper(CcTest::isolate());
+  T.CheckCall(T.Val(42), T.Val("x"), T.undefined());
+}
+
+
+TEST(InlineOmitArguments) {
+  FLAG_turbo_inlining = true;
+  FunctionTester T(
+      "(function () {"
+      "var x = 42;"
+      "function bar(s, t, u, v) { AssertStackDepth(1); return x + s; };"
+      "return (function (s,t) { return bar(s); });"
+      "})();");
+
+  InstallAssertStackDepthHelper(CcTest::isolate());
+  T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined());
+}
+
+
+TEST(InlineSurplusArguments) {
+  FLAG_turbo_inlining = true;
+  FunctionTester T(
+      "(function () {"
+      "var x = 42;"
+      "function foo(s) { AssertStackDepth(1); return x + s; };"
+      "function bar(s,t) { return foo(s,t,13); };"
+      "return bar;"
+      "})();");
+
+  InstallAssertStackDepthHelper(CcTest::isolate());
+  T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined());
+}
+
+
+TEST(InlineTwice) {
+  FLAG_turbo_inlining = true;
+  FunctionTester T(
+      "(function () {"
+      "var x = 42;"
+      "function bar(s) { AssertStackDepth(1); return x + s; };"
+      "return (function (s,t) { return bar(s) + bar(t); });"
+      "})();");
+
+  InstallAssertStackDepthHelper(CcTest::isolate());
+  T.CheckCall(T.Val(2 * 42 + 12 + 4), T.Val(12), T.Val(4));
+}
+
+
+TEST(InlineTwiceDependent) {
+  FLAG_turbo_inlining = true;
+  FunctionTester T(
+      "(function () {"
+      "var x = 42;"
+      "function foo(s) { AssertStackDepth(1); return x + s; };"
+      "function bar(s,t) { return foo(foo(s)); };"
+      "return bar;"
+      "})();");
+
+  InstallAssertStackDepthHelper(CcTest::isolate());
+  T.CheckCall(T.Val(42 + 42 + 12), T.Val(12), T.Val(4));
+}
+
+
+TEST(InlineTwiceDependentDiamond) {
+  FLAG_turbo_inlining = true;
+  FunctionTester T(
+      "(function () {"
+      "function foo(s) { if (true) {"
+      "                  return 12 } else { return 13; } };"
+      "function bar(s,t) { return foo(foo(1)); };"
+      "return bar;"
+      "})();");
+
+  InstallAssertStackDepthHelper(CcTest::isolate());
+  T.CheckCall(T.Val(12), T.undefined(), T.undefined());
+}
+
+
+TEST(InlineTwiceDependentDiamondReal) {
+  FLAG_turbo_inlining = true;
+  FunctionTester T(
+      "(function () {"
+      "var x = 41;"
+      "function foo(s) { AssertStackDepth(1); if (s % 2 == 0) {"
+      "                  return x - s } else { return x + s; } };"
+      "function bar(s,t) { return foo(foo(s)); };"
+      "return bar;"
+      "})();");
+
+  InstallAssertStackDepthHelper(CcTest::isolate());
+  T.CheckCall(T.Val(-11), T.Val(11), T.Val(4));
+}
+
+#endif  // V8_TURBOFAN_TARGET
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/compiler/shift-shr.js   Thu Aug 21 07:23:04 2014 UTC
@@ -0,0 +1,26 @@
+// 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.
+
+// Flags: --allow-natives-syntax --noopt-safe-uint32-operations
+
+// Check the results of `left >>> right`. The result is always unsigned (and
+// therefore positive).
+function test_shr(left) {
+  var errors = 0;
+
+  for (var i = 1; i < 1024; i++) {
+    var temp = left >>> i;
+    if (temp < 0) {
+      errors++;
+    }
+  }
+
+  return errors;
+}
+
+assertEquals(0, test_shr(1));
+%OptimizeFunctionOnNextCall(test_shr);
+for (var i = 5; i >= -5; i--) {
+  assertEquals(0, test_shr(i));
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/number-literal.js       Thu Aug 21 07:23:04 2014 UTC
@@ -0,0 +1,33 @@
+// 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 test(message, a, b, skipStrictMode) {
+  assertSame(eval(a), eval(b), message);
+  if (!skipStrictMode) {
+    (function() {
+      'use strict';
+      assertSame(eval(a), eval(b), message);
+    })();
+  }
+}
+
+test('hex-int', '0x20', '32');
+test('oct-int', '040', '32', true);  // Octals disallowed in strict mode.
+test('dec-int', '32.00', '32');
+test('dec-underflow-int', '32.00000000000000000000000000000000000000001', 
'32');
+test('exp-int', '3.2e1', '32');
+test('exp-int', '3200e-2', '32');
+test('overflow-inf', '1e2000', 'Infinity');
+test('overflow-inf-exact', '1.797693134862315808e+308', 'Infinity');
+test('non-overflow-inf-exact', '1.797693134862315807e+308',
+     '1.7976931348623157e+308');
+test('underflow-0', '1e-2000', '0');
+test('underflow-0-exact', '2.4703282292062E-324', '0');
+test('non-underflow-0-exact', '2.4703282292063E-324', '5e-324');
+test('precission-loss-high', '9007199254740992', '9007199254740993');
+test('precission-loss-low', '1.9999999999999998', '1.9999999999999997');
+test('non-canonical-literal-int', '1.0', '1');
+test('non-canonical-literal-frac', '1.50', '1.5');
+test('rounding-down', '1.12512512512512452', '1.1251251251251244');
+test('rounding-up', '1.12512512512512453', '1.1251251251251246');
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-crbug-405491.js Thu Aug 21 07:23:04 2014 UTC
@@ -0,0 +1,5 @@
+// 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.
+
+// Flags: --expose-debug-as 1
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/runtime-gen/createglobalprivateownsymbol.js Thu Aug 21 07:23:04 2014 UTC
@@ -0,0 +1,5 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
+// Flags: --allow-natives-syntax --harmony --harmony-proxies
+var _name = "foo";
+%CreateGlobalPrivateOwnSymbol(_name);
=======================================
--- /dev/null
+++ /trunk/tools/cpu.sh Thu Aug 21 07:23:04 2014 UTC
@@ -0,0 +1,62 @@
+#!/bin/bash
+# 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.
+
+CPUPATH=/sys/devices/system/cpu
+
+MAXID=$(cat $CPUPATH/present | awk -F- '{print $NF}')
+
+set_governor() {
+  echo "Setting CPU frequency governor to \"$1\""
+  for (( i=0; i<=$MAXID; i++ )); do
+    echo "$1" > $CPUPATH/cpu$i/cpufreq/scaling_governor
+  done
+}
+
+dual_core() {
+  echo "Switching to dual-core mode"
+  for (( i=2; i<=$MAXID; i++ )); do
+    echo 0 > $CPUPATH/cpu$i/online
+  done
+}
+
+single_core() {
+  echo "Switching to single-core mode"
+  for (( i=1; i<=$MAXID; i++ )); do
+    echo 0 > $CPUPATH/cpu$i/online
+  done
+}
+
+
+all_cores() {
+  echo "Reactivating all CPU cores"
+  for (( i=2; i<=$MAXID; i++ )); do
+    echo 1 > $CPUPATH/cpu$i/online
+  done
+}
+
+case "$1" in
+  fast | performance)
+    set_governor "performance"
+    ;;
+  slow | powersave)
+    set_governor "powersave"
+    ;;
+  default | ondemand)
+    set_governor "ondemand"
+    ;;
+  dualcore | dual)
+    dual_core
+    ;;
+  singlecore | single)
+    single_core
+    ;;
+  allcores | all)
+    all_cores
+    ;;
+  *)
+    echo "Usage: $0 fast|slow|default|singlecore|dualcore|all"
+    exit 1
+    ;;
+esac
=======================================
--- /trunk/src/compiler-intrinsics.h    Thu Jul 31 18:45:14 2014 UTC
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2006-2008 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.
-
-#ifndef V8_COMPILER_INTRINSICS_H_
-#define V8_COMPILER_INTRINSICS_H_
-
-#include "src/base/macros.h"
-
-namespace v8 {
-namespace internal {
-
-class CompilerIntrinsics {
- public:
-  // Returns number of zero bits preceding least significant 1 bit.
-  // Undefined for zero value.
-  INLINE(static int CountTrailingZeros(uint32_t value));
-
-  // Returns number of zero bits following most significant 1 bit.
-  // Undefined for zero value.
-  INLINE(static int CountLeadingZeros(uint32_t value));
-
-  // Returns the number of bits set.
-  INLINE(static int CountSetBits(uint32_t value));
-};
-
-#ifdef __GNUC__
-int CompilerIntrinsics::CountTrailingZeros(uint32_t value) {
-  return __builtin_ctz(value);
-}
-
-int CompilerIntrinsics::CountLeadingZeros(uint32_t value) {
-  return __builtin_clz(value);
-}
-
-int CompilerIntrinsics::CountSetBits(uint32_t value) {
-  return __builtin_popcount(value);
-}
-
-#elif defined(_MSC_VER)
-
-#pragma intrinsic(_BitScanForward)
-#pragma intrinsic(_BitScanReverse)
-
-int CompilerIntrinsics::CountTrailingZeros(uint32_t value) {
-  unsigned long result;  //NOLINT
-  _BitScanForward(&result, static_cast<long>(value));  //NOLINT
-  return static_cast<int>(result);
-}
-
-int CompilerIntrinsics::CountLeadingZeros(uint32_t value) {
-  unsigned long result;  //NOLINT
-  _BitScanReverse(&result, static_cast<long>(value));  //NOLINT
-  return 31 - static_cast<int>(result);
-}
-
-int CompilerIntrinsics::CountSetBits(uint32_t value) {
-  // Manually count set bits.
-  value = ((value >>  1) & 0x55555555) + (value & 0x55555555);
-  value = ((value >>  2) & 0x33333333) + (value & 0x33333333);
-  value = ((value >>  4) & 0x0f0f0f0f) + (value & 0x0f0f0f0f);
-  value = ((value >>  8) & 0x00ff00ff) + (value & 0x00ff00ff);
-  value = ((value >> 16) & 0x0000ffff) + (value & 0x0000ffff);
-  return value;
-}
-
-#else
-#error Unsupported compiler
-#endif
-
-} }  // namespace v8::internal
-
-#endif  // V8_COMPILER_INTRINSICS_H_
=======================================
--- /trunk/test/mjsunit/runtime-gen/createglobalprivatesymbol.js Fri Aug 8 15:46:17 2014 UTC
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
-// Flags: --allow-natives-syntax --harmony --harmony-proxies
-var _name = "foo";
-%CreateGlobalPrivateSymbol(_name);
=======================================
--- /trunk/test/mjsunit/runtime-gen/internalsetprototype.js Tue Aug 12 06:42:13 2014 UTC
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
-// Flags: --allow-natives-syntax --harmony --harmony-proxies
-var _obj = new Object();
-var _prototype = new Object();
-%InternalSetPrototype(_obj, _prototype);
=======================================
--- /trunk/test/preparser/duplicate-property.pyt Tue Jun 17 08:22:36 2014 UTC
+++ /dev/null
@@ -1,162 +0,0 @@
-# Copyright 2011 the V8 project authors. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-#       copyright notice, this list of conditions and the following
-#       disclaimer in the documentation and/or other materials provided
-#       with the distribution.
-#     * Neither the name of Google Inc. nor the names of its
-#       contributors may be used to endorse or promote products derived
-#       from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# Tests of duplicate properties in object literals.
-
-# ----------------------------------------------------------------------
-# Utility functions to generate a number of tests for each property
-# name pair.
-
-def PropertyTest(name, propa, propb, allow_strict = True):
-  replacement = {"id1": propa, "id2": propb, "name": name}
-
-  # Tests same test in both strict and non-strict context.
-  def StrictTest(name, source, replacement, expectation):
-    if (allow_strict):
-      Template("strict-" + name,
-               "\"use strict\";\n" + source)(replacement, expectation)
-      Template(name, source)(replacement, expectation)
-
-  # This one only fails in non-strict context.
-  if (allow_strict):
-    Template("strict-$name-data-data", """
-        "use strict";
-        var o = {$id1: 42, $id2: 42};
-      """)(replacement, "strict_duplicate_property")
-
-  Template("$name-data-data", """
-      var o = {$id1: 42, $id2: 42};
-    """)(replacement, None)
-
-  StrictTest("$name-data-get", """
-      var o = {$id1: 42, get $id2(){}};
-    """, replacement, "accessor_data_property")
-
-  StrictTest("$name-data-set", """
-      var o = {$id1: 42, set $id2(v){}};
-    """, replacement, "accessor_data_property")
-
-  StrictTest("$name-get-data", """
-      var o = {get $id1(){}, $id2: 42};
-    """, replacement, "accessor_data_property")
-
-  StrictTest("$name-set-data", """
-      var o = {set $id1(v){}, $id2: 42};
-    """, replacement, "accessor_data_property")
-
-  StrictTest("$name-get-get", """
-      var o = {get $id1(){}, get $id2(){}};
-    """, replacement, "accessor_get_set")
-
-  StrictTest("$name-set-set", """
-      var o = {set $id1(v){}, set $id2(v){}};
-    """, replacement, "accessor_get_set")
-
-  StrictTest("$name-nested-get", """
-      var o = {get $id1(){}, o: {get $id2(){} } };
-    """, replacement, None)
-
-  StrictTest("$name-nested-set", """
-      var o = {set $id1(v){}, o: {set $id2(v){} } };
-    """, replacement, None)
-
-
-def TestBothWays(name, propa, propb, allow_strict = True):
-  PropertyTest(name + "-1", propa, propb, allow_strict)
-  PropertyTest(name + "-2", propb, propa, allow_strict)
-
-def TestSame(name, prop, allow_strict = True):
-  PropertyTest(name, prop, prop, allow_strict)
-
-#-----------------------------------------------------------------------
-
-# Simple identifier property
-TestSame("a", "a")
-
-# Get/set identifiers
-TestSame("get-id", "get")
-TestSame("set-id", "set")
-
-# Number properties
-TestSame("0", "0")
-TestSame("0.1", "0.1")
-TestSame("1.0", "1.0")
-TestSame("42.33", "42.33")
-TestSame("2^32-2", "4294967294")
-TestSame("2^32", "4294967296")
-TestSame("2^53", "9007199254740992")
-TestSame("Hex20", "0x20")
-TestSame("exp10", "1e10")
-TestSame("exp20", "1e20")
-TestSame("Oct40", "040", False);
-
-
-# String properties
-TestSame("str-a", '"a"')
-TestSame("str-0", '"0"')
-TestSame("str-42", '"42"')
-TestSame("str-empty", '""')
-
-# Keywords
-TestSame("if", "if")
-TestSame("case", "case")
-
-# Future reserved keywords
-TestSame("public", "public")
-TestSame("class", "class")
-
-
-# Test that numbers are converted to string correctly.
-
-TestBothWays("hex-int", "0x20", "32")
-TestBothWays("oct-int", "040", "32", False) # Octals disallowed in strict mode.
-TestBothWays("dec-int", "32.00", "32")
-TestBothWays("dec-underflow-int",
-             "32.00000000000000000000000000000000000000001", "32")
-TestBothWays("exp-int", "3.2e1", "32")
-TestBothWays("exp-int", "3200e-2", "32")
-TestBothWays("overflow-inf", "1e2000", "Infinity")
-TestBothWays("overflow-inf-exact", "1.797693134862315808e+308", "Infinity")
-TestBothWays("non-overflow-inf-exact", "1.797693134862315807e+308",
-                                       "1.7976931348623157e+308")
-TestBothWays("underflow-0", "1e-2000", "0")
-TestBothWays("underflow-0-exact", "2.4703282292062E-324", "0")
-TestBothWays("non-underflow-0-exact", "2.4703282292063E-324", "5e-324")
-TestBothWays("precission-loss-high", "9007199254740992", "9007199254740993")
-TestBothWays("precission-loss-low", "1.9999999999999998", "1.9999999999999997")
-TestBothWays("non-canonical-literal-int", "1.0", "1")
-TestBothWays("non-canonical-literal-frac", "1.50", "1.5")
-TestBothWays("rounding-down", "1.12512512512512452", "1.1251251251251244")
-TestBothWays("rounding-up", "1.12512512512512453", "1.1251251251251246")
-
-TestBothWays("hex-int-str", "0x20", '"32"')
-TestBothWays("dec-int-str", "32.00", '"32"')
-TestBothWays("exp-int-str", "3.2e1", '"32"')
-TestBothWays("overflow-inf-str", "1e2000", '"Infinity"')
-TestBothWays("underflow-0-str", "1e-2000", '"0"')
-TestBothWays("non-canonical-literal-int-str", "1.0", '"1"')
-TestBothWays("non-canonical-literal-frac-str", "1.50", '"1.5"')
=======================================
--- /trunk/BUILD.gn     Thu Aug 21 00:04:56 2014 UTC
+++ /trunk/BUILD.gn     Thu Aug 21 07:23:04 2014 UTC
@@ -499,6 +499,8 @@
     "src/compiler/js-generic-lowering.h",
     "src/compiler/js-graph.cc",
     "src/compiler/js-graph.h",
+    "src/compiler/js-inlining.cc",
+    "src/compiler/js-inlining.h",
     "src/compiler/js-operator.h",
     "src/compiler/js-typed-lowering.cc",
     "src/compiler/js-typed-lowering.h",
@@ -509,6 +511,8 @@
     "src/compiler/machine-operator-reducer.cc",
     "src/compiler/machine-operator-reducer.h",
     "src/compiler/machine-operator.h",
+    "src/compiler/machine-type.cc",
+    "src/compiler/machine-type.h",
     "src/compiler/node-aux-data-inl.h",
     "src/compiler/node-aux-data.h",
     "src/compiler/node-cache.cc",
@@ -628,6 +632,8 @@
     "src/heap-snapshot-generator-inl.h",
     "src/heap-snapshot-generator.cc",
     "src/heap-snapshot-generator.h",
+    "src/heap/gc-idle-time-handler.cc",
+    "src/heap/gc-idle-time-handler.h",
     "src/heap/gc-tracer.cc",
     "src/heap/gc-tracer.h",
     "src/heap/heap-inl.h",
=======================================
--- /trunk/ChangeLog    Thu Aug 21 00:04:56 2014 UTC
+++ /trunk/ChangeLog    Thu Aug 21 07:23:04 2014 UTC
@@ -1,3 +1,20 @@
+2014-08-21: Version 3.29.11
+
+        Refactor ParseObjectLiteral.
+
+        Support symbol-named properties in API (issue 3394).
+
+        Suppress test262 test that tests duplicate properties.
+
+        ES6: Duplicate properties are no longer an error (issue 3498).
+
+        Expose function CheckDebugBreak in the debugger api.
+
+        Remove RegExp.$input (issue 3486).
+
+        Performance and stability improvements on all platforms.
+
+
 2014-08-21: Version 3.29.10

ES6: Make sure we do not store -0 as the key in Map/Set (issue 3515).
=======================================
--- /trunk/include/v8-debug.h   Mon Jul  7 00:05:07 2014 UTC
+++ /trunk/include/v8-debug.h   Thu Aug 21 07:23:04 2014 UTC
@@ -167,6 +167,9 @@
   // happened yet.
   static void CancelDebugBreak(Isolate* isolate);

+  // Check if a debugger break is scheduled in the given isolate.
+  static bool CheckDebugBreak(Isolate* isolate);
+
   // Break execution of JavaScript in the given isolate (this method
   // can be invoked from a non-VM thread) for further client command
   // execution on a VM thread. Client data is then passed in
=======================================
--- /trunk/include/v8.h Thu Aug 21 00:04:56 2014 UTC
+++ /trunk/include/v8.h Thu Aug 21 07:23:04 2014 UTC
@@ -77,6 +77,7 @@
 class Int32;
 class Integer;
 class Isolate;
+class Name;
 class Number;
 class NumberObject;
 class Object;
@@ -1366,6 +1367,12 @@
    */
   bool IsFalse() const;

+  /**
+   * Returns true if this value is a symbol or a string.
+   * This is an experimental feature.
+   */
+  bool IsName() const;
+
   /**
    * Returns true if this value is an instance of the String type.
    * See ECMA-262 8.4.
@@ -1598,10 +1605,21 @@
 };


+/**
+ * A superclass for symbols and strings.
+ */
+class V8_EXPORT Name : public Primitive {
+ public:
+  V8_INLINE static Name* Cast(v8::Value* obj);
+ private:
+  static void CheckCast(v8::Value* obj);
+};
+
+
 /**
  * A JavaScript string value (ECMA-262, 4.3.17).
  */
-class V8_EXPORT String : public Primitive {
+class V8_EXPORT String : public Name {
  public:
   enum Encoding {
     UNKNOWN_ENCODING = 0x1,
@@ -1940,7 +1958,7 @@
  *
  * This is an experimental feature. Use at your own risk.
  */
-class V8_EXPORT Symbol : public Primitive {
+class V8_EXPORT Symbol : public Name {
  public:
   // Returns the print name string of the symbol, or undefined if none.
   Local<Value> Name() const;
@@ -2089,11 +2107,18 @@
 typedef void (*AccessorGetterCallback)(
     Local<String> property,
     const PropertyCallbackInfo<Value>& info);
+typedef void (*AccessorNameGetterCallback)(
+    Local<Name> property,
+    const PropertyCallbackInfo<Value>& info);


 typedef void (*AccessorSetterCallback)(
     Local<String> property,
     Local<Value> value,
+    const PropertyCallbackInfo<void>& info);
+typedef void (*AccessorNameSetterCallback)(
+    Local<Name> property,
+    Local<Value> value,
     const PropertyCallbackInfo<void>& info);


@@ -2169,14 +2194,20 @@
                    Handle<Value> data = Handle<Value>(),
                    AccessControl settings = DEFAULT,
                    PropertyAttribute attribute = None);
+  bool SetAccessor(Handle<Name> name,
+                   AccessorNameGetterCallback getter,
+                   AccessorNameSetterCallback setter = 0,
+                   Handle<Value> data = Handle<Value>(),
+                   AccessControl settings = DEFAULT,
+                   PropertyAttribute attribute = None);

   // This function is not yet stable and should not be used at this time.
-  bool SetDeclaredAccessor(Local<String> name,
+  bool SetDeclaredAccessor(Local<Name> name,
                            Local<DeclaredAccessorDescriptor> descriptor,
                            PropertyAttribute attribute = None,
                            AccessControl settings = DEFAULT);

-  void SetAccessorProperty(Local<String> name,
+  void SetAccessorProperty(Local<Name> name,
                            Local<Function> getter,
                            Handle<Function> setter = Handle<Function>(),
                            PropertyAttribute attribute = None,
@@ -3178,12 +3209,12 @@
 class V8_EXPORT Template : public Data {
  public:
   /** Adds a property to each instance created by this template.*/
-  void Set(Handle<String> name, Handle<Data> value,
+  void Set(Handle<Name> name, Handle<Data> value,
            PropertyAttribute attributes = None);
V8_INLINE void Set(Isolate* isolate, const char* name, Handle<Data> value);

   void SetAccessorProperty(
-     Local<String> name,
+     Local<Name> name,
      Local<FunctionTemplate> getter = Local<FunctionTemplate>(),
      Local<FunctionTemplate> setter = Local<FunctionTemplate>(),
      PropertyAttribute attribute = None,
@@ -3225,9 +3256,18 @@
                              Local<AccessorSignature> signature =
                                  Local<AccessorSignature>(),
                              AccessControl settings = DEFAULT);
+  void SetNativeDataProperty(Local<Name> name,
+                             AccessorNameGetterCallback getter,
+                             AccessorNameSetterCallback setter = 0,
+                             // TODO(dcarney): gcc can't handle Local below
+                             Handle<Value> data = Handle<Value>(),
+                             PropertyAttribute attribute = None,
+                             Local<AccessorSignature> signature =
+                                 Local<AccessorSignature>(),
+                             AccessControl settings = DEFAULT);

   // This function is not yet stable and should not be used at this time.
-  bool SetDeclaredAccessor(Local<String> name,
+  bool SetDeclaredAccessor(Local<Name> name,
                            Local<DeclaredAccessorDescriptor> descriptor,
                            PropertyAttribute attribute = None,
                            Local<AccessorSignature> signature =
@@ -3594,12 +3634,20 @@
                    PropertyAttribute attribute = None,
                    Handle<AccessorSignature> signature =
                        Handle<AccessorSignature>());
+  void SetAccessor(Handle<Name> name,
+                   AccessorNameGetterCallback getter,
+                   AccessorNameSetterCallback setter = 0,
+                   Handle<Value> data = Handle<Value>(),
+                   AccessControl settings = DEFAULT,
+                   PropertyAttribute attribute = None,
+                   Handle<AccessorSignature> signature =
+                       Handle<AccessorSignature>());

   /**
    * Sets a named property handler on the object template.
    *
-   * Whenever a named property is accessed on objects created from
-   * this object template, the provided callback is invoked instead of
+ * Whenever a property whose name is a string is accessed on objects created
+   * from this object template, the provided callback is invoked instead of
    * accessing the property directly on the JavaScript object.
    *
    * \param getter The callback to invoke when getting a property.
@@ -6346,6 +6394,14 @@
 template <class T> Value* Value::Cast(T* value) {
   return static_cast<Value*>(value);
 }
+
+
+Name* Name::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+  CheckCast(value);
+#endif
+  return static_cast<Name*>(value);
+}


 Symbol* Symbol::Cast(v8::Value* value) {
=======================================
--- /trunk/include/v8config.h   Tue Apr 29 16:30:47 2014 UTC
+++ /trunk/include/v8config.h   Thu Aug 21 07:23:04 2014 UTC
@@ -175,7 +175,10 @@
// V8_HAS_ATTRIBUTE_VISIBILITY - __attribute__((visibility)) supported // V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT - __attribute__((warn_unused_result))
 //                                        supported
+//  V8_HAS_BUILTIN_CLZ                  - __builtin_clz() supported
+//  V8_HAS_BUILTIN_CTZ                  - __builtin_ctz() supported
 //  V8_HAS_BUILTIN_EXPECT               - __builtin_expect() supported
+//  V8_HAS_BUILTIN_POPCOUNT             - __builtin_popcount() supported
 //  V8_HAS_DECLSPEC_ALIGN               - __declspec(align(n)) supported
 //  V8_HAS_DECLSPEC_DEPRECATED          - __declspec(deprecated) supported
 //  V8_HAS_DECLSPEC_NOINLINE            - __declspec(noinline) supported
@@ -206,7 +209,10 @@
 # define V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT \
     (__has_attribute(warn_unused_result))

+# define V8_HAS_BUILTIN_CLZ (__has_builtin(__builtin_clz))
+# define V8_HAS_BUILTIN_CTZ (__has_builtin(__builtin_ctz))
 # define V8_HAS_BUILTIN_EXPECT (__has_builtin(__builtin_expect))
+# define V8_HAS_BUILTIN_POPCOUNT (__has_builtin(__builtin_popcount))

 # define V8_HAS_CXX11_ALIGNAS (__has_feature(cxx_alignas))
 # define V8_HAS_CXX11_STATIC_ASSERT (__has_feature(cxx_static_assert))
@@ -238,7 +244,10 @@
 # define V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT \
     (!V8_CC_INTEL && V8_GNUC_PREREQ(4, 1, 0))

+# define V8_HAS_BUILTIN_CLZ (V8_GNUC_PREREQ(3, 4, 0))
+# define V8_HAS_BUILTIN_CTZ (V8_GNUC_PREREQ(3, 4, 0))
 # define V8_HAS_BUILTIN_EXPECT (V8_GNUC_PREREQ(2, 96, 0))
+# define V8_HAS_BUILTIN_POPCOUNT (V8_GNUC_PREREQ(3, 4, 0))

 // g++ requires -std=c++0x or -std=gnu++0x to support C++11 functionality
 // without warnings (functionality used by the macros below).  These modes
=======================================
--- /trunk/src/accessors.cc     Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/accessors.cc     Thu Aug 21 07:23:04 2014 UTC
@@ -23,9 +23,9 @@

 Handle<AccessorInfo> Accessors::MakeAccessor(
     Isolate* isolate,
-    Handle<String> name,
-    AccessorGetterCallback getter,
-    AccessorSetterCallback setter,
+    Handle<Name> name,
+    AccessorNameGetterCallback getter,
+    AccessorNameSetterCallback setter,
     PropertyAttributes attributes) {
   Factory* factory = isolate->factory();
Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
@@ -138,7 +138,7 @@

 bool SetPropertyOnInstanceIfInherited(
     Isolate* isolate, const v8::PropertyCallbackInfo<void>& info,
-    v8::Local<v8::String> name, Handle<Object> value) {
+    v8::Local<v8::Name> name, Handle<Object> value) {
   Handle<Object> holder = Utils::OpenHandle(*info.Holder());
   Handle<Object> receiver = Utils::OpenHandle(*info.This());
   if (*holder == *receiver) return false;
@@ -176,7 +176,7 @@


 void Accessors::ArrayLengthGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
@@ -188,7 +188,7 @@


 void Accessors::ArrayLengthSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> val,
     const v8::PropertyCallbackInfo<void>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
@@ -244,7 +244,7 @@
 //

 void Accessors::StringLengthGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
@@ -267,7 +267,7 @@


 void Accessors::StringLengthSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -290,7 +290,7 @@


 void Accessors::ScriptColumnOffsetGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
@@ -302,7 +302,7 @@


 void Accessors::ScriptColumnOffsetSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -327,7 +327,7 @@


 void Accessors::ScriptIdGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
@@ -339,7 +339,7 @@


 void Accessors::ScriptIdSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -364,7 +364,7 @@


 void Accessors::ScriptNameGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
@@ -376,7 +376,7 @@


 void Accessors::ScriptNameSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -399,7 +399,7 @@


 void Accessors::ScriptSourceGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
@@ -411,7 +411,7 @@


 void Accessors::ScriptSourceSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -434,7 +434,7 @@


 void Accessors::ScriptLineOffsetGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
@@ -446,7 +446,7 @@


 void Accessors::ScriptLineOffsetSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -471,7 +471,7 @@


 void Accessors::ScriptTypeGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
@@ -483,7 +483,7 @@


 void Accessors::ScriptTypeSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -508,7 +508,7 @@


 void Accessors::ScriptCompilationTypeGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
@@ -521,7 +521,7 @@


 void Accessors::ScriptCompilationTypeSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -546,7 +546,7 @@


 void Accessors::ScriptLineEndsGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
@@ -566,7 +566,7 @@


 void Accessors::ScriptLineEndsSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -591,7 +591,7 @@


 void Accessors::ScriptSourceUrlGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
@@ -603,7 +603,7 @@


 void Accessors::ScriptSourceUrlSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -626,7 +626,7 @@


 void Accessors::ScriptSourceMappingUrlGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
@@ -639,7 +639,7 @@


 void Accessors::ScriptSourceMappingUrlSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -662,7 +662,7 @@


 void Accessors::ScriptContextDataGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
@@ -674,7 +674,7 @@


 void Accessors::ScriptContextDataSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -699,7 +699,7 @@


 void Accessors::ScriptEvalFromScriptGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
@@ -721,7 +721,7 @@


 void Accessors::ScriptEvalFromScriptSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -746,7 +746,7 @@


 void Accessors::ScriptEvalFromScriptPositionGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
@@ -767,7 +767,7 @@


 void Accessors::ScriptEvalFromScriptPositionSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -792,7 +792,7 @@


 void Accessors::ScriptEvalFromFunctionNameGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
@@ -813,7 +813,7 @@


 void Accessors::ScriptEvalFromFunctionNameSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> value,
     const v8::PropertyCallbackInfo<void>& info) {
   UNREACHABLE();
@@ -884,7 +884,7 @@


 void Accessors::FunctionPrototypeGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
@@ -896,7 +896,7 @@


 void Accessors::FunctionPrototypeSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> val,
     const v8::PropertyCallbackInfo<void>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
@@ -927,7 +927,7 @@


 void Accessors::FunctionLengthGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
@@ -953,7 +953,7 @@


 void Accessors::FunctionLengthSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> val,
     const v8::PropertyCallbackInfo<void>& info) {
   // Function length is non writable, non configurable.
@@ -977,7 +977,7 @@


 void Accessors::FunctionNameGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
@@ -989,7 +989,7 @@


 void Accessors::FunctionNameSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> val,
     const v8::PropertyCallbackInfo<void>& info) {
   // Function name is non writable, non configurable.
@@ -1114,7 +1114,7 @@


 void Accessors::FunctionArgumentsGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
@@ -1126,7 +1126,7 @@


 void Accessors::FunctionArgumentsSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> val,
     const v8::PropertyCallbackInfo<void>& info) {
   // Function arguments is non writable, non configurable.
@@ -1257,7 +1257,7 @@


 void Accessors::FunctionCallerGetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
@@ -1277,7 +1277,7 @@


 void Accessors::FunctionCallerSetter(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<v8::Value> val,
     const v8::PropertyCallbackInfo<void>& info) {
   // Function caller is non writable, non configurable.
=======================================
--- /trunk/src/accessors.h      Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/accessors.h      Thu Aug 21 07:23:04 2014 UTC
@@ -43,10 +43,10 @@
   // Accessor descriptors.
 #define ACCESSOR_INFO_DECLARATION(name)                   \
   static void name##Getter(                               \
-      v8::Local<v8::String> name,                         \
+      v8::Local<v8::Name> name,                           \
       const v8::PropertyCallbackInfo<v8::Value>& info);   \
   static void name##Setter(                               \
-      v8::Local<v8::String> name,                         \
+      v8::Local<v8::Name> name,                           \
       v8::Local<v8::Value> value,                         \
       const v8::PropertyCallbackInfo<void>& info);   \
   static Handle<AccessorInfo> name##Info(                 \
@@ -83,9 +83,9 @@

   static Handle<AccessorInfo> MakeAccessor(
       Isolate* isolate,
-      Handle<String> name,
-      AccessorGetterCallback getter,
-      AccessorSetterCallback setter,
+      Handle<Name> name,
+      AccessorNameGetterCallback getter,
+      AccessorNameSetterCallback setter,
       PropertyAttributes attributes);

   static Handle<ExecutableAccessorInfo> CloneAccessor(
=======================================
--- /trunk/src/api.cc   Thu Aug 21 00:04:56 2014 UTC
+++ /trunk/src/api.cc   Thu Aug 21 07:23:04 2014 UTC
@@ -828,7 +828,7 @@
 }


-void Template::Set(v8::Handle<String> name,
+void Template::Set(v8::Handle<Name> name,
                    v8::Handle<Data> value,
                    v8::PropertyAttribute attribute) {
   i::Isolate* isolate = i::Isolate::Current();
@@ -845,7 +845,7 @@


 void Template::SetAccessorProperty(
-    v8::Local<v8::String> name,
+    v8::Local<v8::Name> name,
     v8::Local<FunctionTemplate> getter,
     v8::Local<FunctionTemplate> setter,
     v8::PropertyAttribute attribute,
@@ -1156,7 +1156,7 @@

 static i::Handle<i::AccessorInfo> SetAccessorInfoProperties(
     i::Handle<i::AccessorInfo> obj,
-    v8::Handle<String> name,
+    v8::Handle<Name> name,
     v8::AccessControl settings,
     v8::PropertyAttribute attributes,
     v8::Handle<AccessorSignature> signature) {
@@ -1173,7 +1173,7 @@

 template<typename Getter, typename Setter>
 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
-    v8::Handle<String> name,
+    v8::Handle<Name> name,
     Getter getter,
     Setter setter,
     v8::Handle<Value> data,
@@ -1194,7 +1194,7 @@


 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
-    v8::Handle<String> name,
+    v8::Handle<Name> name,
     v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,
     void* setter_ignored,
     void* data_ignored,
@@ -1345,10 +1345,10 @@
 }


-template<typename Setter, typename Getter, typename Data, typename Template> +template<typename Getter, typename Setter, typename Data, typename Template>
 static bool TemplateSetAccessor(
     Template* template_obj,
-    v8::Local<String> name,
+    v8::Local<Name> name,
     Getter getter,
     Setter setter,
     Data data,
@@ -1368,7 +1368,7 @@


 bool Template::SetDeclaredAccessor(
-    Local<String> name,
+    Local<Name> name,
     Local<DeclaredAccessorDescriptor> descriptor,
     PropertyAttribute attribute,
     Local<AccessorSignature> signature,
@@ -1389,6 +1389,18 @@
   TemplateSetAccessor(
       this, name, getter, setter, data, settings, attribute, signature);
 }
+
+
+void Template::SetNativeDataProperty(v8::Local<Name> name,
+                                     AccessorNameGetterCallback getter,
+                                     AccessorNameSetterCallback setter,
+                                     v8::Handle<Value> data,
+                                     PropertyAttribute attribute,
+ v8::Local<AccessorSignature> signature,
+                                     AccessControl settings) {
+  TemplateSetAccessor(
+      this, name, getter, setter, data, settings, attribute, signature);
+}


 void ObjectTemplate::SetAccessor(v8::Handle<String> name,
@@ -1401,6 +1413,18 @@
   TemplateSetAccessor(
       this, name, getter, setter, data, settings, attribute, signature);
 }
+
+
+void ObjectTemplate::SetAccessor(v8::Handle<Name> name,
+                                 AccessorNameGetterCallback getter,
+                                 AccessorNameSetterCallback setter,
+                                 v8::Handle<Value> data,
+                                 AccessControl settings,
+                                 PropertyAttribute attribute,
+                                 v8::Handle<AccessorSignature> signature) {
+  TemplateSetAccessor(
+      this, name, getter, setter, data, settings, attribute, signature);
+}


 void ObjectTemplate::SetNamedPropertyHandler(
@@ -2322,6 +2346,11 @@
 bool Value::IsFunction() const {
   return Utils::OpenHandle(this)->IsJSFunction();
 }
+
+
+bool Value::IsName() const {
+  return Utils::OpenHandle(this)->IsName();
+}


 bool Value::FullIsString() const {
@@ -2638,6 +2667,14 @@
                   "v8::Function::Cast()",
                   "Could not convert to function");
 }
+
+
+void v8::Name::CheckCast(v8::Value* that) {
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  Utils::ApiCheck(obj->IsName(),
+                  "v8::Name::Cast()",
+                  "Could not convert to name");
+}


 void v8::String::CheckCast(v8::Value* that) {
@@ -3423,11 +3460,11 @@
 }


-template<typename Setter, typename Getter, typename Data>
+template<typename Getter, typename Setter, typename Data>
 static inline bool ObjectSetAccessor(Object* obj,
-                                     Handle<String> name,
-                                     Setter getter,
-                                     Getter setter,
+                                     Handle<Name> name,
+                                     Getter getter,
+                                     Setter setter,
                                      Data data,
                                      AccessControl settings,
                                      PropertyAttribute attributes) {
@@ -3462,7 +3499,18 @@
 }


-bool Object::SetDeclaredAccessor(Local<String> name,
+bool Object::SetAccessor(Handle<Name> name,
+                         AccessorNameGetterCallback getter,
+                         AccessorNameSetterCallback setter,
+                         v8::Handle<Value> data,
+                         AccessControl settings,
+                         PropertyAttribute attributes) {
+  return ObjectSetAccessor(
+      this, name, getter, setter, data, settings, attributes);
+}
+
+
+bool Object::SetDeclaredAccessor(Local<Name> name,
Local<DeclaredAccessorDescriptor> descriptor,
                                  PropertyAttribute attributes,
                                  AccessControl settings) {
@@ -3472,7 +3520,7 @@
 }


-void Object::SetAccessorProperty(Local<String> name,
+void Object::SetAccessorProperty(Local<Name> name,
                                  Local<Function> getter,
                                  Handle<Function> setter,
                                  PropertyAttribute attribute,
@@ -3571,7 +3619,8 @@
   has_pending_exception = !i::Object::GetProperty(it).ToHandle(&result);
   EXCEPTION_BAILOUT_CHECK(it->isolate(), Local<Value>());

-  return Utils::ToLocal(result);
+  if (it->IsFound()) return Utils::ToLocal(result);
+  return Local<Value>();
 }


@@ -6910,6 +6959,12 @@
   internal_isolate->stack_guard()->ClearDebugBreak();
 }

+
+bool Debug::CheckDebugBreak(Isolate* isolate) {
+  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  return internal_isolate->stack_guard()->CheckDebugBreak();
+}
+

 void Debug::DebugBreakForCommand(Isolate* isolate, ClientData* data) {
   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
@@ -7630,9 +7685,9 @@


 void InvokeAccessorGetterCallback(
-    v8::Local<v8::String> property,
+    v8::Local<v8::Name> property,
     const v8::PropertyCallbackInfo<v8::Value>& info,
-    v8::AccessorGetterCallback getter) {
+    v8::AccessorNameGetterCallback getter) {
   // Leaving JavaScript.
   Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
Address getter_address = reinterpret_cast<Address>(reinterpret_cast<intptr_t>(
=======================================
--- /trunk/src/api.h    Tue Aug  5 00:05:55 2014 UTC
+++ /trunk/src/api.h    Thu Aug 21 07:23:04 2014 UTC
@@ -158,6 +158,7 @@
   V(Float32Array, JSTypedArray)                \
   V(Float64Array, JSTypedArray)                \
   V(DataView, JSDataView)                      \
+  V(Name, Name)                                \
   V(String, String)                            \
   V(Symbol, Symbol)                            \
   V(Script, JSFunction)                        \
@@ -189,6 +190,8 @@
       v8::internal::Handle<v8::internal::Object> obj);
   static inline Local<Function> ToLocal(
       v8::internal::Handle<v8::internal::JSFunction> obj);
+  static inline Local<Name> ToLocal(
+      v8::internal::Handle<v8::internal::Name> obj);
   static inline Local<String> ToLocal(
       v8::internal::Handle<v8::internal::String> obj);
   static inline Local<Symbol> ToLocal(
@@ -333,6 +336,7 @@
 MAKE_TO_LOCAL(ToLocal, Context, Context)
 MAKE_TO_LOCAL(ToLocal, Object, Value)
 MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
+MAKE_TO_LOCAL(ToLocal, Name, Name)
 MAKE_TO_LOCAL(ToLocal, String, String)
 MAKE_TO_LOCAL(ToLocal, Symbol, Symbol)
 MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
@@ -671,9 +675,9 @@
 // Interceptor functions called from generated inline caches to notify
 // CPU profiler that external callbacks are invoked.
 void InvokeAccessorGetterCallback(
-    v8::Local<v8::String> property,
+    v8::Local<v8::Name> property,
     const v8::PropertyCallbackInfo<v8::Value>& info,
-    v8::AccessorGetterCallback getter);
+    v8::AccessorNameGetterCallback getter);

void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
                             v8::FunctionCallback callback);
=======================================
--- /trunk/src/arguments.h      Tue Aug  5 00:05:55 2014 UTC
+++ /trunk/src/arguments.h      Thu Aug 21 07:23:04 2014 UTC
@@ -68,13 +68,13 @@
 // They are used to generate the Call() functions below
 // These aren't included in the list as they have duplicate signatures
 // F(NamedPropertyEnumeratorCallback, ...)
-// F(NamedPropertyGetterCallback, ...)

 #define FOR_EACH_CALLBACK_TABLE_MAPPING_0(F) \
   F(IndexedPropertyEnumeratorCallback, v8::Array) \

 #define FOR_EACH_CALLBACK_TABLE_MAPPING_1(F) \
-  F(AccessorGetterCallback, v8::Value, v8::Local<v8::String>) \
+  F(NamedPropertyGetterCallback, v8::Value, v8::Local<v8::String>) \
+  F(AccessorNameGetterCallback, v8::Value, v8::Local<v8::Name>) \
   F(NamedPropertyQueryCallback, \
     v8::Integer, \
     v8::Local<v8::String>) \
@@ -102,9 +102,9 @@
     v8::Local<v8::Value>) \

 #define FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(F) \
-  F(AccessorSetterCallback, \
+  F(AccessorNameSetterCallback, \
     void, \
-    v8::Local<v8::String>, \
+    v8::Local<v8::Name>, \
     v8::Local<v8::Value>) \


=======================================
--- /trunk/src/arm64/full-codegen-arm64.cc      Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/arm64/full-codegen-arm64.cc      Thu Aug 21 07:23:04 2014 UTC
@@ -2019,16 +2019,14 @@
       __ Ubfx(right, right, kSmiShift, 5);
       __ Lsl(result, left, right);
       break;
-    case Token::SHR: {
-      Label right_not_zero;
-      __ Cbnz(right, &right_not_zero);
-      __ Tbnz(left, kXSignBit, &stub_call);
-      __ Bind(&right_not_zero);
+    case Token::SHR:
+ // If `left >>> right` >= 0x80000000, the result is not representable in a
+      // signed 32-bit smi.
       __ Ubfx(right, right, kSmiShift, 5);
-      __ Lsr(result, left, right);
-      __ Bic(result, result, kSmiShiftMask);
+      __ Lsr(x10, left, right);
+      __ Tbnz(x10, kXSignBit, &stub_call);
+      __ Bic(result, x10, kSmiShiftMask);
       break;
-    }
     case Token::ADD:
       __ Adds(x10, left, right);
       __ B(vs, &stub_call);
=======================================
--- /trunk/src/arm64/lithium-codegen-arm64.cc   Thu Aug 21 00:04:56 2014 UTC
+++ /trunk/src/arm64/lithium-codegen-arm64.cc   Thu Aug 21 07:23:04 2014 UTC
@@ -4891,13 +4891,12 @@
       case Token::SAR: __ Asr(result, left, right); break;
       case Token::SHL: __ Lsl(result, left, right); break;
       case Token::SHR:
+        __ Lsr(result, left, right);
         if (instr->can_deopt()) {
-          Label right_not_zero;
-          __ Cbnz(right, &right_not_zero);
-          DeoptimizeIfNegative(left, instr->environment());
-          __ Bind(&right_not_zero);
+ // If `left >>> right` >= 0x80000000, the result is not representable
+          // in a signed 32-bit smi.
+          DeoptimizeIfNegative(result, instr->environment());
         }
-        __ Lsr(result, left, right);
         break;
       default: UNREACHABLE();
     }
@@ -4952,15 +4951,14 @@
         __ Lsl(result, left, result);
         break;
       case Token::SHR:
-        if (instr->can_deopt()) {
-          Label right_not_zero;
-          __ Cbnz(right, &right_not_zero);
-          DeoptimizeIfNegative(left, instr->environment());
-          __ Bind(&right_not_zero);
-        }
         __ Ubfx(result, right, kSmiShift, 5);
         __ Lsr(result, left, result);
         __ Bic(result, result, kSmiShiftMask);
+        if (instr->can_deopt()) {
+ // If `left >>> right` >= 0x80000000, the result is not representable
+          // in a signed 32-bit smi.
+          DeoptimizeIfNegative(result, instr->environment());
+        }
         break;
       default: UNREACHABLE();
     }
=======================================
--- /trunk/src/arm64/simulator-arm64.cc Tue Aug  5 00:05:55 2014 UTC
+++ /trunk/src/arm64/simulator-arm64.cc Thu Aug 21 07:23:04 2014 UTC
@@ -704,7 +704,7 @@

     case ExternalReference::PROFILING_GETTER_CALL: {
       // void f(Local<String> property, PropertyCallbackInfo& info,
-      //        AccessorGetterCallback callback)
+      //        AccessorNameGetterCallback callback)
       TraceSim("Type: PROFILING_GETTER_CALL\n");
       SimulatorRuntimeProfilingGetterCall target =
         reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
=======================================
--- /trunk/src/array-iterator.js        Tue Jul 15 00:04:47 2014 UTC
+++ /trunk/src/array-iterator.js        Thu Aug 21 07:23:04 2014 UTC
@@ -50,7 +50,7 @@
 function ArrayIteratorNext() {
   var iterator = ToObject(this);

-  if (!HAS_PRIVATE(iterator, arrayIteratorObjectSymbol)) {
+  if (!HAS_DEFINED_PRIVATE(iterator, arrayIteratorNextIndexSymbol)) {
     throw MakeTypeError('incompatible_method_receiver',
                         ['Array Iterator.prototype.next']);
   }
=======================================
--- /trunk/src/assembler.h      Thu Aug  7 08:39:21 2014 UTC
+++ /trunk/src/assembler.h      Thu Aug 21 07:23:04 2014 UTC
@@ -774,12 +774,12 @@
     PROFILING_API_CALL,

     // Direct call to accessor getter callback.
-    // void f(Local<String> property, PropertyCallbackInfo& info)
+    // void f(Local<Name> property, PropertyCallbackInfo& info)
     DIRECT_GETTER_CALL,

     // Call to accessor getter callback via InvokeAccessorGetterCallback.
-    // void f(Local<String> property, PropertyCallbackInfo& info,
-    //     AccessorGetterCallback callback)
+    // void f(Local<Name> property, PropertyCallbackInfo& info,
+    //     AccessorNameGetterCallback callback)
     PROFILING_GETTER_CALL
   };

=======================================
--- /trunk/src/base/bits.h      Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/base/bits.h      Thu Aug 21 07:23:04 2014 UTC
@@ -6,6 +6,9 @@
 #define V8_BASE_BITS_H_

 #include "include/v8stdint.h"
+#if V8_CC_MSVC
+#include <intrin.h>
+#endif
 #if V8_OS_WIN32
 #include "src/base/win32-headers.h"
 #endif
@@ -14,6 +17,61 @@
 namespace base {
 namespace bits {

+// CountSetBits32(value) returns the number of bits set in |value|.
+inline uint32_t CountSetBits32(uint32_t value) {
+#if V8_HAS_BUILTIN_POPCOUNT
+  return __builtin_popcount(value);
+#else
+  value = ((value >> 1) & 0x55555555) + (value & 0x55555555);
+  value = ((value >> 2) & 0x33333333) + (value & 0x33333333);
+  value = ((value >> 4) & 0x0f0f0f0f) + (value & 0x0f0f0f0f);
+  value = ((value >> 8) & 0x00ff00ff) + (value & 0x00ff00ff);
+  value = ((value >> 16) & 0x0000ffff) + (value & 0x0000ffff);
+  return value;
+#endif
+}
+
+
+// CountLeadingZeros32(value) returns the number of zero bits following the most +// significant 1 bit in |value| if |value| is non-zero, otherwise it returns 32.
+inline uint32_t CountLeadingZeros32(uint32_t value) {
+#if V8_HAS_BUILTIN_CLZ
+  return value ? __builtin_clz(value) : 32;
+#elif V8_CC_MSVC
+  unsigned long result;  // NOLINT(runtime/int)
+  if (!_BitScanReverse(&result, value)) return 32;
+  return static_cast<uint32_t>(31 - result);
+#else
+  value = value | (value >> 1);
+  value = value | (value >> 2);
+  value = value | (value >> 4);
+  value = value | (value >> 8);
+  value = value | (value >> 16);
+  return CountSetBits32(~value);
+#endif
+}
+
+
+// CountTrailingZeros32(value) returns the number of zero bits preceding the
+// least significant 1 bit in |value| if |value| is non-zero, otherwise it
+// returns 32.
+inline uint32_t CountTrailingZeros32(uint32_t value) {
+#if V8_HAS_BUILTIN_CTZ
+  return value ? __builtin_ctz(value) : 32;
+#elif V8_CC_MSVC
+  unsigned long result;  // NOLINT(runtime/int)
+  if (!_BitScanForward(&result, value)) return 32;
+  return static_cast<uint32_t>(result);
+#else
+  if (value == 0) return 32;
+  unsigned count = 0;
+  for (value ^= value - 1; value >>= 1; ++count)
+    ;
+  return count;
+#endif
+}
+
+
 inline uint32_t RotateRight32(uint32_t value, uint32_t shift) {
   if (shift == 0) return value;
   return (value >> shift) | (value << (32 - shift));
=======================================
--- /trunk/src/bootstrapper.cc  Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/bootstrapper.cc  Thu Aug 21 07:23:04 2014 UTC
@@ -2204,6 +2204,8 @@
     debug_context->set_security_token(native_context->security_token());
     Handle<String> debug_string =
         factory->InternalizeUtf8String(FLAG_expose_debug_as);
+    uint32_t index;
+    if (debug_string->AsArrayIndex(&index)) return true;
     Handle<Object> global_proxy(debug_context->global_proxy(), isolate);
     JSObject::AddProperty(global, debug_string, global_proxy, DONT_ENUM);
   }
@@ -2445,11 +2447,10 @@
           break;
         }
         case CALLBACKS: {
-          LookupResult result(isolate());
-          Handle<Name> key(Name::cast(descs->GetKey(i)), isolate());
-          to->LookupOwn(key, &result);
+          Handle<Name> key(descs->GetKey(i));
+          LookupIterator it(to, key, LookupIterator::CHECK_PROPERTY);
           // If the property is already there we skip it
-          if (result.IsFound()) continue;
+          if (it.IsFound() && it.HasProperty()) continue;
           HandleScope inner(isolate());
           DCHECK(!to->HasFastProperties());
           // Add to dictionary.
@@ -2478,10 +2479,9 @@
       if (properties->IsKey(raw_key)) {
         DCHECK(raw_key->IsName());
         // If the property is already there we skip it.
-        LookupResult result(isolate());
         Handle<Name> key(Name::cast(raw_key));
-        to->LookupOwn(key, &result);
-        if (result.IsFound()) continue;
+        LookupIterator it(to, key, LookupIterator::CHECK_PROPERTY);
+        if (it.IsFound() && it.HasProperty()) continue;
         // Set the property.
         Handle<Object> value = Handle<Object>(properties->ValueAt(i),
                                               isolate());
=======================================
--- /trunk/src/compiler/arm/instruction-selector-arm.cc Thu Aug 21 00:04:56 2014 UTC +++ /trunk/src/compiler/arm/instruction-selector-arm.cc Thu Aug 21 07:23:04 2014 UTC
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.

+#include "src/base/bits.h"
 #include "src/compiler/instruction-selector-impl.h"
 #include "src/compiler/node-matchers.h"
-#include "src/compiler-intrinsics.h"

 namespace v8 {
 namespace internal {
@@ -423,10 +423,10 @@
   }
   if (IsSupported(ARMv7) && m.right().HasValue()) {
     uint32_t value = m.right().Value();
-    uint32_t width = CompilerIntrinsics::CountSetBits(value);
-    uint32_t msb = CompilerIntrinsics::CountLeadingZeros(value);
+    uint32_t width = base::bits::CountSetBits32(value);
+    uint32_t msb = base::bits::CountLeadingZeros32(value);
     if (width != 0 && msb + width == 32) {
-      DCHECK_EQ(0, CompilerIntrinsics::CountTrailingZeros(value));
+      DCHECK_EQ(0, base::bits::CountTrailingZeros32(value));
       if (m.left().IsWord32Shr()) {
         Int32BinopMatcher mleft(m.left().node());
         if (mleft.right().IsInRange(0, 31)) {
@@ -442,8 +442,8 @@
     }
     // Try to interpret this AND as BFC.
     width = 32 - width;
-    msb = CompilerIntrinsics::CountLeadingZeros(~value);
-    uint32_t lsb = CompilerIntrinsics::CountTrailingZeros(~value);
+    msb = base::bits::CountLeadingZeros32(~value);
+    uint32_t lsb = base::bits::CountTrailingZeros32(~value);
     if (msb + width + lsb == 32) {
Emit(kArmBfc, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
            g.TempImmediate(lsb), g.TempImmediate(width));
@@ -536,10 +536,10 @@
     Int32BinopMatcher mleft(m.left().node());
     if (mleft.right().HasValue()) {
       uint32_t value = (mleft.right().Value() >> lsb) << lsb;
-      uint32_t width = CompilerIntrinsics::CountSetBits(value);
-      uint32_t msb = CompilerIntrinsics::CountLeadingZeros(value);
+      uint32_t width = base::bits::CountSetBits32(value);
+      uint32_t msb = base::bits::CountLeadingZeros32(value);
       if (msb + width + lsb == 32) {
-        DCHECK_EQ(lsb, CompilerIntrinsics::CountTrailingZeros(value));
+        DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(value));
         Emit(kArmUbfx, g.DefineAsRegister(node),
              g.UseRegister(mleft.left().node()), g.TempImmediate(lsb),
              g.TempImmediate(width));
=======================================
--- /trunk/src/compiler/arm64/instruction-selector-arm64.cc Wed Aug 20 00:06:26 2014 UTC +++ /trunk/src/compiler/arm64/instruction-selector-arm64.cc Thu Aug 21 07:23:04 2014 UTC
@@ -57,9 +57,9 @@
         // TODO(dcarney): -values can be handled by instruction swapping
         return Assembler::IsImmAddSub(value);
       case kShift32Imm:
-        return 0 <= value && value < 31;
+        return 0 <= value && value < 32;
       case kShift64Imm:
-        return 0 <= value && value < 63;
+        return 0 <= value && value < 64;
       case kLoadStoreImm:
         return (0 <= value && value < (1 << 9)) ||
                (-(1 << 6) <= value && value < (1 << 6));
=======================================
--- /trunk/src/compiler/change-lowering.cc      Thu Aug 21 00:04:56 2014 UTC
+++ /trunk/src/compiler/change-lowering.cc      Thu Aug 21 07:23:04 2014 UTC
@@ -27,7 +27,14 @@
     case IrOpcode::kChangeTaggedToFloat64:
       return ChangeTaggedToFloat64(node->InputAt(0), control);
     case IrOpcode::kChangeTaggedToInt32:
+    case IrOpcode::kChangeTaggedToUint32:
+      // ToInt32 and ToUint32 perform exactly the same operation, just the
+ // interpretation of the resulting 32 bit value is different, so we can
+      // use the same subgraph for both operations.
+      // See ECMA-262 9.5: ToInt32 and ECMA-262 9.6: ToUint32.
       return ChangeTaggedToInt32(node->InputAt(0), control);
+    case IrOpcode::kChangeUint32ToTagged:
+      return ChangeUint32ToTagged(node->InputAt(0), control);
     default:
       return NoChange();
   }
@@ -42,6 +49,20 @@
((HeapNumber::kValueOffset / kPointerSize) * (machine()->is64() ? 8 : 4)); return jsgraph()->Int32Constant(heap_number_value_offset - kHeapObjectTag);
 }
+
+
+Node* ChangeLowering::SmiMaxValueConstant() {
+  // TODO(turbofan): Work-around for weird GCC 4.6 linker issue:
+  // src/compiler/change-lowering.cc:46: undefined reference to
+  // `v8::internal::SmiTagging<4u>::kSmiValueSize'
+  // src/compiler/change-lowering.cc:46: undefined reference to
+  // `v8::internal::SmiTagging<8u>::kSmiValueSize'
+  STATIC_ASSERT(SmiTagging<4>::kSmiValueSize == 31);
+  STATIC_ASSERT(SmiTagging<8>::kSmiValueSize == 32);
+  const int smi_value_size = machine()->is64() ? 32 : 31;
+  return jsgraph()->Int32Constant(
+      -(static_cast<int>(0xffffffffu << (smi_value_size - 1)) + 1));
+}


 Node* ChangeLowering::SmiShiftBitsConstant() {
@@ -55,6 +76,43 @@
   const int smi_shift_size = machine()->is64() ? 31 : 0;
   return jsgraph()->Int32Constant(smi_shift_size + kSmiTagSize);
 }
+
+
+Node* ChangeLowering::AllocateHeapNumberWithValue(Node* value, Node* control) { + // The AllocateHeapNumber() runtime function does not use the context, so we
+  // can safely pass in Smi zero here.
+  Node* context = jsgraph()->ZeroConstant();
+  Node* effect = graph()->NewNode(common()->ValueEffect(1), value);
+  const Runtime::Function* function =
+      Runtime::FunctionForId(Runtime::kAllocateHeapNumber);
+  DCHECK_EQ(0, function->nargs);
+  CallDescriptor* desc = linkage()->GetRuntimeCallDescriptor(
+      function->function_id, 0, Operator::kNoProperties);
+  Node* heap_number = graph()->NewNode(
+      common()->Call(desc), jsgraph()->CEntryStubConstant(),
+      jsgraph()->ExternalConstant(ExternalReference(function, isolate())),
+      jsgraph()->Int32Constant(function->nargs), context, effect, control);
+  Node* store = graph()->NewNode(
+      machine()->Store(kMachFloat64, kNoWriteBarrier), heap_number,
+      HeapNumberValueIndexConstant(), value, heap_number, control);
+  return graph()->NewNode(common()->Finish(1), heap_number, store);
+}
+
+
+Node* ChangeLowering::ChangeSmiToInt32(Node* value) {
+ value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant());
+  if (machine()->is64()) {
+    value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value);
+  }
+  return value;
+}
+
+
+Node* ChangeLowering::LoadHeapNumberValue(Node* value, Node* control) {
+  return graph()->NewNode(machine()->Load(kMachFloat64), value,
+                          HeapNumberValueIndexConstant(),
+ graph()->NewNode(common()->ControlEffect(), control));
+}


 Reduction ChangeLowering::ChangeBitToBool(Node* val, Node* control) {
@@ -121,18 +179,11 @@
   Node* branch = graph()->NewNode(common()->Branch(), tag, control);

   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* load = graph()->NewNode(
-      machine()->Load(kMachFloat64), val, HeapNumberValueIndexConstant(),
-      graph()->NewNode(common()->ControlEffect(), if_true));
- Node* change = graph()->NewNode(machine()->TruncateFloat64ToInt32(), load);
+  Node* change = graph()->NewNode(machine()->TruncateFloat64ToInt32(),
+                                  LoadHeapNumberValue(val, if_true));

   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
-  Node* integer =
-      graph()->NewNode(machine()->WordSar(), val, SmiShiftBitsConstant());
-  Node* number =
-      machine()->is64()
-          ? graph()->NewNode(machine()->TruncateInt64ToInt32(), integer)
-          : integer;
+  Node* number = ChangeSmiToInt32(val);

   Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
   Node* phi = graph()->NewNode(common()->Phi(2), change, number, merge);
@@ -150,21 +201,41 @@
   Node* branch = graph()->NewNode(common()->Branch(), tag, control);

   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* load = graph()->NewNode(
-      machine()->Load(kMachFloat64), val, HeapNumberValueIndexConstant(),
-      graph()->NewNode(common()->ControlEffect(), if_true));
+  Node* load = LoadHeapNumberValue(val, if_true);

   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
-  Node* integer =
-      graph()->NewNode(machine()->WordSar(), val, SmiShiftBitsConstant());
-  Node* number = graph()->NewNode(
-      machine()->ChangeInt32ToFloat64(),
+  Node* number = graph()->NewNode(machine()->ChangeInt32ToFloat64(),
+                                  ChangeSmiToInt32(val));
+
+  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  Node* phi = graph()->NewNode(common()->Phi(2), load, number, merge);
+
+  return Replace(phi);
+}
+
+
+Reduction ChangeLowering::ChangeUint32ToTagged(Node* val, Node* control) {
+  STATIC_ASSERT(kSmiTag == 0);
+  STATIC_ASSERT(kSmiTagMask == 1);
+
+  Node* cmp = graph()->NewNode(machine()->Uint32LessThanOrEqual(), val,
+                               SmiMaxValueConstant());
+  Node* branch = graph()->NewNode(common()->Branch(), cmp, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* smi = graph()->NewNode(
+      machine()->WordShl(),
       machine()->is64()
-          ? graph()->NewNode(machine()->TruncateInt64ToInt32(), integer)
-          : integer);
+          ? graph()->NewNode(machine()->ChangeUint32ToUint64(), val)
+          : val,
+      SmiShiftBitsConstant());
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* heap_number = AllocateHeapNumberWithValue(
+      graph()->NewNode(machine()->ChangeUint32ToFloat64(), val), if_false);

   Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-  Node* phi = graph()->NewNode(common()->Phi(2), load, number, merge);
+  Node* phi = graph()->NewNode(common()->Phi(2), smi, heap_number, merge);

   return Replace(phi);
 }
@@ -179,27 +250,6 @@
 CommonOperatorBuilder* ChangeLowering::common() const {
   return jsgraph()->common();
 }
-
-
-Node* ChangeLowering::AllocateHeapNumberWithValue(Node* value, Node* control) { - // The AllocateHeapNumber() runtime function does not use the context, so we
-  // can safely pass in Smi zero here.
-  Node* context = jsgraph()->ZeroConstant();
-  Node* effect = graph()->NewNode(common()->ValueEffect(1), value);
-  const Runtime::Function* function =
-      Runtime::FunctionForId(Runtime::kAllocateHeapNumber);
-  DCHECK_EQ(0, function->nargs);
-  CallDescriptor* desc = linkage()->GetRuntimeCallDescriptor(
-      function->function_id, 0, Operator::kNoProperties);
-  Node* heap_number = graph()->NewNode(
-      common()->Call(desc), jsgraph()->CEntryStubConstant(),
-      jsgraph()->ExternalConstant(ExternalReference(function, isolate())),
-      jsgraph()->Int32Constant(function->nargs), context, effect, control);
-  Node* store = graph()->NewNode(
-      machine()->Store(kMachFloat64, kNoWriteBarrier), heap_number,
-      HeapNumberValueIndexConstant(), value, heap_number, control);
-  return graph()->NewNode(common()->Finish(1), heap_number, store);
-}

 }  // namespace compiler
 }  // namespace internal
=======================================
--- /trunk/src/compiler/change-lowering.h       Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/compiler/change-lowering.h       Thu Aug 21 07:23:04 2014 UTC
@@ -26,16 +26,22 @@

   virtual Reduction Reduce(Node* node) V8_OVERRIDE;

- protected:
+ private:
   Node* HeapNumberValueIndexConstant();
+  Node* SmiMaxValueConstant();
   Node* SmiShiftBitsConstant();

+  Node* AllocateHeapNumberWithValue(Node* value, Node* control);
+  Node* ChangeSmiToInt32(Node* value);
+  Node* LoadHeapNumberValue(Node* value, Node* control);
+
   Reduction ChangeBitToBool(Node* val, Node* control);
   Reduction ChangeBoolToBit(Node* val);
   Reduction ChangeFloat64ToTagged(Node* val, Node* control);
   Reduction ChangeInt32ToTagged(Node* val, Node* control);
   Reduction ChangeTaggedToFloat64(Node* val, Node* control);
   Reduction ChangeTaggedToInt32(Node* val, Node* control);
+  Reduction ChangeUint32ToTagged(Node* val, Node* control);

   Graph* graph() const;
   Isolate* isolate() const;
@@ -43,9 +49,6 @@
   Linkage* linkage() const { return linkage_; }
   CommonOperatorBuilder* common() const;
   MachineOperatorBuilder* machine() const { return machine_; }
-
- private:
-  Node* AllocateHeapNumberWithValue(Node* value, Node* control);

   JSGraph* jsgraph_;
   Linkage* linkage_;
=======================================
--- /trunk/src/compiler/generic-graph.h Thu Jul 31 18:45:14 2014 UTC
+++ /trunk/src/compiler/generic-graph.h Thu Aug 21 07:23:04 2014 UTC
@@ -22,6 +22,7 @@

   NodeId NextNodeID() { return next_node_id_++; }
   NodeId NodeCount() const { return next_node_id_; }
+  void SetNextNodeId(NodeId next) { next_node_id_ = next; }

  private:
   Zone* zone_;
=======================================
--- /trunk/src/compiler/generic-node.h  Tue Aug  5 00:05:55 2014 UTC
+++ /trunk/src/compiler/generic-node.h  Thu Aug 21 07:23:04 2014 UTC
@@ -204,6 +204,12 @@
     ++index_;
     return *this;
   }
+  iterator& UpdateToAndIncrement(GenericNode<B, S>* new_to) {
+    typename GenericNode<B, S>::Input* input = GetInput();
+    input->Update(new_to);
+    index_++;
+    return *this;
+  }
   int index() { return index_; }

  private:
=======================================
--- /trunk/src/compiler/instruction-selector.cc Thu Aug 21 00:04:56 2014 UTC
+++ /trunk/src/compiler/instruction-selector.cc Thu Aug 21 07:23:04 2014 UTC
@@ -199,12 +199,18 @@
   DCHECK(!IsReference(node));
   sequence()->MarkAsDouble(node->id());

-  // Propagate "doubleness" throughout phis.
+  // Propagate "doubleness" throughout Finish/Phi nodes.
   for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) {
     Node* user = *i;
-    if (user->opcode() != IrOpcode::kPhi) continue;
-    if (IsDouble(user)) continue;
-    MarkAsDouble(user);
+    switch (user->opcode()) {
+      case IrOpcode::kFinish:
+      case IrOpcode::kPhi:
+        if (IsDouble(user)) continue;
+        MarkAsDouble(user);
+        break;
+      default:
+        break;
+    }
   }
 }

@@ -220,12 +226,18 @@
   DCHECK(!IsDouble(node));
   sequence()->MarkAsReference(node->id());

-  // Propagate "referenceness" throughout phis.
+  // Propagate "referenceness" throughout Finish/Phi nodes.
   for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) {
     Node* user = *i;
-    if (user->opcode() != IrOpcode::kPhi) continue;
-    if (IsReference(user)) continue;
-    MarkAsReference(user);
+    switch (user->opcode()) {
+      case IrOpcode::kFinish:
+      case IrOpcode::kPhi:
+        if (IsReference(user)) continue;
+        MarkAsReference(user);
+        break;
+      default:
+        break;
+    }
   }
 }

@@ -464,13 +476,12 @@
     case IrOpcode::kContinuation:
       // No code needed for these graph artifacts.
       return;
+    case IrOpcode::kFinish:
+      return VisitFinish(node);
     case IrOpcode::kParameter: {
-      int index = OpParameter<int>(node);
-      MachineType rep = linkage()
-                            ->GetIncomingDescriptor()
-                            ->GetInputLocation(index)
-                            .representation();
-      MarkAsRepresentation(rep, node);
+      LinkageLocation location =
+          linkage()->GetParameterLocation(OpParameter<int>(node));
+      MarkAsRepresentation(location.representation(), node);
       return VisitParameter(node);
     }
     case IrOpcode::kPhi:
@@ -797,6 +808,13 @@
 #endif  // V8_TARGET_ARCH_32_BIT || !V8_TURBOFAN_BACKEND


+void InstructionSelector::VisitFinish(Node* node) {
+  OperandGenerator g(this);
+  Node* value = node->InputAt(0);
+  Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
+}
+
+
 void InstructionSelector::VisitParameter(Node* node) {
   OperandGenerator g(this);
   Emit(kArchNop, g.DefineAsLocation(node, linkage()->GetParameterLocation(
=======================================
--- /trunk/src/compiler/instruction-selector.h  Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/compiler/instruction-selector.h  Thu Aug 21 07:23:04 2014 UTC
@@ -169,6 +169,7 @@
   void VisitWord64Compare(Node* node, FlagsContinuation* cont);
   void VisitFloat64Compare(Node* node, FlagsContinuation* cont);

+  void VisitFinish(Node* node);
   void VisitParameter(Node* node);
   void VisitPhi(Node* node);
   void VisitProjection(Node* node);
=======================================
--- /trunk/src/compiler/js-context-specialization.cc Fri Aug 8 15:46:17 2014 UTC +++ /trunk/src/compiler/js-context-specialization.cc Thu Aug 21 07:23:04 2014 UTC
@@ -15,26 +15,6 @@
 namespace internal {
 namespace compiler {

-// TODO(titzer): factor this out to a common routine with js-typed-lowering.
-static void ReplaceEffectfulWithValue(Node* node, Node* value) {
-  Node* effect = NULL;
-  if (OperatorProperties::HasEffectInput(node->op())) {
-    effect = NodeProperties::GetEffectInput(node);
-  }
-
-  // Requires distinguishing between value and effect edges.
-  UseIter iter = node->uses().begin();
-  while (iter != node->uses().end()) {
-    if (NodeProperties::IsEffectEdge(iter.edge())) {
-      DCHECK_NE(NULL, effect);
-      iter = iter.UpdateToAndIncrement(effect);
-    } else {
-      iter = iter.UpdateToAndIncrement(value);
-    }
-  }
-}
-
-
 class ContextSpecializationVisitor : public NullNodeVisitor {
  public:
   explicit ContextSpecializationVisitor(JSContextSpecializer* spec)
@@ -45,14 +25,16 @@
       case IrOpcode::kJSLoadContext: {
         Reduction r = spec_->ReduceJSLoadContext(node);
         if (r.Changed() && r.replacement() != node) {
-          ReplaceEffectfulWithValue(node, r.replacement());
+          NodeProperties::ReplaceWithValue(node, r.replacement());
+          node->RemoveAllInputs();
         }
         break;
       }
       case IrOpcode::kJSStoreContext: {
         Reduction r = spec_->ReduceJSStoreContext(node);
         if (r.Changed() && r.replacement() != node) {
-          ReplaceEffectfulWithValue(node, r.replacement());
+          NodeProperties::ReplaceWithValue(node, r.replacement());
+          node->RemoveAllInputs();
         }
         break;
       }
@@ -68,7 +50,8 @@


 void JSContextSpecializer::SpecializeToContext() {
- ReplaceEffectfulWithValue(context_, jsgraph_->Constant(info_->context()));
+  NodeProperties::ReplaceWithValue(context_,
+                                   jsgraph_->Constant(info_->context()));

   ContextSpecializationVisitor visitor(this);
   jsgraph_->graph()->VisitNodeInputsFromEnd(&visitor);
=======================================
--- /trunk/src/compiler/js-typed-lowering.cc    Tue Aug  5 00:05:55 2014 UTC
+++ /trunk/src/compiler/js-typed-lowering.cc    Thu Aug 21 07:23:04 2014 UTC
@@ -17,39 +17,18 @@
 // - relax effects from generic but not-side-effecting operations
 // - relax effects for ToNumber(mixed)

-// Replace value uses of {node} with {value} and effect uses of {node} with
-// {effect}. If {effect == NULL}, then use the effect input to {node}.
-// TODO(titzer): move into a GraphEditor?
-static void ReplaceUses(Node* node, Node* value, Node* effect) {
-  if (value == effect) {
-    // Effect and value updates are the same; no special iteration needed.
-    if (value != node) node->ReplaceUses(value);
-    return;
-  }
-
-  if (effect == NULL) effect = NodeProperties::GetEffectInput(node);
-
-  // The iteration requires distinguishing between value and effect edges.
-  UseIter iter = node->uses().begin();
-  while (iter != node->uses().end()) {
-    if (NodeProperties::IsEffectEdge(iter.edge())) {
-      iter = iter.UpdateToAndIncrement(effect);
-    } else {
-      iter = iter.UpdateToAndIncrement(value);
-    }
-  }
-}
-

// Relax the effects of {node} by immediately replacing effect uses of {node}
 // with the effect input to {node}.
// TODO(turbofan): replace the effect input to {node} with {graph->start()}.
 // TODO(titzer): move into a GraphEditor?
-static void RelaxEffects(Node* node) { ReplaceUses(node, node, NULL); }
+static void RelaxEffects(Node* node) {
+  NodeProperties::ReplaceWithValue(node, node, NULL);
+}


 Reduction JSTypedLowering::ReplaceEagerly(Node* old, Node* node) {
-  ReplaceUses(old, node, node);
+  NodeProperties::ReplaceWithValue(old, node, node);
   return Reducer::Changed(node);
 }

@@ -522,7 +501,7 @@

 static Reduction ReplaceWithReduction(Node* node, Reduction reduction) {
   if (reduction.Changed()) {
-    ReplaceUses(node, reduction.replacement(), NULL);
+    NodeProperties::ReplaceWithValue(node, reduction.replacement());
     return reduction;
   }
   return Reducer::NoChange();
@@ -573,13 +552,13 @@
         // !x => BooleanNot(x)
         value =
graph()->NewNode(simplified()->BooleanNot(), result.replacement());
-        ReplaceUses(node, value, NULL);
+        NodeProperties::ReplaceWithValue(node, value);
         return Changed(value);
       } else {
         // !x => BooleanNot(JSToBoolean(x))
         value = graph()->NewNode(simplified()->BooleanNot(), node);
         node->set_op(javascript()->ToBoolean());
-        ReplaceUses(node, value, node);
+        NodeProperties::ReplaceWithValue(node, value, node);
         // Note: ReplaceUses() smashes all uses, so smash it back here.
         value->ReplaceInput(0, node);
         return ReplaceWith(value);
=======================================
--- /trunk/src/compiler/machine-type.cc Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/compiler/machine-type.cc Thu Aug 21 07:23:04 2014 UTC
@@ -11,7 +11,7 @@

 #define PRINT(bit)         \
   if (type & bit) {        \
-    if (before) os << "|"; \
+    if (before) os << "+"; \
     os << #bit;            \
     before = true;         \
   }
=======================================
--- /trunk/src/compiler/node-properties-inl.h   Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/compiler/node-properties-inl.h   Thu Aug 21 07:23:04 2014 UTC
@@ -146,6 +146,28 @@
 inline void NodeProperties::RemoveNonValueInputs(Node* node) {
   node->TrimInputCount(OperatorProperties::GetValueInputCount(node->op()));
 }
+
+
+// Replace value uses of {node} with {value} and effect uses of {node} with
+// {effect}. If {effect == NULL}, then use the effect input to {node}.
+inline void NodeProperties::ReplaceWithValue(Node* node, Node* value,
+                                             Node* effect) {
+  DCHECK(!OperatorProperties::HasControlOutput(node->op()));
+  if (effect == NULL && OperatorProperties::HasEffectInput(node->op())) {
+    effect = NodeProperties::GetEffectInput(node);
+  }
+
+  // Requires distinguishing between value and effect edges.
+  UseIter iter = node->uses().begin();
+  while (iter != node->uses().end()) {
+    if (NodeProperties::IsEffectEdge(iter.edge())) {
+      DCHECK_NE(NULL, effect);
+      iter = iter.UpdateToAndIncrement(effect);
+    } else {
+      iter = iter.UpdateToAndIncrement(value);
+    }
+  }
+}


// -----------------------------------------------------------------------------
=======================================
--- /trunk/src/compiler/node-properties.h       Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/compiler/node-properties.h       Thu Aug 21 07:23:04 2014 UTC
@@ -33,6 +33,8 @@
   static inline void ReplaceEffectInput(Node* node, Node* effect,
                                         int index = 0);
   static inline void RemoveNonValueInputs(Node* node);
+  static inline void ReplaceWithValue(Node* node, Node* value,
+                                      Node* effect = NULL);

   static inline Bounds GetBounds(Node* node);
   static inline void SetBounds(Node* node, Bounds bounds);
=======================================
--- /trunk/src/compiler/pipeline.cc     Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/compiler/pipeline.cc     Thu Aug 21 07:23:04 2014 UTC
@@ -13,6 +13,7 @@
 #include "src/compiler/instruction-selector.h"
 #include "src/compiler/js-context-specialization.h"
 #include "src/compiler/js-generic-lowering.h"
+#include "src/compiler/js-inlining.h"
 #include "src/compiler/js-typed-lowering.h"
 #include "src/compiler/phi-reducer.h"
 #include "src/compiler/register-allocator.h"
@@ -186,13 +187,21 @@
   VerifyAndPrintGraph(&graph, "Initial untyped");

   if (FLAG_context_specialization) {
-    SourcePositionTable::Scope pos_(&source_positions,
-                                    SourcePosition::Unknown());
+    SourcePositionTable::Scope pos(&source_positions,
+                                   SourcePosition::Unknown());
     // Specialize the code to the context as aggressively as possible.
     JSContextSpecializer spec(info(), &jsgraph, context_node);
     spec.SpecializeToContext();
     VerifyAndPrintGraph(&graph, "Context specialized");
   }
+
+  if (FLAG_turbo_inlining) {
+    SourcePositionTable::Scope pos(&source_positions,
+                                   SourcePosition::Unknown());
+    JSInliner inliner(info(), &jsgraph);
+    inliner.Inline();
+    VerifyAndPrintGraph(&graph, "Inlined");
+  }

   // Print a replay of the initial graph.
   if (FLAG_print_turbo_replay) {
=======================================
--- /trunk/src/compiler/scheduler.cc    Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/compiler/scheduler.cc    Thu Aug 21 07:23:04 2014 UTC
@@ -15,15 +15,198 @@
 namespace internal {
 namespace compiler {

+static inline void Trace(const char* msg, ...) {
+  if (FLAG_trace_turbo_scheduler) {
+    va_list arguments;
+    va_start(arguments, msg);
+    base::OS::VPrint(msg, arguments);
+    va_end(arguments);
+  }
+}
+
+
+// Internal class to build a control flow graph (i.e the basic blocks and edges
+// between them within a Schedule) from the node graph.
+// Visits the graph backwards from end, following control and data edges.
+class CFGBuilder : public NullNodeVisitor {
+ public:
+  Schedule* schedule_;
+
+  explicit CFGBuilder(Schedule* schedule) : schedule_(schedule) {}
+
+  // Create the blocks for the schedule in pre-order.
+  void PreEdge(Node* from, int index, Node* node) {
+    switch (node->opcode()) {
+      case IrOpcode::kLoop:
+      case IrOpcode::kMerge:
+        BuildBlockForNode(node);
+        break;
+      case IrOpcode::kBranch:
+ BuildBlocksForSuccessors(node, IrOpcode::kIfTrue, IrOpcode::kIfFalse);
+        break;
+      case IrOpcode::kCall:
+        if (OperatorProperties::CanLazilyDeoptimize(node->op())) {
+          BuildBlocksForSuccessors(node, IrOpcode::kContinuation,
+                                   IrOpcode::kLazyDeoptimization);
+        }
+        break;
+      default:
+        break;
+    }
+  }
+
+  // Connect the blocks after nodes have been visited in post-order.
+  GenericGraphVisit::Control Post(Node* node) {
+    switch (node->opcode()) {
+      case IrOpcode::kLoop:
+      case IrOpcode::kMerge:
+        ConnectMerge(node);
+        break;
+      case IrOpcode::kBranch:
+        ConnectBranch(node);
+        break;
+      case IrOpcode::kDeoptimize:
+        ConnectDeoptimize(node);
+      case IrOpcode::kCall:
+        if (OperatorProperties::CanLazilyDeoptimize(node->op())) {
+          ConnectCall(node);
+        }
+        break;
+      case IrOpcode::kReturn:
+        ConnectReturn(node);
+        break;
+      default:
+        break;
+    }
+    return GenericGraphVisit::CONTINUE;
+  }
+
+  void BuildBlockForNode(Node* node) {
+    if (schedule_->block(node) == NULL) {
+      BasicBlock* block = schedule_->NewBasicBlock();
+      Trace("Create block B%d for node %d (%s)\n", block->id(), node->id(),
+            IrOpcode::Mnemonic(node->opcode()));
+      schedule_->AddNode(block, node);
+    }
+  }
+
+  void BuildBlocksForSuccessors(Node* node, IrOpcode::Value a,
+                                IrOpcode::Value b) {
+    Node* successors[2];
+    CollectSuccessorProjections(node, successors, a, b);
+    BuildBlockForNode(successors[0]);
+    BuildBlockForNode(successors[1]);
+  }
+
+  // Collect the branch-related projections from a node, such as IfTrue,
+  // IfFalse, Continuation, and LazyDeoptimization.
+  // TODO(titzer): consider moving this to node.h
+  void CollectSuccessorProjections(Node* node, Node** buffer,
+                                   IrOpcode::Value true_opcode,
+                                   IrOpcode::Value false_opcode) {
+    buffer[0] = NULL;
+    buffer[1] = NULL;
+    for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) {
+      if ((*i)->opcode() == true_opcode) {
+        DCHECK_EQ(NULL, buffer[0]);
+        buffer[0] = *i;
+      }
+      if ((*i)->opcode() == false_opcode) {
+        DCHECK_EQ(NULL, buffer[1]);
+        buffer[1] = *i;
+      }
+    }
+    DCHECK_NE(NULL, buffer[0]);
+    DCHECK_NE(NULL, buffer[1]);
+  }
+
+  void CollectSuccessorBlocks(Node* node, BasicBlock** buffer,
+                              IrOpcode::Value true_opcode,
+                              IrOpcode::Value false_opcode) {
+    Node* successors[2];
+ CollectSuccessorProjections(node, successors, true_opcode, false_opcode);
+    buffer[0] = schedule_->block(successors[0]);
+    buffer[1] = schedule_->block(successors[1]);
+  }
+
+  void ConnectBranch(Node* branch) {
+    Node* branch_block_node = NodeProperties::GetControlInput(branch);
+    BasicBlock* branch_block = schedule_->block(branch_block_node);
+    DCHECK(branch_block != NULL);
+
+    BasicBlock* successor_blocks[2];
+    CollectSuccessorBlocks(branch, successor_blocks, IrOpcode::kIfTrue,
+                           IrOpcode::kIfFalse);
+
+    TraceConnect(branch, branch_block, successor_blocks[0]);
+    TraceConnect(branch, branch_block, successor_blocks[1]);
+
+    schedule_->AddBranch(branch_block, branch, successor_blocks[0],
+                         successor_blocks[1]);
+  }
+
+  void ConnectMerge(Node* merge) {
+    BasicBlock* block = schedule_->block(merge);
+    DCHECK(block != NULL);
+    // For all of the merge's control inputs, add a goto at the end to the
+    // merge's basic block.
+    for (InputIter j = merge->inputs().begin(); j != merge->inputs().end();
+         ++j) {
+      BasicBlock* predecessor_block = schedule_->block(*j);
+      if ((*j)->opcode() != IrOpcode::kReturn &&
+          (*j)->opcode() != IrOpcode::kDeoptimize) {
+        TraceConnect(merge, predecessor_block, block);
+        schedule_->AddGoto(predecessor_block, block);
+      }
+    }
+  }
+
+  void ConnectDeoptimize(Node* deopt) {
+    Node* deopt_block_node = NodeProperties::GetControlInput(deopt);
+    BasicBlock* deopt_block = schedule_->block(deopt_block_node);
+    TraceConnect(deopt, deopt_block, NULL);
+    schedule_->AddDeoptimize(deopt_block, deopt);
+  }
+
+  void ConnectReturn(Node* ret) {
+    Node* return_block_node = NodeProperties::GetControlInput(ret);
+    BasicBlock* return_block = schedule_->block(return_block_node);
+    TraceConnect(ret, return_block, NULL);
+    schedule_->AddReturn(return_block, ret);
+  }
+
+  void ConnectCall(Node* call) {
+    Node* call_block_node = NodeProperties::GetControlInput(call);
+    BasicBlock* call_block = schedule_->block(call_block_node);
+
+    BasicBlock* successor_blocks[2];
+    CollectSuccessorBlocks(call, successor_blocks, IrOpcode::kContinuation,
+                           IrOpcode::kLazyDeoptimization);
+
+    TraceConnect(call, call_block, successor_blocks[0]);
+    TraceConnect(call, call_block, successor_blocks[1]);
+
+    schedule_->AddCall(call_block, call, successor_blocks[0],
+                       successor_blocks[1]);
+  }
+
+  void TraceConnect(Node* node, BasicBlock* block, BasicBlock* succ) {
+    DCHECK_NE(NULL, block);
+    if (succ == NULL) {
+      Trace("node %d (%s) in block %d -> end\n", node->id(),
+            IrOpcode::Mnemonic(node->opcode()), block->id());
+    } else {
+      Trace("node %d (%s) in block %d -> block %d\n", node->id(),
+            IrOpcode::Mnemonic(node->opcode()), block->id(), succ->id());
+    }
+  }
+};
+
+
 Scheduler::Scheduler(Zone* zone, Graph* graph, Schedule* schedule)
     : zone_(zone),
       graph_(graph),
       schedule_(schedule),
-      branches_(NodeVector::allocator_type(zone)),
-      calls_(NodeVector::allocator_type(zone)),
-      deopts_(NodeVector::allocator_type(zone)),
-      returns_(NodeVector::allocator_type(zone)),
-      loops_and_merges_(NodeVector::allocator_type(zone)),
       unscheduled_uses_(IntVector::allocator_type(zone)),
       scheduled_nodes_(NodeVectorVector::allocator_type(zone)),
       schedule_root_nodes_(NodeVector::allocator_type(zone)),
@@ -33,13 +216,13 @@
 Schedule* Scheduler::ComputeSchedule(Graph* graph) {
   Zone tmp_zone(graph->zone()->isolate());
   Schedule* schedule = new (graph->zone()) Schedule(graph->zone());
+
+  Scheduler::ComputeCFG(graph, schedule);
+
   Scheduler scheduler(&tmp_zone, graph, schedule);

-  schedule->AddNode(schedule->end(), graph->end());
-
   scheduler.PrepareAuxiliaryNodeData();
-  scheduler.CreateBlocks();
-  scheduler.WireBlocks();
+
   scheduler.PrepareAuxiliaryBlockData();

   Scheduler::ComputeSpecialRPO(schedule);
@@ -56,9 +239,6 @@
 bool Scheduler::IsBasicBlockBegin(Node* node) {
   return OperatorProperties::IsBasicBlockBegin(node->op());
 }
-
-
-bool Scheduler::CanBeScheduled(Node* node) { return true; }


 bool Scheduler::HasFixedSchedulePosition(Node* node) {
@@ -76,77 +256,12 @@
 }


-class CreateBlockVisitor : public NullNodeVisitor {
- public:
- explicit CreateBlockVisitor(Scheduler* scheduler) : scheduler_(scheduler) {}
-
-  GenericGraphVisit::Control Post(Node* node) {
-    Schedule* schedule = scheduler_->schedule_;
-    switch (node->opcode()) {
-      case IrOpcode::kIfTrue:
-      case IrOpcode::kIfFalse:
-      case IrOpcode::kContinuation:
-      case IrOpcode::kLazyDeoptimization: {
-        BasicBlock* block = schedule->NewBasicBlock();
-        schedule->AddNode(block, node);
-        break;
-      }
-      case IrOpcode::kLoop:
-      case IrOpcode::kMerge: {
-        BasicBlock* block = schedule->NewBasicBlock();
-        schedule->AddNode(block, node);
-        scheduler_->loops_and_merges_.push_back(node);
-        break;
-      }
-      case IrOpcode::kBranch: {
-        scheduler_->branches_.push_back(node);
-        break;
-      }
-      case IrOpcode::kDeoptimize: {
-        scheduler_->deopts_.push_back(node);
-        break;
-      }
-      case IrOpcode::kCall: {
-        if (OperatorProperties::CanLazilyDeoptimize(node->op())) {
-          scheduler_->calls_.push_back(node);
-        }
-        break;
-      }
-      case IrOpcode::kReturn:
-        scheduler_->returns_.push_back(node);
-        break;
-      default:
-        break;
-    }
-
-    return GenericGraphVisit::CONTINUE;
-  }
-
- private:
-  Scheduler* scheduler_;
-};
-
-
-void Scheduler::CreateBlocks() {
-  CreateBlockVisitor create_blocks(this);
-  if (FLAG_trace_turbo_scheduler) {
-    PrintF("---------------- CREATING BLOCKS ------------------\n");
-  }
-  schedule_->AddNode(schedule_->start(), graph_->start());
-  graph_->VisitNodeInputsFromEnd(&create_blocks);
-}
-
-
-void Scheduler::WireBlocks() {
-  if (FLAG_trace_turbo_scheduler) {
-    PrintF("----------------- WIRING BLOCKS -------------------\n");
-  }
-  AddSuccessorsForBranches();
-  AddSuccessorsForReturns();
-  AddSuccessorsForCalls();
-  AddSuccessorsForDeopts();
-  AddPredecessorsForLoopsAndMerges();
-  // TODO(danno): Handle Throw, et al.
+void Scheduler::ComputeCFG(Graph* graph, Schedule* schedule) {
+  CFGBuilder cfg_builder(schedule);
+  Trace("---------------- CREATING CFG ------------------\n");
+  schedule->AddNode(schedule->start(), graph->start());
+  graph->VisitNodeInputsFromEnd(&cfg_builder);
+  schedule->AddNode(schedule->end(), graph->end());
 }


@@ -162,151 +277,6 @@
                           NodeVector(NodeVector::allocator_type(zone)));
schedule_->immediate_dominator_.resize(schedule_->BasicBlockCount(), NULL);
 }
-
-
-void Scheduler::AddPredecessorsForLoopsAndMerges() {
-  for (NodeVectorIter i = loops_and_merges_.begin();
-       i != loops_and_merges_.end(); ++i) {
-    Node* merge_or_loop = *i;
-    BasicBlock* block = schedule_->block(merge_or_loop);
-    DCHECK(block != NULL);
-    // For all of the merge's control inputs, add a goto at the end to the
-    // merge's basic block.
- for (InputIter j = (*i)->inputs().begin(); j != (*i)->inputs().end(); ++j) {
-      if (IsBasicBlockBegin((*i))) {
-        BasicBlock* predecessor_block = schedule_->block(*j);
-        if ((*j)->opcode() != IrOpcode::kReturn &&
-            (*j)->opcode() != IrOpcode::kDeoptimize) {
-          DCHECK(predecessor_block != NULL);
-          if (FLAG_trace_turbo_scheduler) {
-            IrOpcode::Value opcode = (*i)->opcode();
-            PrintF("node %d (%s) in block %d -> block %d\n", (*i)->id(),
-                   IrOpcode::Mnemonic(opcode), predecessor_block->id(),
-                   block->id());
-          }
-          schedule_->AddGoto(predecessor_block, block);
-        }
-      }
-    }
-  }
-}
-
-
-void Scheduler::AddSuccessorsForCalls() {
-  for (NodeVectorIter i = calls_.begin(); i != calls_.end(); ++i) {
-    Node* call = *i;
-    DCHECK(call->opcode() == IrOpcode::kCall);
-    DCHECK(OperatorProperties::CanLazilyDeoptimize(call->op()));
-
-    Node* lazy_deopt_node = NULL;
-    Node* cont_node = NULL;
-    // Find the continuation and lazy-deopt nodes among the uses.
-    for (UseIter use_iter = call->uses().begin();
-         use_iter != call->uses().end(); ++use_iter) {
-      switch ((*use_iter)->opcode()) {
-        case IrOpcode::kContinuation: {
-          DCHECK(cont_node == NULL);
-          cont_node = *use_iter;
-          break;
-        }
-        case IrOpcode::kLazyDeoptimization: {
-          DCHECK(lazy_deopt_node == NULL);
-          lazy_deopt_node = *use_iter;
-          break;
-        }
-        default:
-          break;
-      }
-    }
-    DCHECK(lazy_deopt_node != NULL);
-    DCHECK(cont_node != NULL);
-    BasicBlock* cont_successor_block = schedule_->block(cont_node);
-    BasicBlock* deopt_successor_block = schedule_->block(lazy_deopt_node);
-    Node* call_block_node = NodeProperties::GetControlInput(call);
-    BasicBlock* call_block = schedule_->block(call_block_node);
-    if (FLAG_trace_turbo_scheduler) {
-      IrOpcode::Value opcode = call->opcode();
-      PrintF("node %d (%s) in block %d -> block %d\n", call->id(),
-             IrOpcode::Mnemonic(opcode), call_block->id(),
-             cont_successor_block->id());
-      PrintF("node %d (%s) in block %d -> block %d\n", call->id(),
-             IrOpcode::Mnemonic(opcode), call_block->id(),
-             deopt_successor_block->id());
-    }
-    schedule_->AddCall(call_block, call, cont_successor_block,
-                       deopt_successor_block);
-  }
-}
-
-
-void Scheduler::AddSuccessorsForDeopts() {
-  for (NodeVectorIter i = deopts_.begin(); i != deopts_.end(); ++i) {
-    Node* deopt_block_node = NodeProperties::GetControlInput(*i);
-    BasicBlock* deopt_block = schedule_->block(deopt_block_node);
-    DCHECK(deopt_block != NULL);
-    if (FLAG_trace_turbo_scheduler) {
-      IrOpcode::Value opcode = (*i)->opcode();
-      PrintF("node %d (%s) in block %d -> end\n", (*i)->id(),
-             IrOpcode::Mnemonic(opcode), deopt_block->id());
-    }
-    schedule_->AddDeoptimize(deopt_block, *i);
-  }
-}
-
-
-void Scheduler::AddSuccessorsForBranches() {
-  for (NodeVectorIter i = branches_.begin(); i != branches_.end(); ++i) {
-    Node* branch = *i;
-    DCHECK(branch->opcode() == IrOpcode::kBranch);
-    Node* branch_block_node = NodeProperties::GetControlInput(branch);
-    BasicBlock* branch_block = schedule_->block(branch_block_node);
-    DCHECK(branch_block != NULL);
-    UseIter use_iter = branch->uses().begin();
-    Node* first_successor = *use_iter;
-    ++use_iter;
-    DCHECK(use_iter != branch->uses().end());
-    Node* second_successor = *use_iter;
-    DCHECK(++use_iter == branch->uses().end());
- Node* true_successor_node = first_successor->opcode() == IrOpcode::kIfTrue
-                                    ? first_successor
-                                    : second_successor;
- Node* false_successor_node = first_successor->opcode() == IrOpcode::kIfTrue
-                                     ? second_successor
-                                     : first_successor;
-    DCHECK(true_successor_node->opcode() == IrOpcode::kIfTrue);
-    DCHECK(false_successor_node->opcode() == IrOpcode::kIfFalse);
- BasicBlock* true_successor_block = schedule_->block(true_successor_node); - BasicBlock* false_successor_block = schedule_->block(false_successor_node);
-    DCHECK(true_successor_block != NULL);
-    DCHECK(false_successor_block != NULL);
-    if (FLAG_trace_turbo_scheduler) {
-      IrOpcode::Value opcode = branch->opcode();
-      PrintF("node %d (%s) in block %d -> block %d\n", branch->id(),
-             IrOpcode::Mnemonic(opcode), branch_block->id(),
-             true_successor_block->id());
-      PrintF("node %d (%s) in block %d -> block %d\n", branch->id(),
-             IrOpcode::Mnemonic(opcode), branch_block->id(),
-             false_successor_block->id());
-    }
-    schedule_->AddBranch(branch_block, branch, true_successor_block,
-                         false_successor_block);
-  }
-}
-
-
-void Scheduler::AddSuccessorsForReturns() {
-  for (NodeVectorIter i = returns_.begin(); i != returns_.end(); ++i) {
-    Node* return_block_node = NodeProperties::GetControlInput(*i);
-    BasicBlock* return_block = schedule_->block(return_block_node);
-    DCHECK(return_block != NULL);
-    if (FLAG_trace_turbo_scheduler) {
-      IrOpcode::Value opcode = (*i)->opcode();
-      PrintF("node %d (%s) in block %d -> end\n", (*i)->id(),
-             IrOpcode::Mnemonic(opcode), return_block->id());
-    }
-    schedule_->AddReturn(return_block, *i);
-  }
-}


 BasicBlock* Scheduler::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) {
@@ -327,9 +297,7 @@
 void Scheduler::GenerateImmediateDominatorTree() {
// Build the dominator graph. TODO(danno): consider using Lengauer & Tarjan's
   // if this becomes really slow.
-  if (FLAG_trace_turbo_scheduler) {
-    PrintF("------------ IMMEDIATE BLOCK DOMINATORS -----------\n");
-  }
+  Trace("------------ IMMEDIATE BLOCK DOMINATORS -----------\n");
   for (size_t i = 0; i < schedule_->rpo_order_.size(); i++) {
     BasicBlock* current_rpo = schedule_->rpo_order_[i];
     if (current_rpo != schedule_->start()) {
@@ -352,9 +320,7 @@
         ++current_pred;
       }
       schedule_->immediate_dominator_[current_rpo->id()] = dominator;
-      if (FLAG_trace_turbo_scheduler) {
- PrintF("Block %d's idom is %d\n", current_rpo->id(), dominator->id());
-      }
+      Trace("Block %d's idom is %d\n", current_rpo->id(), dominator->id());
     }
   }
 }
@@ -371,7 +337,7 @@
     int id = node->id();
     int max_rpo = 0;
     // Fixed nodes already know their schedule early position.
-    if (IsFixedNode(node)) {
+    if (scheduler_->HasFixedSchedulePosition(node)) {
       BasicBlock* block = schedule_->block(node);
       DCHECK(block != NULL);
       max_rpo = block->rpo_number_;
@@ -379,9 +345,7 @@
         has_changed_rpo_constraints_ = true;
       }
       scheduler_->schedule_early_rpo_index_[id] = max_rpo;
-      if (FLAG_trace_turbo_scheduler) {
- PrintF("Node %d pre-scheduled early at rpo limit %d\n", id, max_rpo);
-      }
+      Trace("Node %d pre-scheduled early at rpo limit %d\n", id, max_rpo);
     }
     return GenericGraphVisit::CONTINUE;
   }
@@ -390,8 +354,7 @@
     int id = node->id();
     int max_rpo = 0;
// Otherwise, the minimum rpo for the node is the max of all of the inputs.
-    if (!IsFixedNode(node)) {
-      DCHECK(!scheduler_->IsBasicBlockBegin(node));
+    if (!scheduler_->HasFixedSchedulePosition(node)) {
       for (InputIter i = node->inputs().begin(); i != node->inputs().end();
            ++i) {
int control_rpo = scheduler_->schedule_early_rpo_index_[(*i)->id()];
@@ -403,17 +366,10 @@
         has_changed_rpo_constraints_ = true;
       }
       scheduler_->schedule_early_rpo_index_[id] = max_rpo;
-      if (FLAG_trace_turbo_scheduler) {
- PrintF("Node %d post-scheduled early at rpo limit %d\n", id, max_rpo);
-      }
+      Trace("Node %d post-scheduled early at rpo limit %d\n", id, max_rpo);
     }
     return GenericGraphVisit::CONTINUE;
   }
-
-  bool IsFixedNode(Node* node) {
-    return scheduler_->HasFixedSchedulePosition(node) ||
-           !scheduler_->CanBeScheduled(node);
-  }

// TODO(mstarzinger): Dirty hack to unblock others, schedule early should be
   // rewritten to use a pre-order traversal from the start instead.
@@ -426,9 +382,7 @@


 void Scheduler::ScheduleEarly() {
-  if (FLAG_trace_turbo_scheduler) {
-    PrintF("------------------- SCHEDULE EARLY ----------------\n");
-  }
+  Trace("------------------- SCHEDULE EARLY ----------------\n");

   int fixpoint_count = 0;
   ScheduleEarlyNodeVisitor visitor(this);
@@ -438,9 +392,7 @@
     fixpoint_count++;
   }

-  if (FLAG_trace_turbo_scheduler) {
- PrintF("It took %d iterations to determine fixpoint\n", fixpoint_count);
-  }
+  Trace("It took %d iterations to determine fixpoint\n", fixpoint_count);
 }


@@ -455,10 +407,8 @@
     // to schedule them.
     if (!schedule_->IsScheduled(node) &&
         scheduler_->HasFixedSchedulePosition(node)) {
-      if (FLAG_trace_turbo_scheduler) {
-        PrintF("Fixed position node %d is unscheduled, scheduling now\n",
-               node->id());
-      }
+      Trace("Fixed position node %d is unscheduled, scheduling now\n",
+            node->id());
       IrOpcode::Value opcode = node->opcode();
       BasicBlock* block =
           opcode == IrOpcode::kParameter
@@ -479,13 +429,11 @@
// If the edge is from an unscheduled node, then tally it in the use count // for all of its inputs. The same criterion will be used in ScheduleLate
     // for decrementing use counts.
- if (!schedule_->IsScheduled(from) && scheduler_->CanBeScheduled(from)) {
+    if (!schedule_->IsScheduled(from)) {
       DCHECK(!scheduler_->HasFixedSchedulePosition(from));
       ++scheduler_->unscheduled_uses_[to->id()];
-      if (FLAG_trace_turbo_scheduler) {
-        PrintF("Incrementing uses of node %d from %d to %d\n", to->id(),
-               from->id(), scheduler_->unscheduled_uses_[to->id()]);
-      }
+      Trace("Incrementing uses of node %d from %d to %d\n", to->id(),
+            from->id(), scheduler_->unscheduled_uses_[to->id()]);
     }
   }

@@ -496,9 +444,7 @@


 void Scheduler::PrepareUses() {
-  if (FLAG_trace_turbo_scheduler) {
-    PrintF("------------------- PREPARE USES ------------------\n");
-  }
+  Trace("------------------- PREPARE USES ------------------\n");
   // Count the uses of every node, it will be used to ensure that all of a
   // node's uses are scheduled before the node itself.
   PrepareUsesVisitor prepare_uses(this);
@@ -512,8 +458,8 @@
       : scheduler_(scheduler), schedule_(scheduler_->schedule_) {}

   GenericGraphVisit::Control Pre(Node* node) {
- // Don't schedule nodes that cannot be scheduled or are already scheduled. - if (!scheduler_->CanBeScheduled(node) || schedule_->IsScheduled(node)) {
+    // Don't schedule nodes that are already scheduled.
+    if (schedule_->IsScheduled(node)) {
       return GenericGraphVisit::CONTINUE;
     }
     DCHECK(!scheduler_->HasFixedSchedulePosition(node));
@@ -521,10 +467,8 @@
// If all the uses of a node have been scheduled, then the node itself can
     // be scheduled.
     bool eligible = scheduler_->unscheduled_uses_[node->id()] == 0;
-    if (FLAG_trace_turbo_scheduler) {
- PrintF("Testing for schedule eligibility for node %d -> %s\n", node->id(),
-             eligible ? "true" : "false");
-    }
+ Trace("Testing for schedule eligibility for node %d -> %s\n", node->id(),
+          eligible ? "true" : "false");
     if (!eligible) return GenericGraphVisit::DEFER;

// Determine the dominating block for all of the uses of this node. It is
@@ -541,12 +485,10 @@
     DCHECK(block != NULL);

     int min_rpo = scheduler_->schedule_early_rpo_index_[node->id()];
-    if (FLAG_trace_turbo_scheduler) {
-      PrintF(
-          "Schedule late conservative for node %d is block %d at "
-          "loop depth %d, min rpo = %d\n",
-          node->id(), block->id(), block->loop_depth_, min_rpo);
-    }
+    Trace(
+        "Schedule late conservative for node %d is block %d at "
+        "loop depth %d, min rpo = %d\n",
+        node->id(), block->id(), block->loop_depth_, min_rpo);
// Hoist nodes out of loops if possible. Nodes can be hoisted iteratively
     // into enlcosing loop pre-headers until they would preceed their
     // ScheduleEarly position.
@@ -554,9 +496,7 @@
     while (hoist_block != NULL && hoist_block->rpo_number_ >= min_rpo) {
       if (hoist_block->loop_depth_ < block->loop_depth_) {
         block = hoist_block;
-        if (FLAG_trace_turbo_scheduler) {
- PrintF("Hoisting node %d to block %d\n", node->id(), block->id());
-        }
+        Trace("Hoisting node %d to block %d\n", node->id(), block->id());
       }
       // Try to hoist to the pre-header of the loop header.
       hoist_block = hoist_block->loop_header();
@@ -564,12 +504,10 @@
         BasicBlock* pre_header = schedule_->dominator(hoist_block);
         DCHECK(pre_header == NULL ||
                *hoist_block->predecessors().begin() == pre_header);
-        if (FLAG_trace_turbo_scheduler) {
-          PrintF(
-              "Try hoist to pre-header block %d of loop header block %d,"
-              " depth would be %d\n",
- pre_header->id(), hoist_block->id(), pre_header->loop_depth_);
-        }
+        Trace(
+            "Try hoist to pre-header block %d of loop header block %d,"
+            " depth would be %d\n",
+            pre_header->id(), hoist_block->id(), pre_header->loop_depth_);
         hoist_block = pre_header;
       }
     }
@@ -587,9 +525,7 @@
     // corresponding to the phi's input.
     if (opcode == IrOpcode::kPhi || opcode == IrOpcode::kEffectPhi) {
       int index = edge.index();
-      if (FLAG_trace_turbo_scheduler) {
-        PrintF("Use %d is input %d to a phi\n", use->id(), index);
-      }
+      Trace("Use %d is input %d to a phi\n", use->id(), index);
       use = NodeProperties::GetControlInput(use, 0);
       opcode = use->opcode();
       DCHECK(opcode == IrOpcode::kMerge || opcode == IrOpcode::kLoop);
@@ -597,9 +533,7 @@
     }
     BasicBlock* result = schedule_->block(use);
     if (result == NULL) return NULL;
-    if (FLAG_trace_turbo_scheduler) {
- PrintF("Must dominate use %d in block %d\n", use->id(), result->id());
-    }
+    Trace("Must dominate use %d in block %d\n", use->id(), result->id());
     return result;
   }

@@ -613,11 +547,11 @@
       DCHECK(scheduler_->unscheduled_uses_[(*i)->id()] > 0);
       --scheduler_->unscheduled_uses_[(*i)->id()];
       if (FLAG_trace_turbo_scheduler) {
- PrintF("Decrementing use count for node %d from node %d (now %d)\n",
-               (*i)->id(), i.edge().from()->id(),
-               scheduler_->unscheduled_uses_[(*i)->id()]);
+        Trace("Decrementing use count for node %d from node %d (now %d)\n",
+              (*i)->id(), i.edge().from()->id(),
+              scheduler_->unscheduled_uses_[(*i)->id()]);
         if (scheduler_->unscheduled_uses_[(*i)->id()] == 0) {
-          PrintF("node %d is now eligible for scheduling\n", (*i)->id());
+          Trace("node %d is now eligible for scheduling\n", (*i)->id());
         }
       }
     }
@@ -629,9 +563,7 @@


 void Scheduler::ScheduleLate() {
-  if (FLAG_trace_turbo_scheduler) {
-    PrintF("------------------- SCHEDULE LATE -----------------\n");
-  }
+  Trace("------------------- SCHEDULE LATE -----------------\n");

   // Schedule: Places nodes in dominator block of all their uses.
   ScheduleLateNodeVisitor schedule_late_visitor(this);
@@ -865,9 +797,7 @@
 BasicBlockVector* Scheduler::ComputeSpecialRPO(Schedule* schedule) {
   Zone tmp_zone(schedule->zone()->isolate());
   Zone* zone = &tmp_zone;
-  if (FLAG_trace_turbo_scheduler) {
-    PrintF("------------- COMPUTING SPECIAL RPO ---------------\n");
-  }
+  Trace("------------- COMPUTING SPECIAL RPO ---------------\n");
   // RPO should not have been computed for this schedule yet.
   CHECK_EQ(kBlockUnvisited1, schedule->start()->rpo_number_);
   CHECK_EQ(0, static_cast<int>(schedule->rpo_order_.size()));
@@ -1027,10 +957,8 @@
current->loop_end_ = end == NULL ? static_cast<int>(final_order->size())
                                        : end->block->rpo_number_;
       current_header = current_loop->header;
-      if (FLAG_trace_turbo_scheduler) {
-        PrintF("Block %d is a loop header, increment loop depth to %d\n",
-               current->id(), loop_depth);
-      }
+      Trace("Block %d is a loop header, increment loop depth to %d\n",
+            current->id(), loop_depth);
     } else {
       while (current_header != NULL &&
              current->rpo_number_ >= current_header->loop_end_) {
@@ -1042,16 +970,9 @@
       }
     }
     current->loop_depth_ = loop_depth;
-    if (FLAG_trace_turbo_scheduler) {
-      if (current->loop_header_ == NULL) {
- PrintF("Block %d's loop header is NULL, loop depth %d\n", current->id(),
-               current->loop_depth_);
-      } else {
-        PrintF("Block %d's loop header is block %d, loop depth %d\n",
-               current->id(), current->loop_header_->id(),
-               current->loop_depth_);
-      }
-    }
+ Trace("Block %d's loop header is block %d, loop depth %d\n", current->id(),
+          current->loop_header_ == NULL ? -1 : current->loop_header_->id(),
+          current->loop_depth_);
   }

 #if DEBUG
=======================================
--- /trunk/src/compiler/scheduler.h     Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/compiler/scheduler.h     Thu Aug 21 07:23:04 2014 UTC
@@ -22,21 +22,21 @@
 // ordering the basic blocks in the special RPO order.
 class Scheduler {
  public:
-  // Create a new schedule and place all computations from the graph in it.
+  // The complete scheduling algorithm.
+  // Create a new schedule and place all nodes from the graph into it.
   static Schedule* ComputeSchedule(Graph* graph);

   // Compute the RPO of blocks in an existing schedule.
   static BasicBlockVector* ComputeSpecialRPO(Schedule* schedule);

+  // (Exposed for testing only)
+  // Build and connect the CFG for a node graph, but don't schedule nodes.
+  static void ComputeCFG(Graph* graph, Schedule* schedule);
+
  private:
   Zone* zone_;
   Graph* graph_;
   Schedule* schedule_;
-  NodeVector branches_;
-  NodeVector calls_;
-  NodeVector deopts_;
-  NodeVector returns_;
-  NodeVector loops_and_merges_;
   IntVector unscheduled_uses_;
   NodeVectorVector scheduled_nodes_;
   NodeVector schedule_root_nodes_;
@@ -45,7 +45,6 @@
   Scheduler(Zone* zone, Graph* graph, Schedule* schedule);

   bool IsBasicBlockBegin(Node* node);
-  bool CanBeScheduled(Node* node);
   bool HasFixedSchedulePosition(Node* node);
   bool IsScheduleRoot(Node* node);

@@ -59,17 +58,6 @@
   void PrepareAuxiliaryNodeData();
   void PrepareAuxiliaryBlockData();

-  friend class CreateBlockVisitor;
-  void CreateBlocks();
-
-  void WireBlocks();
-
-  void AddPredecessorsForLoopsAndMerges();
-  void AddSuccessorsForBranches();
-  void AddSuccessorsForReturns();
-  void AddSuccessorsForCalls();
-  void AddSuccessorsForDeopts();
-
   void GenerateImmediateDominatorTree();
   BasicBlock* GetCommonDominator(BasicBlock* b1, BasicBlock* b2);

=======================================
--- /trunk/src/data-flow.cc     Wed Jun  4 00:06:13 2014 UTC
+++ /trunk/src/data-flow.cc     Thu Aug 21 07:23:04 2014 UTC
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.

-#include "src/v8.h"
+#include "src/data-flow.h"

-#include "src/data-flow.h"
+#include "src/base/bits.h"
 #include "src/scopes.h"

 namespace v8 {
@@ -40,4 +40,15 @@
   current_value_ = val >> 1;
 }

-} }  // namespace v8::internal
+
+int BitVector::Count() const {
+  int count = 0;
+  for (int i = 0; i < data_length_; i++) {
+    int data = data_[i];
+    if (data != 0) count += base::bits::CountSetBits32(data);
+  }
+  return count;
+}
+
+}  // namespace internal
+}  // namespace v8
=======================================
--- /trunk/src/data-flow.h      Tue Aug  5 00:05:55 2014 UTC
+++ /trunk/src/data-flow.h      Thu Aug 21 07:23:04 2014 UTC
@@ -164,14 +164,7 @@
     return true;
   }

-  int Count() const {
-    int count = 0;
-    for (int i = 0; i < data_length_; i++) {
-      int data = data_[i];
-      if (data != 0) count += CompilerIntrinsics::CountSetBits(data);
-    }
-    return count;
-  }
+  int Count() const;

   int length() const { return length_; }

@@ -185,6 +178,7 @@
   uint32_t* data_;
 };

+
 class GrowableBitVector BASE_EMBEDDED {
  public:
   class Iterator BASE_EMBEDDED {
@@ -241,8 +235,7 @@
   BitVector* bits_;
 };

-
-} }  // namespace v8::internal
-
+}  // namespace internal
+}  // namespace v8

 #endif  // V8_DATAFLOW_H_
=======================================
--- /trunk/src/elements.cc      Wed Aug  6 00:06:29 2014 UTC
+++ /trunk/src/elements.cc      Thu Aug 21 07:23:04 2014 UTC
@@ -652,28 +652,6 @@
         Handle<BackingStore>::cast(backing_store)->is_the_hole(key)
           ? ABSENT : NONE;
   }
-
-  MUST_USE_RESULT virtual PropertyType GetType(
-      Handle<Object> receiver,
-      Handle<JSObject> holder,
-      uint32_t key,
-      Handle<FixedArrayBase> backing_store) V8_FINAL V8_OVERRIDE {
-    return ElementsAccessorSubclass::GetTypeImpl(
-        receiver, holder, key, backing_store);
-  }
-
-  MUST_USE_RESULT static PropertyType GetTypeImpl(
-      Handle<Object> receiver,
-      Handle<JSObject> obj,
-      uint32_t key,
-      Handle<FixedArrayBase> backing_store) {
-    if (key >= ElementsAccessorSubclass::GetCapacityImpl(backing_store)) {
-      return NONEXISTENT;
-    }
-    return
-        Handle<BackingStore>::cast(backing_store)->is_the_hole(key)
-          ? NONEXISTENT : FIELD;
-  }

   MUST_USE_RESULT virtual MaybeHandle<AccessorPair> GetAccessorPair(
       Handle<Object> receiver,
@@ -1309,16 +1287,6 @@
         key < AccessorClass::GetCapacityImpl(backing_store)
           ? NONE : ABSENT;
   }
-
-  MUST_USE_RESULT static PropertyType GetTypeImpl(
-      Handle<Object> receiver,
-      Handle<JSObject> obj,
-      uint32_t key,
-      Handle<FixedArrayBase> backing_store) {
-    return
-        key < AccessorClass::GetCapacityImpl(backing_store)
-          ? FIELD : NONEXISTENT;
-  }

   MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl(
       Handle<JSObject> obj,
@@ -1529,20 +1497,6 @@
     }
     return ABSENT;
   }
-
-  MUST_USE_RESULT static PropertyType GetTypeImpl(
-      Handle<Object> receiver,
-      Handle<JSObject> obj,
-      uint32_t key,
-      Handle<FixedArrayBase> store) {
-    Handle<SeededNumberDictionary> backing_store =
-        Handle<SeededNumberDictionary>::cast(store);
-    int entry = backing_store->FindEntry(key);
-    if (entry != SeededNumberDictionary::kNotFound) {
-      return backing_store->DetailsAt(entry).type();
-    }
-    return NONEXISTENT;
-  }

   MUST_USE_RESULT static MaybeHandle<AccessorPair> GetAccessorPairImpl(
       Handle<Object> receiver,
@@ -1647,23 +1601,6 @@
           receiver, obj, key, arguments);
     }
   }
-
-  MUST_USE_RESULT static PropertyType GetTypeImpl(
-      Handle<Object> receiver,
-      Handle<JSObject> obj,
-      uint32_t key,
-      Handle<FixedArrayBase> parameters) {
- Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
-    Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key);
-    if (!probe->IsTheHole()) {
-      return FIELD;
-    } else {
-      // If not aliased, check the arguments.
- Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
-      return ElementsAccessor::ForArray(arguments)->GetType(
-          receiver, obj, key, arguments);
-    }
-  }

   MUST_USE_RESULT static MaybeHandle<AccessorPair> GetAccessorPairImpl(
       Handle<Object> receiver,
=======================================
***Additional files exist in this changeset.***

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to