Revision: 23989
Author:   [email protected]
Date:     Wed Sep 17 00:05:08 2014 UTC
Log:      Version 3.29.70 (based on bleeding_edge revision r23986)

Enable ES6 generators (issue 2355).

Fixed int vs. uintptr_t confusion (plus some cleanup on the way) (issue 3556).

Move configuration of ResourceConstraints to Isolate construction.

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

Added:
 /trunk/src/ic/ic-state.cc
 /trunk/src/ic/ic-state.h
 /trunk/test/mjsunit/regress/regress-3564.js
Modified:
 /trunk/BUILD.gn
 /trunk/ChangeLog
 /trunk/include/v8.h
 /trunk/src/api.cc
 /trunk/src/arm/code-stubs-arm.cc
 /trunk/src/arm/full-codegen-arm.cc
 /trunk/src/arm/lithium-arm.cc
 /trunk/src/arm/lithium-codegen-arm.cc
 /trunk/src/arm64/code-stubs-arm64.cc
 /trunk/src/arm64/full-codegen-arm64.cc
 /trunk/src/arm64/lithium-codegen-arm64.cc
 /trunk/src/arm64/macro-assembler-arm64.cc
 /trunk/src/arm64/macro-assembler-arm64.h
 /trunk/src/assembler.cc
 /trunk/src/bootstrapper.cc
 /trunk/src/code-factory.cc
 /trunk/src/code-stubs-hydrogen.cc
 /trunk/src/code-stubs.cc
 /trunk/src/code-stubs.h
 /trunk/src/codegen.cc
 /trunk/src/compiler/ast-graph-builder.cc
 /trunk/src/compiler/change-lowering-unittest.cc
 /trunk/src/compiler/change-lowering.cc
 /trunk/src/compiler/change-lowering.h
 /trunk/src/compiler/js-typed-lowering.cc
 /trunk/src/compiler/js-typed-lowering.h
 /trunk/src/compiler/machine-operator-reducer.cc
 /trunk/src/compiler/machine-operator-reducer.h
 /trunk/src/compiler/pipeline.cc
 /trunk/src/compiler/representation-change.h
 /trunk/src/compiler/simplified-lowering.cc
 /trunk/src/compiler/simplified-lowering.h
 /trunk/src/compiler/simplified-operator-reducer-unittest.cc
 /trunk/src/compiler/simplified-operator-reducer.cc
 /trunk/src/compiler/simplified-operator-reducer.h
 /trunk/src/counters.h
 /trunk/src/d8.cc
 /trunk/src/disassembler.cc
 /trunk/src/flag-definitions.h
 /trunk/src/full-codegen.h
 /trunk/src/heap/gc-idle-time-handler-unittest.cc
 /trunk/src/heap/gc-idle-time-handler.cc
 /trunk/src/heap/gc-idle-time-handler.h
 /trunk/src/heap/heap.cc
 /trunk/src/heap/incremental-marking.cc
 /trunk/src/heap/incremental-marking.h
 /trunk/src/heap/mark-compact.cc
 /trunk/src/heap/objects-visiting-inl.h
 /trunk/src/heap/spaces.h
 /trunk/src/hydrogen.cc
 /trunk/src/hydrogen.h
 /trunk/src/ia32/code-stubs-ia32.cc
 /trunk/src/ia32/full-codegen-ia32.cc
 /trunk/src/ia32/lithium-codegen-ia32.cc
 /trunk/src/ia32/lithium-ia32.cc
 /trunk/src/ic/arm/handler-compiler-arm.cc
 /trunk/src/ic/arm/ic-compiler-arm.cc
 /trunk/src/ic/arm64/handler-compiler-arm64.cc
 /trunk/src/ic/arm64/ic-compiler-arm64.cc
 /trunk/src/ic/handler-compiler.cc
 /trunk/src/ic/handler-compiler.h
 /trunk/src/ic/ia32/handler-compiler-ia32.cc
 /trunk/src/ic/ia32/ic-compiler-ia32.cc
 /trunk/src/ic/ic-inl.h
 /trunk/src/ic/ic.cc
 /trunk/src/ic/ic.h
 /trunk/src/ic/mips/handler-compiler-mips.cc
 /trunk/src/ic/mips/ic-compiler-mips.cc
 /trunk/src/ic/mips64/handler-compiler-mips64.cc
 /trunk/src/ic/mips64/ic-compiler-mips64.cc
 /trunk/src/ic/x64/ic-compiler-x64.cc
 /trunk/src/jsregexp.cc
 /trunk/src/jsregexp.h
 /trunk/src/lookup-inl.h
 /trunk/src/lookup.cc
 /trunk/src/lookup.h
 /trunk/src/mips/code-stubs-mips.cc
 /trunk/src/mips/full-codegen-mips.cc
 /trunk/src/mips/lithium-codegen-mips.cc
 /trunk/src/mips/lithium-mips.cc
 /trunk/src/mips64/code-stubs-mips64.cc
 /trunk/src/mips64/full-codegen-mips64.cc
 /trunk/src/mips64/lithium-codegen-mips64.cc
 /trunk/src/mips64/lithium-mips64.cc
 /trunk/src/objects.cc
 /trunk/src/parser.cc
 /trunk/src/preparser.cc
 /trunk/src/preparser.h
 /trunk/src/runtime.cc
 /trunk/src/type-info.cc
 /trunk/src/types-inl.h
 /trunk/src/types.cc
 /trunk/src/types.h
 /trunk/src/version.cc
 /trunk/src/x64/code-stubs-x64.cc
 /trunk/src/x64/full-codegen-x64.cc
 /trunk/src/x64/lithium-codegen-x64.cc
 /trunk/src/x64/lithium-x64.cc
 /trunk/src/x87/lithium-x87.cc
 /trunk/test/cctest/compiler/test-changes-lowering.cc
 /trunk/test/cctest/compiler/test-js-typed-lowering.cc
 /trunk/test/cctest/compiler/test-representation-change.cc
 /trunk/test/cctest/test-api.cc
 /trunk/test/cctest/test-assembler-arm64.cc
 /trunk/test/cctest/test-parsing.cc
 /trunk/test/cctest/test-platform.cc
 /trunk/test/cctest/test-strings.cc
 /trunk/test/cctest/test-types.cc
 /trunk/test/mjsunit/debug-script.js
 /trunk/test/mjsunit/es6/generators-debug-liveedit.js
 /trunk/test/mjsunit/es6/generators-debug-scopes.js
 /trunk/test/mjsunit/es6/generators-iteration.js
 /trunk/test/mjsunit/es6/generators-objects.js
 /trunk/test/mjsunit/es6/generators-parsing.js
 /trunk/test/mjsunit/es6/generators-poisoned-properties.js
 /trunk/test/mjsunit/es6/generators-relocation.js
 /trunk/test/mjsunit/es6/generators-runtime.js
 /trunk/test/mjsunit/es6/iteration-semantics.js
 /trunk/test/mjsunit/es6/regress/regress-2681.js
 /trunk/test/mjsunit/es6/regress/regress-2691.js
 /trunk/test/mjsunit/es6/regress/regress-3280.js
 /trunk/test/mjsunit/mjsunit.status
 /trunk/test/mjsunit/regress/regress-crbug-357052.js
 /trunk/test/mjsunit/regress-3225.js
 /trunk/test/mjsunit/string-oom-concat.js
 /trunk/tools/gyp/v8.gyp

