| 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. |
| 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. |
| 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); |
| 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)) |
| 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 if (!FLAG_hydrogen_vector_dispatcher) { |
| 2121 Add<HDebugBreak>(); |
| 2122 } |
| 2123 |
| 2124 // Are we monomorphic? |
| 2125 HValue* feedback = |
| 2126 Add<HLoadKeyed>(vector, slot, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 2127 IfBuilder array_checker(this); |
| 2128 array_checker.If<HCompareMap>(feedback, |
| 2129 isolate()->factory()->fixed_array_map()); |
| 2130 array_checker.Then(); |
| 2131 { |
| 2132 Add<HCheckHeapObject>(receiver); |
| 2133 HandleArrayCases(feedback, receiver, name, slot, vector, false); |
| 2134 } |
| 2135 array_checker.Else(); |
| 2136 { |
| 2137 // Are we megamorphic? |
| 2138 IfBuilder mega_checker(this); |
| 2139 HConstant* megamorphic_symbol = |
| 2140 Add<HConstant>(isolate()->factory()->megamorphic_symbol()); |
| 2141 mega_checker.If<HCompareObjectEqAndBranch>(feedback, megamorphic_symbol); |
| 2142 mega_checker.Then(); |
| 2143 { |
| 2144 // Probe the stub cache. |
| 2145 Add<HTailCallThroughMegamorphicCache>( |
| 2146 receiver, name, slot, vector, |
| 2147 HTailCallThroughMegamorphicCache::ComputeFlags(false, false)); |
| 2148 } |
| 2149 mega_checker.End(); |
| 2150 |
| 2151 TailCallMiss(receiver, name, slot, vector, false); |
| 2152 } |
| 2153 array_checker.End(); |
| 2154 |
| 2155 // We never get here. |
| 2156 return graph()->GetConstant0(); |
| 2011 } | 2157 } |
| 2012 | 2158 |
| 2013 | 2159 |
| 2014 Handle<Code> VectorLoadStub::GenerateCode() { return DoGenerateCode(this); } | 2160 Handle<Code> VectorLoadStub::GenerateCode() { return DoGenerateCode(this); } |
| 2015 | 2161 |
| 2016 | 2162 |
| 2017 template <> | 2163 template <> |
| 2018 HValue* CodeStubGraphBuilder<VectorKeyedLoadStub>::BuildCodeStub() { | 2164 HValue* CodeStubGraphBuilder<VectorKeyedLoadStub>::BuildCodeStub() { |
| 2019 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); | 2165 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); |
| 2020 Add<HDeoptimize>("Always deopt", Deoptimizer::EAGER); | 2166 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); |
| 2021 return receiver; | 2167 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); |
| 2168 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); |
| 2169 HConstant* zero = graph()->GetConstant0(); |
| 2170 |
| 2171 if (!FLAG_hydrogen_vector_dispatcher) { |
| 2172 Add<HDebugBreak>(); |
| 2173 } |
| 2174 |
| 2175 // Are we monomorphic? |
| 2176 HValue* feedback = |
| 2177 Add<HLoadKeyed>(vector, slot, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 2178 IfBuilder array_checker(this); |
| 2179 array_checker.If<HCompareMap>(feedback, |
| 2180 isolate()->factory()->fixed_array_map()); |
| 2181 array_checker.Then(); |
| 2182 { |
| 2183 // Deal with the key. If feedback[0] is 0, then we are dealing with element |
| 2184 // handlers. Otherwise, it's a string, verify that name matches. |
| 2185 HValue* recorded_name = Add<HLoadKeyed>( |
| 2186 feedback, zero, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 2187 |
| 2188 IfBuilder recorded_name_is_zero(this); |
| 2189 recorded_name_is_zero.If<HCompareNumericAndBranch>(recorded_name, zero, |
| 2190 Token::EQ); |
| 2191 recorded_name_is_zero.Then(); |
| 2192 { |
| 2193 // TODO(mvstanton): is this necessary? Anyway, I should call the |
| 2194 // miss handler directly and not let the bailout mechanism run. |
| 2195 Add<HCheckSmi>(name); |
| 2196 } |
| 2197 recorded_name_is_zero.Else(); |
| 2198 { |
| 2199 IfBuilder strings_match(this); |
| 2200 strings_match.IfNot<HCompareObjectEqAndBranch>(name, recorded_name); |
| 2201 strings_match.Then(); |
| 2202 TailCallMiss(receiver, name, slot, vector, true); |
| 2203 strings_match.End(); |
| 2204 } |
| 2205 recorded_name_is_zero.End(); |
| 2206 |
| 2207 Add<HCheckHeapObject>(receiver); |
| 2208 HandleArrayCases(feedback, receiver, name, slot, vector, true); |
| 2209 } |
| 2210 array_checker.Else(); |
| 2211 { |
| 2212 // Are we megamorphic? |
| 2213 IfBuilder mega_checker(this); |
| 2214 HConstant* megamorphic_symbol = |
| 2215 Add<HConstant>(isolate()->factory()->megamorphic_symbol()); |
| 2216 mega_checker.If<HCompareObjectEqAndBranch>(feedback, megamorphic_symbol); |
| 2217 mega_checker.Then(); |
| 2218 { |
| 2219 // HTailCallThroughMegamorphicCache expects name to be a string. |
| 2220 // TODO(mvstanton): I don't understand why I need this check. How does it |
| 2221 // work without --vector-ics on? Because there isn't a check on the name |
| 2222 // in that case right? |
| 2223 Add<HCheckHeapObject>(name); |
| 2224 // Probe the stub cache. |
| 2225 Add<HTailCallThroughMegamorphicCache>( |
| 2226 receiver, name, slot, vector, |
| 2227 HTailCallThroughMegamorphicCache::ComputeFlags(true, false)); |
| 2228 } |
| 2229 mega_checker.End(); |
| 2230 |
| 2231 // Are we generic? |
| 2232 IfBuilder generic_checker(this); |
| 2233 HConstant* generic_symbol = |
| 2234 Add<HConstant>(isolate()->factory()->generic_symbol()); |
| 2235 generic_checker.If<HCompareObjectEqAndBranch>(feedback, generic_symbol); |
| 2236 generic_checker.Then(); |
| 2237 { |
| 2238 // Tail-call to the generic KeyedLoadIC, treating it like a handler. |
| 2239 Handle<Code> stub = KeyedLoadIC::generic_stub(isolate()); |
| 2240 HValue* constant_stub = Add<HConstant>(stub); |
| 2241 LoadDescriptor descriptor(isolate()); |
| 2242 HValue* op_vals[] = {context(), receiver, name}; |
| 2243 // We never return here, it is a tail call. |
| 2244 Add<HCallWithDescriptor>(constant_stub, 0, descriptor, |
| 2245 Vector<HValue*>(op_vals, 3), TAIL_CALL); |
| 2246 } |
| 2247 generic_checker.End(); |
| 2248 |
| 2249 TailCallMiss(receiver, name, slot, vector, true); |
| 2250 } |
| 2251 array_checker.End(); |
| 2252 |
| 2253 // We never get here. |
| 2254 return zero; |
| 2022 } | 2255 } |
| 2023 | 2256 |
| 2024 | 2257 |
| 2025 Handle<Code> VectorKeyedLoadStub::GenerateCode() { | 2258 Handle<Code> VectorKeyedLoadStub::GenerateCode() { |
| 2026 return DoGenerateCode(this); | 2259 return DoGenerateCode(this); |
| 2027 } | 2260 } |
| 2028 | 2261 |
| 2029 | 2262 |
| 2030 Handle<Code> MegamorphicLoadStub::GenerateCode() { | 2263 Handle<Code> MegamorphicLoadStub::GenerateCode() { |
| 2031 return DoGenerateCode(this); | 2264 return DoGenerateCode(this); |
| 2032 } | 2265 } |
| 2033 | 2266 |
| 2034 | 2267 |
| 2035 template <> | 2268 template <> |
| 2036 HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() { | 2269 HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() { |
| 2037 // The return address is on the stack. | |
| 2038 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); | 2270 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); |
| 2039 HValue* name = GetParameter(LoadDescriptor::kNameIndex); | 2271 HValue* name = GetParameter(LoadDescriptor::kNameIndex); |
| 2040 | 2272 |
| 2273 // We shouldn't generate this when FLAG_vector_ics is true because the |
| 2274 // megamorphic case is handled as part of the default stub. |
| 2275 DCHECK(!FLAG_vector_ics); |
| 2276 |
| 2041 // Probe the stub cache. | 2277 // Probe the stub cache. |
| 2042 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 2278 Add<HTailCallThroughMegamorphicCache>(receiver, name); |
| 2043 Code::ComputeHandlerFlags(Code::LOAD_IC)); | |
| 2044 Add<HTailCallThroughMegamorphicCache>(receiver, name, flags); | |
| 2045 | 2279 |
| 2046 // We never continue. | 2280 // We never continue. |
| 2047 return graph()->GetConstant0(); | 2281 return graph()->GetConstant0(); |
| 2048 } | 2282 } |
| 2049 } } // namespace v8::internal | 2283 } } // namespace v8::internal |
| OLD | NEW |