Chromium Code Reviews| 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" |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 | 106 |
| 107 // Tail calls handler_code. | 107 // Tail calls handler_code. |
| 108 void TailCallHandler(HValue* receiver, HValue* name, HValue* slot, | 108 void TailCallHandler(HValue* receiver, HValue* name, HValue* slot, |
| 109 HValue* vector, HValue* handler_code); | 109 HValue* vector, HValue* handler_code); |
| 110 | 110 |
| 111 void TailCallMiss(HValue* receiver, HValue* name, HValue* slot, | 111 void TailCallMiss(HValue* receiver, HValue* name, HValue* slot, |
| 112 HValue* vector, bool keyed_load); | 112 HValue* vector, bool keyed_load); |
| 113 | 113 |
| 114 // Handle MONOMORPHIC and POLYMORPHIC LoadIC and KeyedLoadIC cases. | 114 // Handle MONOMORPHIC and POLYMORPHIC LoadIC and KeyedLoadIC cases. |
| 115 void HandleArrayCases(HValue* array, HValue* receiver, HValue* name, | 115 void HandleArrayCases(HValue* array, HValue* receiver, HValue* name, |
| 116 HValue* slot, HValue* vector, bool keyed_load); | 116 HValue* slot, HValue* vector); |
| 117 void HandleMonoCase(HValue* weak_cell, HValue* receiver, HValue* name, | |
|
Toon Verwaest
2015/03/11 17:55:01
HandleMonomorphicCase
mvstanton
2015/03/12 17:05:33
Happily all this code is dead. Removing.
| |
| 118 HValue* slot, HValue* vector); | |
| 117 | 119 |
| 118 private: | 120 private: |
| 119 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); | 121 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); |
| 120 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, | 122 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, |
| 121 ElementsKind kind); | 123 ElementsKind kind); |
| 122 | 124 |
| 123 SmartArrayPointer<HParameter*> parameters_; | 125 SmartArrayPointer<HParameter*> parameters_; |
| 124 HValue* arguments_length_; | 126 HValue* arguments_length_; |
| 125 CompilationInfoWithZone* info_; | 127 CompilationInfoWithZone* info_; |
| 126 CodeStubDescriptor descriptor_; | 128 CodeStubDescriptor descriptor_; |
| (...skipping 1932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2059 DCHECK(FLAG_vector_ics); | 2061 DCHECK(FLAG_vector_ics); |
| 2060 Add<HTailCallThroughMegamorphicCache>( | 2062 Add<HTailCallThroughMegamorphicCache>( |
| 2061 receiver, name, slot, vector, | 2063 receiver, name, slot, vector, |
| 2062 HTailCallThroughMegamorphicCache::ComputeFlags(keyed_load, true)); | 2064 HTailCallThroughMegamorphicCache::ComputeFlags(keyed_load, true)); |
| 2063 // We never return here, it is a tail call. | 2065 // We never return here, it is a tail call. |
| 2064 } | 2066 } |
| 2065 | 2067 |
| 2066 | 2068 |
| 2067 void CodeStubGraphBuilderBase::HandleArrayCases(HValue* array, HValue* receiver, | 2069 void CodeStubGraphBuilderBase::HandleArrayCases(HValue* array, HValue* receiver, |
| 2068 HValue* name, HValue* slot, | 2070 HValue* name, HValue* slot, |
| 2069 HValue* vector, | 2071 HValue* vector) { |
| 2070 bool keyed_load) { | |
| 2071 HConstant* constant_two = Add<HConstant>(2); | 2072 HConstant* constant_two = Add<HConstant>(2); |
| 2072 HConstant* constant_three = Add<HConstant>(3); | |
| 2073 | 2073 |
| 2074 IfBuilder if_receiver_heap_object(this); | 2074 IfBuilder if_receiver_heap_object(this); |
| 2075 if_receiver_heap_object.IfNot<HIsSmiAndBranch>(receiver); | 2075 if_receiver_heap_object.IfNot<HIsSmiAndBranch>(receiver); |
| 2076 if_receiver_heap_object.Then(); | 2076 if_receiver_heap_object.Then(); |
| 2077 Push(AddLoadMap(receiver, nullptr)); | 2077 Push(AddLoadMap(receiver, nullptr)); |
| 2078 if_receiver_heap_object.Else(); | 2078 if_receiver_heap_object.Else(); |
| 2079 HConstant* heap_number_map = | 2079 HConstant* heap_number_map = |
| 2080 Add<HConstant>(isolate()->factory()->heap_number_map()); | 2080 Add<HConstant>(isolate()->factory()->heap_number_map()); |
| 2081 Push(heap_number_map); | 2081 Push(heap_number_map); |
| 2082 if_receiver_heap_object.End(); | 2082 if_receiver_heap_object.End(); |
| 2083 HValue* receiver_map = Pop(); | 2083 HValue* receiver_map = Pop(); |
| 2084 | 2084 |
| 2085 HValue* start = | 2085 HValue* start = graph()->GetConstant0(); |
| 2086 keyed_load ? graph()->GetConstant1() : graph()->GetConstant0(); | |
| 2087 HValue* weak_cell = | 2086 HValue* weak_cell = |
| 2088 Add<HLoadKeyed>(array, start, nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE); | 2087 Add<HLoadKeyed>(array, start, nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 2089 // Load the weak cell value. It may be Smi(0), or a map. Compare nonetheless | 2088 // Load the weak cell value. It may be Smi(0), or a map. Compare nonetheless |
| 2090 // against the receiver_map. | 2089 // against the receiver_map. |
| 2091 HValue* array_map = Add<HLoadNamedField>(weak_cell, nullptr, | 2090 HValue* array_map = Add<HLoadNamedField>(weak_cell, nullptr, |
| 2092 HObjectAccess::ForWeakCellValue()); | 2091 HObjectAccess::ForWeakCellValue()); |
| 2093 | 2092 |
| 2094 IfBuilder if_correct_map(this); | 2093 IfBuilder if_correct_map(this); |
| 2095 if_correct_map.If<HCompareObjectEqAndBranch>(receiver_map, array_map); | 2094 if_correct_map.If<HCompareObjectEqAndBranch>(receiver_map, array_map); |
| 2096 if_correct_map.Then(); | 2095 if_correct_map.Then(); |
| 2097 { TailCallHandler(receiver, name, array, start, slot, vector); } | 2096 { TailCallHandler(receiver, name, array, start, slot, vector); } |
| 2098 if_correct_map.Else(); | 2097 if_correct_map.Else(); |
| 2099 { | 2098 { |
| 2100 // If our array has more elements, the ic is polymorphic. Look for the | 2099 // If our array has more elements, the ic is polymorphic. Look for the |
| 2101 // receiver map in the rest of the array. | 2100 // receiver map in the rest of the array. |
| 2102 HValue* length = AddLoadFixedArrayLength(array, nullptr); | 2101 HValue* length = AddLoadFixedArrayLength(array, nullptr); |
| 2103 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement, | 2102 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement, |
| 2104 constant_two); | 2103 constant_two); |
| 2105 start = keyed_load ? constant_three : constant_two; | 2104 start = constant_two; |
| 2106 HValue* key = builder.BeginBody(start, length, Token::LT); | 2105 HValue* key = builder.BeginBody(start, length, Token::LT); |
| 2107 { | 2106 { |
| 2108 HValue* weak_cell = Add<HLoadKeyed>(array, key, nullptr, FAST_ELEMENTS, | 2107 HValue* weak_cell = Add<HLoadKeyed>(array, key, nullptr, FAST_ELEMENTS, |
| 2109 ALLOW_RETURN_HOLE); | 2108 ALLOW_RETURN_HOLE); |
| 2110 HValue* array_map = Add<HLoadNamedField>( | 2109 HValue* array_map = Add<HLoadNamedField>( |
| 2111 weak_cell, nullptr, HObjectAccess::ForWeakCellValue()); | 2110 weak_cell, nullptr, HObjectAccess::ForWeakCellValue()); |
| 2112 IfBuilder if_correct_poly_map(this); | 2111 IfBuilder if_correct_poly_map(this); |
| 2113 if_correct_poly_map.If<HCompareObjectEqAndBranch>(receiver_map, | 2112 if_correct_poly_map.If<HCompareObjectEqAndBranch>(receiver_map, |
| 2114 array_map); | 2113 array_map); |
| 2115 if_correct_poly_map.Then(); | 2114 if_correct_poly_map.Then(); |
| 2116 { TailCallHandler(receiver, name, array, key, slot, vector); } | 2115 { TailCallHandler(receiver, name, array, key, slot, vector); } |
| 2117 } | 2116 } |
| 2118 builder.EndBody(); | 2117 builder.EndBody(); |
| 2119 } | 2118 } |
| 2120 if_correct_map.End(); | 2119 if_correct_map.End(); |
| 2121 } | 2120 } |
| 2122 | 2121 |
| 2123 | 2122 |
| 2124 template <> | 2123 void CodeStubGraphBuilderBase::HandleMonoCase(HValue* weak_cell, |
| 2125 HValue* CodeStubGraphBuilder<VectorLoadStub>::BuildCodeStub() { | 2124 HValue* receiver, HValue* name, |
| 2126 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); | 2125 HValue* slot, HValue* vector) { |
| 2127 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); | 2126 IfBuilder if_receiver_heap_object(this); |
| 2128 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); | 2127 if_receiver_heap_object.IfNot<HIsSmiAndBranch>(receiver); |
| 2129 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); | 2128 if_receiver_heap_object.Then(); |
| 2129 Push(AddLoadMap(receiver, nullptr)); | |
| 2130 if_receiver_heap_object.Else(); | |
| 2131 HConstant* heap_number_map = | |
| 2132 Add<HConstant>(isolate()->factory()->heap_number_map()); | |
| 2133 Push(heap_number_map); | |
| 2134 if_receiver_heap_object.End(); | |
| 2135 HValue* receiver_map = Pop(); | |
| 2130 | 2136 |
| 2131 // If the feedback is an array, then the IC is in the monomorphic or | 2137 // Load the weak cell value. It may be Smi(0), or a map. Compare nonetheless |
| 2132 // polymorphic state. | 2138 // against the receiver_map. |
| 2133 HValue* feedback = | 2139 HValue* array_map = Add<HLoadNamedField>(weak_cell, nullptr, |
| 2134 Add<HLoadKeyed>(vector, slot, nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE); | 2140 HObjectAccess::ForWeakCellValue()); |
| 2135 IfBuilder array_checker(this); | |
| 2136 array_checker.If<HCompareMap>(feedback, | |
| 2137 isolate()->factory()->fixed_array_map()); | |
| 2138 array_checker.Then(); | |
| 2139 { HandleArrayCases(feedback, receiver, name, slot, vector, false); } | |
| 2140 array_checker.Else(); | |
| 2141 { | |
| 2142 // Is the IC megamorphic? | |
| 2143 IfBuilder mega_checker(this); | |
| 2144 HConstant* megamorphic_symbol = | |
| 2145 Add<HConstant>(isolate()->factory()->megamorphic_symbol()); | |
| 2146 mega_checker.If<HCompareObjectEqAndBranch>(feedback, megamorphic_symbol); | |
| 2147 mega_checker.Then(); | |
| 2148 { | |
| 2149 // Probe the stub cache. | |
| 2150 Add<HTailCallThroughMegamorphicCache>( | |
| 2151 receiver, name, slot, vector, | |
| 2152 HTailCallThroughMegamorphicCache::ComputeFlags(false, false)); | |
| 2153 } | |
| 2154 mega_checker.End(); | |
| 2155 } | |
| 2156 array_checker.End(); | |
| 2157 | 2141 |
| 2158 TailCallMiss(receiver, name, slot, vector, false); | 2142 IfBuilder if_correct_map(this); |
| 2159 return graph()->GetConstant0(); | 2143 if_correct_map.If<HCompareObjectEqAndBranch>(receiver_map, array_map); |
| 2144 if_correct_map.Then(); | |
| 2145 { TailCallHandler(receiver, name, vector, slot, slot, vector); } | |
| 2146 if_correct_map.End(); | |
| 2160 } | 2147 } |
| 2161 | 2148 |
| 2162 | 2149 |
| 2163 Handle<Code> VectorLoadStub::GenerateCode() { return DoGenerateCode(this); } | |
| 2164 | |
| 2165 | |
| 2166 template <> | |
| 2167 HValue* CodeStubGraphBuilder<VectorKeyedLoadStub>::BuildCodeStub() { | |
| 2168 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); | |
| 2169 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); | |
| 2170 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); | |
| 2171 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); | |
| 2172 HConstant* zero = graph()->GetConstant0(); | |
| 2173 | |
| 2174 // If the feedback is an array, then the IC is in the monomorphic or | |
| 2175 // polymorphic state. | |
| 2176 HValue* feedback = | |
| 2177 Add<HLoadKeyed>(vector, slot, nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE); | |
| 2178 IfBuilder array_checker(this); | |
| 2179 array_checker.If<HCompareMap>(feedback, | |
| 2180 isolate()->factory()->fixed_array_map()); | |
| 2181 array_checker.Then(); | |
| 2182 { | |
| 2183 // If feedback[0] is 0, then the IC has element handlers and name should be | |
| 2184 // a smi. If feedback[0] is a string, verify that it matches name. | |
| 2185 HValue* recorded_name = Add<HLoadKeyed>(feedback, zero, nullptr, | |
| 2186 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | |
| 2187 | |
| 2188 IfBuilder recorded_name_is_zero(this); | |
| 2189 recorded_name_is_zero.If<HCompareObjectEqAndBranch>(recorded_name, zero); | |
| 2190 recorded_name_is_zero.Then(); | |
| 2191 { Add<HCheckSmi>(name); } | |
| 2192 recorded_name_is_zero.Else(); | |
| 2193 { | |
| 2194 IfBuilder strings_match(this); | |
| 2195 strings_match.IfNot<HCompareObjectEqAndBranch>(name, recorded_name); | |
| 2196 strings_match.Then(); | |
| 2197 TailCallMiss(receiver, name, slot, vector, true); | |
| 2198 strings_match.End(); | |
| 2199 } | |
| 2200 recorded_name_is_zero.End(); | |
| 2201 | |
| 2202 HandleArrayCases(feedback, receiver, name, slot, vector, true); | |
| 2203 } | |
| 2204 array_checker.Else(); | |
| 2205 { | |
| 2206 // Check if the IC is in megamorphic state. | |
| 2207 IfBuilder megamorphic_checker(this); | |
| 2208 HConstant* megamorphic_symbol = | |
| 2209 Add<HConstant>(isolate()->factory()->megamorphic_symbol()); | |
| 2210 megamorphic_checker.If<HCompareObjectEqAndBranch>(feedback, | |
| 2211 megamorphic_symbol); | |
| 2212 megamorphic_checker.Then(); | |
| 2213 { | |
| 2214 // Tail-call to the megamorphic KeyedLoadIC, treating it like a handler. | |
| 2215 Handle<Code> stub = KeyedLoadIC::ChooseMegamorphicStub(isolate()); | |
| 2216 HValue* constant_stub = Add<HConstant>(stub); | |
| 2217 LoadDescriptor descriptor(isolate()); | |
| 2218 HValue* op_vals[] = {context(), receiver, name}; | |
| 2219 Add<HCallWithDescriptor>(constant_stub, 0, descriptor, | |
| 2220 Vector<HValue*>(op_vals, 3), TAIL_CALL); | |
| 2221 // We never return here, it is a tail call. | |
| 2222 } | |
| 2223 megamorphic_checker.End(); | |
| 2224 } | |
| 2225 array_checker.End(); | |
| 2226 | |
| 2227 TailCallMiss(receiver, name, slot, vector, true); | |
| 2228 return zero; | |
| 2229 } | |
| 2230 | |
| 2231 | |
| 2232 Handle<Code> VectorKeyedLoadStub::GenerateCode() { | |
| 2233 return DoGenerateCode(this); | |
| 2234 } | |
| 2235 | |
| 2236 | |
| 2237 Handle<Code> MegamorphicLoadStub::GenerateCode() { | 2150 Handle<Code> MegamorphicLoadStub::GenerateCode() { |
| 2238 return DoGenerateCode(this); | 2151 return DoGenerateCode(this); |
| 2239 } | 2152 } |
| 2240 | 2153 |
| 2241 | 2154 |
| 2242 template <> | 2155 template <> |
| 2243 HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() { | 2156 HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() { |
| 2244 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); | 2157 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); |
| 2245 HValue* name = GetParameter(LoadDescriptor::kNameIndex); | 2158 HValue* name = GetParameter(LoadDescriptor::kNameIndex); |
| 2246 | 2159 |
| 2247 // We shouldn't generate this when FLAG_vector_ics is true because the | 2160 // We shouldn't generate this when FLAG_vector_ics is true because the |
| 2248 // megamorphic case is handled as part of the default stub. | 2161 // megamorphic case is handled as part of the default stub. |
| 2249 DCHECK(!FLAG_vector_ics); | 2162 DCHECK(!FLAG_vector_ics); |
| 2250 | 2163 |
| 2251 // Probe the stub cache. | 2164 // Probe the stub cache. |
| 2252 Add<HTailCallThroughMegamorphicCache>(receiver, name); | 2165 Add<HTailCallThroughMegamorphicCache>(receiver, name); |
| 2253 | 2166 |
| 2254 // We never continue. | 2167 // We never continue. |
| 2255 return graph()->GetConstant0(); | 2168 return graph()->GetConstant0(); |
| 2256 } | 2169 } |
| 2257 } } // namespace v8::internal | 2170 } } // namespace v8::internal |
| OLD | NEW |