=======================================
--- /dev/null
+++ /trunk/src/ic/ic-state.cc   Wed Sep 17 00:05:08 2014 UTC
@@ -0,0 +1,614 @@
+// 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 "src/ic/ic.h"
+#include "src/ic/ic-state.h"
+
+namespace v8 {
+namespace internal {
+
+void ICUtility::Clear(Isolate* isolate, Address address,
+                      ConstantPoolArray* constant_pool) {
+  IC::Clear(isolate, address, constant_pool);
+}
+
+
+CallICState::CallICState(ExtraICState extra_ic_state)
+    : argc_(ArgcBits::decode(extra_ic_state)),
+      call_type_(CallTypeBits::decode(extra_ic_state)) {}
+
+
+ExtraICState CallICState::GetExtraICState() const {
+  ExtraICState extra_ic_state =
+      ArgcBits::encode(argc_) | CallTypeBits::encode(call_type_);
+  return extra_ic_state;
+}
+
+
+OStream& operator<<(OStream& os, const CallICState& s) {
+  return os << "(args(" << s.arg_count() << "), "
+ << (s.call_type() == CallICState::METHOD ? "METHOD" : "FUNCTION")
+            << ", ";
+}
+
+
+BinaryOpICState::BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state)
+    : isolate_(isolate) {
+  op_ =
+ static_cast<Token::Value>(FIRST_TOKEN + OpField::decode(extra_ic_state));
+  mode_ = OverwriteModeField::decode(extra_ic_state);
+  fixed_right_arg_ =
+      Maybe<int>(HasFixedRightArgField::decode(extra_ic_state),
+                 1 << FixedRightArgValueField::decode(extra_ic_state));
+  left_kind_ = LeftKindField::decode(extra_ic_state);
+  if (fixed_right_arg_.has_value) {
+    right_kind_ = Smi::IsValid(fixed_right_arg_.value) ? SMI : INT32;
+  } else {
+    right_kind_ = RightKindField::decode(extra_ic_state);
+  }
+  result_kind_ = ResultKindField::decode(extra_ic_state);
+  DCHECK_LE(FIRST_TOKEN, op_);
+  DCHECK_LE(op_, LAST_TOKEN);
+}
+
+
+ExtraICState BinaryOpICState::GetExtraICState() const {
+  ExtraICState extra_ic_state =
+ OpField::encode(op_ - FIRST_TOKEN) | OverwriteModeField::encode(mode_) |
+      LeftKindField::encode(left_kind_) |
+      ResultKindField::encode(result_kind_) |
+      HasFixedRightArgField::encode(fixed_right_arg_.has_value);
+  if (fixed_right_arg_.has_value) {
+    extra_ic_state = FixedRightArgValueField::update(
+        extra_ic_state, WhichPowerOf2(fixed_right_arg_.value));
+  } else {
+    extra_ic_state = RightKindField::update(extra_ic_state, right_kind_);
+  }
+  return extra_ic_state;
+}
+
+
+// static
+void BinaryOpICState::GenerateAheadOfTime(
+    Isolate* isolate, void (*Generate)(Isolate*, const BinaryOpICState&)) {
+// TODO(olivf) We should investigate why adding stubs to the snapshot is so
+// expensive at runtime. When solved we should be able to add most binops to
+// the snapshot instead of hand-picking them.
+// Generated list of commonly used stubs
+#define GENERATE(op, left_kind, right_kind, result_kind, mode) \
+  do {                                                         \
+    BinaryOpICState state(isolate, op, mode);                  \
+    state.left_kind_ = left_kind;                              \
+    state.fixed_right_arg_.has_value = false;                  \
+    state.right_kind_ = right_kind;                            \
+    state.result_kind_ = result_kind;                          \
+    Generate(isolate, state);                                  \
+  } while (false)
+  GENERATE(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE);
+  GENERATE(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::ADD, INT32, INT32, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::ADD, INT32, NUMBER, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::ADD, INT32, SMI, INT32, NO_OVERWRITE);
+  GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::ADD, NUMBER, INT32, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::ADD, NUMBER, SMI, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::ADD, SMI, INT32, INT32, NO_OVERWRITE);
+  GENERATE(Token::ADD, SMI, INT32, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::ADD, SMI, INT32, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::ADD, SMI, NUMBER, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::ADD, SMI, SMI, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::ADD, SMI, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_AND, INT32, INT32, INT32, NO_OVERWRITE);
+  GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_AND, INT32, INT32, SMI, NO_OVERWRITE);
+  GENERATE(Token::BIT_AND, INT32, INT32, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_AND, INT32, SMI, INT32, NO_OVERWRITE);
+  GENERATE(Token::BIT_AND, INT32, SMI, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_AND, INT32, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_AND, NUMBER, INT32, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_AND, SMI, INT32, INT32, NO_OVERWRITE);
+  GENERATE(Token::BIT_AND, SMI, INT32, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_AND, SMI, NUMBER, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_AND, SMI, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_OR, INT32, INT32, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_OR, INT32, SMI, INT32, NO_OVERWRITE);
+  GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_OR, INT32, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::BIT_OR, INT32, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, NO_OVERWRITE);
+  GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_OR, SMI, INT32, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_XOR, INT32, INT32, INT32, NO_OVERWRITE);
+  GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_XOR, INT32, INT32, SMI, NO_OVERWRITE);
+  GENERATE(Token::BIT_XOR, INT32, INT32, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_XOR, INT32, NUMBER, SMI, NO_OVERWRITE);
+  GENERATE(Token::BIT_XOR, INT32, SMI, INT32, NO_OVERWRITE);
+  GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::BIT_XOR, NUMBER, INT32, INT32, NO_OVERWRITE);
+  GENERATE(Token::BIT_XOR, NUMBER, SMI, INT32, NO_OVERWRITE);
+  GENERATE(Token::BIT_XOR, NUMBER, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::BIT_XOR, SMI, INT32, INT32, NO_OVERWRITE);
+  GENERATE(Token::BIT_XOR, SMI, INT32, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_XOR, SMI, INT32, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_XOR, SMI, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::DIV, INT32, INT32, INT32, NO_OVERWRITE);
+  GENERATE(Token::DIV, INT32, INT32, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::DIV, INT32, NUMBER, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::DIV, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::DIV, INT32, SMI, INT32, NO_OVERWRITE);
+  GENERATE(Token::DIV, INT32, SMI, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::DIV, NUMBER, INT32, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::DIV, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::DIV, NUMBER, SMI, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::DIV, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::DIV, SMI, INT32, INT32, NO_OVERWRITE);
+  GENERATE(Token::DIV, SMI, INT32, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::DIV, SMI, INT32, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::DIV, SMI, NUMBER, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::DIV, SMI, SMI, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::DIV, SMI, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::MOD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::MOD, SMI, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::MOD, SMI, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::MUL, INT32, INT32, INT32, NO_OVERWRITE);
+  GENERATE(Token::MUL, INT32, INT32, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::MUL, INT32, NUMBER, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::MUL, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::MUL, INT32, SMI, INT32, NO_OVERWRITE);
+  GENERATE(Token::MUL, INT32, SMI, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::MUL, INT32, SMI, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::MUL, NUMBER, INT32, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::MUL, NUMBER, SMI, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::MUL, SMI, INT32, INT32, NO_OVERWRITE);
+  GENERATE(Token::MUL, SMI, INT32, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::MUL, SMI, INT32, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::MUL, SMI, NUMBER, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::MUL, SMI, SMI, INT32, NO_OVERWRITE);
+  GENERATE(Token::MUL, SMI, SMI, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::MUL, SMI, SMI, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::MUL, SMI, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::SAR, INT32, SMI, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::SAR, INT32, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::SAR, INT32, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::SAR, NUMBER, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::SAR, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::SHL, INT32, SMI, INT32, NO_OVERWRITE);
+  GENERATE(Token::SHL, INT32, SMI, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::SHL, INT32, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::SHL, INT32, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::SHL, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::SHL, SMI, SMI, INT32, NO_OVERWRITE);
+  GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::SHL, SMI, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::SHR, INT32, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::SHR, NUMBER, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::SHR, NUMBER, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::SHR, NUMBER, SMI, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::SHR, SMI, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_RIGHT);
+  GENERATE(Token::SUB, INT32, INT32, INT32, NO_OVERWRITE);
+  GENERATE(Token::SUB, INT32, INT32, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::SUB, INT32, NUMBER, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::SUB, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_LEFT);
+  GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_RIGHT);
+  GENERATE(Token::SUB, NUMBER, INT32, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::SUB, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::SUB, NUMBER, SMI, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::SUB, SMI, INT32, INT32, NO_OVERWRITE);
+  GENERATE(Token::SUB, SMI, NUMBER, NUMBER, NO_OVERWRITE);
+  GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
+  GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
+  GENERATE(Token::SUB, SMI, SMI, SMI, NO_OVERWRITE);
+  GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_RIGHT);
+#undef GENERATE
+#define GENERATE(op, left_kind, fixed_right_arg_value, result_kind, mode) \
+  do {                                                                    \
+    BinaryOpICState state(isolate, op, mode);                             \
+    state.left_kind_ = left_kind;                                         \
+    state.fixed_right_arg_.has_value = true;                              \
+    state.fixed_right_arg_.value = fixed_right_arg_value;                 \
+    state.right_kind_ = SMI;                                              \
+    state.result_kind_ = result_kind;                                     \
+    Generate(isolate, state);                                             \
+  } while (false)
+  GENERATE(Token::MOD, SMI, 2, SMI, NO_OVERWRITE);
+  GENERATE(Token::MOD, SMI, 4, SMI, NO_OVERWRITE);
+  GENERATE(Token::MOD, SMI, 4, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::MOD, SMI, 8, SMI, NO_OVERWRITE);
+  GENERATE(Token::MOD, SMI, 16, SMI, OVERWRITE_LEFT);
+  GENERATE(Token::MOD, SMI, 32, SMI, NO_OVERWRITE);
+  GENERATE(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE);
+#undef GENERATE
+}
+
+
+Type* BinaryOpICState::GetResultType(Zone* zone) const {
+  Kind result_kind = result_kind_;
+  if (HasSideEffects()) {
+    result_kind = NONE;
+  } else if (result_kind == GENERIC && op_ == Token::ADD) {
+    return Type::Union(Type::Number(zone), Type::String(zone), zone);
+  } else if (result_kind == NUMBER && op_ == Token::SHR) {
+    return Type::Unsigned32(zone);
+  }
+  DCHECK_NE(GENERIC, result_kind);
+  return KindToType(result_kind, zone);
+}
+
+
+OStream& operator<<(OStream& os, const BinaryOpICState& s) {
+  os << "(" << Token::Name(s.op_);
+  if (s.mode_ == OVERWRITE_LEFT)
+    os << "_ReuseLeft";
+  else if (s.mode_ == OVERWRITE_RIGHT)
+    os << "_ReuseRight";
+  if (s.CouldCreateAllocationMementos()) os << "_CreateAllocationMementos";
+  os << ":" << BinaryOpICState::KindToString(s.left_kind_) << "*";
+  if (s.fixed_right_arg_.has_value) {
+    os << s.fixed_right_arg_.value;
+  } else {
+    os << BinaryOpICState::KindToString(s.right_kind_);
+  }
+ return os << "->" << BinaryOpICState::KindToString(s.result_kind_) << ")";
+}
+
+
+void BinaryOpICState::Update(Handle<Object> left, Handle<Object> right,
+                             Handle<Object> result) {
+  ExtraICState old_extra_ic_state = GetExtraICState();
+
+  left_kind_ = UpdateKind(left, left_kind_);
+  right_kind_ = UpdateKind(right, right_kind_);
+
+  int32_t fixed_right_arg_value = 0;
+  bool has_fixed_right_arg =
+      op_ == Token::MOD && right->ToInt32(&fixed_right_arg_value) &&
+      fixed_right_arg_value > 0 &&
+      base::bits::IsPowerOfTwo32(fixed_right_arg_value) &&
+ FixedRightArgValueField::is_valid(WhichPowerOf2(fixed_right_arg_value)) &&
+      (left_kind_ == SMI || left_kind_ == INT32) &&
+      (result_kind_ == NONE || !fixed_right_arg_.has_value);
+ fixed_right_arg_ = Maybe<int32_t>(has_fixed_right_arg, fixed_right_arg_value);
+
+  result_kind_ = UpdateKind(result, result_kind_);
+
+  if (!Token::IsTruncatingBinaryOp(op_)) {
+    Kind input_kind = Max(left_kind_, right_kind_);
+    if (result_kind_ < input_kind && input_kind <= NUMBER) {
+      result_kind_ = input_kind;
+    }
+  }
+
+  // We don't want to distinguish INT32 and NUMBER for string add (because
+  // NumberToString can't make use of this anyway).
+  if (left_kind_ == STRING && right_kind_ == INT32) {
+    DCHECK_EQ(STRING, result_kind_);
+    DCHECK_EQ(Token::ADD, op_);
+    right_kind_ = NUMBER;
+  } else if (right_kind_ == STRING && left_kind_ == INT32) {
+    DCHECK_EQ(STRING, result_kind_);
+    DCHECK_EQ(Token::ADD, op_);
+    left_kind_ = NUMBER;
+  }
+
+ // Reset overwrite mode unless we can actually make use of it, or may be able
+  // to make use of it at some point in the future.
+  if ((mode_ == OVERWRITE_LEFT && left_kind_ > NUMBER) ||
+      (mode_ == OVERWRITE_RIGHT && right_kind_ > NUMBER) ||
+      result_kind_ > NUMBER) {
+    mode_ = NO_OVERWRITE;
+  }
+
+  if (old_extra_ic_state == GetExtraICState()) {
+    // Tagged operations can lead to non-truncating HChanges
+    if (left->IsUndefined() || left->IsBoolean()) {
+      left_kind_ = GENERIC;
+    } else {
+      DCHECK(right->IsUndefined() || right->IsBoolean());
+      right_kind_ = GENERIC;
+    }
+  }
+}
+
+
+BinaryOpICState::Kind BinaryOpICState::UpdateKind(Handle<Object> object,
+                                                  Kind kind) const {
+  Kind new_kind = GENERIC;
+  bool is_truncating = Token::IsTruncatingBinaryOp(op());
+  if (object->IsBoolean() && is_truncating) {
+    // Booleans will be automatically truncated by HChange.
+    new_kind = INT32;
+  } else if (object->IsUndefined()) {
+    // Undefined will be automatically truncated by HChange.
+    new_kind = is_truncating ? INT32 : NUMBER;
+  } else if (object->IsSmi()) {
+    new_kind = SMI;
+  } else if (object->IsHeapNumber()) {
+    double value = Handle<HeapNumber>::cast(object)->value();
+    new_kind = IsInt32Double(value) ? INT32 : NUMBER;
+  } else if (object->IsString() && op() == Token::ADD) {
+    new_kind = STRING;
+  }
+  if (new_kind == INT32 && SmiValuesAre32Bits()) {
+    new_kind = NUMBER;
+  }
+  if (kind != NONE && ((new_kind <= NUMBER && kind > NUMBER) ||
+                       (new_kind > NUMBER && kind <= NUMBER))) {
+    new_kind = GENERIC;
+  }
+  return Max(kind, new_kind);
+}
+
+
+// static
+const char* BinaryOpICState::KindToString(Kind kind) {
+  switch (kind) {
+    case NONE:
+      return "None";
+    case SMI:
+      return "Smi";
+    case INT32:
+      return "Int32";
+    case NUMBER:
+      return "Number";
+    case STRING:
+      return "String";
+    case GENERIC:
+      return "Generic";
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+// static
+Type* BinaryOpICState::KindToType(Kind kind, Zone* zone) {
+  switch (kind) {
+    case NONE:
+      return Type::None(zone);
+    case SMI:
+      return Type::SignedSmall(zone);
+    case INT32:
+      return Type::Signed32(zone);
+    case NUMBER:
+      return Type::Number(zone);
+    case STRING:
+      return Type::String(zone);
+    case GENERIC:
+      return Type::Any(zone);
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+const char* CompareICState::GetStateName(State state) {
+  switch (state) {
+    case UNINITIALIZED:
+      return "UNINITIALIZED";
+    case SMI:
+      return "SMI";
+    case NUMBER:
+      return "NUMBER";
+    case INTERNALIZED_STRING:
+      return "INTERNALIZED_STRING";
+    case STRING:
+      return "STRING";
+    case UNIQUE_NAME:
+      return "UNIQUE_NAME";
+    case OBJECT:
+      return "OBJECT";
+    case KNOWN_OBJECT:
+      return "KNOWN_OBJECT";
+    case GENERIC:
+      return "GENERIC";
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+Type* CompareICState::StateToType(Zone* zone, State state, Handle<Map> map) {
+  switch (state) {
+    case UNINITIALIZED:
+      return Type::None(zone);
+    case SMI:
+      return Type::SignedSmall(zone);
+    case NUMBER:
+      return Type::Number(zone);
+    case STRING:
+      return Type::String(zone);
+    case INTERNALIZED_STRING:
+      return Type::InternalizedString(zone);
+    case UNIQUE_NAME:
+      return Type::UniqueName(zone);
+    case OBJECT:
+      return Type::Receiver(zone);
+    case KNOWN_OBJECT:
+      return map.is_null() ? Type::Receiver(zone) : Type::Class(map, zone);
+    case GENERIC:
+      return Type::Any(zone);
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+CompareICState::State CompareICState::NewInputState(State old_state,
+                                                    Handle<Object> value) {
+  switch (old_state) {
+    case UNINITIALIZED:
+      if (value->IsSmi()) return SMI;
+      if (value->IsHeapNumber()) return NUMBER;
+      if (value->IsInternalizedString()) return INTERNALIZED_STRING;
+      if (value->IsString()) return STRING;
+      if (value->IsSymbol()) return UNIQUE_NAME;
+      if (value->IsJSObject()) return OBJECT;
+      break;
+    case SMI:
+      if (value->IsSmi()) return SMI;
+      if (value->IsHeapNumber()) return NUMBER;
+      break;
+    case NUMBER:
+      if (value->IsNumber()) return NUMBER;
+      break;
+    case INTERNALIZED_STRING:
+      if (value->IsInternalizedString()) return INTERNALIZED_STRING;
+      if (value->IsString()) return STRING;
+      if (value->IsSymbol()) return UNIQUE_NAME;
+      break;
+    case STRING:
+      if (value->IsString()) return STRING;
+      break;
+    case UNIQUE_NAME:
+      if (value->IsUniqueName()) return UNIQUE_NAME;
+      break;
+    case OBJECT:
+      if (value->IsJSObject()) return OBJECT;
+      break;
+    case GENERIC:
+      break;
+    case KNOWN_OBJECT:
+      UNREACHABLE();
+      break;
+  }
+  return GENERIC;
+}
+
+
+// static
+CompareICState::State CompareICState::TargetState(
+    State old_state, State old_left, State old_right, Token::Value op,
+    bool has_inlined_smi_code, Handle<Object> x, Handle<Object> y) {
+  switch (old_state) {
+    case UNINITIALIZED:
+      if (x->IsSmi() && y->IsSmi()) return SMI;
+      if (x->IsNumber() && y->IsNumber()) return NUMBER;
+      if (Token::IsOrderedRelationalCompareOp(op)) {
+        // Ordered comparisons treat undefined as NaN, so the
+        // NUMBER stub will do the right thing.
+        if ((x->IsNumber() && y->IsUndefined()) ||
+            (y->IsNumber() && x->IsUndefined())) {
+          return NUMBER;
+        }
+      }
+      if (x->IsInternalizedString() && y->IsInternalizedString()) {
+ // We compare internalized strings as plain ones if we need to determine
+        // the order in a non-equality compare.
+        return Token::IsEqualityOp(op) ? INTERNALIZED_STRING : STRING;
+      }
+      if (x->IsString() && y->IsString()) return STRING;
+      if (!Token::IsEqualityOp(op)) return GENERIC;
+      if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
+      if (x->IsJSObject() && y->IsJSObject()) {
+        if (Handle<JSObject>::cast(x)->map() ==
+            Handle<JSObject>::cast(y)->map()) {
+          return KNOWN_OBJECT;
+        } else {
+          return OBJECT;
+        }
+      }
+      return GENERIC;
+    case SMI:
+      return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC;
+    case INTERNALIZED_STRING:
+      DCHECK(Token::IsEqualityOp(op));
+      if (x->IsString() && y->IsString()) return STRING;
+      if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
+      return GENERIC;
+    case NUMBER:
+ // If the failure was due to one side changing from smi to heap number, + // then keep the state (if other changed at the same time, we will get
+      // a second miss and then go to generic).
+      if (old_left == SMI && x->IsHeapNumber()) return NUMBER;
+      if (old_right == SMI && y->IsHeapNumber()) return NUMBER;
+      return GENERIC;
+    case KNOWN_OBJECT:
+      DCHECK(Token::IsEqualityOp(op));
+      if (x->IsJSObject() && y->IsJSObject()) {
+        return OBJECT;
+      }
+      return GENERIC;
+    case STRING:
+    case UNIQUE_NAME:
+    case OBJECT:
+    case GENERIC:
+      return GENERIC;
+  }
+  UNREACHABLE();
+  return GENERIC;  // Make the compiler happy.
+}
+}
+}  // namespace v8::internal
=======================================
--- /dev/null
+++ /trunk/src/ic/ic-state.h    Wed Sep 17 00:05:08 2014 UTC
@@ -0,0 +1,238 @@
+// Copyright 2012 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_IC_STATE_H_
+#define V8_IC_STATE_H_
+
+#include "src/macro-assembler.h"
+
+namespace v8 {
+namespace internal {
+
+
+const int kMaxKeyedPolymorphism = 4;
+
+
+class ICUtility : public AllStatic {
+ public:
+  // Clear the inline cache to initial state.
+  static void Clear(Isolate* isolate, Address address,
+                    ConstantPoolArray* constant_pool);
+};
+
+
+class CallICState FINAL BASE_EMBEDDED {
+ public:
+  explicit CallICState(ExtraICState extra_ic_state);
+
+  enum CallType { METHOD, FUNCTION };
+
+  CallICState(int argc, CallType call_type)
+      : argc_(argc), call_type_(call_type) {}
+
+  ExtraICState GetExtraICState() const;
+
+  static void GenerateAheadOfTime(Isolate*,
+                                  void (*Generate)(Isolate*,
+                                                   const CallICState&));
+
+  int arg_count() const { return argc_; }
+  CallType call_type() const { return call_type_; }
+
+  bool CallAsMethod() const { return call_type_ == METHOD; }
+
+ private:
+  class ArgcBits : public BitField<int, 0, Code::kArgumentsBits> {};
+ class CallTypeBits : public BitField<CallType, Code::kArgumentsBits, 1> {};
+
+  const int argc_;
+  const CallType call_type_;
+};
+
+
+OStream& operator<<(OStream& os, const CallICState& s);
+
+
+// Mode to overwrite BinaryExpression values.
+enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
+
+class BinaryOpICState FINAL BASE_EMBEDDED {
+ public:
+  BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state);
+
+  BinaryOpICState(Isolate* isolate, Token::Value op, OverwriteMode mode)
+      : op_(op),
+        mode_(mode),
+        left_kind_(NONE),
+        right_kind_(NONE),
+        result_kind_(NONE),
+        isolate_(isolate) {
+    DCHECK_LE(FIRST_TOKEN, op);
+    DCHECK_LE(op, LAST_TOKEN);
+  }
+
+  InlineCacheState GetICState() const {
+    if (Max(left_kind_, right_kind_) == NONE) {
+      return ::v8::internal::UNINITIALIZED;
+    }
+    if (Max(left_kind_, right_kind_) == GENERIC) {
+      return ::v8::internal::MEGAMORPHIC;
+    }
+    if (Min(left_kind_, right_kind_) == GENERIC) {
+      return ::v8::internal::GENERIC;
+    }
+    return ::v8::internal::MONOMORPHIC;
+  }
+
+  ExtraICState GetExtraICState() const;
+
+  static void GenerateAheadOfTime(Isolate*,
+                                  void (*Generate)(Isolate*,
+ const BinaryOpICState&));
+
+  bool CanReuseDoubleBox() const {
+    return (result_kind_ > SMI && result_kind_ <= NUMBER) &&
+           ((mode_ == OVERWRITE_LEFT && left_kind_ > SMI &&
+             left_kind_ <= NUMBER) ||
+            (mode_ == OVERWRITE_RIGHT && right_kind_ > SMI &&
+             right_kind_ <= NUMBER));
+  }
+
+  // Returns true if the IC _could_ create allocation mementos.
+  bool CouldCreateAllocationMementos() const {
+    if (left_kind_ == STRING || right_kind_ == STRING) {
+      DCHECK_EQ(Token::ADD, op_);
+      return true;
+    }
+    return false;
+  }
+
+  // Returns true if the IC _should_ create allocation mementos.
+  bool ShouldCreateAllocationMementos() const {
+ return FLAG_allocation_site_pretenuring && CouldCreateAllocationMementos();
+  }
+
+  bool HasSideEffects() const {
+    return Max(left_kind_, right_kind_) == GENERIC;
+  }
+
+ // Returns true if the IC should enable the inline smi code (i.e. if either
+  // parameter may be a smi).
+  bool UseInlinedSmiCode() const {
+    return KindMaybeSmi(left_kind_) || KindMaybeSmi(right_kind_);
+  }
+
+  static const int FIRST_TOKEN = Token::BIT_OR;
+  static const int LAST_TOKEN = Token::MOD;
+
+  Token::Value op() const { return op_; }
+  OverwriteMode mode() const { return mode_; }
+  Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
+
+ Type* GetLeftType(Zone* zone) const { return KindToType(left_kind_, zone); } + Type* GetRightType(Zone* zone) const { return KindToType(right_kind_, zone); }
+  Type* GetResultType(Zone* zone) const;
+
+ void Update(Handle<Object> left, Handle<Object> right, Handle<Object> result);
+
+  Isolate* isolate() const { return isolate_; }
+
+ private:
+  friend OStream& operator<<(OStream& os, const BinaryOpICState& s);
+
+  enum Kind { NONE, SMI, INT32, NUMBER, STRING, GENERIC };
+
+  Kind UpdateKind(Handle<Object> object, Kind kind) const;
+
+  static const char* KindToString(Kind kind);
+  static Type* KindToType(Kind kind, Zone* zone);
+  static bool KindMaybeSmi(Kind kind) {
+    return (kind >= SMI && kind <= NUMBER) || kind == GENERIC;
+  }
+
+  // We truncate the last bit of the token.
+  STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 4));
+  class OpField : public BitField<int, 0, 4> {};
+  class OverwriteModeField : public BitField<OverwriteMode, 4, 2> {};
+  class ResultKindField : public BitField<Kind, 6, 3> {};
+  class LeftKindField : public BitField<Kind, 9, 3> {};
+  // When fixed right arg is set, we don't need to store the right kind.
+  // Thus the two fields can overlap.
+  class HasFixedRightArgField : public BitField<bool, 12, 1> {};
+  class FixedRightArgValueField : public BitField<int, 13, 4> {};
+  class RightKindField : public BitField<Kind, 13, 3> {};
+
+  Token::Value op_;
+  OverwriteMode mode_;
+  Kind left_kind_;
+  Kind right_kind_;
+  Kind result_kind_;
+  Maybe<int> fixed_right_arg_;
+  Isolate* isolate_;
+};
+
+
+OStream& operator<<(OStream& os, const BinaryOpICState& s);
+
+
+class CompareICState {
+ public:
+  // The type/state lattice is defined by the following inequations:
+  //   UNINITIALIZED < ...
+  //   ... < GENERIC
+  //   SMI < NUMBER
+  //   INTERNALIZED_STRING < STRING
+  //   KNOWN_OBJECT < OBJECT
+  enum State {
+    UNINITIALIZED,
+    SMI,
+    NUMBER,
+    STRING,
+    INTERNALIZED_STRING,
+    UNIQUE_NAME,   // Symbol or InternalizedString
+    OBJECT,        // JSObject
+    KNOWN_OBJECT,  // JSObject with specific map (faster check)
+    GENERIC
+  };
+
+  static Type* StateToType(Zone* zone, State state,
+                           Handle<Map> map = Handle<Map>());
+
+  static State NewInputState(State old_state, Handle<Object> value);
+
+  static const char* GetStateName(CompareICState::State state);
+
+ static State TargetState(State old_state, State old_left, State old_right,
+                           Token::Value op, bool has_inlined_smi_code,
+                           Handle<Object> x, Handle<Object> y);
+};
+
+
+class LoadICState FINAL BASE_EMBEDDED {
+ public:
+ explicit LoadICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {}
+
+  explicit LoadICState(ContextualMode mode)
+      : state_(ContextualModeBits::encode(mode)) {}
+
+  ExtraICState GetExtraICState() const { return state_; }
+
+  ContextualMode contextual_mode() const {
+    return ContextualModeBits::decode(state_);
+  }
+
+  static ContextualMode GetContextualMode(ExtraICState state) {
+    return LoadICState(state).contextual_mode();
+  }
+
+ private:
+  class ContextualModeBits : public BitField<ContextualMode, 0, 1> {};
+  STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
+
+  const ExtraICState state_;
+};
+}
+}
+
+#endif  // V8_IC_STATE_H_
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-3564.js Wed Sep 17 00:05:08 2014 UTC
@@ -0,0 +1,24 @@
+// 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
+
+function MyWrapper(v) {
+  return { valueOf: function() { return v } };
+}
+
+function f() {
+  assertTrue("a" < "x");
+  assertTrue("a" < new String("y"));
+  assertTrue("a" < new MyWrapper("z"));
+
+  assertFalse("a" > "x");
+  assertFalse("a" > new String("y"));
+  assertFalse("a" > new MyWrapper("z"));
+}
+
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
=======================================
--- /trunk/BUILD.gn     Tue Sep 16 07:50:38 2014 UTC
+++ /trunk/BUILD.gn     Wed Sep 17 00:05:08 2014 UTC
@@ -189,6 +189,7 @@
     "src/regexp.js",
     "src/arraybuffer.js",
     "src/typedarray.js",
+    "src/generator.js",
     "src/object-observe.js",
     "src/collection.js",
     "src/weak-collection.js",
@@ -730,6 +731,8 @@
     "src/ic/handler-compiler.cc",
     "src/ic/handler-compiler.h",
     "src/ic/ic-inl.h",
+    "src/ic/ic-state.cc",
+    "src/ic/ic-state.h",
     "src/ic/ic.cc",
     "src/ic/ic.h",
     "src/ic/ic-compiler.cc",
=======================================
--- /trunk/ChangeLog    Tue Sep 16 07:50:38 2014 UTC
+++ /trunk/ChangeLog    Wed Sep 17 00:05:08 2014 UTC
@@ -1,3 +1,15 @@
+2014-09-17: Version 3.29.70
+
+        Enable ES6 generators (issue 2355).
+
+ Fixed int vs. uintptr_t confusion (plus some cleanup on the way) (issue
+        3556).
+
+        Move configuration of ResourceConstraints to Isolate construction.
+
+        Performance and stability improvements on all platforms.
+
+
 2014-09-16: Version 3.29.66

         Currently, a new isolate is created in an uninitialized state, and
=======================================
--- /trunk/include/v8.h Tue Sep 16 07:50:38 2014 UTC
+++ /trunk/include/v8.h Wed Sep 17 00:05:08 2014 UTC
@@ -4101,6 +4101,9 @@

 /**
  * Sets the given ResourceConstraints on the given Isolate.
+ *
+ * Deprecated, will be removed. Pass constraints via Isolate::New or modify
+ * the stack limit via Isolate::SetStackLimit.
  */
 bool V8_EXPORT SetResourceConstraints(Isolate* isolate,
                                       ResourceConstraints* constraints);
@@ -4371,6 +4374,11 @@
      * notified each time code is added, moved or removed.
      */
     JitCodeEventHandler code_event_handler;
+
+    /**
+     * ResourceConstraints to use for the new Isolate.
+     */
+    ResourceConstraints constraints;
   };


@@ -4817,6 +4825,17 @@
   void SetJitCodeEventHandler(JitCodeEventOptions options,
                               JitCodeEventHandler event_handler);

+  /**
+   * Modifies the stack limit for this Isolate.
+   *
+ * \param stack_limit An address beyond which the Vm's stack may not grow.
+   *
+ * \note If you are using threads then you should hold the V8::Locker lock
+   *     while setting the stack limit and you must set a non-default stack
+   *     limit separately for each thread.
+   */
+  void SetStackLimit(uintptr_t stack_limit);
+
  private:
   template<class K, class V, class Traits> friend class PersistentValueMap;

=======================================
--- /trunk/src/api.cc   Tue Sep 16 07:50:38 2014 UTC
+++ /trunk/src/api.cc   Wed Sep 17 00:05:08 2014 UTC
@@ -6664,6 +6664,7 @@

 Isolate* Isolate::New(const Isolate::CreateParams& params) {
   i::Isolate* isolate = new i::Isolate();
+  Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
   if (params.entry_hook) {
     isolate->set_function_entry_hook(params.entry_hook);
   }
@@ -6672,7 +6673,9 @@
     isolate->logger()->SetCodeEventHandler(kJitCodeEventDefault,
                                            params.code_event_handler);
   }
-  return reinterpret_cast<Isolate*>(isolate);
+  SetResourceConstraints(v8_isolate,
+ const_cast<ResourceConstraints*>(&params.constraints));
+  return v8_isolate;
 }


@@ -6887,6 +6890,13 @@
   isolate->InitializeLoggingAndCounters();
   isolate->logger()->SetCodeEventHandler(options, event_handler);
 }
