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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 HValue* map_index); | 93 HValue* map_index); |
94 void BuildInstallCode(HValue* js_function, HValue* shared_info); | 94 void BuildInstallCode(HValue* js_function, HValue* shared_info); |
95 | 95 |
96 HInstruction* LoadFromOptimizedCodeMap(HValue* optimized_map, | 96 HInstruction* LoadFromOptimizedCodeMap(HValue* optimized_map, |
97 HValue* iterator, | 97 HValue* iterator, |
98 int field_offset); | 98 int field_offset); |
99 void BuildInstallFromOptimizedCodeMap(HValue* js_function, | 99 void BuildInstallFromOptimizedCodeMap(HValue* js_function, |
100 HValue* shared_info, | 100 HValue* shared_info, |
101 HValue* native_context); | 101 HValue* native_context); |
102 | 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 | |
118 private: | 103 private: |
119 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); | 104 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); |
120 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, | 105 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, |
121 ElementsKind kind); | 106 ElementsKind kind); |
122 | 107 |
123 SmartArrayPointer<HParameter*> parameters_; | 108 SmartArrayPointer<HParameter*> parameters_; |
124 HValue* arguments_length_; | 109 HValue* arguments_length_; |
125 CompilationInfoWithZone* info_; | 110 CompilationInfoWithZone* info_; |
126 CodeStubDescriptor descriptor_; | 111 CodeStubDescriptor descriptor_; |
127 HContext* context_; | 112 HContext* context_; |
(...skipping 1894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2022 | 2007 |
2023 return Pop(); | 2008 return Pop(); |
2024 } | 2009 } |
2025 | 2010 |
2026 | 2011 |
2027 Handle<Code> KeyedLoadGenericStub::GenerateCode() { | 2012 Handle<Code> KeyedLoadGenericStub::GenerateCode() { |
2028 return DoGenerateCode(this); | 2013 return DoGenerateCode(this); |
2029 } | 2014 } |
2030 | 2015 |
2031 | 2016 |
2032 void CodeStubGraphBuilderBase::TailCallHandler(HValue* receiver, HValue* name, | |
2033 HValue* array, HValue* map_index, | |
2034 HValue* slot, HValue* vector) { | |
2035 // The handler is at array[map_index + 1]. Compute this with a custom offset | |
2036 // to HLoadKeyed. | |
2037 int offset = | |
2038 GetDefaultHeaderSizeForElementsKind(FAST_ELEMENTS) + kPointerSize; | |
2039 HValue* handler_code = Add<HLoadKeyed>( | |
2040 array, map_index, nullptr, FAST_ELEMENTS, NEVER_RETURN_HOLE, offset); | |
2041 TailCallHandler(receiver, name, slot, vector, handler_code); | |
2042 } | |
2043 | |
2044 | |
2045 void CodeStubGraphBuilderBase::TailCallHandler(HValue* receiver, HValue* name, | |
2046 HValue* slot, HValue* vector, | |
2047 HValue* handler_code) { | |
2048 VectorLoadICDescriptor descriptor(isolate()); | |
2049 HValue* op_vals[] = {context(), receiver, name, slot, vector}; | |
2050 Add<HCallWithDescriptor>(handler_code, 0, descriptor, | |
2051 Vector<HValue*>(op_vals, 5), TAIL_CALL); | |
2052 // We never return here, it is a tail call. | |
2053 } | |
2054 | |
2055 | |
2056 void CodeStubGraphBuilderBase::TailCallMiss(HValue* receiver, HValue* name, | |
2057 HValue* slot, HValue* vector, | |
2058 bool keyed_load) { | |
2059 DCHECK(FLAG_vector_ics); | |
2060 Add<HTailCallThroughMegamorphicCache>( | |
2061 receiver, name, slot, vector, | |
2062 HTailCallThroughMegamorphicCache::ComputeFlags(keyed_load, true)); | |
2063 // We never return here, it is a tail call. | |
2064 } | |
2065 | |
2066 | |
2067 void CodeStubGraphBuilderBase::HandleArrayCases(HValue* array, HValue* receiver, | |
2068 HValue* name, HValue* slot, | |
2069 HValue* vector, | |
2070 bool keyed_load) { | |
2071 HConstant* constant_two = Add<HConstant>(2); | |
2072 HConstant* constant_three = Add<HConstant>(3); | |
2073 | |
2074 IfBuilder if_receiver_heap_object(this); | |
2075 if_receiver_heap_object.IfNot<HIsSmiAndBranch>(receiver); | |
2076 if_receiver_heap_object.Then(); | |
2077 Push(AddLoadMap(receiver, nullptr)); | |
2078 if_receiver_heap_object.Else(); | |
2079 HConstant* heap_number_map = | |
2080 Add<HConstant>(isolate()->factory()->heap_number_map()); | |
2081 Push(heap_number_map); | |
2082 if_receiver_heap_object.End(); | |
2083 HValue* receiver_map = Pop(); | |
2084 | |
2085 HValue* start = | |
2086 keyed_load ? graph()->GetConstant1() : graph()->GetConstant0(); | |
2087 HValue* weak_cell = | |
2088 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 | |
2090 // against the receiver_map. | |
2091 HValue* array_map = Add<HLoadNamedField>(weak_cell, nullptr, | |
2092 HObjectAccess::ForWeakCellValue()); | |
2093 | |
2094 IfBuilder if_correct_map(this); | |
2095 if_correct_map.If<HCompareObjectEqAndBranch>(receiver_map, array_map); | |
2096 if_correct_map.Then(); | |
2097 { TailCallHandler(receiver, name, array, start, slot, vector); } | |
2098 if_correct_map.Else(); | |
2099 { | |
2100 // If our array has more elements, the ic is polymorphic. Look for the | |
2101 // receiver map in the rest of the array. | |
2102 HValue* length = AddLoadFixedArrayLength(array, nullptr); | |
2103 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement, | |
2104 constant_two); | |
2105 start = keyed_load ? constant_three : constant_two; | |
2106 HValue* key = builder.BeginBody(start, length, Token::LT); | |
2107 { | |
2108 HValue* weak_cell = Add<HLoadKeyed>(array, key, nullptr, FAST_ELEMENTS, | |
2109 ALLOW_RETURN_HOLE); | |
2110 HValue* array_map = Add<HLoadNamedField>( | |
2111 weak_cell, nullptr, HObjectAccess::ForWeakCellValue()); | |
2112 IfBuilder if_correct_poly_map(this); | |
2113 if_correct_poly_map.If<HCompareObjectEqAndBranch>(receiver_map, | |
2114 array_map); | |
2115 if_correct_poly_map.Then(); | |
2116 { TailCallHandler(receiver, name, array, key, slot, vector); } | |
2117 } | |
2118 builder.EndBody(); | |
2119 } | |
2120 if_correct_map.End(); | |
2121 } | |
2122 | |
2123 | |
2124 template <> | |
2125 HValue* CodeStubGraphBuilder<VectorLoadStub>::BuildCodeStub() { | |
2126 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); | |
2127 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); | |
2128 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); | |
2129 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); | |
2130 | |
2131 // If the feedback is an array, then the IC is in the monomorphic or | |
2132 // polymorphic state. | |
2133 HValue* feedback = | |
2134 Add<HLoadKeyed>(vector, slot, nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE); | |
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 | |
2158 TailCallMiss(receiver, name, slot, vector, false); | |
2159 return graph()->GetConstant0(); | |
2160 } | |
2161 | |
2162 | |
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() { | 2017 Handle<Code> MegamorphicLoadStub::GenerateCode() { |
2238 return DoGenerateCode(this); | 2018 return DoGenerateCode(this); |
2239 } | 2019 } |
2240 | 2020 |
2241 | 2021 |
2242 template <> | 2022 template <> |
2243 HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() { | 2023 HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() { |
2244 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); | 2024 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); |
2245 HValue* name = GetParameter(LoadDescriptor::kNameIndex); | 2025 HValue* name = GetParameter(LoadDescriptor::kNameIndex); |
2246 | 2026 |
2247 // We shouldn't generate this when FLAG_vector_ics is true because the | 2027 // We shouldn't generate this when FLAG_vector_ics is true because the |
2248 // megamorphic case is handled as part of the default stub. | 2028 // megamorphic case is handled as part of the default stub. |
2249 DCHECK(!FLAG_vector_ics); | 2029 DCHECK(!FLAG_vector_ics); |
2250 | 2030 |
2251 // Probe the stub cache. | 2031 // Probe the stub cache. |
2252 Add<HTailCallThroughMegamorphicCache>(receiver, name); | 2032 Add<HTailCallThroughMegamorphicCache>(receiver, name); |
2253 | 2033 |
2254 // We never continue. | 2034 // We never continue. |
2255 return graph()->GetConstant0(); | 2035 return graph()->GetConstant0(); |
2256 } | 2036 } |
2257 } } // namespace v8::internal | 2037 } } // namespace v8::internal |
OLD | NEW |