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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 #endif | 116 #endif |
117 | 117 |
118 // Combined list of code stubs. | 118 // Combined list of code stubs. |
119 #define CODE_STUB_LIST(V) \ | 119 #define CODE_STUB_LIST(V) \ |
120 CODE_STUB_LIST_ALL_PLATFORMS(V) \ | 120 CODE_STUB_LIST_ALL_PLATFORMS(V) \ |
121 CODE_STUB_LIST_ARM(V) \ | 121 CODE_STUB_LIST_ARM(V) \ |
122 CODE_STUB_LIST_MIPS(V) | 122 CODE_STUB_LIST_MIPS(V) |
123 | 123 |
124 // Mode to overwrite BinaryExpression values. | 124 // Mode to overwrite BinaryExpression values. |
125 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT }; | 125 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT }; |
| 126 enum UnaryOverwriteMode { UNARY_OVERWRITE, UNARY_NO_OVERWRITE }; |
| 127 |
126 | 128 |
127 // Stub is base classes of all stubs. | 129 // Stub is base classes of all stubs. |
128 class CodeStub BASE_EMBEDDED { | 130 class CodeStub BASE_EMBEDDED { |
129 public: | 131 public: |
130 enum Major { | 132 enum Major { |
131 #define DEF_ENUM(name) name, | 133 #define DEF_ENUM(name) name, |
132 CODE_STUB_LIST(DEF_ENUM) | 134 CODE_STUB_LIST(DEF_ENUM) |
133 #undef DEF_ENUM | 135 #undef DEF_ENUM |
134 NoCache, // marker for stubs that do custom caching | 136 NoCache, // marker for stubs that do custom caching |
135 NUMBER_OF_IDS | 137 NUMBER_OF_IDS |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 virtual Code::ExtraICState GetExtraICState() { | 190 virtual Code::ExtraICState GetExtraICState() { |
189 return Code::kNoExtraICState; | 191 return Code::kNoExtraICState; |
190 } | 192 } |
191 virtual Code::StubType GetStubType() { | 193 virtual Code::StubType GetStubType() { |
192 return Code::NORMAL; | 194 return Code::NORMAL; |
193 } | 195 } |
194 virtual int GetStubFlags() { | 196 virtual int GetStubFlags() { |
195 return -1; | 197 return -1; |
196 } | 198 } |
197 | 199 |
198 virtual void PrintName(StringStream* stream); | |
199 | |
200 protected: | 200 protected: |
201 static bool CanUseFPRegisters(); | 201 static bool CanUseFPRegisters(); |
202 | 202 |
203 // Generates the assembler code for the stub. | 203 // Generates the assembler code for the stub. |
204 virtual Handle<Code> GenerateCode() = 0; | 204 virtual Handle<Code> GenerateCode() = 0; |
205 | 205 |
206 | 206 |
207 // Returns whether the code generated for this stub needs to be allocated as | 207 // Returns whether the code generated for this stub needs to be allocated as |
208 // a fixed (non-moveable) code object. | 208 // a fixed (non-moveable) code object. |
209 virtual bool NeedsImmovableCode() { return false; } | 209 virtual bool NeedsImmovableCode() { return false; } |
210 | 210 |
211 // Returns a name for logging/debugging purposes. | |
212 SmartArrayPointer<const char> GetName(); | |
213 virtual void PrintBaseName(StringStream* stream); | |
214 virtual void PrintState(StringStream* stream) { } | |
215 | |
216 private: | 211 private: |
217 // Perform bookkeeping required after code generation when stub code is | 212 // Perform bookkeeping required after code generation when stub code is |
218 // initially generated. | 213 // initially generated. |
219 void RecordCodeGeneration(Code* code, Isolate* isolate); | 214 void RecordCodeGeneration(Code* code, Isolate* isolate); |
220 | 215 |
221 // Finish the code object after it has been generated. | 216 // Finish the code object after it has been generated. |
222 virtual void FinishCode(Handle<Code> code) { } | 217 virtual void FinishCode(Handle<Code> code) { } |
223 | 218 |
224 // Activate newly generated stub. Is called after | 219 // Activate newly generated stub. Is called after |
225 // registering stub in the stub cache. | 220 // registering stub in the stub cache. |
226 virtual void Activate(Code* code) { } | 221 virtual void Activate(Code* code) { } |
227 | 222 |
228 // BinaryOpStub needs to override this. | 223 // BinaryOpStub needs to override this. |
229 virtual Code::Kind GetCodeKind() const; | 224 virtual Code::Kind GetCodeKind() const; |
230 | 225 |
231 // Add the code to a specialized cache, specific to an individual | 226 // Add the code to a specialized cache, specific to an individual |
232 // stub type. Please note, this method must add the code object to a | 227 // stub type. Please note, this method must add the code object to a |
233 // roots object, otherwise we will remove the code during GC. | 228 // roots object, otherwise we will remove the code during GC. |
234 virtual void AddToSpecialCache(Handle<Code> new_object) { } | 229 virtual void AddToSpecialCache(Handle<Code> new_object) { } |
235 | 230 |
236 // Find code in a specialized cache, work is delegated to the specific stub. | 231 // Find code in a specialized cache, work is delegated to the specific stub. |
237 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate) { | 232 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate) { |
238 return false; | 233 return false; |
239 } | 234 } |
240 | 235 |
241 // If a stub uses a special cache override this. | 236 // If a stub uses a special cache override this. |
242 virtual bool UseSpecialCache() { return false; } | 237 virtual bool UseSpecialCache() { return false; } |
243 | 238 |
| 239 // Returns a name for logging/debugging purposes. |
| 240 SmartArrayPointer<const char> GetName(); |
| 241 virtual void PrintName(StringStream* stream); |
| 242 |
244 // Computes the key based on major and minor. | 243 // Computes the key based on major and minor. |
245 uint32_t GetKey() { | 244 uint32_t GetKey() { |
246 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS); | 245 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS); |
247 return MinorKeyBits::encode(MinorKey()) | | 246 return MinorKeyBits::encode(MinorKey()) | |
248 MajorKeyBits::encode(MajorKey()); | 247 MajorKeyBits::encode(MajorKey()); |
249 } | 248 } |
250 | 249 |
251 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {}; | 250 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {}; |
252 class MinorKeyBits: public BitField<uint32_t, | 251 class MinorKeyBits: public BitField<uint32_t, |
253 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT | 252 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 Isolate* isolate, | 347 Isolate* isolate, |
349 CodeStubInterfaceDescriptor* descriptor) = 0; | 348 CodeStubInterfaceDescriptor* descriptor) = 0; |
350 | 349 |
351 // Retrieve the code for the stub. Generate the code if needed. | 350 // Retrieve the code for the stub. Generate the code if needed. |
352 virtual Handle<Code> GenerateCode() = 0; | 351 virtual Handle<Code> GenerateCode() = 0; |
353 | 352 |
354 virtual int NotMissMinorKey() = 0; | 353 virtual int NotMissMinorKey() = 0; |
355 | 354 |
356 Handle<Code> GenerateLightweightMissCode(Isolate* isolate); | 355 Handle<Code> GenerateLightweightMissCode(Isolate* isolate); |
357 | 356 |
358 template<class StateType> | |
359 void TraceTransition(StateType from, StateType to); | |
360 | |
361 private: | 357 private: |
362 class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {}; | 358 class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {}; |
363 class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {}; | 359 class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {}; |
364 | 360 |
365 void GenerateLightweightMiss(MacroAssembler* masm); | 361 void GenerateLightweightMiss(MacroAssembler* masm); |
366 virtual int MinorKey() { | 362 virtual int MinorKey() { |
367 return IsMissBits::encode(is_uninitialized_) | | 363 return IsMissBits::encode(is_uninitialized_) | |
368 MinorKeyBits::encode(NotMissMinorKey()); | 364 MinorKeyBits::encode(NotMissMinorKey()); |
369 } | 365 } |
370 | 366 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 void Generate(MacroAssembler* masm); | 513 void Generate(MacroAssembler* masm); |
518 | 514 |
519 private: | 515 private: |
520 int slots_; | 516 int slots_; |
521 | 517 |
522 Major MajorKey() { return FastNewBlockContext; } | 518 Major MajorKey() { return FastNewBlockContext; } |
523 int MinorKey() { return slots_; } | 519 int MinorKey() { return slots_; } |
524 }; | 520 }; |
525 | 521 |
526 | 522 |
527 class UnaryOpStub : public HydrogenCodeStub { | |
528 public: | |
529 // Stub without type info available -> construct uninitialized | |
530 explicit UnaryOpStub(Token::Value operation) | |
531 : HydrogenCodeStub(UNINITIALIZED), operation_(operation) { } | |
532 explicit UnaryOpStub(Code::ExtraICState ic_state) : | |
533 state_(StateBits::decode(ic_state)), | |
534 operation_(OperatorBits::decode(ic_state)) { } | |
535 | |
536 virtual void InitializeInterfaceDescriptor( | |
537 Isolate* isolate, | |
538 CodeStubInterfaceDescriptor* descriptor); | |
539 | |
540 virtual Code::Kind GetCodeKind() const { return Code::UNARY_OP_IC; } | |
541 virtual InlineCacheState GetICState() { | |
542 if (state_.Contains(GENERIC)) { | |
543 return MEGAMORPHIC; | |
544 } else if (state_.IsEmpty()) { | |
545 return PREMONOMORPHIC; | |
546 } else { | |
547 return MONOMORPHIC; | |
548 } | |
549 } | |
550 virtual Code::ExtraICState GetExtraICState() { | |
551 return OperatorBits::encode(operation_) | | |
552 StateBits::encode(state_.ToIntegral()); | |
553 } | |
554 | |
555 Token::Value operation() { return operation_; } | |
556 Handle<JSFunction> ToJSFunction(Isolate* isolate); | |
557 | |
558 void UpdateStatus(Handle<Object> object); | |
559 MaybeObject* Result(Handle<Object> object, Isolate* isolate); | |
560 Handle<Code> GenerateCode(); | |
561 Handle<Type> GetType(Isolate* isolate); | |
562 | |
563 protected: | |
564 void PrintState(StringStream* stream); | |
565 void PrintBaseName(StringStream* stream); | |
566 | |
567 private: | |
568 Builtins::JavaScript ToJSBuiltin(); | |
569 | |
570 enum UnaryOpType { | |
571 SMI, | |
572 HEAP_NUMBER, | |
573 GENERIC, | |
574 NUMBER_OF_TYPES | |
575 }; | |
576 | |
577 class State : public EnumSet<UnaryOpType, byte> { | |
578 public: | |
579 State() : EnumSet<UnaryOpType, byte>() { } | |
580 explicit State(byte bits) : EnumSet<UnaryOpType, byte>(bits) { } | |
581 void Print(StringStream* stream) const; | |
582 }; | |
583 | |
584 class StateBits : public BitField<int, 0, NUMBER_OF_TYPES> { }; | |
585 class OperatorBits : public BitField<Token::Value, NUMBER_OF_TYPES, 8> { }; | |
586 | |
587 State state_; | |
588 Token::Value operation_; | |
589 | |
590 virtual CodeStub::Major MajorKey() { return UnaryOp; } | |
591 virtual int NotMissMinorKey() { return GetExtraICState(); } | |
592 }; | |
593 | |
594 | |
595 class FastCloneShallowArrayStub : public HydrogenCodeStub { | 523 class FastCloneShallowArrayStub : public HydrogenCodeStub { |
596 public: | 524 public: |
597 // Maximum length of copied elements array. | 525 // Maximum length of copied elements array. |
598 static const int kMaximumClonedLength = 8; | 526 static const int kMaximumClonedLength = 8; |
599 enum Mode { | 527 enum Mode { |
600 CLONE_ELEMENTS, | 528 CLONE_ELEMENTS, |
601 CLONE_DOUBLE_ELEMENTS, | 529 CLONE_DOUBLE_ELEMENTS, |
602 COPY_ON_WRITE_ELEMENTS, | 530 COPY_ON_WRITE_ELEMENTS, |
603 CLONE_ANY_ELEMENTS, | 531 CLONE_ANY_ELEMENTS, |
604 LAST_CLONE_MODE = CLONE_ANY_ELEMENTS | 532 LAST_CLONE_MODE = CLONE_ANY_ELEMENTS |
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1208 static State Generic() { | 1136 static State Generic() { |
1209 State set; | 1137 State set; |
1210 set.Add(UNDEFINED); | 1138 set.Add(UNDEFINED); |
1211 set.Add(NULL_TYPE); | 1139 set.Add(NULL_TYPE); |
1212 set.Add(UNDETECTABLE); | 1140 set.Add(UNDETECTABLE); |
1213 set.Add(GENERIC); | 1141 set.Add(GENERIC); |
1214 return set; | 1142 return set; |
1215 } | 1143 } |
1216 | 1144 |
1217 void Print(StringStream* stream) const; | 1145 void Print(StringStream* stream) const; |
| 1146 void TraceTransition(State to) const; |
1218 }; | 1147 }; |
1219 | 1148 |
1220 static Handle<Type> StateToType( | 1149 static Handle<Type> StateToType( |
1221 Isolate* isolate, State state, Handle<Map> map = Handle<Map>()); | 1150 Isolate* isolate, State state, Handle<Map> map = Handle<Map>()); |
1222 | 1151 |
1223 // At most 6 different types can be distinguished, because the Code object | 1152 // At most 6 different types can be distinguished, because the Code object |
1224 // only has room for a single byte to hold a set and there are two more | 1153 // only has room for a single byte to hold a set and there are two more |
1225 // boolean flags we need to store. :-P | 1154 // boolean flags we need to store. :-P |
1226 STATIC_ASSERT(NUMBER_OF_TYPES <= 6); | 1155 STATIC_ASSERT(NUMBER_OF_TYPES <= 6); |
1227 | 1156 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 virtual Code::ExtraICState GetExtraICState() { | 1199 virtual Code::ExtraICState GetExtraICState() { |
1271 return NilValueField::encode(nil_value_) | state_.ToIntegral(); | 1200 return NilValueField::encode(nil_value_) | state_.ToIntegral(); |
1272 } | 1201 } |
1273 static byte ExtractTypesFromExtraICState(Code::ExtraICState state) { | 1202 static byte ExtractTypesFromExtraICState(Code::ExtraICState state) { |
1274 return state & ((1 << NUMBER_OF_TYPES) - 1); | 1203 return state & ((1 << NUMBER_OF_TYPES) - 1); |
1275 } | 1204 } |
1276 static NilValue ExtractNilValueFromExtraICState(Code::ExtraICState state) { | 1205 static NilValue ExtractNilValueFromExtraICState(Code::ExtraICState state) { |
1277 return NilValueField::decode(state); | 1206 return NilValueField::decode(state); |
1278 } | 1207 } |
1279 | 1208 |
1280 void UpdateStatus(Handle<Object> object); | 1209 void Record(Handle<Object> object); |
1281 | 1210 |
1282 bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); } | 1211 bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); } |
1283 NilValue GetNilValue() const { return nil_value_; } | 1212 NilValue GetNilValue() const { return nil_value_; } |
1284 State GetState() const { return state_; } | 1213 State GetState() const { return state_; } |
1285 void ClearState() { state_.RemoveAll(); } | 1214 void ClearState() { state_.RemoveAll(); } |
1286 | 1215 |
1287 virtual void PrintState(StringStream* stream); | 1216 virtual void PrintName(StringStream* stream); |
1288 virtual void PrintBaseName(StringStream* stream); | |
1289 | 1217 |
1290 private: | 1218 private: |
1291 friend class CompareNilIC; | 1219 friend class CompareNilIC; |
1292 | 1220 |
1293 CompareNilICStub(NilValue nil, InitializationState init_state) | 1221 CompareNilICStub(NilValue nil, InitializationState init_state) |
1294 : HydrogenCodeStub(init_state) { | 1222 : HydrogenCodeStub(init_state) { |
1295 nil_value_ = nil; | 1223 nil_value_ = nil; |
1296 } | 1224 } |
1297 | 1225 |
1298 class NilValueField : public BitField<NilValue, NUMBER_OF_TYPES, 1> {}; | 1226 class NilValueField : public BitField<NilValue, NUMBER_OF_TYPES, 1> {}; |
(...skipping 775 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2074 // only has room for a single byte to hold a set of these types. :-P | 2002 // only has room for a single byte to hold a set of these types. :-P |
2075 STATIC_ASSERT(NUMBER_OF_TYPES <= 8); | 2003 STATIC_ASSERT(NUMBER_OF_TYPES <= 8); |
2076 | 2004 |
2077 class Types : public EnumSet<Type, byte> { | 2005 class Types : public EnumSet<Type, byte> { |
2078 public: | 2006 public: |
2079 Types() : EnumSet<Type, byte>(0) {} | 2007 Types() : EnumSet<Type, byte>(0) {} |
2080 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {} | 2008 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {} |
2081 | 2009 |
2082 byte ToByte() const { return ToIntegral(); } | 2010 byte ToByte() const { return ToIntegral(); } |
2083 void Print(StringStream* stream) const; | 2011 void Print(StringStream* stream) const; |
2084 bool UpdateStatus(Handle<Object> object); | 2012 void TraceTransition(Types to) const; |
| 2013 bool Record(Handle<Object> object); |
2085 bool NeedsMap() const; | 2014 bool NeedsMap() const; |
2086 bool CanBeUndetectable() const; | 2015 bool CanBeUndetectable() const; |
2087 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); } | 2016 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); } |
2088 | 2017 |
2089 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); } | 2018 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); } |
2090 }; | 2019 }; |
2091 | 2020 |
2092 explicit ToBooleanStub(Types types = Types()) | 2021 explicit ToBooleanStub(Types types = Types()) |
2093 : types_(types) { } | 2022 : types_(types) { } |
2094 explicit ToBooleanStub(Code::ExtraICState state) | 2023 explicit ToBooleanStub(Code::ExtraICState state) |
2095 : types_(static_cast<byte>(state)) { } | 2024 : types_(static_cast<byte>(state)) { } |
2096 | 2025 |
2097 bool UpdateStatus(Handle<Object> object); | 2026 bool Record(Handle<Object> object); |
2098 Types GetTypes() { return types_; } | 2027 Types GetTypes() { return types_; } |
2099 | 2028 |
2100 virtual Handle<Code> GenerateCode(); | 2029 virtual Handle<Code> GenerateCode(); |
2101 virtual void InitializeInterfaceDescriptor( | 2030 virtual void InitializeInterfaceDescriptor( |
2102 Isolate* isolate, | 2031 Isolate* isolate, |
2103 CodeStubInterfaceDescriptor* descriptor); | 2032 CodeStubInterfaceDescriptor* descriptor); |
2104 | 2033 |
2105 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; } | 2034 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; } |
2106 virtual void PrintState(StringStream* stream); | 2035 virtual void PrintName(StringStream* stream); |
2107 | 2036 |
2108 virtual bool SometimesSetsUpAFrame() { return false; } | 2037 virtual bool SometimesSetsUpAFrame() { return false; } |
2109 | 2038 |
2110 static void InitializeForIsolate(Isolate* isolate) { | 2039 static void InitializeForIsolate(Isolate* isolate) { |
2111 ToBooleanStub stub; | 2040 ToBooleanStub stub; |
2112 stub.InitializeInterfaceDescriptor( | 2041 stub.InitializeInterfaceDescriptor( |
2113 isolate, | 2042 isolate, |
2114 isolate->code_stub_interface_descriptor(CodeStub::ToBoolean)); | 2043 isolate->code_stub_interface_descriptor(CodeStub::ToBoolean)); |
2115 } | 2044 } |
2116 | 2045 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2247 int MinorKey() { return 0; } | 2176 int MinorKey() { return 0; } |
2248 | 2177 |
2249 void Generate(MacroAssembler* masm); | 2178 void Generate(MacroAssembler* masm); |
2250 | 2179 |
2251 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub); | 2180 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub); |
2252 }; | 2181 }; |
2253 | 2182 |
2254 } } // namespace v8::internal | 2183 } } // namespace v8::internal |
2255 | 2184 |
2256 #endif // V8_CODE_STUBS_H_ | 2185 #endif // V8_CODE_STUBS_H_ |
OLD | NEW |