| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 #include "globals.h" | 34 #include "globals.h" |
| 35 #include "macro-assembler.h" | 35 #include "macro-assembler.h" |
| 36 | 36 |
| 37 namespace v8 { | 37 namespace v8 { |
| 38 namespace internal { | 38 namespace internal { |
| 39 | 39 |
| 40 // List of code stubs used on all platforms. | 40 // List of code stubs used on all platforms. |
| 41 #define CODE_STUB_LIST_ALL_PLATFORMS(V) \ | 41 #define CODE_STUB_LIST_ALL_PLATFORMS(V) \ |
| 42 V(CallFunction) \ | 42 V(CallFunction) \ |
| 43 V(CallConstruct) \ | 43 V(CallConstruct) \ |
| 44 V(BinaryOp) \ | 44 V(BinaryOpIC) \ |
| 45 V(StringAdd) \ | 45 V(StringAdd) \ |
| 46 V(NewStringAdd) \ | 46 V(NewStringAdd) \ |
| 47 V(SubString) \ | 47 V(SubString) \ |
| 48 V(StringCompare) \ | 48 V(StringCompare) \ |
| 49 V(Compare) \ | 49 V(Compare) \ |
| 50 V(CompareIC) \ | 50 V(CompareIC) \ |
| 51 V(CompareNilIC) \ | 51 V(CompareNilIC) \ |
| 52 V(MathPow) \ | 52 V(MathPow) \ |
| 53 V(StringLength) \ | 53 V(StringLength) \ |
| 54 V(FunctionPrototype) \ | 54 V(FunctionPrototype) \ |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 #else | 119 #else |
| 120 #define CODE_STUB_LIST_MIPS(V) | 120 #define CODE_STUB_LIST_MIPS(V) |
| 121 #endif | 121 #endif |
| 122 | 122 |
| 123 // Combined list of code stubs. | 123 // Combined list of code stubs. |
| 124 #define CODE_STUB_LIST(V) \ | 124 #define CODE_STUB_LIST(V) \ |
| 125 CODE_STUB_LIST_ALL_PLATFORMS(V) \ | 125 CODE_STUB_LIST_ALL_PLATFORMS(V) \ |
| 126 CODE_STUB_LIST_ARM(V) \ | 126 CODE_STUB_LIST_ARM(V) \ |
| 127 CODE_STUB_LIST_MIPS(V) | 127 CODE_STUB_LIST_MIPS(V) |
| 128 | 128 |
| 129 // Mode to overwrite BinaryExpression values. | |
| 130 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT }; | |
| 131 | |
| 132 // Stub is base classes of all stubs. | 129 // Stub is base classes of all stubs. |
| 133 class CodeStub BASE_EMBEDDED { | 130 class CodeStub BASE_EMBEDDED { |
| 134 public: | 131 public: |
| 135 enum Major { | 132 enum Major { |
| 136 #define DEF_ENUM(name) name, | 133 #define DEF_ENUM(name) name, |
| 137 CODE_STUB_LIST(DEF_ENUM) | 134 CODE_STUB_LIST(DEF_ENUM) |
| 138 #undef DEF_ENUM | 135 #undef DEF_ENUM |
| 139 NoCache, // marker for stubs that do custom caching | 136 NoCache, // marker for stubs that do custom caching |
| 140 NUMBER_OF_IDS | 137 NUMBER_OF_IDS |
| 141 }; | 138 }; |
| (...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1054 STATIC_ASSERT(CallICBase::Contextual::kSize == ContextualBits::kSize); | 1051 STATIC_ASSERT(CallICBase::Contextual::kSize == ContextualBits::kSize); |
| 1055 class HoleyBits: public BitField<bool, 1, 1> {}; | 1052 class HoleyBits: public BitField<bool, 1, 1> {}; |
| 1056 STATIC_ASSERT(Code::kArgumentsBits <= kStubMinorKeyBits - 2); | 1053 STATIC_ASSERT(Code::kArgumentsBits <= kStubMinorKeyBits - 2); |
| 1057 class ArgcBits: public BitField<int, 2, Code::kArgumentsBits> {}; | 1054 class ArgcBits: public BitField<int, 2, Code::kArgumentsBits> {}; |
| 1058 virtual CodeStub::Major MajorKey() { return KeyedArrayCall; } | 1055 virtual CodeStub::Major MajorKey() { return KeyedArrayCall; } |
| 1059 int bit_field_; | 1056 int bit_field_; |
| 1060 int argc_; | 1057 int argc_; |
| 1061 }; | 1058 }; |
| 1062 | 1059 |
| 1063 | 1060 |
| 1064 class BinaryOpStub: public HydrogenCodeStub { | 1061 class BinaryOpICStub V8_FINAL : public HydrogenCodeStub { |
| 1065 public: | 1062 public: |
| 1066 BinaryOpStub(Token::Value op, OverwriteMode mode) | 1063 BinaryOpICStub(Token::Value op, OverwriteMode mode) |
| 1067 : HydrogenCodeStub(UNINITIALIZED), op_(op), mode_(mode) { | 1064 : HydrogenCodeStub(UNINITIALIZED), state_(op, mode) {} |
| 1068 ASSERT(op <= LAST_TOKEN && op >= FIRST_TOKEN); | 1065 |
| 1069 Initialize(); | 1066 explicit BinaryOpICStub(const BinaryOpIC::State& state) : state_(state) {} |
| 1067 |
| 1068 static void GenerateAheadOfTime(Isolate* isolate); |
| 1069 |
| 1070 virtual void InitializeInterfaceDescriptor( |
| 1071 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE; |
| 1072 |
| 1073 static void InstallDescriptors(Isolate* isolate); |
| 1074 |
| 1075 virtual Code::Kind GetCodeKind() const V8_OVERRIDE { |
| 1076 return Code::BINARY_OP_IC; |
| 1070 } | 1077 } |
| 1071 | 1078 |
| 1072 explicit BinaryOpStub(ExtraICState state) | 1079 virtual InlineCacheState GetICState() V8_OVERRIDE { |
| 1073 : op_(decode_token(OpBits::decode(state))), | 1080 return state_.GetICState(); |
| 1074 mode_(OverwriteModeField::decode(state)), | |
| 1075 fixed_right_arg_( | |
| 1076 Maybe<int>(HasFixedRightArgBits::decode(state), | |
| 1077 decode_arg_value(FixedRightArgValueBits::decode(state)))), | |
| 1078 left_state_(LeftStateField::decode(state)), | |
| 1079 right_state_(fixed_right_arg_.has_value | |
| 1080 ? ((fixed_right_arg_.value <= Smi::kMaxValue) ? SMI : INT32) | |
| 1081 : RightStateField::decode(state)), | |
| 1082 result_state_(ResultStateField::decode(state)) { | |
| 1083 // We don't deserialize the SSE2 Field, since this is only used to be able | |
| 1084 // to include SSE2 as well as non-SSE2 versions in the snapshot. For code | |
| 1085 // generation we always want it to reflect the current state. | |
| 1086 ASSERT(!fixed_right_arg_.has_value || | |
| 1087 can_encode_arg_value(fixed_right_arg_.value)); | |
| 1088 } | 1081 } |
| 1089 | 1082 |
| 1090 static const int FIRST_TOKEN = Token::BIT_OR; | 1083 virtual ExtraICState GetExtraICState() V8_OVERRIDE { |
| 1091 static const int LAST_TOKEN = Token::MOD; | 1084 return state_.GetExtraICState(); |
| 1092 | |
| 1093 static void GenerateAheadOfTime(Isolate* isolate); | |
| 1094 virtual void InitializeInterfaceDescriptor( | |
| 1095 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor); | |
| 1096 static void InitializeForIsolate(Isolate* isolate) { | |
| 1097 BinaryOpStub binopStub(UNINITIALIZED); | |
| 1098 binopStub.InitializeInterfaceDescriptor( | |
| 1099 isolate, isolate->code_stub_interface_descriptor(CodeStub::BinaryOp)); | |
| 1100 } | |
| 1101 | |
| 1102 virtual Code::Kind GetCodeKind() const { return Code::BINARY_OP_IC; } | |
| 1103 virtual InlineCacheState GetICState() { | |
| 1104 if (Max(left_state_, right_state_) == NONE) { | |
| 1105 return ::v8::internal::UNINITIALIZED; | |
| 1106 } | |
| 1107 if (Max(left_state_, right_state_) == GENERIC) return MEGAMORPHIC; | |
| 1108 return MONOMORPHIC; | |
| 1109 } | 1085 } |
| 1110 | 1086 |
| 1111 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE { | 1087 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE { |
| 1112 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2)); | 1088 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2)); |
| 1113 } | 1089 } |
| 1114 | 1090 |
| 1115 virtual ExtraICState GetExtraICState() { | 1091 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE; |
| 1116 bool sse_field = Max(result_state_, Max(left_state_, right_state_)) > SMI && | |
| 1117 CpuFeatures::IsSafeForSnapshot(SSE2); | |
| 1118 | 1092 |
| 1119 return OpBits::encode(encode_token(op_)) | 1093 const BinaryOpIC::State& state() const { return state_; } |
| 1120 | LeftStateField::encode(left_state_) | |
| 1121 | RightStateField::encode(fixed_right_arg_.has_value | |
| 1122 ? NONE : right_state_) | |
| 1123 | ResultStateField::encode(result_state_) | |
| 1124 | HasFixedRightArgBits::encode(fixed_right_arg_.has_value) | |
| 1125 | FixedRightArgValueBits::encode(fixed_right_arg_.has_value | |
| 1126 ? encode_arg_value( | |
| 1127 fixed_right_arg_.value) | |
| 1128 : 0) | |
| 1129 | SSE2Field::encode(sse_field) | |
| 1130 | OverwriteModeField::encode(mode_); | |
| 1131 } | |
| 1132 | 1094 |
| 1133 bool CanReuseDoubleBox() { | 1095 virtual void PrintState(StringStream* stream) V8_OVERRIDE; |
| 1134 return result_state_ <= NUMBER && result_state_ > SMI && | |
| 1135 ((left_state_ > SMI && left_state_ <= NUMBER && | |
| 1136 mode_ == OVERWRITE_LEFT) || | |
| 1137 (right_state_ > SMI && right_state_ <= NUMBER && | |
| 1138 mode_ == OVERWRITE_RIGHT)); | |
| 1139 } | |
| 1140 | 1096 |
| 1141 bool HasSideEffects(Isolate* isolate) const { | 1097 // Parameters accessed via CodeStubGraphBuilder::GetParameter() |
| 1142 Handle<Type> left = GetLeftType(isolate); | 1098 static const int kLeft = 0; |
| 1143 Handle<Type> right = GetRightType(isolate); | 1099 static const int kRight = 1; |
| 1144 return left->Maybe(Type::Receiver()) || right->Maybe(Type::Receiver()); | |
| 1145 } | |
| 1146 | |
| 1147 virtual Handle<Code> GenerateCode(Isolate* isolate); | |
| 1148 | |
| 1149 Maybe<Handle<Object> > Result(Handle<Object> left, | |
| 1150 Handle<Object> right, | |
| 1151 Isolate* isolate); | |
| 1152 | |
| 1153 Token::Value operation() const { return op_; } | |
| 1154 OverwriteMode mode() const { return mode_; } | |
| 1155 Maybe<int> fixed_right_arg() const { return fixed_right_arg_; } | |
| 1156 | |
| 1157 Handle<Type> GetLeftType(Isolate* isolate) const; | |
| 1158 Handle<Type> GetRightType(Isolate* isolate) const; | |
| 1159 Handle<Type> GetResultType(Isolate* isolate) const; | |
| 1160 | |
| 1161 void UpdateStatus(Handle<Object> left, | |
| 1162 Handle<Object> right, | |
| 1163 Maybe<Handle<Object> > result); | |
| 1164 | |
| 1165 void PrintState(StringStream* stream); | |
| 1166 | 1100 |
| 1167 private: | 1101 private: |
| 1168 explicit BinaryOpStub(InitializationState state) : HydrogenCodeStub(state), | 1102 static void GenerateAheadOfTime(Isolate* isolate, |
| 1169 op_(Token::ADD), | 1103 const BinaryOpIC::State& state); |
| 1170 mode_(NO_OVERWRITE) { | |
| 1171 Initialize(); | |
| 1172 } | |
| 1173 void Initialize(); | |
| 1174 | 1104 |
| 1175 enum State { NONE, SMI, INT32, NUMBER, STRING, GENERIC }; | 1105 virtual Major MajorKey() V8_OVERRIDE { return BinaryOpIC; } |
| 1106 virtual int NotMissMinorKey() V8_OVERRIDE { return GetExtraICState(); } |
| 1176 | 1107 |
| 1177 // We truncate the last bit of the token. | 1108 BinaryOpIC::State state_; |
| 1178 STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 5)); | |
| 1179 class LeftStateField: public BitField<State, 0, 3> {}; | |
| 1180 // When fixed right arg is set, we don't need to store the right state. | |
| 1181 // Thus the two fields can overlap. | |
| 1182 class HasFixedRightArgBits: public BitField<bool, 4, 1> {}; | |
| 1183 class FixedRightArgValueBits: public BitField<int, 5, 4> {}; | |
| 1184 class RightStateField: public BitField<State, 5, 3> {}; | |
| 1185 class ResultStateField: public BitField<State, 9, 3> {}; | |
| 1186 class SSE2Field: public BitField<bool, 12, 1> {}; | |
| 1187 class OverwriteModeField: public BitField<OverwriteMode, 13, 2> {}; | |
| 1188 class OpBits: public BitField<int, 15, 5> {}; | |
| 1189 | 1109 |
| 1190 virtual CodeStub::Major MajorKey() { return BinaryOp; } | 1110 DISALLOW_COPY_AND_ASSIGN(BinaryOpICStub); |
| 1191 virtual int NotMissMinorKey() { return GetExtraICState(); } | |
| 1192 | |
| 1193 static Handle<Type> StateToType(State state, | |
| 1194 Isolate* isolate); | |
| 1195 | |
| 1196 static void Generate(Token::Value op, | |
| 1197 State left, | |
| 1198 int right, | |
| 1199 State result, | |
| 1200 OverwriteMode mode, | |
| 1201 Isolate* isolate); | |
| 1202 | |
| 1203 static void Generate(Token::Value op, | |
| 1204 State left, | |
| 1205 State right, | |
| 1206 State result, | |
| 1207 OverwriteMode mode, | |
| 1208 Isolate* isolate); | |
| 1209 | |
| 1210 void UpdateStatus(Handle<Object> object, | |
| 1211 State* state); | |
| 1212 | |
| 1213 bool can_encode_arg_value(int32_t value) const; | |
| 1214 int encode_arg_value(int32_t value) const; | |
| 1215 int32_t decode_arg_value(int value) const; | |
| 1216 int encode_token(Token::Value op) const; | |
| 1217 Token::Value decode_token(int op) const; | |
| 1218 | |
| 1219 bool has_int_result() const { | |
| 1220 return op_ == Token::BIT_XOR || op_ == Token::BIT_AND || | |
| 1221 op_ == Token::BIT_OR || op_ == Token::SAR || op_ == Token::SHL; | |
| 1222 } | |
| 1223 | |
| 1224 const char* StateToName(State state); | |
| 1225 | |
| 1226 void PrintBaseName(StringStream* stream); | |
| 1227 | |
| 1228 Token::Value op_; | |
| 1229 OverwriteMode mode_; | |
| 1230 | |
| 1231 Maybe<int> fixed_right_arg_; | |
| 1232 State left_state_; | |
| 1233 State right_state_; | |
| 1234 State result_state_; | |
| 1235 }; | 1111 }; |
| 1236 | 1112 |
| 1237 | 1113 |
| 1238 // TODO(bmeurer): Rename to StringAddStub once we dropped the old StringAddStub. | 1114 // TODO(bmeurer): Rename to StringAddStub once we dropped the old StringAddStub. |
| 1239 class NewStringAddStub V8_FINAL : public HydrogenCodeStub { | 1115 class NewStringAddStub V8_FINAL : public HydrogenCodeStub { |
| 1240 public: | 1116 public: |
| 1241 NewStringAddStub(StringAddFlags flags, PretenureFlag pretenure_flag) | 1117 NewStringAddStub(StringAddFlags flags, PretenureFlag pretenure_flag) |
| 1242 : bit_field_(StringAddFlagsBits::encode(flags) | | 1118 : bit_field_(StringAddFlagsBits::encode(flags) | |
| 1243 PretenureFlagBits::encode(pretenure_flag)) {} | 1119 PretenureFlagBits::encode(pretenure_flag)) {} |
| 1244 | 1120 |
| (...skipping 1226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2471 int MinorKey() { return 0; } | 2347 int MinorKey() { return 0; } |
| 2472 | 2348 |
| 2473 void Generate(MacroAssembler* masm); | 2349 void Generate(MacroAssembler* masm); |
| 2474 | 2350 |
| 2475 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub); | 2351 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub); |
| 2476 }; | 2352 }; |
| 2477 | 2353 |
| 2478 } } // namespace v8::internal | 2354 } } // namespace v8::internal |
| 2479 | 2355 |
| 2480 #endif // V8_CODE_STUBS_H_ | 2356 #endif // V8_CODE_STUBS_H_ |
| OLD | NEW |