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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 V(InternalArrayNoArgumentConstructor) \ | 83 V(InternalArrayNoArgumentConstructor) \ |
84 V(InternalArraySingleArgumentConstructor) \ | 84 V(InternalArraySingleArgumentConstructor) \ |
85 V(InternalArrayNArgumentsConstructor) \ | 85 V(InternalArrayNArgumentsConstructor) \ |
86 V(KeyedStoreElement) \ | 86 V(KeyedStoreElement) \ |
87 V(DebuggerStatement) \ | 87 V(DebuggerStatement) \ |
88 V(NameDictionaryLookup) \ | 88 V(NameDictionaryLookup) \ |
89 V(ElementsTransitionAndStore) \ | 89 V(ElementsTransitionAndStore) \ |
90 V(TransitionElementsKind) \ | 90 V(TransitionElementsKind) \ |
91 V(StoreArrayLiteralElement) \ | 91 V(StoreArrayLiteralElement) \ |
92 V(StubFailureTrampoline) \ | 92 V(StubFailureTrampoline) \ |
93 V(StubFailureTailCallTrampoline) \ | |
94 V(ArrayConstructor) \ | 93 V(ArrayConstructor) \ |
95 V(InternalArrayConstructor) \ | 94 V(InternalArrayConstructor) \ |
96 V(ProfileEntryHook) \ | 95 V(ProfileEntryHook) \ |
97 V(StoreGlobal) \ | 96 V(StoreGlobal) \ |
98 V(CallApiFunction) \ | 97 V(CallApiFunction) \ |
99 V(CallApiGetter) \ | 98 V(CallApiGetter) \ |
100 /* IC Handler stubs */ \ | 99 /* IC Handler stubs */ \ |
101 V(LoadField) \ | 100 V(LoadField) \ |
102 V(KeyedLoadField) \ | 101 V(KeyedLoadField) |
103 V(KeyedArrayCall) | |
104 | 102 |
105 // List of code stubs only used on ARM platforms. | 103 // List of code stubs only used on ARM platforms. |
106 #if V8_TARGET_ARCH_ARM | 104 #if V8_TARGET_ARCH_ARM |
107 #define CODE_STUB_LIST_ARM(V) \ | 105 #define CODE_STUB_LIST_ARM(V) \ |
108 V(GetProperty) \ | 106 V(GetProperty) \ |
109 V(SetProperty) \ | 107 V(SetProperty) \ |
110 V(InvokeBuiltin) \ | 108 V(InvokeBuiltin) \ |
111 V(DirectCEntry) | 109 V(DirectCEntry) |
112 #else | 110 #else |
113 #define CODE_STUB_LIST_ARM(V) | 111 #define CODE_STUB_LIST_ARM(V) |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 // Gets the major key from a code object that is a code stub or binary op IC. | 155 // Gets the major key from a code object that is a code stub or binary op IC. |
158 static Major GetMajorKey(Code* code_stub) { | 156 static Major GetMajorKey(Code* code_stub) { |
159 return static_cast<Major>(code_stub->major_key()); | 157 return static_cast<Major>(code_stub->major_key()); |
160 } | 158 } |
161 | 159 |
162 static const char* MajorName(Major major_key, bool allow_unknown_keys); | 160 static const char* MajorName(Major major_key, bool allow_unknown_keys); |
163 | 161 |
164 virtual ~CodeStub() {} | 162 virtual ~CodeStub() {} |
165 | 163 |
166 static void GenerateStubsAheadOfTime(Isolate* isolate); | 164 static void GenerateStubsAheadOfTime(Isolate* isolate); |
167 static void GenerateStubsRequiringBuiltinsAheadOfTime(Isolate* isolate); | |
168 static void GenerateFPStubs(Isolate* isolate); | 165 static void GenerateFPStubs(Isolate* isolate); |
169 | 166 |
170 // Some stubs put untagged junk on the stack that cannot be scanned by the | 167 // Some stubs put untagged junk on the stack that cannot be scanned by the |
171 // GC. This means that we must be statically sure that no GC can occur while | 168 // GC. This means that we must be statically sure that no GC can occur while |
172 // they are running. If that is the case they should override this to return | 169 // they are running. If that is the case they should override this to return |
173 // true, which will cause an assertion if we try to call something that can | 170 // true, which will cause an assertion if we try to call something that can |
174 // GC or if we try to put a stack frame on top of the junk, which would not | 171 // GC or if we try to put a stack frame on top of the junk, which would not |
175 // result in a traversable stack. | 172 // result in a traversable stack. |
176 virtual bool SometimesSetsUpAFrame() { return true; } | 173 virtual bool SometimesSetsUpAFrame() { return true; } |
177 | 174 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 | 265 |
269 protected: | 266 protected: |
270 // Generates the assembler code for the stub. | 267 // Generates the assembler code for the stub. |
271 virtual void Generate(MacroAssembler* masm) = 0; | 268 virtual void Generate(MacroAssembler* masm) = 0; |
272 }; | 269 }; |
273 | 270 |
274 | 271 |
275 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE }; | 272 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE }; |
276 enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS }; | 273 enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS }; |
277 | 274 |
278 enum ContinuationType { NORMAL_CONTINUATION, TAIL_CALL_CONTINUATION }; | |
279 | |
280 | |
281 struct CodeStubInterfaceDescriptor { | 275 struct CodeStubInterfaceDescriptor { |
282 CodeStubInterfaceDescriptor(); | 276 CodeStubInterfaceDescriptor(); |
283 int register_param_count_; | 277 int register_param_count_; |
284 | 278 |
285 Register stack_parameter_count_; | 279 Register stack_parameter_count_; |
286 // if hint_stack_parameter_count_ > 0, the code stub can optimize the | 280 // if hint_stack_parameter_count_ > 0, the code stub can optimize the |
287 // return sequence. Default value is -1, which means it is ignored. | 281 // return sequence. Default value is -1, which means it is ignored. |
288 int hint_stack_parameter_count_; | 282 int hint_stack_parameter_count_; |
289 ContinuationType continuation_type_; | |
290 StubFunctionMode function_mode_; | 283 StubFunctionMode function_mode_; |
291 Register* register_params_; | 284 Register* register_params_; |
292 | 285 |
293 Address deoptimization_handler_; | 286 Address deoptimization_handler_; |
294 HandlerArgumentsMode handler_arguments_mode_; | 287 HandlerArgumentsMode handler_arguments_mode_; |
295 | 288 |
296 bool initialized() const { return register_param_count_ >= 0; } | 289 bool initialized() const { return register_param_count_ >= 0; } |
297 | 290 |
298 bool HasTailCallContinuation() const { | |
299 return continuation_type_ == TAIL_CALL_CONTINUATION; | |
300 } | |
301 | |
302 int environment_length() const { | 291 int environment_length() const { |
303 return register_param_count_; | 292 return register_param_count_; |
304 } | 293 } |
305 | 294 |
306 void SetMissHandler(ExternalReference handler) { | 295 void SetMissHandler(ExternalReference handler) { |
307 miss_handler_ = handler; | 296 miss_handler_ = handler; |
308 has_miss_handler_ = true; | 297 has_miss_handler_ = true; |
309 // Our miss handler infrastructure doesn't currently support | 298 // Our miss handler infrastructure doesn't currently support |
310 // variable stack parameter counts. | 299 // variable stack parameter counts. |
311 ASSERT(!stack_parameter_count_.is_valid()); | 300 ASSERT(!stack_parameter_count_.is_valid()); |
(...skipping 757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1069 Isolate* isolate, | 1058 Isolate* isolate, |
1070 CodeStubInterfaceDescriptor* descriptor); | 1059 CodeStubInterfaceDescriptor* descriptor); |
1071 | 1060 |
1072 virtual Handle<Code> GenerateCode(Isolate* isolate); | 1061 virtual Handle<Code> GenerateCode(Isolate* isolate); |
1073 | 1062 |
1074 private: | 1063 private: |
1075 virtual CodeStub::Major MajorKey() { return KeyedLoadField; } | 1064 virtual CodeStub::Major MajorKey() { return KeyedLoadField; } |
1076 }; | 1065 }; |
1077 | 1066 |
1078 | 1067 |
1079 class KeyedArrayCallStub: public HICStub { | |
1080 public: | |
1081 KeyedArrayCallStub(bool holey, int argc) : HICStub(), argc_(argc) { | |
1082 bit_field_ = HoleyBits::encode(holey); | |
1083 } | |
1084 | |
1085 virtual Code::Kind kind() const { return Code::KEYED_CALL_IC; } | |
1086 virtual ExtraICState GetExtraICState() { return bit_field_; } | |
1087 | |
1088 ElementsKind elements_kind() { | |
1089 return HoleyBits::decode(bit_field_) ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; | |
1090 } | |
1091 | |
1092 int argc() { return argc_; } | |
1093 virtual int GetStubFlags() { return argc(); } | |
1094 | |
1095 static bool IsHoley(Handle<Code> code) { | |
1096 ExtraICState state = code->extra_ic_state(); | |
1097 return HoleyBits::decode(state); | |
1098 } | |
1099 | |
1100 virtual void InitializeInterfaceDescriptor( | |
1101 Isolate* isolate, | |
1102 CodeStubInterfaceDescriptor* descriptor); | |
1103 | |
1104 virtual Handle<Code> GenerateCode(Isolate* isolate); | |
1105 | |
1106 private: | |
1107 virtual int NotMissMinorKey() { | |
1108 return GetExtraICState() | ArgcBits::encode(argc_); | |
1109 } | |
1110 | |
1111 class HoleyBits: public BitField<bool, 0, 1> {}; | |
1112 STATIC_ASSERT(Code::kArgumentsBits <= kStubMinorKeyBits - 1); | |
1113 class ArgcBits: public BitField<int, 1, Code::kArgumentsBits> {}; | |
1114 virtual CodeStub::Major MajorKey() { return KeyedArrayCall; } | |
1115 int bit_field_; | |
1116 int argc_; | |
1117 }; | |
1118 | |
1119 | |
1120 class BinaryOpICStub : public HydrogenCodeStub { | 1068 class BinaryOpICStub : public HydrogenCodeStub { |
1121 public: | 1069 public: |
1122 BinaryOpICStub(Token::Value op, OverwriteMode mode) | 1070 BinaryOpICStub(Token::Value op, OverwriteMode mode) |
1123 : HydrogenCodeStub(UNINITIALIZED), state_(op, mode) {} | 1071 : HydrogenCodeStub(UNINITIALIZED), state_(op, mode) {} |
1124 | 1072 |
1125 explicit BinaryOpICStub(const BinaryOpIC::State& state) : state_(state) {} | 1073 explicit BinaryOpICStub(const BinaryOpIC::State& state) : state_(state) {} |
1126 | 1074 |
1127 static void GenerateAheadOfTime(Isolate* isolate); | 1075 static void GenerateAheadOfTime(Isolate* isolate); |
1128 | 1076 |
1129 virtual void InitializeInterfaceDescriptor( | 1077 virtual void InitializeInterfaceDescriptor( |
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1647 return ArgcBits::decode(minor_key); | 1595 return ArgcBits::decode(minor_key); |
1648 } | 1596 } |
1649 | 1597 |
1650 private: | 1598 private: |
1651 int argc_; | 1599 int argc_; |
1652 CallFunctionFlags flags_; | 1600 CallFunctionFlags flags_; |
1653 | 1601 |
1654 virtual void PrintName(StringStream* stream); | 1602 virtual void PrintName(StringStream* stream); |
1655 | 1603 |
1656 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>. | 1604 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>. |
1657 class FlagBits: public BitField<CallFunctionFlags, 0, 1> {}; | 1605 class FlagBits: public BitField<CallFunctionFlags, 0, 2> {}; |
1658 class ArgcBits: public BitField<unsigned, 1, 32 - 1> {}; | 1606 class ArgcBits: public BitField<unsigned, 2, 32 - 2> {}; |
1659 | 1607 |
1660 Major MajorKey() { return CallFunction; } | 1608 Major MajorKey() { return CallFunction; } |
1661 int MinorKey() { | 1609 int MinorKey() { |
1662 // Encode the parameters in a unique 32 bit value. | 1610 // Encode the parameters in a unique 32 bit value. |
1663 return FlagBits::encode(flags_) | ArgcBits::encode(argc_); | 1611 return FlagBits::encode(flags_) | ArgcBits::encode(argc_); |
1664 } | 1612 } |
1665 | 1613 |
1666 bool RecordCallTarget() { | 1614 bool RecordCallTarget() { |
1667 return (flags_ & RECORD_CALL_TARGET) != 0; | 1615 return flags_ == RECORD_CALL_TARGET; |
| 1616 } |
| 1617 |
| 1618 bool CallAsMethod() { |
| 1619 return flags_ == CALL_AS_METHOD || flags_ == WRAP_AND_CALL; |
| 1620 } |
| 1621 |
| 1622 bool NeedsChecks() { |
| 1623 return flags_ != WRAP_AND_CALL; |
1668 } | 1624 } |
1669 }; | 1625 }; |
1670 | 1626 |
1671 | 1627 |
1672 class CallConstructStub: public PlatformCodeStub { | 1628 class CallConstructStub: public PlatformCodeStub { |
1673 public: | 1629 public: |
1674 explicit CallConstructStub(CallFunctionFlags flags) : flags_(flags) {} | 1630 explicit CallConstructStub(CallFunctionFlags flags) : flags_(flags) {} |
1675 | 1631 |
1676 void Generate(MacroAssembler* masm); | 1632 void Generate(MacroAssembler* masm); |
1677 | 1633 |
1678 virtual void FinishCode(Handle<Code> code) { | 1634 virtual void FinishCode(Handle<Code> code) { |
1679 code->set_has_function_cache(RecordCallTarget()); | 1635 code->set_has_function_cache(RecordCallTarget()); |
1680 } | 1636 } |
1681 | 1637 |
1682 private: | 1638 private: |
1683 CallFunctionFlags flags_; | 1639 CallFunctionFlags flags_; |
1684 | 1640 |
1685 virtual void PrintName(StringStream* stream); | 1641 virtual void PrintName(StringStream* stream); |
1686 | 1642 |
1687 Major MajorKey() { return CallConstruct; } | 1643 Major MajorKey() { return CallConstruct; } |
1688 int MinorKey() { return flags_; } | 1644 int MinorKey() { return flags_; } |
1689 | 1645 |
1690 bool RecordCallTarget() { | 1646 bool RecordCallTarget() { |
1691 return (flags_ & RECORD_CALL_TARGET) != 0; | 1647 return (flags_ & RECORD_CALL_TARGET) != 0; |
1692 } | 1648 } |
| 1649 |
| 1650 bool CallAsMethod() { |
| 1651 return (flags_ & CALL_AS_METHOD) != 0; |
| 1652 } |
1693 }; | 1653 }; |
1694 | 1654 |
1695 | 1655 |
1696 enum StringIndexFlags { | 1656 enum StringIndexFlags { |
1697 // Accepts smis or heap numbers. | 1657 // Accepts smis or heap numbers. |
1698 STRING_INDEX_IS_NUMBER, | 1658 STRING_INDEX_IS_NUMBER, |
1699 | 1659 |
1700 // Accepts smis or heap numbers that are valid array indices | 1660 // Accepts smis or heap numbers that are valid array indices |
1701 // (ECMA-262 15.4). Invalid indices are reported as being out of | 1661 // (ECMA-262 15.4). Invalid indices are reported as being out of |
1702 // range. | 1662 // range. |
(...skipping 781 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2484 | 2444 |
2485 void Generate(MacroAssembler* masm); | 2445 void Generate(MacroAssembler* masm); |
2486 | 2446 |
2487 bool fp_registers_; | 2447 bool fp_registers_; |
2488 StubFunctionMode function_mode_; | 2448 StubFunctionMode function_mode_; |
2489 | 2449 |
2490 DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub); | 2450 DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub); |
2491 }; | 2451 }; |
2492 | 2452 |
2493 | 2453 |
2494 class StubFailureTailCallTrampolineStub : public PlatformCodeStub { | |
2495 public: | |
2496 StubFailureTailCallTrampolineStub() : fp_registers_(CanUseFPRegisters()) {} | |
2497 | |
2498 static void GenerateAheadOfTime(Isolate* isolate); | |
2499 | |
2500 private: | |
2501 class FPRegisters: public BitField<bool, 0, 1> {}; | |
2502 Major MajorKey() { return StubFailureTailCallTrampoline; } | |
2503 int MinorKey() { return FPRegisters::encode(fp_registers_); } | |
2504 | |
2505 void Generate(MacroAssembler* masm); | |
2506 | |
2507 bool fp_registers_; | |
2508 | |
2509 DISALLOW_COPY_AND_ASSIGN(StubFailureTailCallTrampolineStub); | |
2510 }; | |
2511 | |
2512 | |
2513 class ProfileEntryHookStub : public PlatformCodeStub { | 2454 class ProfileEntryHookStub : public PlatformCodeStub { |
2514 public: | 2455 public: |
2515 explicit ProfileEntryHookStub() {} | 2456 explicit ProfileEntryHookStub() {} |
2516 | 2457 |
2517 // The profile entry hook function is not allowed to cause a GC. | 2458 // The profile entry hook function is not allowed to cause a GC. |
2518 virtual bool SometimesSetsUpAFrame() { return false; } | 2459 virtual bool SometimesSetsUpAFrame() { return false; } |
2519 | 2460 |
2520 // Generates a call to the entry hook if it's enabled. | 2461 // Generates a call to the entry hook if it's enabled. |
2521 static void MaybeCallEntryHook(MacroAssembler* masm); | 2462 static void MaybeCallEntryHook(MacroAssembler* masm); |
2522 | 2463 |
(...skipping 12 matching lines...) Expand all Loading... |
2535 | 2476 |
2536 | 2477 |
2537 class CallDescriptors { | 2478 class CallDescriptors { |
2538 public: | 2479 public: |
2539 static void InitializeForIsolate(Isolate* isolate); | 2480 static void InitializeForIsolate(Isolate* isolate); |
2540 }; | 2481 }; |
2541 | 2482 |
2542 } } // namespace v8::internal | 2483 } } // namespace v8::internal |
2543 | 2484 |
2544 #endif // V8_CODE_STUBS_H_ | 2485 #endif // V8_CODE_STUBS_H_ |
OLD | NEW |