+
+
+void v8::Isolate::SetStackLimit(uintptr_t stack_limit) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  CHECK(stack_limit);
+  isolate->stack_guard()->SetStackLimit(stack_limit);
+}


 String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj)
=======================================
--- /trunk/src/arm/code-stubs-arm.cc    Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/arm/code-stubs-arm.cc    Wed Sep 17 00:05:08 2014 UTC
@@ -11,6 +11,7 @@
 #include "src/code-stubs.h"
 #include "src/codegen.h"
 #include "src/ic/handler-compiler.h"
+#include "src/ic/ic.h"
 #include "src/isolate.h"
 #include "src/jsregexp.h"
 #include "src/regexp-macro-assembler.h"
@@ -566,12 +567,12 @@

static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input,
                                          Register scratch,
-                                         CompareIC::State expected,
+                                         CompareICState::State expected,
                                          Label* fail) {
   Label ok;
-  if (expected == CompareIC::SMI) {
+  if (expected == CompareICState::SMI) {
     __ JumpIfNotSmi(input, fail);
-  } else if (expected == CompareIC::NUMBER) {
+  } else if (expected == CompareICState::NUMBER) {
     __ JumpIfSmi(input, &ok);
     __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail,
                 DONT_DO_SMI_CHECK);
@@ -2615,7 +2616,7 @@
   __ TailCallStub(&stub);

   __ bind(&miss);
-  GenerateMiss(masm, IC::kCallIC_Customization_Miss);
+  GenerateMiss(masm);

// The slow case, we need this no matter what to complete a call after a miss.
   CallFunctionNoFeedback(masm,
@@ -2690,7 +2691,7 @@

   // We are here because tracing is on or we are going monomorphic.
   __ bind(&miss);
-  GenerateMiss(masm, IC::kCallIC_Miss);
+  GenerateMiss(masm);

   // the slow case
   __ bind(&slow_start);
@@ -2705,7 +2706,7 @@
 }


-void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) {
+void CallICStub::GenerateMiss(MacroAssembler* masm) {
   // Get the receiver of the function from the stack; 1 ~ return address.
   __ ldr(r4, MemOperand(sp, (arg_count() + 1) * kPointerSize));

@@ -2716,6 +2717,9 @@
     __ Push(r4, r1, r2, r3);

     // Call the entry.
+    IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss
+ : IC::kCallIC_Customization_Miss;
+
     ExternalReference miss = ExternalReference(IC_Utility(id),
                                                masm->isolate());
     __ CallExternalReference(miss, 4);
@@ -3279,7 +3283,7 @@


 void CompareICStub::GenerateSmis(MacroAssembler* masm) {
-  DCHECK(state() == CompareIC::SMI);
+  DCHECK(state() == CompareICState::SMI);
   Label miss;
   __ orr(r2, r1, r0);
   __ JumpIfNotSmi(r2, &miss);
@@ -3300,16 +3304,16 @@


 void CompareICStub::GenerateNumbers(MacroAssembler* masm) {
-  DCHECK(state() == CompareIC::NUMBER);
+  DCHECK(state() == CompareICState::NUMBER);

   Label generic_stub;
   Label unordered, maybe_undefined1, maybe_undefined2;
   Label miss;

-  if (left() == CompareIC::SMI) {
+  if (left() == CompareICState::SMI) {
     __ JumpIfNotSmi(r1, &miss);
   }
-  if (right() == CompareIC::SMI) {
+  if (right() == CompareICState::SMI) {
     __ JumpIfNotSmi(r0, &miss);
   }

@@ -3351,8 +3355,8 @@

   __ bind(&unordered);
   __ bind(&generic_stub);
- CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC,
-                     CompareIC::GENERIC);
+  CompareICStub stub(isolate(), op(), CompareICState::GENERIC,
+                     CompareICState::GENERIC, CompareICState::GENERIC);
   __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);

   __ bind(&maybe_undefined1);
@@ -3377,7 +3381,7 @@


 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) {
-  DCHECK(state() == CompareIC::INTERNALIZED_STRING);
+  DCHECK(state() == CompareICState::INTERNALIZED_STRING);
   Label miss;

   // Registers containing left and right operands respectively.
@@ -3415,7 +3419,7 @@


 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) {
-  DCHECK(state() == CompareIC::UNIQUE_NAME);
+  DCHECK(state() == CompareICState::UNIQUE_NAME);
   DCHECK(GetCondition() == eq);
   Label miss;

@@ -3454,7 +3458,7 @@


 void CompareICStub::GenerateStrings(MacroAssembler* masm) {
-  DCHECK(state() == CompareIC::STRING);
+  DCHECK(state() == CompareICState::STRING);
   Label miss;

   bool equality = Token::IsEqualityOp(op());
@@ -3533,7 +3537,7 @@


 void CompareICStub::GenerateObjects(MacroAssembler* masm) {
-  DCHECK(state() == CompareIC::OBJECT);
+  DCHECK(state() == CompareICState::OBJECT);
   Label miss;
   __ and_(r2, r1, Operand(r0));
   __ JumpIfSmi(r2, &miss);
=======================================
--- /trunk/src/arm/full-codegen-arm.cc  Mon Sep 15 00:05:18 2014 UTC
+++ /trunk/src/arm/full-codegen-arm.cc  Wed Sep 17 00:05:08 2014 UTC
@@ -12,6 +12,7 @@
 #include "src/compiler.h"
 #include "src/debug.h"
 #include "src/full-codegen.h"
+#include "src/ic/ic.h"
 #include "src/isolate-inl.h"
 #include "src/parser.h"
 #include "src/scopes.h"
@@ -2627,12 +2628,11 @@
 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
   Expression* callee = expr->expression();

-  CallIC::CallType call_type = callee->IsVariableProxy()
-      ? CallIC::FUNCTION
-      : CallIC::METHOD;
+  CallICState::CallType call_type =
+ callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD;

   // Get the target function.
-  if (call_type == CallIC::FUNCTION) {
+  if (call_type == CallICState::FUNCTION) {
     { StackValueContext context(this);
       EmitVariableLoad(callee->AsVariableProxy());
       PrepareForBailout(callee, NO_REGISTERS);
@@ -2676,11 +2676,11 @@
   __ push(ip);
   __ str(r0, MemOperand(sp, kPointerSize));

-  EmitCall(expr, CallIC::METHOD);
+  EmitCall(expr, CallICState::METHOD);
 }


-void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) {
+void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
   // Load the arguments.
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
=======================================
--- /trunk/src/arm/lithium-arm.cc       Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/arm/lithium-arm.cc       Wed Sep 17 00:05:08 2014 UTC
@@ -2362,7 +2362,7 @@
   }

   LOperand* val;
-  if (needs_write_barrier || instr->field_representation().IsSmi()) {
+  if (needs_write_barrier) {
     val = UseTempRegister(instr->value());
   } else if (instr->field_representation().IsDouble()) {
     val = UseRegisterAtStart(instr->value());
=======================================
--- /trunk/src/arm/lithium-codegen-arm.cc       Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/arm/lithium-codegen-arm.cc       Wed Sep 17 00:05:08 2014 UTC
@@ -10,6 +10,7 @@
 #include "src/code-factory.h"
 #include "src/code-stubs.h"
 #include "src/hydrogen-osr.h"
+#include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"

 namespace v8 {
=======================================
--- /trunk/src/arm64/code-stubs-arm64.cc        Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/arm64/code-stubs-arm64.cc        Wed Sep 17 00:05:08 2014 UTC
@@ -10,6 +10,7 @@
 #include "src/code-stubs.h"
 #include "src/codegen.h"
 #include "src/ic/handler-compiler.h"
+#include "src/ic/ic.h"
 #include "src/isolate.h"
 #include "src/jsregexp.h"
 #include "src/regexp-macro-assembler.h"
@@ -472,12 +473,12 @@

static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input,
                                          Register scratch,
-                                         CompareIC::State expected,
+                                         CompareICState::State expected,
                                          Label* fail) {
   Label ok;
-  if (expected == CompareIC::SMI) {
+  if (expected == CompareICState::SMI) {
     __ JumpIfNotSmi(input, fail);
-  } else if (expected == CompareIC::NUMBER) {
+  } else if (expected == CompareICState::NUMBER) {
     __ JumpIfSmi(input, &ok);
     __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail,
                 DONT_DO_SMI_CHECK);
@@ -2953,7 +2954,7 @@
   __ TailCallStub(&stub);

   __ bind(&miss);
-  GenerateMiss(masm, IC::kCallIC_Customization_Miss);
+  GenerateMiss(masm);

// The slow case, we need this no matter what to complete a call after a miss.
   CallFunctionNoFeedback(masm,
@@ -3037,7 +3038,7 @@

   // We are here because tracing is on or we are going monomorphic.
   __ bind(&miss);
-  GenerateMiss(masm, IC::kCallIC_Miss);
+  GenerateMiss(masm);

   // the slow case
   __ bind(&slow_start);
@@ -3051,7 +3052,7 @@
 }


-void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) {
+void CallICStub::GenerateMiss(MacroAssembler* masm) {
   ASM_LOCATION("CallICStub[Miss]");

   // Get the receiver of the function from the stack; 1 ~ return address.
@@ -3064,6 +3065,9 @@
     __ Push(x4, x1, x2, x3);

     // Call the entry.
+    IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss
+ : IC::kCallIC_Customization_Miss;
+
     ExternalReference miss = ExternalReference(IC_Utility(id),
                                                masm->isolate());
     __ CallExternalReference(miss, 4);
@@ -3191,7 +3195,7 @@

 void CompareICStub::GenerateSmis(MacroAssembler* masm) {
   // Inputs are in x0 (lhs) and x1 (rhs).
-  DCHECK(state() == CompareIC::SMI);
+  DCHECK(state() == CompareICState::SMI);
   ASM_LOCATION("CompareICStub[Smis]");
   Label miss;
   // Bail out (to 'miss') unless both x0 and x1 are smis.
@@ -3213,7 +3217,7 @@


 void CompareICStub::GenerateNumbers(MacroAssembler* masm) {
-  DCHECK(state() == CompareIC::NUMBER);
+  DCHECK(state() == CompareICState::NUMBER);
   ASM_LOCATION("CompareICStub[HeapNumbers]");

   Label unordered, maybe_undefined1, maybe_undefined2;
@@ -3226,10 +3230,10 @@
   FPRegister rhs_d = d0;
   FPRegister lhs_d = d1;

-  if (left() == CompareIC::SMI) {
+  if (left() == CompareICState::SMI) {
     __ JumpIfNotSmi(lhs, &miss);
   }
-  if (right() == CompareIC::SMI) {
+  if (right() == CompareICState::SMI) {
     __ JumpIfNotSmi(rhs, &miss);
   }

@@ -3258,8 +3262,8 @@
   __ Ret();

   __ Bind(&unordered);
- CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC,
-                     CompareIC::GENERIC);
+  CompareICStub stub(isolate(), op(), CompareICState::GENERIC,
+                     CompareICState::GENERIC, CompareICState::GENERIC);
   __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);

   __ Bind(&maybe_undefined1);
@@ -3281,7 +3285,7 @@


 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) {
-  DCHECK(state() == CompareIC::INTERNALIZED_STRING);
+  DCHECK(state() == CompareICState::INTERNALIZED_STRING);
   ASM_LOCATION("CompareICStub[InternalizedStrings]");
   Label miss;

@@ -3319,7 +3323,7 @@


 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) {
-  DCHECK(state() == CompareIC::UNIQUE_NAME);
+  DCHECK(state() == CompareICState::UNIQUE_NAME);
   ASM_LOCATION("CompareICStub[UniqueNames]");
   DCHECK(GetCondition() == eq);
   Label miss;
@@ -3358,7 +3362,7 @@


 void CompareICStub::GenerateStrings(MacroAssembler* masm) {
-  DCHECK(state() == CompareIC::STRING);
+  DCHECK(state() == CompareICState::STRING);
   ASM_LOCATION("CompareICStub[Strings]");

   Label miss;
@@ -3439,7 +3443,7 @@


 void CompareICStub::GenerateObjects(MacroAssembler* masm) {
-  DCHECK(state() == CompareIC::OBJECT);
+  DCHECK(state() == CompareICState::OBJECT);
   ASM_LOCATION("CompareICStub[Objects]");

   Label miss;
=======================================
--- /trunk/src/arm64/full-codegen-arm64.cc      Mon Sep 15 00:05:18 2014 UTC
+++ /trunk/src/arm64/full-codegen-arm64.cc      Wed Sep 17 00:05:08 2014 UTC
@@ -12,6 +12,7 @@
 #include "src/compiler.h"
 #include "src/debug.h"
 #include "src/full-codegen.h"
+#include "src/ic/ic.h"
 #include "src/isolate-inl.h"
 #include "src/parser.h"
 #include "src/scopes.h"
@@ -2291,12 +2292,11 @@
 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
   Expression* callee = expr->expression();

-  CallIC::CallType call_type = callee->IsVariableProxy()
-      ? CallIC::FUNCTION
-      : CallIC::METHOD;
+  CallICState::CallType call_type =
+ callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD;

   // Get the target function.
-  if (call_type == CallIC::FUNCTION) {
+  if (call_type == CallICState::FUNCTION) {
     { StackValueContext context(this);
       EmitVariableLoad(callee->AsVariableProxy());
       PrepareForBailout(callee, NO_REGISTERS);
@@ -2338,11 +2338,11 @@
   __ Pop(x10);
   __ Push(x0, x10);

-  EmitCall(expr, CallIC::METHOD);
+  EmitCall(expr, CallICState::METHOD);
 }


-void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) {
+void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
   // Load the arguments.
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
=======================================
--- /trunk/src/arm64/lithium-codegen-arm64.cc   Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/arm64/lithium-codegen-arm64.cc   Wed Sep 17 00:05:08 2014 UTC
@@ -10,6 +10,7 @@
 #include "src/code-factory.h"
 #include "src/code-stubs.h"
 #include "src/hydrogen-osr.h"
+#include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"

 namespace v8 {
=======================================
--- /trunk/src/arm64/macro-assembler-arm64.cc   Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/arm64/macro-assembler-arm64.cc   Wed Sep 17 00:05:08 2014 UTC
@@ -1656,12 +1656,6 @@

   JumpToHandlerEntry(value, object, state, scratch3, scratch4);
 }
-
-
-void MacroAssembler::SmiAbs(const Register& smi, Label* slow) {
-  DCHECK(smi.Is64Bits());
-  Abs(smi, smi, slow);
-}


 void MacroAssembler::AssertSmi(Register object, BailoutReason reason) {
=======================================
--- /trunk/src/arm64/macro-assembler-arm64.h    Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/arm64/macro-assembler-arm64.h    Wed Sep 17 00:05:08 2014 UTC
@@ -910,11 +910,6 @@
   inline void SmiTagAndPush(Register src);
   inline void SmiTagAndPush(Register src1, Register src2);

-  // Compute the absolute value of 'smi' and leave the result in 'smi'
-  // register. If 'smi' is the most negative SMI, the absolute value cannot
-  // be represented as a SMI and a jump to 'slow' is done.
-  void SmiAbs(const Register& smi, Label* slow);
-
   inline void JumpIfSmi(Register value,
                         Label* smi_label,
                         Label* not_smi_label = NULL);
=======================================
--- /trunk/src/assembler.cc     Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/assembler.cc     Wed Sep 17 00:05:08 2014 UTC
@@ -46,6 +46,7 @@
 #include "src/debug.h"
 #include "src/deoptimizer.h"
 #include "src/execution.h"
+#include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"
 #include "src/isolate-inl.h"
 #include "src/jsregexp.h"
=======================================
--- /trunk/src/bootstrapper.cc  Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/bootstrapper.cc  Wed Sep 17 00:05:08 2014 UTC
@@ -126,7 +126,7 @@
 void Bootstrapper::TearDown() {
   if (delete_these_non_arrays_on_tear_down_ != NULL) {
     int len = delete_these_non_arrays_on_tear_down_->length();
- DCHECK(len < 27); // Don't use this mechanism for unbounded allocations. + DCHECK(len < 28); // Don't use this mechanism for unbounded allocations.
     for (int i = 0; i < len; i++) {
       delete delete_these_non_arrays_on_tear_down_->at(i);
       delete_these_non_arrays_on_tear_down_->at(i) = NULL;
@@ -203,7 +203,6 @@
   // New context initialization.  Used for creating a context from scratch.
   void InitializeGlobal(Handle<GlobalObject> global_object,
                         Handle<JSFunction> empty_function);
-  void InitializeExperimentalGlobal();
   // Installs the contents of the native .js files on the global objects.
   // Used for creating a context from scratch.
   void InstallNativeFunctions();
@@ -1350,74 +1349,6 @@
ElementsKind external_kind = GetNextTransitionElementsKind(elements_kind);
   *external_map = Map::AsElementsKind(initial_map, external_kind);
 }
-
-
-void Genesis::InitializeExperimentalGlobal() {
-  // TODO(mstarzinger): Move this into Genesis::InitializeGlobal once we no
- // longer need to live behind flags, so functions get added to the snapshot.
-
-  if (FLAG_harmony_generators) {
- // Create generator meta-objects and install them on the builtins object.
-    Handle<JSObject> builtins(native_context()->builtins());
-    Handle<JSObject> generator_object_prototype =
-        factory()->NewJSObject(isolate()->object_function(), TENURED);
-    Handle<JSFunction> generator_function_prototype = InstallFunction(
-        builtins, "GeneratorFunctionPrototype", JS_FUNCTION_TYPE,
-        JSFunction::kHeaderSize, generator_object_prototype,
-        Builtins::kIllegal);
-    InstallFunction(builtins, "GeneratorFunction",
-                    JS_FUNCTION_TYPE, JSFunction::kSize,
-                    generator_function_prototype, Builtins::kIllegal);
-
- // Create maps for generator functions and their prototypes. Store those
-    // maps in the native context.
- Handle<Map> sloppy_function_map(native_context()->sloppy_function_map());
-    Handle<Map> generator_function_map = Map::Copy(sloppy_function_map);
-    generator_function_map->set_prototype(*generator_function_prototype);
-    native_context()->set_sloppy_generator_function_map(
-        *generator_function_map);
-
- // The "arguments" and "caller" instance properties aren't specified, so
-    // technically we could leave them out.  They make even less sense for
- // generators than for functions. Still, the same argument that it makes
-    // sense to keep them around but poisoned in strict mode applies to
- // generators as well. With poisoned accessors, naive callers can still
-    // iterate over the properties without accessing them.
-    //
- // We can't use PoisonArgumentsAndCaller because that mutates accessor pairs - // in place, and the initial state of the generator function map shares the - // accessor pair with sloppy functions. Also the error message should be - // different. Also unhappily, we can't use the API accessors to implement - // poisoning, because API accessors present themselves as data properties,
-    // not accessor properties, and so getOwnPropertyDescriptor raises an
-    // exception as it tries to get the values.  Sadness.
-    Handle<AccessorPair> poison_pair(factory()->NewAccessorPair());
-    PropertyAttributes rw_attribs =
-        static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
-    Handle<JSFunction> poison_function = GetGeneratorPoisonFunction();
-    poison_pair->set_getter(*poison_function);
-    poison_pair->set_setter(*poison_function);
-    ReplaceAccessors(generator_function_map, factory()->arguments_string(),
-        rw_attribs, poison_pair);
-    ReplaceAccessors(generator_function_map, factory()->caller_string(),
-        rw_attribs, poison_pair);
-
- Handle<Map> strict_function_map(native_context()->strict_function_map()); - Handle<Map> strict_generator_function_map = Map::Copy(strict_function_map);
-    // "arguments" and "caller" already poisoned.
- strict_generator_function_map->set_prototype(*generator_function_prototype);
-    native_context()->set_strict_generator_function_map(
-        *strict_generator_function_map);
-
- Handle<JSFunction> object_function(native_context()->object_function());
-    Handle<Map> generator_object_prototype_map = Map::Create(
-        object_function, 0);
-    generator_object_prototype_map->set_prototype(
-        *generator_object_prototype);
-    native_context()->set_generator_object_prototype_map(
-        *generator_object_prototype_map);
-  }
-}


 bool Genesis::CompileBuiltin(Isolate* isolate, int index) {
@@ -1922,6 +1853,67 @@
     native_context()->set_map_iterator_map(
         map_iterator_function->initial_map());
   }
+
+  {
+ // Create generator meta-objects and install them on the builtins object.
+    Handle<JSObject> builtins(native_context()->builtins());
+    Handle<JSObject> generator_object_prototype =
+        factory()->NewJSObject(isolate()->object_function(), TENURED);
+    Handle<JSFunction> generator_function_prototype =
+        InstallFunction(builtins, "GeneratorFunctionPrototype",
+                        JS_FUNCTION_TYPE, JSFunction::kHeaderSize,
+                        generator_object_prototype, Builtins::kIllegal);
+    InstallFunction(builtins, "GeneratorFunction", JS_FUNCTION_TYPE,
+                    JSFunction::kSize, generator_function_prototype,
+                    Builtins::kIllegal);
+
+ // Create maps for generator functions and their prototypes. Store those
+    // maps in the native context.
+    Handle<Map> generator_function_map =
+        Map::Copy(sloppy_function_map_writable_prototype_);
+    generator_function_map->set_prototype(*generator_function_prototype);
+    native_context()->set_sloppy_generator_function_map(
+        *generator_function_map);
+
+ // The "arguments" and "caller" instance properties aren't specified, so
+    // technically we could leave them out.  They make even less sense for
+ // generators than for functions. Still, the same argument that it makes
+    // sense to keep them around but poisoned in strict mode applies to
+ // generators as well. With poisoned accessors, naive callers can still
+    // iterate over the properties without accessing them.
+    //
+ // We can't use PoisonArgumentsAndCaller because that mutates accessor pairs + // in place, and the initial state of the generator function map shares the + // accessor pair with sloppy functions. Also the error message should be + // different. Also unhappily, we can't use the API accessors to implement + // poisoning, because API accessors present themselves as data properties,
+    // not accessor properties, and so getOwnPropertyDescriptor raises an
+    // exception as it tries to get the values.  Sadness.
+    Handle<AccessorPair> poison_pair(factory()->NewAccessorPair());
+    PropertyAttributes rw_attribs =
+        static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
+    Handle<JSFunction> poison_function = GetGeneratorPoisonFunction();
+    poison_pair->set_getter(*poison_function);
+    poison_pair->set_setter(*poison_function);
+    ReplaceAccessors(generator_function_map, factory()->arguments_string(),
+                     rw_attribs, poison_pair);
+    ReplaceAccessors(generator_function_map, factory()->caller_string(),
+                     rw_attribs, poison_pair);
+
+ Handle<Map> strict_function_map(native_context()->strict_function_map()); + Handle<Map> strict_generator_function_map = Map::Copy(strict_function_map);
+    // "arguments" and "caller" already poisoned.
+ strict_generator_function_map->set_prototype(*generator_function_prototype);
+    native_context()->set_strict_generator_function_map(
+        *strict_generator_function_map);
+
+ Handle<JSFunction> object_function(native_context()->object_function());
+    Handle<Map> generator_object_prototype_map =
+        Map::Create(object_function, 0);
+ generator_object_prototype_map->set_prototype(*generator_object_prototype);
+    native_context()->set_generator_object_prototype_map(
+        *generator_object_prototype_map);
+  }

   if (FLAG_disable_native_files) {
     PrintF("Warning: Running without installed natives!\n");
@@ -2096,7 +2088,6 @@
        i < ExperimentalNatives::GetBuiltinsCount();
        i++) {
     INSTALL_EXPERIMENTAL_NATIVE(i, proxies, "proxy.js")
-    INSTALL_EXPERIMENTAL_NATIVE(i, generators, "generator.js")
     INSTALL_EXPERIMENTAL_NATIVE(i, strings, "harmony-string.js")
     INSTALL_EXPERIMENTAL_NATIVE(i, arrays, "harmony-array.js")
     INSTALL_EXPERIMENTAL_NATIVE(i, classes, "harmony-classes.js")
@@ -2657,8 +2648,7 @@
     isolate->counters()->contexts_created_from_scratch()->Increment();
   }

-  // Initialize experimental globals and install experimental natives.
-  InitializeExperimentalGlobal();
+  // Install experimental natives.
   if (!InstallExperimentalNatives()) return;

// We can't (de-)serialize typed arrays currently, but we are lucky: The state
=======================================
--- /trunk/src/code-factory.cc  Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/code-factory.cc  Wed Sep 17 00:05:08 2014 UTC
@@ -14,7 +14,7 @@
 // static
 Callable CodeFactory::LoadIC(Isolate* isolate, ContextualMode mode) {
   return Callable(
- LoadIC::initialize_stub(isolate, LoadIC::State(mode).GetExtraICState()), + LoadIC::initialize_stub(isolate, LoadICState(mode).GetExtraICState()),
       LoadDescriptor(isolate));
 }

=======================================
--- /trunk/src/code-stubs-hydrogen.cc   Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/code-stubs-hydrogen.cc   Wed Sep 17 00:05:08 2014 UTC
@@ -905,7 +905,7 @@

 template <>
 HValue* CodeStubGraphBuilder<BinaryOpICStub>::BuildCodeInitializedStub() {
-  BinaryOpIC::State state = casted_stub()->state();
+  BinaryOpICState state = casted_stub()->state();

   HValue* left = GetParameter(BinaryOpICStub::kLeft);
   HValue* right = GetParameter(BinaryOpICStub::kRight);
@@ -1004,7 +1004,7 @@

 template <>
HValue* CodeStubGraphBuilder<BinaryOpWithAllocationSiteStub>::BuildCodeStub() {
-  BinaryOpIC::State state = casted_stub()->state();
+  BinaryOpICState state = casted_stub()->state();

   HValue* allocation_site = GetParameter(
       BinaryOpWithAllocationSiteStub::kAllocationSite);
=======================================
--- /trunk/src/code-stubs.cc    Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/code-stubs.cc    Wed Sep 17 00:05:08 2014 UTC
@@ -10,6 +10,7 @@
 #include "src/factory.h"
 #include "src/gdb-jit.h"
 #include "src/ic/handler-compiler.h"
+#include "src/ic/ic.h"
 #include "src/macro-assembler.h"

 namespace v8 {
@@ -258,7 +259,7 @@
   }

   // Generate special versions of the stub.
-  BinaryOpIC::State::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
+  BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
 }


@@ -269,7 +270,7 @@

 // static
 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate,
-                                         const BinaryOpIC::State& state) {
+                                         const BinaryOpICState& state) {
   BinaryOpICStub stub(isolate, state);
   stub.GetCode();
 }
@@ -278,7 +279,7 @@
 // static
void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
   // Generate special versions of the stub.
-  BinaryOpIC::State::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
+  BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
 }


@@ -290,7 +291,7 @@

 // static
 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(
-    Isolate* isolate, const BinaryOpIC::State& state) {
+    Isolate* isolate, const BinaryOpICState& state) {
   if (state.CouldCreateAllocationMementos()) {
     BinaryOpICWithAllocationSiteStub stub(isolate, state);
     stub.GetCode();
@@ -314,24 +315,29 @@


 InlineCacheState CompareICStub::GetICState() const {
-  CompareIC::State state = Max(left(), right());
+  CompareICState::State state = Max(left(), right());
   switch (state) {
-    case CompareIC::UNINITIALIZED:
+    case CompareICState::UNINITIALIZED:
       return ::v8::internal::UNINITIALIZED;
-    case CompareIC::SMI:
-    case CompareIC::NUMBER:
-    case CompareIC::INTERNALIZED_STRING:
-    case CompareIC::STRING:
-    case CompareIC::UNIQUE_NAME:
-    case CompareIC::OBJECT:
-    case CompareIC::KNOWN_OBJECT:
+    case CompareICState::SMI:
+    case CompareICState::NUMBER:
+    case CompareICState::INTERNALIZED_STRING:
+    case CompareICState::STRING:
+    case CompareICState::UNIQUE_NAME:
+    case CompareICState::OBJECT:
+    case CompareICState::KNOWN_OBJECT:
       return MONOMORPHIC;
-    case CompareIC::GENERIC:
+    case CompareICState::GENERIC:
       return ::v8::internal::GENERIC;
   }
   UNREACHABLE();
   return ::v8::internal::UNINITIALIZED;
 }
+
+
+Condition CompareICStub::GetCondition() const {
+  return CompareIC::ComputeCondition(op());
+}


 void CompareICStub::AddToSpecialCache(Handle<Code> new_object) {
@@ -376,32 +382,32 @@

 void CompareICStub::Generate(MacroAssembler* masm) {
   switch (state()) {
-    case CompareIC::UNINITIALIZED:
+    case CompareICState::UNINITIALIZED:
       GenerateMiss(masm);
       break;
-    case CompareIC::SMI:
+    case CompareICState::SMI:
       GenerateSmis(masm);
       break;
-    case CompareIC::NUMBER:
+    case CompareICState::NUMBER:
       GenerateNumbers(masm);
       break;
-    case CompareIC::STRING:
+    case CompareICState::STRING:
       GenerateStrings(masm);
       break;
-    case CompareIC::INTERNALIZED_STRING:
+    case CompareICState::INTERNALIZED_STRING:
       GenerateInternalizedStrings(masm);
       break;
-    case CompareIC::UNIQUE_NAME:
+    case CompareICState::UNIQUE_NAME:
       GenerateUniqueNames(masm);
       break;
-    case CompareIC::OBJECT:
+    case CompareICState::OBJECT:
       GenerateObjects(masm);
       break;
-    case CompareIC::KNOWN_OBJECT:
+    case CompareICState::KNOWN_OBJECT:
       DCHECK(*known_map_ != NULL);
       GenerateKnownObjects(masm);
       break;
-    case CompareIC::GENERIC:
+    case CompareICState::GENERIC:
       GenerateGeneric(masm);
       break;
   }
=======================================
--- /trunk/src/code-stubs.h     Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/code-stubs.h     Wed Sep 17 00:05:08 2014 UTC
@@ -9,7 +9,7 @@
 #include "src/assembler.h"
 #include "src/codegen.h"
 #include "src/globals.h"
-#include "src/ic/ic.h"
+#include "src/ic/ic-state.h"
 #include "src/interface-descriptors.h"
 #include "src/macro-assembler.h"
 #include "src/ostreams.h"
@@ -781,13 +781,13 @@

 class CallICStub: public PlatformCodeStub {
  public:
-  CallICStub(Isolate* isolate, const CallIC::State& state)
+  CallICStub(Isolate* isolate, const CallICState& state)
       : PlatformCodeStub(isolate) {
     minor_key_ = state.GetExtraICState();
   }

   static int ExtractArgcFromMinorKey(int minor_key) {
-    CallIC::State state(static_cast<ExtraICState>(minor_key));
+    CallICState state(static_cast<ExtraICState>(minor_key));
     return state.arg_count();
   }

@@ -800,16 +800,18 @@
   }

  protected:
- bool CallAsMethod() const { return state().call_type() == CallIC::METHOD; }
+  bool CallAsMethod() const {
+    return state().call_type() == CallICState::METHOD;
+  }

   int arg_count() const { return state().arg_count(); }

-  CallIC::State state() const {
-    return CallIC::State(static_cast<ExtraICState>(minor_key_));
+  CallICState state() const {
+    return CallICState(static_cast<ExtraICState>(minor_key_));
   }

   // Code generation helpers.
-  void GenerateMiss(MacroAssembler* masm, IC::UtilityId id);
+  void GenerateMiss(MacroAssembler* masm);

  private:
   virtual void PrintState(OStream& os) const OVERRIDE;  // NOLINT
@@ -821,7 +823,7 @@

 class CallIC_ArrayStub: public CallICStub {
  public:
-  CallIC_ArrayStub(Isolate* isolate, const CallIC::State& state_in)
+  CallIC_ArrayStub(Isolate* isolate, const CallICState& state_in)
       : CallICStub(isolate, state_in) {}

   virtual InlineCacheState GetICState() const FINAL OVERRIDE {
@@ -1058,11 +1060,11 @@
   BinaryOpICStub(Isolate* isolate, Token::Value op,
                  OverwriteMode mode = NO_OVERWRITE)
       : HydrogenCodeStub(isolate, UNINITIALIZED) {
-    BinaryOpIC::State state(isolate, op, mode);
+    BinaryOpICState state(isolate, op, mode);
     set_sub_minor_key(state.GetExtraICState());
   }

-  BinaryOpICStub(Isolate* isolate, const BinaryOpIC::State& state)
+  BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
       : HydrogenCodeStub(isolate) {
     set_sub_minor_key(state.GetExtraICState());
   }
@@ -1081,8 +1083,8 @@
     return static_cast<ExtraICState>(sub_minor_key());
   }

-  BinaryOpIC::State state() const {
-    return BinaryOpIC::State(isolate(), GetExtraICState());
+  BinaryOpICState state() const {
+    return BinaryOpICState(isolate(), GetExtraICState());
   }

   virtual void PrintState(OStream& os) const FINAL OVERRIDE;  // NOLINT
@@ -1093,7 +1095,7 @@

  private:
   static void GenerateAheadOfTime(Isolate* isolate,
-                                  const BinaryOpIC::State& state);
+                                  const BinaryOpICState& state);

   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
   DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
@@ -1105,7 +1107,7 @@
 class BinaryOpICWithAllocationSiteStub FINAL : public PlatformCodeStub {
  public:
   BinaryOpICWithAllocationSiteStub(Isolate* isolate,
-                                   const BinaryOpIC::State& state)
+                                   const BinaryOpICState& state)
       : PlatformCodeStub(isolate) {
     minor_key_ = state.GetExtraICState();
   }
@@ -1133,12 +1135,12 @@
   virtual void PrintState(OStream& os) const OVERRIDE;  // NOLINT

  private:
-  BinaryOpIC::State state() const {
- return BinaryOpIC::State(isolate(), static_cast<ExtraICState>(minor_key_));
+  BinaryOpICState state() const {
+ return BinaryOpICState(isolate(), static_cast<ExtraICState>(minor_key_));
   }

   static void GenerateAheadOfTime(Isolate* isolate,
-                                  const BinaryOpIC::State& state);
+                                  const BinaryOpICState& state);

   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
@@ -1152,8 +1154,7 @@
                                  OverwriteMode mode)
       : BinaryOpICStub(isolate, op, mode) {}

-  BinaryOpWithAllocationSiteStub(Isolate* isolate,
-                                 const BinaryOpIC::State& state)
+ BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
       : BinaryOpICStub(isolate, state) {}

   virtual Code::Kind GetCodeKind() const FINAL OVERRIDE {
@@ -1216,8 +1217,8 @@

 class CompareICStub : public PlatformCodeStub {
  public:
-  CompareICStub(Isolate* isolate, Token::Value op, CompareIC::State left,
-                CompareIC::State right, CompareIC::State state)
+ CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left,
+                CompareICState::State right, CompareICState::State state)
       : PlatformCodeStub(isolate) {
     DCHECK(Token::IsCompareOp(op));
minor_key_ = OpBits::encode(op - Token::EQ) | LeftStateBits::encode(left) |
@@ -1232,9 +1233,13 @@
return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
   }

- CompareIC::State left() const { return LeftStateBits::decode(minor_key_); } - CompareIC::State right() const { return RightStateBits::decode(minor_key_); }
-  CompareIC::State state() const { return StateBits::decode(minor_key_); }
+  CompareICState::State left() const {
+    return LeftStateBits::decode(minor_key_);
+  }
+  CompareICState::State right() const {
+    return RightStateBits::decode(minor_key_);
+  }
+ CompareICState::State state() const { return StateBits::decode(minor_key_); }

  private:
   virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
@@ -1250,16 +1255,18 @@
   void GenerateGeneric(MacroAssembler* masm);

   bool strict() const { return op() == Token::EQ_STRICT; }
- Condition GetCondition() const { return CompareIC::ComputeCondition(op()); }
+  Condition GetCondition() const;

   virtual void AddToSpecialCache(Handle<Code> new_object);
   virtual bool FindCodeInSpecialCache(Code** code_out);
- virtual bool UseSpecialCache() { return state() == CompareIC::KNOWN_OBJECT; }
+  virtual bool UseSpecialCache() {
+    return state() == CompareICState::KNOWN_OBJECT;
+  }

   class OpBits : public BitField<int, 0, 3> {};
-  class LeftStateBits : public BitField<CompareIC::State, 3, 4> {};
-  class RightStateBits : public BitField<CompareIC::State, 7, 4> {};
-  class StateBits : public BitField<CompareIC::State, 11, 4> {};
+  class LeftStateBits : public BitField<CompareICState::State, 3, 4> {};
+  class RightStateBits : public BitField<CompareICState::State, 7, 4> {};
+  class StateBits : public BitField<CompareICState::State, 11, 4> {};

   Handle<Map> known_map_;

@@ -1740,7 +1747,7 @@

 class LoadICTrampolineStub : public PlatformCodeStub {
  public:
-  LoadICTrampolineStub(Isolate* isolate, const LoadIC::State& state)
+  LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
       : PlatformCodeStub(isolate) {
     minor_key_ = state.GetExtraICState();
   }
@@ -1756,8 +1763,8 @@
   }

  private:
-  LoadIC::State state() const {
-    return LoadIC::State(static_cast<ExtraICState>(minor_key_));
+  LoadICState state() const {
+    return LoadICState(static_cast<ExtraICState>(minor_key_));
   }

   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadICTrampoline);
@@ -1768,7 +1775,7 @@
 class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
  public:
   explicit KeyedLoadICTrampolineStub(Isolate* isolate)
-      : LoadICTrampolineStub(isolate, LoadIC::State(0)) {}
+      : LoadICTrampolineStub(isolate, LoadICState(0)) {}

   virtual Code::Kind GetCodeKind() const OVERRIDE {
     return Code::KEYED_LOAD_IC;
@@ -1780,7 +1787,7 @@

 class MegamorphicLoadStub : public HydrogenCodeStub {
  public:
-  MegamorphicLoadStub(Isolate* isolate, const LoadIC::State& state)
+  MegamorphicLoadStub(Isolate* isolate, const LoadICState& state)
       : HydrogenCodeStub(isolate) {
     set_sub_minor_key(state.GetExtraICState());
   }
@@ -1802,7 +1809,7 @@

 class VectorLoadStub : public HydrogenCodeStub {
  public:
-  explicit VectorLoadStub(Isolate* isolate, const LoadIC::State& state)
+  explicit VectorLoadStub(Isolate* isolate, const LoadICState& state)
       : HydrogenCodeStub(isolate) {
     set_sub_minor_key(state.GetExtraICState());
   }
@@ -1818,7 +1825,7 @@
   }

  private:
-  LoadIC::State state() const { return LoadIC::State(GetExtraICState()); }
+  LoadICState state() const { return LoadICState(GetExtraICState()); }

   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadIC);
   DEFINE_HYDROGEN_CODE_STUB(VectorLoad, HydrogenCodeStub);
@@ -1828,7 +1835,7 @@
 class VectorKeyedLoadStub : public VectorLoadStub {
  public:
   explicit VectorKeyedLoadStub(Isolate* isolate)
-      : VectorLoadStub(isolate, LoadIC::State(0)) {}
+      : VectorLoadStub(isolate, LoadICState(0)) {}

   virtual Code::Kind GetCodeKind() const OVERRIDE {
     return Code::KEYED_LOAD_IC;
=======================================
--- /trunk/src/codegen.cc       Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/codegen.cc       Wed Sep 17 00:05:08 2014 UTC
@@ -116,6 +116,7 @@
           CodeStub::MajorName(info->code_stub()->MajorKey(), true);
       PrintF("%s", name == NULL ? "<unknown>" : name);
     } else {
+      AllowDeferredHandleDereference allow_deference_for_trace;
       PrintF("%s", info->function()->debug_name()->ToCString().get());
     }
     PrintF("]\n");
=======================================
--- /trunk/src/compiler/ast-graph-builder.cc    Tue Sep 16 07:50:38 2014 UTC
+++ /trunk/src/compiler/ast-graph-builder.cc    Wed Sep 17 00:05:08 2014 UTC
@@ -1931,9 +1931,8 @@

 Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
   // TODO(sigurds) Use simplified load here once it is ready.
-  MachineOperatorBuilder machine;
-  Node* field_load = NewNode(machine.Load(kMachAnyTagged), object,
- jsgraph_->Int32Constant(offset - kHeapObjectTag)); + Node* field_load = NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object, + jsgraph()->Int32Constant(offset - kHeapObjectTag));
   return field_load;
 }

=======================================
--- /trunk/src/compiler/change-lowering-unittest.cc Mon Sep 15 00:05:18 2014 UTC +++ /trunk/src/compiler/change-lowering-unittest.cc Wed Sep 17 00:05:08 2014 UTC
@@ -79,7 +79,7 @@
     JSGraph jsgraph(graph(), common(), &javascript, &typer, &machine);
     CompilationInfo info(isolate(), zone());
     Linkage linkage(&info);
-    ChangeLowering reducer(&jsgraph, &linkage, &machine);
+    ChangeLowering reducer(&jsgraph, &linkage);
     return reducer.Reduce(node);
   }

=======================================
--- /trunk/src/compiler/change-lowering.cc      Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/compiler/change-lowering.cc      Wed Sep 17 00:05:08 2014 UTC
@@ -245,6 +245,11 @@
 CommonOperatorBuilder* ChangeLowering::common() const {
   return jsgraph()->common();
 }
+
+
+MachineOperatorBuilder* ChangeLowering::machine() const {
+  return jsgraph()->machine();
+}

 }  // namespace compiler
 }  // namespace internal
=======================================
--- /trunk/src/compiler/change-lowering.h       Tue Sep  2 12:59:15 2014 UTC
+++ /trunk/src/compiler/change-lowering.h       Wed Sep 17 00:05:08 2014 UTC
@@ -19,9 +19,8 @@

 class ChangeLowering FINAL : public Reducer {
  public:
-  ChangeLowering(JSGraph* jsgraph, Linkage* linkage,
-                 MachineOperatorBuilder* machine)
-      : jsgraph_(jsgraph), linkage_(linkage), machine_(machine) {}
+  ChangeLowering(JSGraph* jsgraph, Linkage* linkage)
+      : jsgraph_(jsgraph), linkage_(linkage) {}
   virtual ~ChangeLowering();

   virtual Reduction Reduce(Node* node) OVERRIDE;
@@ -50,11 +49,10 @@
   JSGraph* jsgraph() const { return jsgraph_; }
   Linkage* linkage() const { return linkage_; }
   CommonOperatorBuilder* common() const;
-  MachineOperatorBuilder* machine() const { return machine_; }
+  MachineOperatorBuilder* machine() const;

   JSGraph* jsgraph_;
   Linkage* linkage_;
-  MachineOperatorBuilder* machine_;
 };

 }  // namespace compiler
=======================================
--- /trunk/src/compiler/js-typed-lowering.cc    Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/compiler/js-typed-lowering.cc    Wed Sep 17 00:05:08 2014 UTC
@@ -232,6 +232,11 @@
     r.ConvertInputsToNumber();
     return r.ChangeToPureOperator(simplified()->NumberAdd());
   }
+#if 0
+  // TODO(turbofan): Lowering of StringAdd is disabled for now because:
+ // a) The inserted ToString operation screws up valueOf vs. toString order.
+  //   b) Deoptimization at ToString doesn't have corresponding bailout id.
+ // c) Our current StringAddStub is actually non-pure and requires context.
   if (r.OneInputIs(Type::String())) {
     // JSAdd(x:string, y:string) => StringAdd(x, y)
     // JSAdd(x:string, y) => StringAdd(x, ToString(y))
@@ -239,6 +244,7 @@
     r.ConvertInputsToString();
     return r.ChangeToPureOperator(simplified()->StringAdd());
   }
+#endif
   return NoChange();
 }

@@ -303,7 +309,9 @@
         return NoChange();
     }
     return r.ChangeToPureOperator(stringOp);
-  } else if (r.OneInputCannotBe(Type::String())) {
+  }
+ Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone());
+  if (r.OneInputCannotBe(maybe_string)) {
     // If one input cannot be a string, then emit a number comparison.
     const Operator* less_than;
     const Operator* less_than_or_equal;
=======================================
--- /trunk/src/compiler/js-typed-lowering.h     Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/compiler/js-typed-lowering.h     Wed Sep 17 00:05:08 2014 UTC
@@ -51,11 +51,10 @@
   JSOperatorBuilder* javascript() { return jsgraph_->javascript(); }
   CommonOperatorBuilder* common() { return jsgraph_->common(); }
   SimplifiedOperatorBuilder* simplified() { return &simplified_; }
-  MachineOperatorBuilder* machine() { return &machine_; }
+  MachineOperatorBuilder* machine() { return jsgraph_->machine(); }

   JSGraph* jsgraph_;
   SimplifiedOperatorBuilder simplified_;
-  MachineOperatorBuilder machine_;
 };

 }  // namespace compiler
=======================================
--- /trunk/src/compiler/machine-operator-reducer.cc Fri Sep 12 00:05:16 2014 UTC +++ /trunk/src/compiler/machine-operator-reducer.cc Wed Sep 17 00:05:08 2014 UTC
@@ -475,6 +475,11 @@
 CommonOperatorBuilder* MachineOperatorReducer::common() const {
   return jsgraph()->common();
 }
+
+
+MachineOperatorBuilder* MachineOperatorReducer::machine() const {
+  return jsgraph()->machine();
+}


 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); }
=======================================
--- /trunk/src/compiler/machine-operator-reducer.h Thu Sep 11 00:05:22 2014 UTC +++ /trunk/src/compiler/machine-operator-reducer.h Wed Sep 17 00:05:08 2014 UTC
@@ -47,10 +47,9 @@
   Graph* graph() const;
   JSGraph* jsgraph() const { return jsgraph_; }
   CommonOperatorBuilder* common() const;
-  MachineOperatorBuilder* machine() { return &machine_; }
+  MachineOperatorBuilder* machine() const;

   JSGraph* jsgraph_;
-  MachineOperatorBuilder machine_;
 };

 }  // namespace compiler
=======================================
--- /trunk/src/compiler/pipeline.cc     Mon Sep 15 00:05:18 2014 UTC
+++ /trunk/src/compiler/pipeline.cc     Wed Sep 17 00:05:08 2014 UTC
@@ -259,8 +259,8 @@
                                      SourcePosition::Unknown());
       Linkage linkage(info());
       ValueNumberingReducer vn_reducer(zone());
-      SimplifiedOperatorReducer simple_reducer(&jsgraph, &machine);
-      ChangeLowering lowering(&jsgraph, &linkage, &machine);
+      SimplifiedOperatorReducer simple_reducer(&jsgraph);
+      ChangeLowering lowering(&jsgraph, &linkage);
       MachineOperatorReducer mach_reducer(&jsgraph);
       GraphReducer graph_reducer(&graph);
// TODO(titzer): Figure out if we should run all reducers at once here.
=======================================
--- /trunk/src/compiler/representation-change.h Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/compiler/representation-change.h Wed Sep 17 00:05:08 2014 UTC
@@ -21,10 +21,9 @@
 class RepresentationChanger {
  public:
RepresentationChanger(JSGraph* jsgraph, SimplifiedOperatorBuilder* simplified,
-                        MachineOperatorBuilder* machine, Isolate* isolate)
+                        Isolate* isolate)
       : jsgraph_(jsgraph),
         simplified_(simplified),
-        machine_(machine),
         isolate_(isolate),
         testing_type_errors_(false),
         type_error_(false) {}
@@ -309,7 +308,6 @@
  private:
   JSGraph* jsgraph_;
   SimplifiedOperatorBuilder* simplified_;
-  MachineOperatorBuilder* machine_;
   Isolate* isolate_;

   friend class RepresentationChangerTester;  // accesses the below fields.
@@ -339,7 +337,7 @@
   JSGraph* jsgraph() { return jsgraph_; }
   Isolate* isolate() { return isolate_; }
   SimplifiedOperatorBuilder* simplified() { return simplified_; }
-  MachineOperatorBuilder* machine() { return machine_; }
+  MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
 };
 }
 }
=======================================
--- /trunk/src/compiler/simplified-lowering.cc  Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/compiler/simplified-lowering.cc  Wed Sep 17 00:05:08 2014 UTC
@@ -764,7 +764,7 @@

 void SimplifiedLowering::LowerAllNodes() {
   SimplifiedOperatorBuilder simplified(graph()->zone());
-  RepresentationChanger changer(jsgraph(), &simplified, machine(),
+  RepresentationChanger changer(jsgraph(), &simplified,
                                 graph()->zone()->isolate());
   RepresentationSelector selector(jsgraph(), zone(), &changer);
   selector.Run(this);
@@ -805,7 +805,7 @@

 void SimplifiedLowering::DoLoadField(Node* node) {
   const FieldAccess& access = FieldAccessOf(node->op());
-  node->set_op(machine_.Load(access.machine_type));
+  node->set_op(machine()->Load(access.machine_type));
   Node* offset = jsgraph()->Int32Constant(access.offset - access.tag());
   node->InsertInput(zone(), 1, offset);
 }
@@ -815,7 +815,8 @@
   const FieldAccess& access = FieldAccessOf(node->op());
   WriteBarrierKind kind = ComputeWriteBarrierKind(
       access.base_is_tagged, access.machine_type, access.type);
- node->set_op(machine_.Store(StoreRepresentation(access.machine_type, kind)));
+  node->set_op(
+      machine()->Store(StoreRepresentation(access.machine_type, kind)));
   Node* offset = jsgraph()->Int32Constant(access.offset - access.tag());
   node->InsertInput(zone(), 1, offset);
 }
@@ -837,7 +838,7 @@

 void SimplifiedLowering::DoLoadElement(Node* node) {
   const ElementAccess& access = ElementAccessOf(node->op());
-  node->set_op(machine_.Load(access.machine_type));
+  node->set_op(machine()->Load(access.machine_type));
   node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1)));
 }

@@ -846,7 +847,8 @@
   const ElementAccess& access = ElementAccessOf(node->op());
   WriteBarrierKind kind = ComputeWriteBarrierKind(
       access.base_is_tagged, access.machine_type, access.type);
- node->set_op(machine_.Store(StoreRepresentation(access.machine_type, kind)));
+  node->set_op(
+      machine()->Store(StoreRepresentation(access.machine_type, kind)));
   node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1)));
 }

=======================================
--- /trunk/src/compiler/simplified-lowering.h   Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/compiler/simplified-lowering.h   Wed Sep 17 00:05:08 2014 UTC
@@ -33,7 +33,6 @@

  private:
   JSGraph* jsgraph_;
-  MachineOperatorBuilder machine_;

   Node* SmiTag(Node* node);
   Node* IsTagged(Node* node);
@@ -48,7 +47,7 @@
   JSGraph* jsgraph() { return jsgraph_; }
   Graph* graph() { return jsgraph()->graph(); }
   CommonOperatorBuilder* common() { return jsgraph()->common(); }
-  MachineOperatorBuilder* machine() { return &machine_; }
+  MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
 };

 }  // namespace compiler
=======================================
--- /trunk/src/compiler/simplified-operator-reducer-unittest.cc Tue Sep 16 07:50:38 2014 UTC +++ /trunk/src/compiler/simplified-operator-reducer-unittest.cc Wed Sep 17 00:05:08 2014 UTC
@@ -25,7 +25,7 @@
     MachineOperatorBuilder machine;
     JSOperatorBuilder javascript(zone());
     JSGraph jsgraph(graph(), common(), &javascript, &typer, &machine);
-    SimplifiedOperatorReducer reducer(&jsgraph, &machine);
+    SimplifiedOperatorReducer reducer(&jsgraph);
     return reducer.Reduce(node);
   }

