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" |
| 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[map_index + 1]. | |
| 104 void TailCallHandler(HValue* receiver, HValue* name, HValue* array, | |
| 105 HValue* map_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* map_index, | |
| 2024 HValue* slot, HValue* vector) { | |
| 2025 // The handler is at array[map_index + 1]. Compute this with a custom offset | |
| 2026 // to HLoadKeyed. | |
| 2027 int offset = | |
| 2028 GetDefaultHeaderSizeForElementsKind(FAST_ELEMENTS) + kPointerSize; | |
| 2029 HValue* handler_code = | |
| 2030 Add<HLoadKeyed>(array, map_index, static_cast<HValue*>(NULL), | |
| 2031 FAST_ELEMENTS, NEVER_RETURN_HOLE, offset); | |
| 2032 TailCallHandler(receiver, name, slot, vector, handler_code); | |
| 2033 } | |
| 2034 | |
| 2035 | |
| 2036 void CodeStubGraphBuilderBase::TailCallHandler(HValue* receiver, HValue* name, | |
| 2037 HValue* slot, HValue* vector, | |
| 2038 HValue* handler_code) { | |
| 2039 VectorLoadICDescriptor descriptor(isolate()); | |
| 2040 HValue* op_vals[] = {context(), receiver, name, slot, vector}; | |
| 2041 Add<HCallWithDescriptor>(handler_code, 0, descriptor, | |
| 2042 Vector<HValue*>(op_vals, 5), TAIL_CALL); | |
| 2043 // We never return here, it is a tail call. | |
| 2044 } | |
| 2045 | |
| 2046 | |
| 2047 void CodeStubGraphBuilderBase::TailCallMiss(HValue* receiver, HValue* name, | |
| 2048 HValue* slot, HValue* vector, | |
| 2049 bool keyed_load) { | |
| 2050 DCHECK(FLAG_vector_ics); | |
| 2051 Add<HTailCallThroughMegamorphicCache>( | |
| 2052 receiver, name, slot, vector, | |
| 2053 HTailCallThroughMegamorphicCache::ComputeFlags(keyed_load, true)); | |
| 2054 // We never return here, it is a tail call. | |
| 2055 } | |
| 2056 | |
| 2057 | |
| 2058 void CodeStubGraphBuilderBase::HandleArrayCases(HValue* array, HValue* receiver, | |
| 2059 HValue* name, HValue* slot, | |
| 2060 HValue* vector, | |
| 2061 bool keyed_load) { | |
| 2062 IfBuilder if_receiver_heap_object(this); | |
| 2063 if_receiver_heap_object.IfNot<HIsSmiAndBranch>(receiver); | |
| 2064 if_receiver_heap_object.Then(); | |
| 2065 { | |
| 2066 HConstant* constant_two = Add<HConstant>(2); | |
| 2067 HConstant* constant_three = Add<HConstant>(3); | |
| 2068 | |
| 2069 HValue* receiver_map = AddLoadMap(receiver, static_cast<HValue*>(NULL)); | |
| 2070 HValue* start = | |
| 2071 keyed_load ? graph()->GetConstant1() : graph()->GetConstant0(); | |
| 2072 HValue* array_map = Add<HLoadKeyed>( | |
| 2073 array, start, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
| 2074 IfBuilder if_correct_map(this); | |
| 2075 if_correct_map.If<HCompareObjectEqAndBranch>(receiver_map, array_map); | |
| 2076 if_correct_map.Then(); | |
| 2077 { TailCallHandler(receiver, name, array, start, slot, vector); } | |
| 2078 if_correct_map.Else(); | |
| 2079 { | |
| 2080 // If our array has more elements, the ic is polymorphic. Look for the | |
| 2081 // receiver map in the rest of the array. | |
| 2082 HValue* length = | |
| 2083 AddLoadFixedArrayLength(array, static_cast<HValue*>(NULL)); | |
| 2084 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement, | |
| 2085 constant_two); | |
| 2086 start = keyed_load ? constant_three : constant_two; | |
| 2087 HValue* key = builder.BeginBody(start, length, Token::LT); | |
| 2088 { | |
| 2089 HValue* array_map = Add<HLoadKeyed>( | |
| 2090 array, key, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
| 2091 IfBuilder if_correct_map(this); | |
|
Jakob Kummerow
2014/12/03 13:22:17
nit: please don't shadow variables. (There's alrea
mvstanton
2014/12/08 12:44:24
Done.
| |
| 2092 if_correct_map.If<HCompareObjectEqAndBranch>(receiver_map, array_map); | |
| 2093 if_correct_map.Then(); | |
| 2094 { TailCallHandler(receiver, name, array, key, slot, vector); } | |
| 2095 } | |
| 2096 builder.EndBody(); | |
| 2097 | |
| 2098 TailCallMiss(receiver, name, slot, vector, keyed_load); | |
|
Jakob Kummerow
2014/12/03 13:22:17
nit: drop this...
mvstanton
2014/12/08 12:44:24
Done.
| |
| 2099 } | |
| 2100 if_correct_map.End(); | |
| 2101 } | |
| 2102 if_receiver_heap_object.Else(); | |
|
Jakob Kummerow
2014/12/03 13:22:17
...and this, and let all control flow paths fall t
mvstanton
2014/12/08 12:44:24
Done. I removed these two and changed the caller B
| |
| 2103 { TailCallMiss(receiver, name, slot, vector, keyed_load); } | |
| 2104 } | |
| 2105 | |
| 2106 | |
| 2006 template <> | 2107 template <> |
| 2007 HValue* CodeStubGraphBuilder<VectorLoadStub>::BuildCodeStub() { | 2108 HValue* CodeStubGraphBuilder<VectorLoadStub>::BuildCodeStub() { |
| 2008 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); | 2109 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); |
| 2009 Add<HDeoptimize>("Always deopt", Deoptimizer::EAGER); | 2110 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); |
| 2010 return receiver; | 2111 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); |
| 2112 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); | |
| 2113 | |
| 2114 // If the feedback is an array, then the IC is in the monomorphic or | |
| 2115 // polymorphic state. | |
| 2116 HValue* feedback = | |
| 2117 Add<HLoadKeyed>(vector, slot, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
| 2118 IfBuilder array_checker(this); | |
| 2119 array_checker.If<HCompareMap>(feedback, | |
| 2120 isolate()->factory()->fixed_array_map()); | |
| 2121 array_checker.Then(); | |
| 2122 { HandleArrayCases(feedback, receiver, name, slot, vector, false); } | |
| 2123 array_checker.Else(); | |
| 2124 { | |
| 2125 // Is the IC megamorphic? | |
| 2126 IfBuilder mega_checker(this); | |
| 2127 HConstant* megamorphic_symbol = | |
| 2128 Add<HConstant>(isolate()->factory()->megamorphic_symbol()); | |
| 2129 mega_checker.If<HCompareObjectEqAndBranch>(feedback, megamorphic_symbol); | |
| 2130 mega_checker.Then(); | |
| 2131 { | |
| 2132 // Probe the stub cache. | |
| 2133 Add<HTailCallThroughMegamorphicCache>( | |
| 2134 receiver, name, slot, vector, | |
| 2135 HTailCallThroughMegamorphicCache::ComputeFlags(false, false)); | |
| 2136 } | |
| 2137 mega_checker.End(); | |
| 2138 | |
| 2139 TailCallMiss(receiver, name, slot, vector, false); | |
| 2140 } | |
| 2141 array_checker.End(); | |
| 2142 | |
| 2143 // We never get here. | |
| 2144 return graph()->GetConstant0(); | |
| 2011 } | 2145 } |
| 2012 | 2146 |
| 2013 | 2147 |
| 2014 Handle<Code> VectorLoadStub::GenerateCode() { return DoGenerateCode(this); } | 2148 Handle<Code> VectorLoadStub::GenerateCode() { return DoGenerateCode(this); } |
| 2015 | 2149 |
| 2016 | 2150 |
| 2017 template <> | 2151 template <> |
| 2018 HValue* CodeStubGraphBuilder<VectorKeyedLoadStub>::BuildCodeStub() { | 2152 HValue* CodeStubGraphBuilder<VectorKeyedLoadStub>::BuildCodeStub() { |
| 2019 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); | 2153 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); |
| 2020 Add<HDeoptimize>("Always deopt", Deoptimizer::EAGER); | 2154 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); |
| 2021 return receiver; | 2155 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); |
| 2156 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); | |
| 2157 HConstant* zero = graph()->GetConstant0(); | |
| 2158 | |
| 2159 // If the feedback is an array, then the IC is in the monomorphic or | |
| 2160 // polymorphic state. | |
| 2161 HValue* feedback = | |
| 2162 Add<HLoadKeyed>(vector, slot, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
| 2163 IfBuilder array_checker(this); | |
| 2164 array_checker.If<HCompareMap>(feedback, | |
| 2165 isolate()->factory()->fixed_array_map()); | |
| 2166 array_checker.Then(); | |
| 2167 { | |
| 2168 // If feedback[0] is 0, then the IC has element handlers and name should be | |
| 2169 // a smi. If feedback[0] is a string, verify that it matches name. | |
| 2170 HValue* recorded_name = Add<HLoadKeyed>( | |
| 2171 feedback, zero, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
| 2172 | |
| 2173 IfBuilder recorded_name_is_zero(this); | |
| 2174 recorded_name_is_zero.If<HCompareNumericAndBranch>(recorded_name, zero, | |
| 2175 Token::EQ); | |
| 2176 recorded_name_is_zero.Then(); | |
| 2177 { Add<HCheckSmi>(name); } | |
| 2178 recorded_name_is_zero.Else(); | |
| 2179 { | |
| 2180 IfBuilder strings_match(this); | |
| 2181 strings_match.IfNot<HCompareObjectEqAndBranch>(name, recorded_name); | |
| 2182 strings_match.Then(); | |
| 2183 TailCallMiss(receiver, name, slot, vector, true); | |
| 2184 strings_match.End(); | |
| 2185 } | |
| 2186 recorded_name_is_zero.End(); | |
| 2187 | |
| 2188 HandleArrayCases(feedback, receiver, name, slot, vector, true); | |
| 2189 } | |
| 2190 array_checker.Else(); | |
| 2191 { | |
| 2192 // Check if the IC in generic state. | |
|
Jakob Kummerow
2014/12/03 13:22:17
nit: missing "is"
mvstanton
2014/12/08 12:44:24
wow, good eye :D
Jakob Kummerow
2014/12/09 16:59:27
Nah, just OCD ;-)
| |
| 2193 IfBuilder generic_checker(this); | |
| 2194 HConstant* generic_symbol = | |
| 2195 Add<HConstant>(isolate()->factory()->generic_symbol()); | |
| 2196 generic_checker.If<HCompareObjectEqAndBranch>(feedback, generic_symbol); | |
| 2197 generic_checker.Then(); | |
| 2198 { | |
| 2199 // Tail-call to the generic KeyedLoadIC, treating it like a handler. | |
| 2200 Handle<Code> stub = KeyedLoadIC::generic_stub(isolate()); | |
| 2201 HValue* constant_stub = Add<HConstant>(stub); | |
| 2202 LoadDescriptor descriptor(isolate()); | |
| 2203 HValue* op_vals[] = {context(), receiver, name}; | |
| 2204 // We never return here, it is a tail call. | |
|
Jakob Kummerow
2014/12/03 13:22:17
nit: move this comment after the call please.
mvstanton
2014/12/08 12:44:24
Done.
| |
| 2205 Add<HCallWithDescriptor>(constant_stub, 0, descriptor, | |
| 2206 Vector<HValue*>(op_vals, 3), TAIL_CALL); | |
| 2207 } | |
| 2208 generic_checker.End(); | |
| 2209 | |
| 2210 TailCallMiss(receiver, name, slot, vector, true); | |
| 2211 } | |
| 2212 array_checker.End(); | |
| 2213 | |
| 2214 // We never get here. | |
| 2215 return zero; | |
| 2022 } | 2216 } |
| 2023 | 2217 |
| 2024 | 2218 |
| 2025 Handle<Code> VectorKeyedLoadStub::GenerateCode() { | 2219 Handle<Code> VectorKeyedLoadStub::GenerateCode() { |
| 2026 return DoGenerateCode(this); | 2220 return DoGenerateCode(this); |
| 2027 } | 2221 } |
| 2028 | 2222 |
| 2029 | 2223 |
| 2030 Handle<Code> MegamorphicLoadStub::GenerateCode() { | 2224 Handle<Code> MegamorphicLoadStub::GenerateCode() { |
| 2031 return DoGenerateCode(this); | 2225 return DoGenerateCode(this); |
| 2032 } | 2226 } |
| 2033 | 2227 |
| 2034 | 2228 |
| 2035 template <> | 2229 template <> |
| 2036 HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() { | 2230 HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() { |
| 2037 // The return address is on the stack. | |
| 2038 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); | 2231 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); |
| 2039 HValue* name = GetParameter(LoadDescriptor::kNameIndex); | 2232 HValue* name = GetParameter(LoadDescriptor::kNameIndex); |
| 2040 | 2233 |
| 2234 // We shouldn't generate this when FLAG_vector_ics is true because the | |
| 2235 // megamorphic case is handled as part of the default stub. | |
| 2236 DCHECK(!FLAG_vector_ics); | |
| 2237 | |
| 2041 // Probe the stub cache. | 2238 // Probe the stub cache. |
| 2042 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 2239 Add<HTailCallThroughMegamorphicCache>(receiver, name); |
| 2043 Code::ComputeHandlerFlags(Code::LOAD_IC)); | |
| 2044 Add<HTailCallThroughMegamorphicCache>(receiver, name, flags); | |
| 2045 | 2240 |
| 2046 // We never continue. | 2241 // We never continue. |
| 2047 return graph()->GetConstant0(); | 2242 return graph()->GetConstant0(); |
| 2048 } | 2243 } |
| 2049 } } // namespace v8::internal | 2244 } } // namespace v8::internal |
| OLD | NEW |