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 | |
128 | 126 |
129 // Stub is base classes of all stubs. | 127 // Stub is base classes of all stubs. |
130 class CodeStub BASE_EMBEDDED { | 128 class CodeStub BASE_EMBEDDED { |
131 public: | 129 public: |
132 enum Major { | 130 enum Major { |
133 #define DEF_ENUM(name) name, | 131 #define DEF_ENUM(name) name, |
134 CODE_STUB_LIST(DEF_ENUM) | 132 CODE_STUB_LIST(DEF_ENUM) |
135 #undef DEF_ENUM | 133 #undef DEF_ENUM |
136 NoCache, // marker for stubs that do custom caching | 134 NoCache, // marker for stubs that do custom caching |
137 NUMBER_OF_IDS | 135 NUMBER_OF_IDS |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
190 virtual Code::ExtraICState GetExtraICState() { | 188 virtual Code::ExtraICState GetExtraICState() { |
191 return Code::kNoExtraICState; | 189 return Code::kNoExtraICState; |
192 } | 190 } |
193 virtual Code::StubType GetStubType() { | 191 virtual Code::StubType GetStubType() { |
194 return Code::NORMAL; | 192 return Code::NORMAL; |
195 } | 193 } |
196 virtual int GetStubFlags() { | 194 virtual int GetStubFlags() { |
197 return -1; | 195 return -1; |
198 } | 196 } |
199 | 197 |
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 | |
211 private: | 216 private: |
212 // Perform bookkeeping required after code generation when stub code is | 217 // Perform bookkeeping required after code generation when stub code is |
213 // initially generated. | 218 // initially generated. |
214 void RecordCodeGeneration(Code* code, Isolate* isolate); | 219 void RecordCodeGeneration(Code* code, Isolate* isolate); |
215 | 220 |
216 // Finish the code object after it has been generated. | 221 // Finish the code object after it has been generated. |
217 virtual void FinishCode(Handle<Code> code) { } | 222 virtual void FinishCode(Handle<Code> code) { } |
218 | 223 |
219 // Activate newly generated stub. Is called after | 224 // Activate newly generated stub. Is called after |
220 // registering stub in the stub cache. | 225 // registering stub in the stub cache. |
221 virtual void Activate(Code* code) { } | 226 virtual void Activate(Code* code) { } |
222 | 227 |
223 // BinaryOpStub needs to override this. | 228 // BinaryOpStub needs to override this. |
224 virtual Code::Kind GetCodeKind() const; | 229 virtual Code::Kind GetCodeKind() const; |
225 | 230 |
226 // Add the code to a specialized cache, specific to an individual | 231 // Add the code to a specialized cache, specific to an individual |
227 // stub type. Please note, this method must add the code object to a | 232 // stub type. Please note, this method must add the code object to a |
228 // roots object, otherwise we will remove the code during GC. | 233 // roots object, otherwise we will remove the code during GC. |
229 virtual void AddToSpecialCache(Handle<Code> new_object) { } | 234 virtual void AddToSpecialCache(Handle<Code> new_object) { } |
230 | 235 |
231 // Find code in a specialized cache, work is delegated to the specific stub. | 236 // Find code in a specialized cache, work is delegated to the specific stub. |
232 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate) { | 237 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate) { |
233 return false; | 238 return false; |
234 } | 239 } |
235 | 240 |
236 // If a stub uses a special cache override this. | 241 // If a stub uses a special cache override this. |
237 virtual bool UseSpecialCache() { return false; } | 242 virtual bool UseSpecialCache() { return false; } |
238 | 243 |
239 // Returns a name for logging/debugging purposes. | |
240 SmartArrayPointer<const char> GetName(); | |
241 virtual void PrintName(StringStream* stream); | |
242 | |
243 // Computes the key based on major and minor. | 244 // Computes the key based on major and minor. |
244 uint32_t GetKey() { | 245 uint32_t GetKey() { |
245 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS); | 246 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS); |
246 return MinorKeyBits::encode(MinorKey()) | | 247 return MinorKeyBits::encode(MinorKey()) | |
247 MajorKeyBits::encode(MajorKey()); | 248 MajorKeyBits::encode(MajorKey()); |
248 } | 249 } |
249 | 250 |
250 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {}; | 251 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {}; |
251 class MinorKeyBits: public BitField<uint32_t, | 252 class MinorKeyBits: public BitField<uint32_t, |
252 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT | 253 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
347 Isolate* isolate, | 348 Isolate* isolate, |
348 CodeStubInterfaceDescriptor* descriptor) = 0; | 349 CodeStubInterfaceDescriptor* descriptor) = 0; |
349 | 350 |
350 // Retrieve the code for the stub. Generate the code if needed. | 351 // Retrieve the code for the stub. Generate the code if needed. |
351 virtual Handle<Code> GenerateCode() = 0; | 352 virtual Handle<Code> GenerateCode() = 0; |
352 | 353 |
353 virtual int NotMissMinorKey() = 0; | 354 virtual int NotMissMinorKey() = 0; |
354 | 355 |
355 Handle<Code> GenerateLightweightMissCode(Isolate* isolate); | 356 Handle<Code> GenerateLightweightMissCode(Isolate* isolate); |
356 | 357 |
358 template<class StateType> | |
359 void TraceTransition(StateType from, StateType to); | |
360 | |
357 private: | 361 private: |
358 class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {}; | 362 class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {}; |
359 class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {}; | 363 class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {}; |
360 | 364 |
361 void GenerateLightweightMiss(MacroAssembler* masm); | 365 void GenerateLightweightMiss(MacroAssembler* masm); |
362 virtual int MinorKey() { | 366 virtual int MinorKey() { |
363 return IsMissBits::encode(is_uninitialized_) | | 367 return IsMissBits::encode(is_uninitialized_) | |
364 MinorKeyBits::encode(NotMissMinorKey()); | 368 MinorKeyBits::encode(NotMissMinorKey()); |
365 } | 369 } |
366 | 370 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
513 void Generate(MacroAssembler* masm); | 517 void Generate(MacroAssembler* masm); |
514 | 518 |
515 private: | 519 private: |
516 int slots_; | 520 int slots_; |
517 | 521 |
518 Major MajorKey() { return FastNewBlockContext; } | 522 Major MajorKey() { return FastNewBlockContext; } |
519 int MinorKey() { return slots_; } | 523 int MinorKey() { return slots_; } |
520 }; | 524 }; |
521 | 525 |
522 | 526 |
527 class UnaryOpStub : public HydrogenCodeStub { | |
528 public: | |
529 enum UnaryOpType { | |
530 SMI, | |
531 HEAP_NUMBER, | |
532 GENERIC, | |
533 NUMBER_OF_TYPES | |
534 }; | |
535 | |
536 // At most 7 different Types can be distinguished, because the Code object | |
537 // only has room for a single byte to hold and we need to store the operator. | |
538 STATIC_ASSERT(NUMBER_OF_TYPES <= 7); | |
539 | |
540 class State : public EnumSet<UnaryOpType, byte> { | |
541 public: | |
542 State() : EnumSet<UnaryOpType, byte>(0) { } | |
543 explicit State(byte bits) : EnumSet<UnaryOpType, byte>(bits) { } | |
544 bool IsGeneric() const { return Contains(GENERIC); } | |
545 | |
546 void Print(StringStream* stream) const; | |
547 }; | |
548 | |
549 // Stub without type info available -> construct uninitialized | |
550 explicit UnaryOpStub(Token::Value operation) | |
551 : HydrogenCodeStub(UNINITIALIZED), operation_(operation) { } | |
552 explicit UnaryOpStub(Code::ExtraICState ic_state) : | |
553 state_(State(ic_state & ((1 << NUMBER_OF_TYPES) - 1))) { | |
554 operation_ = OperatorBits::decode(ic_state) == UNARY_NOT ? | |
555 Token::BIT_NOT : Token::SUB; | |
556 } | |
557 | |
558 virtual void InitializeInterfaceDescriptor( | |
559 Isolate* isolate, | |
560 CodeStubInterfaceDescriptor* descriptor); | |
561 | |
562 virtual Code::Kind GetCodeKind() const { return Code::UNARY_OP_IC; } | |
563 virtual InlineCacheState GetICState() { | |
564 if (state_.IsGeneric()) { | |
565 return MEGAMORPHIC; | |
566 } else if (state_.IsEmpty()) { | |
567 return PREMONOMORPHIC; | |
568 } else { | |
569 return MONOMORPHIC; | |
570 } | |
571 } | |
572 virtual Code::ExtraICState GetExtraICState() { | |
573 return OperatorBits::encode((operation_ == Token::BIT_NOT) ? | |
574 UNARY_NOT : UNARY_MINUS) | | |
575 state_.ToIntegral(); | |
576 } | |
577 | |
578 Token::Value operation() { return operation_; } | |
579 Handle<JSFunction> ToJSFunction(Isolate* isolate); | |
580 | |
581 void UpdateStatus(Handle<Object> object); | |
582 MaybeObject* Result(Handle<Object> object, Isolate* isolate); | |
583 Handle<Code> GenerateCode(); | |
584 Handle<Type> GetType(Isolate* isolate); | |
585 | |
586 protected: | |
587 void PrintState(StringStream* stream); | |
588 void PrintBaseName(StringStream* stream); | |
589 | |
590 private: | |
591 enum SupportedOperations { | |
592 UNARY_MINUS, | |
593 UNARY_NOT, | |
594 NUMBER_OF_OPERATIONS | |
595 }; | |
596 // There is only one bit reserved for the operation | |
597 STATIC_ASSERT(NUMBER_OF_OPERATIONS == 2); | |
598 | |
599 Builtins::JavaScript ToJSBuiltin(); | |
600 | |
601 class OperatorBits : public BitField<byte, NUMBER_OF_TYPES, 1> {}; | |
danno
2013/06/27 13:31:06
This isn't right. The NUMBER_OF_TYPES doesn't dire
oliv
2013/06/27 17:20:48
I think the code is correct. The encoding of the s
| |
602 | |
603 State state_; | |
604 Token::Value operation_; | |
605 | |
606 virtual CodeStub::Major MajorKey() { return UnaryOp; } | |
607 virtual int NotMissMinorKey() { return GetExtraICState(); } | |
608 }; | |
609 | |
610 | |
523 class FastCloneShallowArrayStub : public HydrogenCodeStub { | 611 class FastCloneShallowArrayStub : public HydrogenCodeStub { |
524 public: | 612 public: |
525 // Maximum length of copied elements array. | 613 // Maximum length of copied elements array. |
526 static const int kMaximumClonedLength = 8; | 614 static const int kMaximumClonedLength = 8; |
527 enum Mode { | 615 enum Mode { |
528 CLONE_ELEMENTS, | 616 CLONE_ELEMENTS, |
529 CLONE_DOUBLE_ELEMENTS, | 617 CLONE_DOUBLE_ELEMENTS, |
530 COPY_ON_WRITE_ELEMENTS, | 618 COPY_ON_WRITE_ELEMENTS, |
531 CLONE_ANY_ELEMENTS, | 619 CLONE_ANY_ELEMENTS, |
532 LAST_CLONE_MODE = CLONE_ANY_ELEMENTS | 620 LAST_CLONE_MODE = CLONE_ANY_ELEMENTS |
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1141 static State Generic() { | 1229 static State Generic() { |
1142 State set; | 1230 State set; |
1143 set.Add(UNDEFINED); | 1231 set.Add(UNDEFINED); |
1144 set.Add(NULL_TYPE); | 1232 set.Add(NULL_TYPE); |
1145 set.Add(UNDETECTABLE); | 1233 set.Add(UNDETECTABLE); |
1146 set.Add(GENERIC); | 1234 set.Add(GENERIC); |
1147 return set; | 1235 return set; |
1148 } | 1236 } |
1149 | 1237 |
1150 void Print(StringStream* stream) const; | 1238 void Print(StringStream* stream) const; |
1151 void TraceTransition(State to) const; | |
1152 }; | 1239 }; |
1153 | 1240 |
1154 static Handle<Type> StateToType( | 1241 static Handle<Type> StateToType( |
1155 Isolate* isolate, State state, Handle<Map> map = Handle<Map>()); | 1242 Isolate* isolate, State state, Handle<Map> map = Handle<Map>()); |
1156 | 1243 |
1157 // At most 6 different types can be distinguished, because the Code object | 1244 // At most 6 different types can be distinguished, because the Code object |
1158 // only has room for a single byte to hold a set and there are two more | 1245 // only has room for a single byte to hold a set and there are two more |
1159 // boolean flags we need to store. :-P | 1246 // boolean flags we need to store. :-P |
1160 STATIC_ASSERT(NUMBER_OF_TYPES <= 6); | 1247 STATIC_ASSERT(NUMBER_OF_TYPES <= 6); |
1161 | 1248 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1201 Handle<Code> GenerateCode(); | 1288 Handle<Code> GenerateCode(); |
1202 | 1289 |
1203 // extra ic state = nil_value | type_n-1 | ... | type_0 | 1290 // extra ic state = nil_value | type_n-1 | ... | type_0 |
1204 virtual Code::ExtraICState GetExtraICState() { | 1291 virtual Code::ExtraICState GetExtraICState() { |
1205 return NilValueField::encode(nil_value_) | state_.ToIntegral(); | 1292 return NilValueField::encode(nil_value_) | state_.ToIntegral(); |
1206 } | 1293 } |
1207 static byte ExtractTypesFromExtraICState(Code::ExtraICState state) { | 1294 static byte ExtractTypesFromExtraICState(Code::ExtraICState state) { |
1208 return state & ((1 << NUMBER_OF_TYPES) - 1); | 1295 return state & ((1 << NUMBER_OF_TYPES) - 1); |
1209 } | 1296 } |
1210 | 1297 |
1211 void Record(Handle<Object> object); | 1298 void UpdateStatus(Handle<Object> object); |
1212 | 1299 |
1213 bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); } | 1300 bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); } |
1214 NilValue GetNilValue() const { return nil_value_; } | 1301 NilValue GetNilValue() const { return nil_value_; } |
1215 State GetState() const { return state_; } | 1302 State GetState() const { return state_; } |
1216 void ClearState() { state_.RemoveAll(); } | 1303 void ClearState() { state_.RemoveAll(); } |
1217 | 1304 |
1218 virtual void PrintName(StringStream* stream); | 1305 virtual void PrintState(StringStream* stream); |
1306 virtual void PrintBaseName(StringStream* stream); | |
1219 | 1307 |
1220 private: | 1308 private: |
1221 friend class CompareNilIC; | 1309 friend class CompareNilIC; |
1222 | 1310 |
1223 CompareNilICStub(NilValue nil, InitializationState init_state) | 1311 CompareNilICStub(NilValue nil, InitializationState init_state) |
1224 : HydrogenCodeStub(init_state) { | 1312 : HydrogenCodeStub(init_state) { |
1225 nil_value_ = nil; | 1313 nil_value_ = nil; |
1226 } | 1314 } |
1227 | 1315 |
1228 class NilValueField : public BitField<NilValue, NUMBER_OF_TYPES, 1> {}; | 1316 class NilValueField : public BitField<NilValue, NUMBER_OF_TYPES, 1> {}; |
(...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1971 // only has room for a single byte to hold a set of these types. :-P | 2059 // only has room for a single byte to hold a set of these types. :-P |
1972 STATIC_ASSERT(NUMBER_OF_TYPES <= 8); | 2060 STATIC_ASSERT(NUMBER_OF_TYPES <= 8); |
1973 | 2061 |
1974 class Types : public EnumSet<Type, byte> { | 2062 class Types : public EnumSet<Type, byte> { |
1975 public: | 2063 public: |
1976 Types() : EnumSet<Type, byte>(0) {} | 2064 Types() : EnumSet<Type, byte>(0) {} |
1977 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {} | 2065 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {} |
1978 | 2066 |
1979 byte ToByte() const { return ToIntegral(); } | 2067 byte ToByte() const { return ToIntegral(); } |
1980 void Print(StringStream* stream) const; | 2068 void Print(StringStream* stream) const; |
1981 void TraceTransition(Types to) const; | 2069 bool UpdateStatus(Handle<Object> object); |
1982 bool Record(Handle<Object> object); | |
1983 bool NeedsMap() const; | 2070 bool NeedsMap() const; |
1984 bool CanBeUndetectable() const; | 2071 bool CanBeUndetectable() const; |
1985 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); } | 2072 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); } |
1986 | 2073 |
1987 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); } | 2074 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); } |
1988 }; | 2075 }; |
1989 | 2076 |
1990 explicit ToBooleanStub(Types types = Types()) | 2077 explicit ToBooleanStub(Types types = Types()) |
1991 : types_(types) { } | 2078 : types_(types) { } |
1992 explicit ToBooleanStub(Code::ExtraICState state) | 2079 explicit ToBooleanStub(Code::ExtraICState state) |
1993 : types_(static_cast<byte>(state)) { } | 2080 : types_(static_cast<byte>(state)) { } |
1994 | 2081 |
1995 bool Record(Handle<Object> object); | 2082 bool UpdateStatus(Handle<Object> object); |
1996 Types GetTypes() { return types_; } | 2083 Types GetTypes() { return types_; } |
1997 | 2084 |
1998 virtual Handle<Code> GenerateCode(); | 2085 virtual Handle<Code> GenerateCode(); |
1999 virtual void InitializeInterfaceDescriptor( | 2086 virtual void InitializeInterfaceDescriptor( |
2000 Isolate* isolate, | 2087 Isolate* isolate, |
2001 CodeStubInterfaceDescriptor* descriptor); | 2088 CodeStubInterfaceDescriptor* descriptor); |
2002 | 2089 |
2003 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; } | 2090 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; } |
2004 virtual void PrintName(StringStream* stream); | 2091 virtual void PrintState(StringStream* stream); |
2005 | 2092 |
2006 virtual bool SometimesSetsUpAFrame() { return false; } | 2093 virtual bool SometimesSetsUpAFrame() { return false; } |
2007 | 2094 |
2008 static void InitializeForIsolate(Isolate* isolate) { | 2095 static void InitializeForIsolate(Isolate* isolate) { |
2009 ToBooleanStub stub; | 2096 ToBooleanStub stub; |
2010 stub.InitializeInterfaceDescriptor( | 2097 stub.InitializeInterfaceDescriptor( |
2011 isolate, | 2098 isolate, |
2012 isolate->code_stub_interface_descriptor(CodeStub::ToBoolean)); | 2099 isolate->code_stub_interface_descriptor(CodeStub::ToBoolean)); |
2013 } | 2100 } |
2014 | 2101 |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2155 | 2242 |
2156 // The current function entry hook. | 2243 // The current function entry hook. |
2157 static FunctionEntryHook entry_hook_; | 2244 static FunctionEntryHook entry_hook_; |
2158 | 2245 |
2159 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub); | 2246 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub); |
2160 }; | 2247 }; |
2161 | 2248 |
2162 } } // namespace v8::internal | 2249 } } // namespace v8::internal |
2163 | 2250 |
2164 #endif // V8_CODE_STUBS_H_ | 2251 #endif // V8_CODE_STUBS_H_ |
OLD | NEW |