=======================================
--- /trunk/src/compiler/simplified-operator-reducer.cc Thu Sep 11 00:05:22 2014 UTC +++ /trunk/src/compiler/simplified-operator-reducer.cc Wed Sep 17 00:05:08 2014 UTC
@@ -136,6 +136,11 @@
 Factory* SimplifiedOperatorReducer::factory() const {
   return jsgraph()->isolate()->factory();
 }
+
+
+MachineOperatorBuilder* SimplifiedOperatorReducer::machine() const {
+  return jsgraph()->machine();
+}

 }  // namespace compiler
 }  // namespace internal
=======================================
--- /trunk/src/compiler/simplified-operator-reducer.h Thu Sep 11 00:05:22 2014 UTC +++ /trunk/src/compiler/simplified-operator-reducer.h Wed Sep 17 00:05:08 2014 UTC
@@ -21,8 +21,7 @@

 class SimplifiedOperatorReducer FINAL : public Reducer {
  public:
- SimplifiedOperatorReducer(JSGraph* jsgraph, MachineOperatorBuilder* machine)
-      : jsgraph_(jsgraph), machine_(machine) {}
+ explicit SimplifiedOperatorReducer(JSGraph* jsgraph) : jsgraph_(jsgraph) {}
   virtual ~SimplifiedOperatorReducer();

   virtual Reduction Reduce(Node* node) OVERRIDE;
@@ -40,10 +39,9 @@
   Graph* graph() const;
   Factory* factory() const;
   JSGraph* jsgraph() const { return jsgraph_; }
-  MachineOperatorBuilder* machine() const { return machine_; }
+  MachineOperatorBuilder* machine() const;

   JSGraph* jsgraph_;
-  MachineOperatorBuilder* machine_;

   DISALLOW_COPY_AND_ASSIGN(SimplifiedOperatorReducer);
 };
