| Index: src/ic/ic-state.h
|
| diff --git a/src/ic/ic-state.h b/src/ic/ic-state.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b84bdb9a70ba628acf4d19d30b77efdb0cacbdc0
|
| --- /dev/null
|
| +++ b/src/ic/ic-state.h
|
| @@ -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_
|
|
|