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; |