=======================================
--- /trunk/src/counters.h       Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/counters.h       Wed Sep 17 00:05:08 2014 UTC
@@ -291,9 +291,11 @@
 #endif
 };

-#define HISTOGRAM_RANGE_LIST(HR) \
-  /* Generic range histograms */ \
-  HR(gc_idle_time_allotted_in_ms, V8.GCIdleTimeAllottedInMS, 0, 10000, 101)
+#define HISTOGRAM_RANGE_LIST(HR) \ + /* Generic range histograms */ \ + HR(gc_idle_time_allotted_in_ms, V8.GCIdleTimeAllottedInMS, 0, 10000, 101) \ + HR(gc_idle_time_limit_overshot, V8.GCIdleTimeLimit.Overshot, 0, 10000, 101) \ + HR(gc_idle_time_limit_undershot, V8.GCIdleTimeLimi.Undershot, 0, 10000, 101)

 #define HISTOGRAM_TIMER_LIST(HT)                             \
   /* Garbage collection timers. */                           \
@@ -309,8 +311,7 @@
   HT(pre_parse, V8.PreParse)                                 \
   /* Total compilation times. */                             \
   HT(compile, V8.Compile)                                    \
-  HT(compile_eval, V8.CompileEval)                           \
-  HT(compile_lazy, V8.CompileLazy)
+  HT(compile_eval, V8.CompileEval)

 #define HISTOGRAM_PERCENTAGE_LIST(HP)                                 \
   /* Heap fragmentation. */                                           \
