OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/bailout-reason.h" | 7 #include "src/bailout-reason.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/field-index.h" | 9 #include "src/field-index.h" |
10 #include "src/hydrogen.h" | 10 #include "src/hydrogen.h" |
11 #include "src/ic/ic.h" | |
11 #include "src/lithium.h" | 12 #include "src/lithium.h" |
12 | 13 |
13 namespace v8 { | 14 namespace v8 { |
14 namespace internal { | 15 namespace internal { |
15 | 16 |
16 | 17 |
17 static LChunk* OptimizeGraph(HGraph* graph) { | 18 static LChunk* OptimizeGraph(HGraph* graph) { |
18 DisallowHeapAllocation no_allocation; | 19 DisallowHeapAllocation no_allocation; |
19 DisallowHandleAllocation no_handles; | 20 DisallowHandleAllocation no_handles; |
20 DisallowHandleDereference no_deref; | 21 DisallowHandleDereference no_deref; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
92 HValue* map_index); | 93 HValue* map_index); |
93 void BuildInstallCode(HValue* js_function, HValue* shared_info); | 94 void BuildInstallCode(HValue* js_function, HValue* shared_info); |
94 | 95 |
95 HInstruction* LoadFromOptimizedCodeMap(HValue* optimized_map, | 96 HInstruction* LoadFromOptimizedCodeMap(HValue* optimized_map, |
96 HValue* iterator, | 97 HValue* iterator, |
97 int field_offset); | 98 int field_offset); |
98 void BuildInstallFromOptimizedCodeMap(HValue* js_function, | 99 void BuildInstallFromOptimizedCodeMap(HValue* js_function, |
99 HValue* shared_info, | 100 HValue* shared_info, |
100 HValue* native_context); | 101 HValue* native_context); |
101 | 102 |
103 // Tail calls handler found at array[index]. | |
104 void TailCallHandler(HValue* receiver, HValue* name, HValue* array, | |
105 HValue* index, HValue* slot, HValue* vector); | |
106 | |
107 // Tail calls handler_code. | |
108 void TailCallHandler(HValue* receiver, HValue* name, HValue* slot, | |
109 HValue* vector, HValue* handler_code); | |
110 | |
111 void TailCallMiss(HValue* receiver, HValue* name, HValue* slot, | |
112 HValue* vector, bool keyed_load); | |
113 | |
114 // Handle MONOMORPHIC and POLYMORPHIC LoadIC and KeyedLoadIC cases. | |
115 void HandleArrayCases(HValue* array, HValue* receiver, HValue* name, | |
116 HValue* slot, HValue* vector, bool keyed_load); | |
117 | |
102 private: | 118 private: |
103 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); | 119 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); |
104 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, | 120 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, |
105 ElementsKind kind); | 121 ElementsKind kind); |
106 | 122 |
107 SmartArrayPointer<HParameter*> parameters_; | 123 SmartArrayPointer<HParameter*> parameters_; |
108 HValue* arguments_length_; | 124 HValue* arguments_length_; |
109 CompilationInfoWithZone info_; | 125 CompilationInfoWithZone info_; |
110 CodeStubDescriptor descriptor_; | 126 CodeStubDescriptor descriptor_; |
111 HContext* context_; | 127 HContext* context_; |
(...skipping 1884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1996 | 2012 |
1997 return Pop(); | 2013 return Pop(); |
1998 } | 2014 } |
1999 | 2015 |
2000 | 2016 |
2001 Handle<Code> KeyedLoadGenericStub::GenerateCode() { | 2017 Handle<Code> KeyedLoadGenericStub::GenerateCode() { |
2002 return DoGenerateCode(this); | 2018 return DoGenerateCode(this); |
2003 } | 2019 } |
2004 | 2020 |
2005 | 2021 |
2022 void CodeStubGraphBuilderBase::TailCallHandler(HValue* receiver, HValue* name, | |
2023 HValue* array, HValue* index, | |
2024 HValue* slot, HValue* vector) { | |
2025 HValue* handler_code = | |
2026 Add<HLoadKeyed>(array, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
2027 TailCallHandler(receiver, name, slot, vector, handler_code); | |
2028 } | |
2029 | |
2030 | |
2031 void CodeStubGraphBuilderBase::TailCallHandler(HValue* receiver, HValue* name, | |
2032 HValue* slot, HValue* vector, | |
2033 HValue* handler_code) { | |
2034 VectorLoadICDescriptor descriptor(isolate()); | |
2035 HValue* op_vals[] = {context(), receiver, name, slot, vector}; | |
2036 // We never return here, it is a tail call. | |
Jakob Kummerow
2014/12/02 08:43:06
nit: I'd move this comment after the Add<...>.
If
mvstanton
2014/12/03 11:48:30
Thanks, sounds like a good idea. I tried approxima
| |
2037 Add<HCallWithDescriptor>(handler_code, 0, descriptor, | |
2038 Vector<HValue*>(op_vals, 5), TAIL_CALL); | |
2039 } | |
2040 | |
2041 | |
2042 void CodeStubGraphBuilderBase::TailCallMiss(HValue* receiver, HValue* name, | |
2043 HValue* slot, HValue* vector, | |
2044 bool keyed_load) { | |
2045 DCHECK(FLAG_vector_ics); | |
2046 // We never return here, it is a tail call. | |
Jakob Kummerow
2014/12/02 08:43:06
same here
mvstanton
2014/12/03 11:48:30
Done.
| |
2047 Add<HTailCallThroughMegamorphicCache>( | |
2048 receiver, name, slot, vector, | |
2049 HTailCallThroughMegamorphicCache::ComputeFlags(keyed_load, true)); | |
2050 } | |
2051 | |
2052 | |
2053 void CodeStubGraphBuilderBase::HandleArrayCases(HValue* array, HValue* receiver, | |
2054 HValue* name, HValue* slot, | |
2055 HValue* vector, | |
2056 bool keyed_load) { | |
2057 HValue* length = AddLoadFixedArrayLength(array, static_cast<HValue*>(NULL)); | |
2058 HValue* receiver_map = AddLoadMap(receiver, static_cast<HValue*>(NULL)); | |
2059 IfBuilder mono_checker(this); | |
Jakob Kummerow
2014/12/02 08:43:06
Naming suggestion: if you name this guy "if_monomo
mvstanton
2014/12/03 11:48:30
Done.
| |
2060 HValue* mono_length = | |
2061 Add<HConstant>(static_cast<int32_t>(keyed_load ? 3 : 2)); | |
2062 mono_checker.If<HCompareNumericAndBranch>(length, mono_length, Token::EQ); | |
2063 mono_checker.Then(); | |
2064 { | |
2065 // Compare map. | |
2066 HValue* start = | |
2067 keyed_load ? graph()->GetConstant1() : graph()->GetConstant0(); | |
2068 HValue* array_map = Add<HLoadKeyed>( | |
2069 array, start, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
2070 IfBuilder correct_map_checker(this); | |
2071 correct_map_checker.If<HCompareObjectEqAndBranch>(receiver_map, array_map); | |
2072 correct_map_checker.Then(); | |
2073 { | |
2074 HValue* handler_index = keyed_load | |
2075 ? Add<HConstant>(static_cast<int32_t>(2)) | |
Jakob Kummerow
2014/12/02 08:43:06
nit: Drop the static_cast, it's cleaner.
mvstanton
2014/12/03 11:48:29
Done.
mvstanton
2014/12/03 11:48:30
Done. I reformulated this code a bit too, noticing
| |
2076 : graph()->GetConstant1(); | |
2077 TailCallHandler(receiver, name, array, handler_index, slot, vector); | |
2078 } | |
2079 correct_map_checker.Else(); | |
2080 { TailCallMiss(receiver, name, slot, vector, keyed_load); } | |
2081 correct_map_checker.End(); | |
2082 } | |
2083 mono_checker.Else(); | |
2084 { | |
2085 // It is polymorphic. | |
2086 HValue* increment_amount = Add<HConstant>(2); | |
2087 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement, | |
2088 increment_amount); | |
2089 HValue* start = | |
2090 keyed_load ? graph()->GetConstant1() : graph()->GetConstant0(); | |
2091 HValue* key = builder.BeginBody(start, length, Token::LT); | |
2092 { | |
2093 HValue* array_map = Add<HLoadKeyed>( | |
2094 array, key, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
2095 IfBuilder correct_map_checker(this); | |
2096 correct_map_checker.If<HCompareObjectEqAndBranch>(receiver_map, | |
2097 array_map); | |
2098 correct_map_checker.Then(); | |
2099 { | |
2100 HValue* one = graph()->GetConstant1(); | |
2101 HValue* index = AddUncasted<HAdd>(key, one); | |
2102 TailCallHandler(receiver, name, array, index, slot, vector); | |
2103 } | |
2104 } | |
2105 builder.EndBody(); | |
2106 | |
2107 TailCallMiss(receiver, name, slot, vector, keyed_load); | |
2108 } | |
2109 mono_checker.End(); | |
2110 } | |
2111 | |
2112 | |
2006 template <> | 2113 template <> |
2007 HValue* CodeStubGraphBuilder<VectorLoadStub>::BuildCodeStub() { | 2114 HValue* CodeStubGraphBuilder<VectorLoadStub>::BuildCodeStub() { |
2008 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); | 2115 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); |
2009 Add<HDeoptimize>("Always deopt", Deoptimizer::EAGER); | 2116 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); |
2010 return receiver; | 2117 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); |
2118 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); | |
2119 | |
2120 // Are we monomorphic? | |
Jakob Kummerow
2014/12/02 08:43:06
nit: s/Are we foo/Is the IC in foo state/, and ple
mvstanton
2014/12/03 11:48:30
Done.
| |
2121 HValue* feedback = | |
2122 Add<HLoadKeyed>(vector, slot, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
2123 IfBuilder array_checker(this); | |
2124 array_checker.If<HCompareMap>(feedback, | |
Jakob Kummerow
2014/12/02 08:43:06
This map check bakes in the assumption that the fe
mvstanton
2014/12/03 11:48:30
Yes indeed, that is why we have a pile of symbols
| |
2125 isolate()->factory()->fixed_array_map()); | |
2126 array_checker.Then(); | |
2127 { | |
2128 Add<HCheckHeapObject>(receiver); | |
Jakob Kummerow
2014/12/02 08:43:06
Ugh. Hydrogen's ugly warts. HCheckHeapObject shoul
mvstanton
2014/12/03 11:48:30
Oh yeah, creepy. Okay, I've turned the HCheckHeapO
Jakob Kummerow
2014/12/03 13:22:17
That's fine, but I didn't mean to imply you should
| |
2129 HandleArrayCases(feedback, receiver, name, slot, vector, false); | |
2130 } | |
2131 array_checker.Else(); | |
2132 { | |
2133 // Are we megamorphic? | |
2134 IfBuilder mega_checker(this); | |
2135 HConstant* megamorphic_symbol = | |
2136 Add<HConstant>(isolate()->factory()->megamorphic_symbol()); | |
2137 mega_checker.If<HCompareObjectEqAndBranch>(feedback, megamorphic_symbol); | |
2138 mega_checker.Then(); | |
2139 { | |
2140 // Probe the stub cache. | |
2141 Add<HTailCallThroughMegamorphicCache>( | |
2142 receiver, name, slot, vector, | |
2143 HTailCallThroughMegamorphicCache::ComputeFlags(false, false)); | |
2144 } | |
2145 mega_checker.End(); | |
2146 | |
2147 TailCallMiss(receiver, name, slot, vector, false); | |
2148 } | |
2149 array_checker.End(); | |
2150 | |
2151 // We never get here. | |
2152 return graph()->GetConstant0(); | |
2011 } | 2153 } |
2012 | 2154 |
2013 | 2155 |
2014 Handle<Code> VectorLoadStub::GenerateCode() { return DoGenerateCode(this); } | 2156 Handle<Code> VectorLoadStub::GenerateCode() { return DoGenerateCode(this); } |
2015 | 2157 |
2016 | 2158 |
2017 template <> | 2159 template <> |
2018 HValue* CodeStubGraphBuilder<VectorKeyedLoadStub>::BuildCodeStub() { | 2160 HValue* CodeStubGraphBuilder<VectorKeyedLoadStub>::BuildCodeStub() { |
2019 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); | 2161 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); |
2020 Add<HDeoptimize>("Always deopt", Deoptimizer::EAGER); | 2162 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); |
2021 return receiver; | 2163 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); |
2164 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); | |
2165 HConstant* zero = graph()->GetConstant0(); | |
2166 | |
2167 // Are we monomorphic? | |
2168 HValue* feedback = | |
2169 Add<HLoadKeyed>(vector, slot, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
2170 IfBuilder array_checker(this); | |
2171 array_checker.If<HCompareMap>(feedback, | |
2172 isolate()->factory()->fixed_array_map()); | |
2173 array_checker.Then(); | |
2174 { | |
2175 // Deal with the key. If feedback[0] is 0, then we are dealing with element | |
2176 // handlers. Otherwise, it's a string, verify that name matches. | |
2177 HValue* recorded_name = Add<HLoadKeyed>( | |
2178 feedback, zero, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
2179 | |
2180 IfBuilder recorded_name_is_zero(this); | |
2181 recorded_name_is_zero.If<HCompareNumericAndBranch>(recorded_name, zero, | |
2182 Token::EQ); | |
2183 recorded_name_is_zero.Then(); | |
2184 { | |
2185 // TODO(mvstanton): is this necessary? Anyway, I should call the | |
2186 // miss handler directly and not let the bailout mechanism run. | |
2187 Add<HCheckSmi>(name); | |
2188 } | |
2189 recorded_name_is_zero.Else(); | |
2190 { | |
2191 IfBuilder strings_match(this); | |
2192 strings_match.IfNot<HCompareObjectEqAndBranch>(name, recorded_name); | |
2193 strings_match.Then(); | |
2194 TailCallMiss(receiver, name, slot, vector, true); | |
2195 strings_match.End(); | |
2196 } | |
2197 recorded_name_is_zero.End(); | |
2198 | |
2199 Add<HCheckHeapObject>(receiver); | |
2200 HandleArrayCases(feedback, receiver, name, slot, vector, true); | |
2201 } | |
2202 array_checker.Else(); | |
2203 { | |
2204 // Are we megamorphic? | |
2205 IfBuilder mega_checker(this); | |
2206 HConstant* megamorphic_symbol = | |
2207 Add<HConstant>(isolate()->factory()->megamorphic_symbol()); | |
2208 mega_checker.If<HCompareObjectEqAndBranch>(feedback, megamorphic_symbol); | |
2209 mega_checker.Then(); | |
2210 { | |
2211 // HTailCallThroughMegamorphicCache expects name to be a string. | |
2212 // TODO(mvstanton): I don't understand why I need this check. How does it | |
2213 // work without --vector-ics on? Because there isn't a check on the name | |
2214 // in that case right? | |
Jakob Kummerow
2014/12/02 08:43:06
KeyedLoadIC currently doesn't support megamorphic
mvstanton
2014/12/03 11:48:30
Wow...the overloaded megamorphic_stub() method in
Jakob Kummerow
2014/12/03 13:22:17
Acknowledged.
| |
2215 Add<HCheckHeapObject>(name); | |
2216 // Probe the stub cache. | |
2217 Add<HTailCallThroughMegamorphicCache>( | |
2218 receiver, name, slot, vector, | |
2219 HTailCallThroughMegamorphicCache::ComputeFlags(true, false)); | |
2220 } | |
2221 mega_checker.End(); | |
2222 | |
2223 // Are we generic? | |
2224 IfBuilder generic_checker(this); | |
2225 HConstant* generic_symbol = | |
2226 Add<HConstant>(isolate()->factory()->generic_symbol()); | |
2227 generic_checker.If<HCompareObjectEqAndBranch>(feedback, generic_symbol); | |
2228 generic_checker.Then(); | |
2229 { | |
2230 // Tail-call to the generic KeyedLoadIC, treating it like a handler. | |
2231 Handle<Code> stub = KeyedLoadIC::generic_stub(isolate()); | |
2232 HValue* constant_stub = Add<HConstant>(stub); | |
2233 LoadDescriptor descriptor(isolate()); | |
2234 HValue* op_vals[] = {context(), receiver, name}; | |
2235 // We never return here, it is a tail call. | |
2236 Add<HCallWithDescriptor>(constant_stub, 0, descriptor, | |
2237 Vector<HValue*>(op_vals, 3), TAIL_CALL); | |
2238 } | |
2239 generic_checker.End(); | |
2240 | |
2241 TailCallMiss(receiver, name, slot, vector, true); | |
2242 } | |
2243 array_checker.End(); | |
2244 | |
2245 // We never get here. | |
2246 return zero; | |
2022 } | 2247 } |
2023 | 2248 |
2024 | 2249 |
2025 Handle<Code> VectorKeyedLoadStub::GenerateCode() { | 2250 Handle<Code> VectorKeyedLoadStub::GenerateCode() { |
2026 return DoGenerateCode(this); | 2251 return DoGenerateCode(this); |
2027 } | 2252 } |
2028 | 2253 |
2029 | 2254 |
2030 Handle<Code> MegamorphicLoadStub::GenerateCode() { | 2255 Handle<Code> MegamorphicLoadStub::GenerateCode() { |
2031 return DoGenerateCode(this); | 2256 return DoGenerateCode(this); |
2032 } | 2257 } |
2033 | 2258 |
2034 | 2259 |
2035 template <> | 2260 template <> |
2036 HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() { | 2261 HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() { |
2037 // The return address is on the stack. | |
2038 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); | 2262 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); |
2039 HValue* name = GetParameter(LoadDescriptor::kNameIndex); | 2263 HValue* name = GetParameter(LoadDescriptor::kNameIndex); |
2040 | 2264 |
2265 // We shouldn't generate this when FLAG_vector_ics is true because the | |
2266 // megamorphic case is handled as part of the default stub. | |
2267 DCHECK(!FLAG_vector_ics); | |
2268 | |
2041 // Probe the stub cache. | 2269 // Probe the stub cache. |
2042 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 2270 Add<HTailCallThroughMegamorphicCache>(receiver, name); |
2043 Code::ComputeHandlerFlags(Code::LOAD_IC)); | |
2044 Add<HTailCallThroughMegamorphicCache>(receiver, name, flags); | |
2045 | 2271 |
2046 // We never continue. | 2272 // We never continue. |
2047 return graph()->GetConstant0(); | 2273 return graph()->GetConstant0(); |
2048 } | 2274 } |
2049 } } // namespace v8::internal | 2275 } } // namespace v8::internal |
OLD | NEW |