| 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 |