=======================================
--- /trunk/src/d8.cc    Tue Sep 16 07:50:38 2014 UTC
+++ /trunk/src/d8.cc    Wed Sep 17 00:05:08 2014 UTC
@@ -1621,14 +1621,13 @@
 #ifdef ENABLE_VTUNE_JIT_INTERFACE
   vTune::InitializeVtuneForV8(create_params);
 #endif
-  Isolate* isolate = Isolate::New(create_params);
 #ifndef V8_SHARED
-  v8::ResourceConstraints constraints;
-  constraints.ConfigureDefaults(base::SysInfo::AmountOfPhysicalMemory(),
-                                base::SysInfo::AmountOfVirtualMemory(),
-                                base::SysInfo::NumberOfProcessors());
-  v8::SetResourceConstraints(isolate, &constraints);
+  create_params.constraints.ConfigureDefaults(
+      base::SysInfo::AmountOfPhysicalMemory(),
+      base::SysInfo::AmountOfVirtualMemory(),
+      base::SysInfo::NumberOfProcessors());
 #endif
+  Isolate* isolate = Isolate::New(create_params);
   DumbLineEditor dumb_line_editor(isolate);
   {
     Isolate::Scope scope(isolate);
=======================================
--- /trunk/src/disassembler.cc  Tue Aug  5 00:05:55 2014 UTC
+++ /trunk/src/disassembler.cc  Wed Sep 17 00:05:08 2014 UTC
@@ -214,7 +214,8 @@
         Code::Kind kind = code->kind();
         if (code->is_inline_cache_stub()) {
           if (kind == Code::LOAD_IC &&
- LoadIC::GetContextualMode(code->extra_ic_state()) == CONTEXTUAL) {
+              LoadICState::GetContextualMode(code->extra_ic_state()) ==
+                  CONTEXTUAL) {
             out.AddFormatted(" contextual,");
           }
           InlineCacheState ic_state = code->ic_state();
=======================================
--- /trunk/src/flag-definitions.h       Mon Sep 15 00:05:18 2014 UTC
+++ /trunk/src/flag-definitions.h       Wed Sep 17 00:05:08 2014 UTC
@@ -154,7 +154,6 @@
 DEFINE_BOOL(harmony_modules, false,
             "enable harmony modules (implies block scoping)")
 DEFINE_BOOL(harmony_proxies, false, "enable harmony proxies")
-DEFINE_BOOL(harmony_generators, false, "enable harmony generators")
 DEFINE_BOOL(harmony_numeric_literals, false,
             "enable harmony numeric literals (0o77, 0b11)")
 DEFINE_BOOL(harmony_strings, false, "enable harmony string")
@@ -178,7 +177,6 @@
 DEFINE_IMPLICATION(harmony_modules, harmony_scoping)

 DEFINE_IMPLICATION(harmony, es_staging)
-DEFINE_IMPLICATION(es_staging, harmony_generators)

 // Flags for experimental implementation features.
 DEFINE_BOOL(compiled_keyed_generic_loads, false,
=======================================
--- /trunk/src/full-codegen.h   Tue Aug  5 00:05:55 2014 UTC
+++ /trunk/src/full-codegen.h   Wed Sep 17 00:05:08 2014 UTC
@@ -475,7 +475,7 @@
   void EmitReturnSequence();

   // Platform-specific code sequences for calls
-  void EmitCall(Call* expr, CallIC::CallType = CallIC::FUNCTION);
+  void EmitCall(Call* expr, CallICState::CallType = CallICState::FUNCTION);
   void EmitCallWithLoadIC(Call* expr);
   void EmitKeyedCallWithLoadIC(Call* expr, Expression* key);

=======================================
--- /trunk/src/heap/gc-idle-time-handler-unittest.cc Tue Sep 16 07:50:38 2014 UTC +++ /trunk/src/heap/gc-idle-time-handler-unittest.cc Wed Sep 17 00:05:08 2014 UTC
@@ -28,12 +28,17 @@
     result.sweeping_in_progress = false;
     result.mark_compact_speed_in_bytes_per_ms = kMarkCompactSpeed;
     result.incremental_marking_speed_in_bytes_per_ms = kMarkingSpeed;
+    result.scavenge_speed_in_bytes_per_ms = kScavengeSpeed;
+    result.available_new_space_memory = kNewSpaceCapacity;
+    result.new_space_capacity = kNewSpaceCapacity;
     return result;
   }

   static const size_t kSizeOfObjects = 100 * MB;
   static const size_t kMarkCompactSpeed = 200 * KB;
   static const size_t kMarkingSpeed = 200 * KB;
+  static const size_t kScavengeSpeed = 100 * KB;
+  static const size_t kNewSpaceCapacity = 1 * MB;

  private:
   GCIdleTimeHandler handler_;
@@ -99,6 +104,21 @@
   size_t time = GCIdleTimeHandler::EstimateMarkCompactTime(size, speed);
   EXPECT_EQ(GCIdleTimeHandler::kMaxMarkCompactTimeInMs, time);
 }
+
+
+TEST(GCIdleTimeHandler, EstimateScavengeTimeInitial) {
+  size_t size = 1 * MB;
+  size_t time = GCIdleTimeHandler::EstimateScavengeTime(size, 0);
+ EXPECT_EQ(size / GCIdleTimeHandler::kInitialConservativeScavengeSpeed, time);
+}
+
+
+TEST(GCIdleTimeHandler, EstimateScavengeTimeNonZero) {
+  size_t size = 1 * MB;
+  size_t speed = 1 * MB;
+  size_t time = GCIdleTimeHandler::EstimateScavengeTime(size, speed);
+  EXPECT_EQ(size / speed, time);
+}


 TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeLargeIdleTime) {
@@ -182,7 +202,7 @@
     handler()->NotifyIdleMarkCompact();
   }
   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
