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) { | |
mvstanton
2013/12/02 09:59:33
Nit: could this be in code-stubs.cc instead of def
Benedikt Meurer
2013/12/02 10:23:45
Done.
| |
1069 // Generate the uninitialized versions of the stub. | |
1070 for (int op = Token::BIT_OR; op <= Token::MOD; ++op) { | |
1071 for (int mode = NO_OVERWRITE; mode <= OVERWRITE_RIGHT; ++mode) { | |
1072 BinaryOpICStub stub(static_cast<Token::Value>(op), | |
1073 static_cast<OverwriteMode>(mode)); | |
1074 stub.GetCode(isolate); | |
1075 } | |
1076 } | |
1077 | |
1078 // Generate special versions of the stub. | |
1079 BinaryOpIC::State::GenerateAheadOfTime(isolate, &GenerateAheadOfTime); | |
1070 } | 1080 } |
1071 | 1081 |
1072 explicit BinaryOpStub(ExtraICState state) | 1082 virtual void InitializeInterfaceDescriptor( |
1073 : op_(decode_token(OpBits::decode(state))), | 1083 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE; |
1074 mode_(OverwriteModeField::decode(state)), | 1084 |
1075 fixed_right_arg_( | 1085 static void InstallDescriptors(Isolate* isolate); |
1076 Maybe<int>(HasFixedRightArgBits::decode(state), | 1086 |
1077 decode_arg_value(FixedRightArgValueBits::decode(state)))), | 1087 virtual Code::Kind GetCodeKind() const V8_OVERRIDE { |
1078 left_state_(LeftStateField::decode(state)), | 1088 return Code::BINARY_OP_IC; |
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 } | 1089 } |
1089 | 1090 |
1090 static const int FIRST_TOKEN = Token::BIT_OR; | 1091 virtual InlineCacheState GetICState() V8_OVERRIDE { |
1091 static const int LAST_TOKEN = Token::MOD; | 1092 return state_.GetICState(); |
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 } | 1093 } |
1101 | 1094 |
1102 virtual Code::Kind GetCodeKind() const { return Code::BINARY_OP_IC; } | 1095 virtual ExtraICState GetExtraICState() V8_OVERRIDE { |
1103 virtual InlineCacheState GetICState() { | 1096 return state_.GetExtraICState(); |
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 } | 1097 } |
1110 | 1098 |
1111 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE { | 1099 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE { |
1112 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2)); | 1100 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2)); |
1113 } | 1101 } |
1114 | 1102 |
1115 virtual ExtraICState GetExtraICState() { | 1103 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 | 1104 |
1119 return OpBits::encode(encode_token(op_)) | 1105 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 | 1106 |
1133 bool CanReuseDoubleBox() { | 1107 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 | 1108 |
1141 bool HasSideEffects(Isolate* isolate) const { | 1109 // Parameters accessed via CodeStubGraphBuilder::GetParameter() |
1142 Handle<Type> left = GetLeftType(isolate); | 1110 static const int kLeft = 0; |
1143 Handle<Type> right = GetRightType(isolate); | 1111 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 | 1112 |
1167 private: | 1113 private: |
1168 explicit BinaryOpStub(InitializationState state) : HydrogenCodeStub(state), | 1114 static void GenerateAheadOfTime(Isolate* isolate, |
1169 op_(Token::ADD), | 1115 const BinaryOpIC::State& state); |
1170 mode_(NO_OVERWRITE) { | |
1171 Initialize(); | |
1172 } | |
1173 void Initialize(); | |
1174 | 1116 |
1175 enum State { NONE, SMI, INT32, NUMBER, STRING, GENERIC }; | 1117 virtual Major MajorKey() V8_OVERRIDE { return BinaryOpIC; } |
1118 virtual int NotMissMinorKey() V8_OVERRIDE { return GetExtraICState(); } | |
1176 | 1119 |
1177 // We truncate the last bit of the token. | 1120 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 | 1121 |
1190 virtual CodeStub::Major MajorKey() { return BinaryOp; } | 1122 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 }; | 1123 }; |
1236 | 1124 |
1237 | 1125 |
1238 // TODO(bmeurer): Rename to StringAddStub once we dropped the old StringAddStub. | 1126 // TODO(bmeurer): Rename to StringAddStub once we dropped the old StringAddStub. |
1239 class NewStringAddStub V8_FINAL : public HydrogenCodeStub { | 1127 class NewStringAddStub V8_FINAL : public HydrogenCodeStub { |
1240 public: | 1128 public: |
1241 NewStringAddStub(StringAddFlags flags, PretenureFlag pretenure_flag) | 1129 NewStringAddStub(StringAddFlags flags, PretenureFlag pretenure_flag) |
1242 : bit_field_(StringAddFlagsBits::encode(flags) | | 1130 : bit_field_(StringAddFlagsBits::encode(flags) | |
1243 PretenureFlagBits::encode(pretenure_flag)) {} | 1131 PretenureFlagBits::encode(pretenure_flag)) {} |
1244 | 1132 |
(...skipping 1226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2471 int MinorKey() { return 0; } | 2359 int MinorKey() { return 0; } |
2472 | 2360 |
2473 void Generate(MacroAssembler* masm); | 2361 void Generate(MacroAssembler* masm); |
2474 | 2362 |
2475 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub); | 2363 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub); |
2476 }; | 2364 }; |
2477 | 2365 |
2478 } } // namespace v8::internal | 2366 } } // namespace v8::internal |
2479 | 2367 |
2480 #endif // V8_CODE_STUBS_H_ | 2368 #endif // V8_CODE_STUBS_H_ |
OLD | NEW |