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*>(¶ms.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.