-  EXPECT_EQ(DO_NOTHING, action.type);
+  EXPECT_EQ(DONE, action.type);
 }


@@ -192,10 +212,13 @@
for (int i = 0; i < GCIdleTimeHandler::kMaxMarkCompactsInIdleRound; i++) {
     GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
     EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
+    // In this case we emulate incremental marking steps that finish with a
+    // full gc.
     handler()->NotifyIdleMarkCompact();
   }
+  heap_state.can_start_incremental_marking = false;
   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
-  EXPECT_EQ(DO_NOTHING, action.type);
+  EXPECT_EQ(DONE, action.type);
 }


@@ -211,7 +234,7 @@
     handler()->NotifyIdleMarkCompact();
   }
   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
-  EXPECT_EQ(DO_NOTHING, action.type);
+  EXPECT_EQ(DONE, action.type);
   // Emulate mutator work.
   for (int i = 0; i < GCIdleTimeHandler::kIdleScavengeThreshold; i++) {
     handler()->NotifyScavenge();
@@ -226,16 +249,20 @@
   int idle_time_ms = 10;
for (int i = 0; i < GCIdleTimeHandler::kMaxMarkCompactsInIdleRound; i++) {
     GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
-    if (action.type == DO_NOTHING) break;
+    if (action.type == DONE) break;
     EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
+ // In this case we try to emulate incremental marking steps the finish with
+    // a full gc.
     handler()->NotifyIdleMarkCompact();
   }
+  heap_state.can_start_incremental_marking = false;
   GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
-  EXPECT_EQ(DO_NOTHING, action.type);
+  EXPECT_EQ(DONE, action.type);
   // Emulate mutator work.
   for (int i = 0; i < GCIdleTimeHandler::kIdleScavengeThreshold; i++) {
     handler()->NotifyScavenge();
   }
+  heap_state.can_start_incremental_marking = true;
   action = handler()->Compute(idle_time_ms, heap_state);
   EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
 }
