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 |