| Index: src/code-stubs.h
|
| diff --git a/src/code-stubs.h b/src/code-stubs.h
|
| index e4384e7573d592af78df0d5166252db8eb087404..3110b54b996afbd6223c5f4ebc59492d93219593 100644
|
| --- a/src/code-stubs.h
|
| +++ b/src/code-stubs.h
|
| @@ -482,10 +482,132 @@ class MathPowStub: public CodeStub {
|
| };
|
|
|
|
|
| +class BinaryOpStub: public CodeStub {
|
| + public:
|
| + BinaryOpStub(Token::Value op, OverwriteMode mode)
|
| + : op_(op),
|
| + mode_(mode),
|
| + platform_specific_bit_(false),
|
| + left_type_(BinaryOpIC::UNINITIALIZED),
|
| + right_type_(BinaryOpIC::UNINITIALIZED),
|
| + result_type_(BinaryOpIC::UNINITIALIZED) {
|
| + Initialize();
|
| + ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
|
| + }
|
| +
|
| + BinaryOpStub(
|
| + int key,
|
| + BinaryOpIC::TypeInfo left_type,
|
| + BinaryOpIC::TypeInfo right_type,
|
| + BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
|
| + : op_(OpBits::decode(key)),
|
| + mode_(ModeBits::decode(key)),
|
| + platform_specific_bit_(PlatformSpecificBits::decode(key)),
|
| + left_type_(left_type),
|
| + right_type_(right_type),
|
| + result_type_(result_type) { }
|
| +
|
| + static void decode_types_from_minor_key(int minor_key,
|
| + BinaryOpIC::TypeInfo* left_type,
|
| + BinaryOpIC::TypeInfo* right_type,
|
| + BinaryOpIC::TypeInfo* result_type) {
|
| + *left_type =
|
| + static_cast<BinaryOpIC::TypeInfo>(LeftTypeBits::decode(minor_key));
|
| + *right_type =
|
| + static_cast<BinaryOpIC::TypeInfo>(RightTypeBits::decode(minor_key));
|
| + *result_type =
|
| + static_cast<BinaryOpIC::TypeInfo>(ResultTypeBits::decode(minor_key));
|
| + }
|
| +
|
| + static Token::Value decode_op_from_minor_key(int minor_key) {
|
| + return static_cast<Token::Value>(OpBits::decode(minor_key));
|
| + }
|
| +
|
| + enum SmiCodeGenerateHeapNumberResults {
|
| + ALLOW_HEAPNUMBER_RESULTS,
|
| + NO_HEAPNUMBER_RESULTS
|
| + };
|
| +
|
| + private:
|
| + Token::Value op_;
|
| + OverwriteMode mode_;
|
| + bool platform_specific_bit_; // Indicates SSE3 on IA32, VFP2 on ARM.
|
| +
|
| + // Operand type information determined at runtime.
|
| + BinaryOpIC::TypeInfo left_type_;
|
| + BinaryOpIC::TypeInfo right_type_;
|
| + BinaryOpIC::TypeInfo result_type_;
|
| +
|
| + virtual void PrintName(StringStream* stream);
|
| +
|
| + // Minor key encoding in 19 bits TTTRRRLLLSOOOOOOOMM.
|
| + class ModeBits: public BitField<OverwriteMode, 0, 2> {};
|
| + class OpBits: public BitField<Token::Value, 2, 7> {};
|
| + class PlatformSpecificBits: public BitField<bool, 9, 1> {};
|
| + class LeftTypeBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
|
| + class RightTypeBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
|
| + class ResultTypeBits: public BitField<BinaryOpIC::TypeInfo, 16, 3> {};
|
| +
|
| + Major MajorKey() { return BinaryOp; }
|
| + int MinorKey() {
|
| + return OpBits::encode(op_)
|
| + | ModeBits::encode(mode_)
|
| + | PlatformSpecificBits::encode(platform_specific_bit_)
|
| + | LeftTypeBits::encode(left_type_)
|
| + | RightTypeBits::encode(right_type_)
|
| + | ResultTypeBits::encode(result_type_);
|
| + }
|
| +
|
| +
|
| + // Platform-independent implementation.
|
| + void Generate(MacroAssembler* masm);
|
| + void GenerateCallRuntime(MacroAssembler* masm);
|
| +
|
| + // Platform-independent signature, platform-specific implementation.
|
| + void Initialize();
|
| + void GenerateAddStrings(MacroAssembler* masm);
|
| + void GenerateBothStringStub(MacroAssembler* masm);
|
| + void GenerateGeneric(MacroAssembler* masm);
|
| + void GenerateGenericStub(MacroAssembler* masm);
|
| + void GenerateHeapNumberStub(MacroAssembler* masm);
|
| + void GenerateInt32Stub(MacroAssembler* masm);
|
| + void GenerateLoadArguments(MacroAssembler* masm);
|
| + void GenerateOddballStub(MacroAssembler* masm);
|
| + void GenerateRegisterArgsPush(MacroAssembler* masm);
|
| + void GenerateReturn(MacroAssembler* masm);
|
| + void GenerateSmiStub(MacroAssembler* masm);
|
| + void GenerateStringStub(MacroAssembler* masm);
|
| + void GenerateTypeTransition(MacroAssembler* masm);
|
| + void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
|
| + void GenerateUninitializedStub(MacroAssembler* masm);
|
| +
|
| + // Entirely platform-specific methods are defined as static helper
|
| + // functions in the <arch>/code-stubs-<arch>.cc files.
|
| +
|
| + virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
|
| +
|
| + virtual InlineCacheState GetICState() {
|
| + return BinaryOpIC::ToState(Max(left_type_, right_type_));
|
| + }
|
| +
|
| + virtual void FinishCode(Handle<Code> code) {
|
| + code->set_stub_info(MinorKey());
|
| + }
|
| +
|
| + friend class CodeGenerator;
|
| +};
|
| +
|
| +
|
| class ICCompareStub: public CodeStub {
|
| public:
|
| - ICCompareStub(Token::Value op, CompareIC::State state)
|
| - : op_(op), state_(state) {
|
| + ICCompareStub(Token::Value op,
|
| + CompareIC::State left,
|
| + CompareIC::State right,
|
| + CompareIC::State handler)
|
| + : op_(op),
|
| + left_(left),
|
| + right_(right),
|
| + state_(handler) {
|
| ASSERT(Token::IsCompareOp(op));
|
| }
|
|
|
| @@ -493,13 +615,24 @@ class ICCompareStub: public CodeStub {
|
|
|
| void set_known_map(Handle<Map> map) { known_map_ = map; }
|
|
|
| + static void DecodeMinorKey(int minor_key,
|
| + CompareIC::State* left_state,
|
| + CompareIC::State* right_state,
|
| + CompareIC::State* handler_state,
|
| + Token::Value* op);
|
| +
|
| + static CompareIC::State CompareState(int minor_key) {
|
| + return static_cast<CompareIC::State>(HandlerStateField::decode(minor_key));
|
| + }
|
| +
|
| private:
|
| class OpField: public BitField<int, 0, 3> { };
|
| - class StateField: public BitField<int, 3, 5> { };
|
| + class LeftStateField: public BitField<int, 3, 3> { };
|
| + class RightStateField: public BitField<int, 6, 3> { };
|
| + class HandlerStateField: public BitField<int, 9, 3> { };
|
|
|
| virtual void FinishCode(Handle<Code> code) {
|
| - code->set_compare_state(state_);
|
| - code->set_compare_operation(op_ - Token::EQ);
|
| + code->set_stub_info(MinorKey());
|
| }
|
|
|
| virtual CodeStub::Major MajorKey() { return CompareIC; }
|
| @@ -514,6 +647,7 @@ class ICCompareStub: public CodeStub {
|
| void GenerateObjects(MacroAssembler* masm);
|
| void GenerateMiss(MacroAssembler* masm);
|
| void GenerateKnownObjects(MacroAssembler* masm);
|
| + void GenerateGeneric(MacroAssembler* masm);
|
|
|
| bool strict() const { return op_ == Token::EQ_STRICT; }
|
| Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
|
| @@ -523,108 +657,13 @@ class ICCompareStub: public CodeStub {
|
| virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECTS; }
|
|
|
| Token::Value op_;
|
| + CompareIC::State left_;
|
| + CompareIC::State right_;
|
| CompareIC::State state_;
|
| Handle<Map> known_map_;
|
| };
|
|
|
|
|
| -// Flags that control the compare stub code generation.
|
| -enum CompareFlags {
|
| - NO_COMPARE_FLAGS = 0,
|
| - NO_SMI_COMPARE_IN_STUB = 1 << 0,
|
| - NO_NUMBER_COMPARE_IN_STUB = 1 << 1,
|
| - CANT_BOTH_BE_NAN = 1 << 2
|
| -};
|
| -
|
| -
|
| -enum NaNInformation {
|
| - kBothCouldBeNaN,
|
| - kCantBothBeNaN
|
| -};
|
| -
|
| -
|
| -class CompareStub: public CodeStub {
|
| - public:
|
| - CompareStub(Condition cc,
|
| - bool strict,
|
| - CompareFlags flags,
|
| - Register lhs,
|
| - Register rhs) :
|
| - cc_(cc),
|
| - strict_(strict),
|
| - never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
|
| - include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
|
| - include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
|
| - lhs_(lhs),
|
| - rhs_(rhs) { }
|
| -
|
| - CompareStub(Condition cc,
|
| - bool strict,
|
| - CompareFlags flags) :
|
| - cc_(cc),
|
| - strict_(strict),
|
| - never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
|
| - include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
|
| - include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
|
| - lhs_(no_reg),
|
| - rhs_(no_reg) { }
|
| -
|
| - void Generate(MacroAssembler* masm);
|
| -
|
| - private:
|
| - Condition cc_;
|
| - bool strict_;
|
| - // Only used for 'equal' comparisons. Tells the stub that we already know
|
| - // that at least one side of the comparison is not NaN. This allows the
|
| - // stub to use object identity in the positive case. We ignore it when
|
| - // generating the minor key for other comparisons to avoid creating more
|
| - // stubs.
|
| - bool never_nan_nan_;
|
| - // Do generate the number comparison code in the stub. Stubs without number
|
| - // comparison code is used when the number comparison has been inlined, and
|
| - // the stub will be called if one of the operands is not a number.
|
| - bool include_number_compare_;
|
| -
|
| - // Generate the comparison code for two smi operands in the stub.
|
| - bool include_smi_compare_;
|
| -
|
| - // Register holding the left hand side of the comparison if the stub gives
|
| - // a choice, no_reg otherwise.
|
| -
|
| - Register lhs_;
|
| - // Register holding the right hand side of the comparison if the stub gives
|
| - // a choice, no_reg otherwise.
|
| - Register rhs_;
|
| -
|
| - // Encoding of the minor key in 16 bits.
|
| - class StrictField: public BitField<bool, 0, 1> {};
|
| - class NeverNanNanField: public BitField<bool, 1, 1> {};
|
| - class IncludeNumberCompareField: public BitField<bool, 2, 1> {};
|
| - class IncludeSmiCompareField: public BitField<bool, 3, 1> {};
|
| - class RegisterField: public BitField<bool, 4, 1> {};
|
| - class ConditionField: public BitField<int, 5, 11> {};
|
| -
|
| - Major MajorKey() { return Compare; }
|
| -
|
| - int MinorKey();
|
| -
|
| - virtual int GetCodeKind() { return Code::COMPARE_IC; }
|
| - virtual void FinishCode(Handle<Code> code) {
|
| - code->set_compare_state(CompareIC::GENERIC);
|
| - }
|
| -
|
| - // Branch to the label if the given object isn't a symbol.
|
| - void BranchIfNonSymbol(MacroAssembler* masm,
|
| - Label* label,
|
| - Register object,
|
| - Register scratch);
|
| -
|
| - // Unfortunately you have to run without snapshots to see most of these
|
| - // names in the profile since most compare stubs end up in the snapshot.
|
| - virtual void PrintName(StringStream* stream);
|
| -};
|
| -
|
| -
|
| class CEntryStub : public CodeStub {
|
| public:
|
| explicit CEntryStub(int result_size,
|
| @@ -1053,6 +1092,9 @@ class ToBooleanStub: public CodeStub {
|
|
|
| bool IsEmpty() const { return set_.IsEmpty(); }
|
| bool Contains(Type type) const { return set_.Contains(type); }
|
| + bool ContainsAnyOf(Types types) const {
|
| + return set_.ContainsAnyOf(types.set_);
|
| + }
|
| void Add(Type type) { set_.Add(type); }
|
| byte ToByte() const { return set_.ToIntegral(); }
|
| void Print(StringStream* stream) const;
|
|
|