=======================================
--- /trunk/src/heap/gc-idle-time-handler.cc     Tue Sep 16 07:50:38 2014 UTC
+++ /trunk/src/heap/gc-idle-time-handler.cc     Wed Sep 17 00:05:08 2014 UTC
@@ -18,6 +18,9 @@

 void GCIdleTimeAction::Print() {
   switch (type) {
+    case DONE:
+      PrintF("done");
+      break;
     case DO_NOTHING:
       PrintF("no action");
       break;
@@ -68,15 +71,47 @@
 }


+size_t GCIdleTimeHandler::EstimateScavengeTime(
+    size_t new_space_size, size_t scavenge_speed_in_bytes_per_ms) {
+  if (scavenge_speed_in_bytes_per_ms == 0) {
+    scavenge_speed_in_bytes_per_ms = kInitialConservativeScavengeSpeed;
+  }
+  return new_space_size / scavenge_speed_in_bytes_per_ms;
+}
+
+
+// The following logic is implemented by the controller:
+// (1) If the new space is almost full and we can effort a Scavenge, then a
+// Scavenge is performed.
+// (2) If there is currently no MarkCompact idle round going on, we start a
+// new idle round if enough garbage was created or we received a context
+// disposal event. Otherwise we do not perform garbage collection to keep
+// system utilization low.
+// (3) If incremental marking is done, we perform a full garbage collection
+// if context was disposed or if we are allowed to still do full garbage
+// collections during this idle round or if we are not allowed to start
+// incremental marking. Otherwise we do not perform garbage collection to
+// keep system utilization low.
+// (4) If sweeping is in progress and we received a large enough idle time
+// request, we finalize sweeping here.
+// (5) If incremental marking is in progress, we perform a marking step. Note,
+// that this currently may trigger a full garbage collection.
 GCIdleTimeAction GCIdleTimeHandler::Compute(size_t idle_time_in_ms,
                                             HeapState heap_state) {
-  if (IsIdleRoundFinished()) {
+ if (heap_state.available_new_space_memory < kNewSpaceAlmostFullTreshold &&
+      idle_time_in_ms >=
+          EstimateScavengeTime(heap_state.new_space_capacity,
+ heap_state.scavenge_speed_in_bytes_per_ms)) {
+    return GCIdleTimeAction::Scavenge();
+  }
+  if (IsMarkCompactIdleRoundFinished()) {
if (EnoughGarbageSinceLastIdleRound() || heap_state.contexts_disposed
0) {
       StartIdleRound();
     } else {
-      return GCIdleTimeAction::Nothing();
+      return GCIdleTimeAction::Done();
     }
   }
+
   if (heap_state.incremental_marking_stopped) {
     size_t estimated_time_in_ms =
         EstimateMarkCompactTime(heap_state.size_of_objects,
@@ -91,8 +126,10 @@
// can get rid of this special case and always start incremental marking.
       int remaining_mark_sweeps =
kMaxMarkCompactsInIdleRound - mark_compacts_since_idle_round_started_;
-      if (heap_state.contexts_disposed > 0 || remaining_mark_sweeps <= 2 ||
-          !heap_state.can_start_incremental_marking) {
+      if (heap_state.contexts_disposed > 0 ||
+          (idle_time_in_ms > kMaxFrameRenderingIdleTime &&
+           (remaining_mark_sweeps <= 2 ||
+            !heap_state.can_start_incremental_marking))) {
         return GCIdleTimeAction::FullGC();
       }
     }
@@ -106,6 +143,10 @@
     return GCIdleTimeAction::FinalizeSweeping();
   }

+  if (heap_state.incremental_marking_stopped &&
+      !heap_state.can_start_incremental_marking) {
+    return GCIdleTimeAction::Nothing();
+  }
   size_t step_size = EstimateMarkingStepSize(
idle_time_in_ms, heap_state.incremental_marking_speed_in_bytes_per_ms);
   return GCIdleTimeAction::IncrementalMarking(step_size);
=======================================
--- /trunk/src/heap/gc-idle-time-handler.h      Fri Sep 12 00:05:16 2014 UTC
+++ /trunk/src/heap/gc-idle-time-handler.h      Wed Sep 17 00:05:08 2014 UTC
@@ -11,6 +11,7 @@
 namespace internal {

 enum GCIdleTimeActionType {
+  DONE,
   DO_NOTHING,
   DO_INCREMENTAL_MARKING,
   DO_SCAVENGE,
@@ -21,6 +22,13 @@

 class GCIdleTimeAction {
  public:
+  static GCIdleTimeAction Done() {
+    GCIdleTimeAction result;
+    result.type = DONE;
+    result.parameter = 0;
+    return result;
+  }
+
   static GCIdleTimeAction Nothing() {
     GCIdleTimeAction result;
     result.type = DO_NOTHING;
@@ -102,6 +110,17 @@
   // step.
   static const size_t kSmallHeapSize = 2 * kPointerSize * MB;

+  // That is the maximum idle time we will have during frame rendering.
+  static const size_t kMaxFrameRenderingIdleTime = 16;
+
+  // If less than that much memory is left in the new space, we consider it
+ // as almost full and force a new space collection earlier in the idle time.
+  static const size_t kNewSpaceAlmostFullTreshold = 100 * KB;
+
+  // If we haven't recorded any scavenger events yet, we use a conservative
+  // lower bound for the scavenger speed.
+  static const size_t kInitialConservativeScavengeSpeed = 100 * KB;
+
   struct HeapState {
     int contexts_disposed;
     size_t size_of_objects;
@@ -110,6 +129,9 @@
     bool sweeping_in_progress;
     size_t mark_compact_speed_in_bytes_per_ms;
     size_t incremental_marking_speed_in_bytes_per_ms;
+    size_t scavenge_speed_in_bytes_per_ms;
+    size_t available_new_space_memory;
+    size_t new_space_capacity;
   };

   GCIdleTimeHandler()
@@ -136,9 +158,12 @@
   static size_t EstimateMarkCompactTime(
       size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms);

+  static size_t EstimateScavengeTime(size_t new_space_size,
+ size_t scavenger_speed_in_bytes_per_ms);
+
  private:
   void StartIdleRound() { mark_compacts_since_idle_round_started_ = 0; }
-  bool IsIdleRoundFinished() {
+  bool IsMarkCompactIdleRoundFinished() {
     return mark_compacts_since_idle_round_started_ ==
            kMaxMarkCompactsInIdleRound;
   }
=======================================
--- /trunk/src/heap/heap.cc     Tue Sep 16 07:50:38 2014 UTC
+++ /trunk/src/heap/heap.cc     Wed Sep 17 00:05:08 2014 UTC
@@ -1548,8 +1548,6 @@
   LOG(isolate_, ResourceEvent("scavenge", "end"));

   gc_state_ = NOT_IN_GC;
-
-  gc_idle_time_handler_.NotifyScavenge();
 }


@@ -4292,9 +4290,7 @@
   // If incremental marking is off, we do not perform idle notification.
   if (!FLAG_incremental_marking) return true;
   base::ElapsedTimer timer;
-  if (FLAG_trace_idle_notification) {
-    timer.Start();
-  }
+  timer.Start();
   isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample(
       idle_time_in_ms);
   HistogramTimerScope idle_notification_scope(
@@ -4305,19 +4301,27 @@
   heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects());
heap_state.incremental_marking_stopped = incremental_marking()->IsStopped();
   // TODO(ulan): Start incremental marking only for large heaps.
-  heap_state.can_start_incremental_marking = true;
+  heap_state.can_start_incremental_marking =
+      incremental_marking()->ShouldActivate();
   heap_state.sweeping_in_progress =
       mark_compact_collector()->sweeping_in_progress();
   heap_state.mark_compact_speed_in_bytes_per_ms =
static_cast<size_t>(tracer()->MarkCompactSpeedInBytesPerMillisecond()); heap_state.incremental_marking_speed_in_bytes_per_ms = static_cast<size_t>(
       tracer()->IncrementalMarkingSpeedInBytesPerMillisecond());
+  heap_state.scavenge_speed_in_bytes_per_ms =
+      static_cast<size_t>(tracer()->ScavengeSpeedInBytesPerMillisecond());
+  heap_state.available_new_space_memory = new_space_.Available();
+  heap_state.new_space_capacity = new_space_.Capacity();

   GCIdleTimeAction action =
       gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state);

   bool result = false;
   switch (action.type) {
+    case DONE:
+      result = true;
+      break;
     case DO_INCREMENTAL_MARKING:
       if (incremental_marking()->IsStopped()) {
         incremental_marking()->Start();
@@ -4340,11 +4344,19 @@
       mark_compact_collector()->EnsureSweepingCompleted();
       break;
     case DO_NOTHING:
-      result = true;
       break;
   }
+
+  int actual_time_ms = static_cast<int>(timer.Elapsed().InMilliseconds());
+  if (actual_time_ms <= idle_time_in_ms) {
+    isolate()->counters()->gc_idle_time_limit_undershot()->AddSample(
+        idle_time_in_ms - actual_time_ms);
+  } else {
+    isolate()->counters()->gc_idle_time_limit_overshot()->AddSample(
+        actual_time_ms - idle_time_in_ms);
+  }
+
   if (FLAG_trace_idle_notification) {
- int actual_time_ms = static_cast<int>(timer.Elapsed().InMilliseconds()); PrintF("Idle notification: requested idle time %d ms, actual time %d ms [",
            idle_time_in_ms, actual_time_ms);
     action.Print();
=======================================
--- /trunk/src/heap/incremental-marking.cc      Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/heap/incremental-marking.cc      Wed Sep 17 00:05:08 2014 UTC
@@ -419,6 +419,11 @@
     lop = lop->next_page();
   }
 }
+
+
+bool IncrementalMarking::ShouldActivate() {
+  return WorthActivating() && heap_->NextGCIsLikelyToBeFull();
+}


 bool IncrementalMarking::WorthActivating() {
@@ -811,7 +816,7 @@


 void IncrementalMarking::OldSpaceStep(intptr_t allocated) {
- if (IsStopped() && WorthActivating() && heap_->NextGCIsLikelyToBeFull()) {
+  if (IsStopped() && ShouldActivate()) {
     // TODO(hpayer): Let's play safe for now, but compaction should be
     // in principle possible.
     Start(PREVENT_COMPACTION);
=======================================
--- /trunk/src/heap/incremental-marking.h       Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/heap/incremental-marking.h       Wed Sep 17 00:05:08 2014 UTC
@@ -44,6 +44,8 @@

   bool WorthActivating();

+  bool ShouldActivate();
+
   enum CompactionFlag { ALLOW_COMPACTION, PREVENT_COMPACTION };

   void Start(CompactionFlag flag = ALLOW_COMPACTION);
=======================================
--- /trunk/src/heap/mark-compact.cc     Thu Sep 11 00:05:22 2014 UTC
+++ /trunk/src/heap/mark-compact.cc     Wed Sep 17 00:05:08 2014 UTC
@@ -20,6 +20,7 @@
 #include "src/heap/spaces-inl.h"
 #include "src/heap/sweeper-thread.h"
 #include "src/heap-profiler.h"
+#include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"

 namespace v8 {
=======================================
***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