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 = |
| 2073 Add<HLoadKeyed>(array, start, static_cast<HValue*>(NULL), FAST_ELEMENTS, |
| 2074 ALLOW_RETURN_HOLE); |
| 2075 IfBuilder if_correct_map(this); |
| 2076 if_correct_map.If<HCompareObjectEqAndBranch>(receiver_map, array_map); |
| 2077 if_correct_map.Then(); |
| 2078 { TailCallHandler(receiver, name, array, start, slot, vector); } |
| 2079 if_correct_map.Else(); |
| 2080 { |
| 2081 // If our array has more elements, the ic is polymorphic. Look for the |
| 2082 // receiver map in the rest of the array. |
| 2083 HValue* length = |
| 2084 AddLoadFixedArrayLength(array, static_cast<HValue*>(NULL)); |
| 2085 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement, |
| 2086 constant_two); |
| 2087 start = keyed_load ? constant_three : constant_two; |
| 2088 HValue* key = builder.BeginBody(start, length, Token::LT); |
| 2089 { |
| 2090 HValue* array_map = |
| 2091 Add<HLoadKeyed>(array, key, static_cast<HValue*>(NULL), |
| 2092 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 2093 IfBuilder if_correct_poly_map(this); |
| 2094 if_correct_poly_map.If<HCompareObjectEqAndBranch>(receiver_map, |
| 2095 array_map); |
| 2096 if_correct_poly_map.Then(); |
| 2097 { TailCallHandler(receiver, name, array, key, slot, vector); } |
| 2098 } |
| 2099 builder.EndBody(); |
| 2100 } |
| 2101 if_correct_map.End(); |
| 2102 } |
| 2103 } |
| 2104 |
| 2105 |
2006 template <> | 2106 template <> |
2007 HValue* CodeStubGraphBuilder<VectorLoadStub>::BuildCodeStub() { | 2107 HValue* CodeStubGraphBuilder<VectorLoadStub>::BuildCodeStub() { |
2008 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); | 2108 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); |
2009 Add<HDeoptimize>("Always deopt", Deoptimizer::EAGER); | 2109 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); |
2010 return receiver; | 2110 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); |
| 2111 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); |
| 2112 |
| 2113 // If the feedback is an array, then the IC is in the monomorphic or |
| 2114 // polymorphic state. |
| 2115 HValue* feedback = Add<HLoadKeyed>(vector, slot, static_cast<HValue*>(NULL), |
| 2116 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 2117 IfBuilder array_checker(this); |
| 2118 array_checker.If<HCompareMap>(feedback, |
| 2119 isolate()->factory()->fixed_array_map()); |
| 2120 array_checker.Then(); |
| 2121 { HandleArrayCases(feedback, receiver, name, slot, vector, false); } |
| 2122 array_checker.Else(); |
| 2123 { |
| 2124 // Is the IC megamorphic? |
| 2125 IfBuilder mega_checker(this); |
| 2126 HConstant* megamorphic_symbol = |
| 2127 Add<HConstant>(isolate()->factory()->megamorphic_symbol()); |
| 2128 mega_checker.If<HCompareObjectEqAndBranch>(feedback, megamorphic_symbol); |
| 2129 mega_checker.Then(); |
| 2130 { |
| 2131 // Probe the stub cache. |
| 2132 Add<HTailCallThroughMegamorphicCache>( |
| 2133 receiver, name, slot, vector, |
| 2134 HTailCallThroughMegamorphicCache::ComputeFlags(false, false)); |
| 2135 } |
| 2136 mega_checker.End(); |
| 2137 } |
| 2138 array_checker.End(); |
| 2139 |
| 2140 TailCallMiss(receiver, name, slot, vector, false); |
| 2141 return graph()->GetConstant0(); |
2011 } | 2142 } |
2012 | 2143 |
2013 | 2144 |
2014 Handle<Code> VectorLoadStub::GenerateCode() { return DoGenerateCode(this); } | 2145 Handle<Code> VectorLoadStub::GenerateCode() { return DoGenerateCode(this); } |
2015 | 2146 |
2016 | 2147 |
2017 template <> | 2148 template <> |
2018 HValue* CodeStubGraphBuilder<VectorKeyedLoadStub>::BuildCodeStub() { | 2149 HValue* CodeStubGraphBuilder<VectorKeyedLoadStub>::BuildCodeStub() { |
2019 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); | 2150 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); |
2020 Add<HDeoptimize>("Always deopt", Deoptimizer::EAGER); | 2151 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); |
2021 return receiver; | 2152 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); |
| 2153 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); |
| 2154 HConstant* zero = graph()->GetConstant0(); |
| 2155 |
| 2156 // If the feedback is an array, then the IC is in the monomorphic or |
| 2157 // polymorphic state. |
| 2158 HValue* feedback = Add<HLoadKeyed>(vector, slot, static_cast<HValue*>(NULL), |
| 2159 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 2160 IfBuilder array_checker(this); |
| 2161 array_checker.If<HCompareMap>(feedback, |
| 2162 isolate()->factory()->fixed_array_map()); |
| 2163 array_checker.Then(); |
| 2164 { |
| 2165 // If feedback[0] is 0, then the IC has element handlers and name should be |
| 2166 // a smi. If feedback[0] is a string, verify that it matches name. |
| 2167 HValue* recorded_name = |
| 2168 Add<HLoadKeyed>(feedback, zero, static_cast<HValue*>(NULL), |
| 2169 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 2170 |
| 2171 IfBuilder recorded_name_is_zero(this); |
| 2172 recorded_name_is_zero.If<HCompareObjectEqAndBranch>(recorded_name, zero); |
| 2173 recorded_name_is_zero.Then(); |
| 2174 { Add<HCheckSmi>(name); } |
| 2175 recorded_name_is_zero.Else(); |
| 2176 { |
| 2177 IfBuilder strings_match(this); |
| 2178 strings_match.IfNot<HCompareObjectEqAndBranch>(name, recorded_name); |
| 2179 strings_match.Then(); |
| 2180 TailCallMiss(receiver, name, slot, vector, true); |
| 2181 strings_match.End(); |
| 2182 } |
| 2183 recorded_name_is_zero.End(); |
| 2184 |
| 2185 HandleArrayCases(feedback, receiver, name, slot, vector, true); |
| 2186 } |
| 2187 array_checker.Else(); |
| 2188 { |
| 2189 // Check if the IC is in generic state. |
| 2190 IfBuilder generic_checker(this); |
| 2191 HConstant* generic_symbol = |
| 2192 Add<HConstant>(isolate()->factory()->generic_symbol()); |
| 2193 generic_checker.If<HCompareObjectEqAndBranch>(feedback, generic_symbol); |
| 2194 generic_checker.Then(); |
| 2195 { |
| 2196 // Tail-call to the generic KeyedLoadIC, treating it like a handler. |
| 2197 Handle<Code> stub = KeyedLoadIC::generic_stub(isolate()); |
| 2198 HValue* constant_stub = Add<HConstant>(stub); |
| 2199 LoadDescriptor descriptor(isolate()); |
| 2200 HValue* op_vals[] = {context(), receiver, name}; |
| 2201 Add<HCallWithDescriptor>(constant_stub, 0, descriptor, |
| 2202 Vector<HValue*>(op_vals, 3), TAIL_CALL); |
| 2203 // We never return here, it is a tail call. |
| 2204 } |
| 2205 generic_checker.End(); |
| 2206 } |
| 2207 array_checker.End(); |
| 2208 |
| 2209 TailCallMiss(receiver, name, slot, vector, true); |
| 2210 return zero; |
2022 } | 2211 } |
2023 | 2212 |
2024 | 2213 |
2025 Handle<Code> VectorKeyedLoadStub::GenerateCode() { | 2214 Handle<Code> VectorKeyedLoadStub::GenerateCode() { |
2026 return DoGenerateCode(this); | 2215 return DoGenerateCode(this); |
2027 } | 2216 } |
2028 | 2217 |
2029 | 2218 |
2030 Handle<Code> MegamorphicLoadStub::GenerateCode() { | 2219 Handle<Code> MegamorphicLoadStub::GenerateCode() { |
2031 return DoGenerateCode(this); | 2220 return DoGenerateCode(this); |
2032 } | 2221 } |
2033 | 2222 |
2034 | 2223 |
2035 template <> | 2224 template <> |
2036 HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() { | 2225 HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() { |
2037 // The return address is on the stack. | |
2038 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); | 2226 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); |
2039 HValue* name = GetParameter(LoadDescriptor::kNameIndex); | 2227 HValue* name = GetParameter(LoadDescriptor::kNameIndex); |
2040 | 2228 |
| 2229 // We shouldn't generate this when FLAG_vector_ics is true because the |
| 2230 // megamorphic case is handled as part of the default stub. |
| 2231 DCHECK(!FLAG_vector_ics); |
| 2232 |
2041 // Probe the stub cache. | 2233 // Probe the stub cache. |
2042 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 2234 Add<HTailCallThroughMegamorphicCache>(receiver, name); |
2043 Code::ComputeHandlerFlags(Code::LOAD_IC)); | |
2044 Add<HTailCallThroughMegamorphicCache>(receiver, name, flags); | |
2045 | 2235 |
2046 // We never continue. | 2236 // We never continue. |
2047 return graph()->GetConstant0(); | 2237 return graph()->GetConstant0(); |
2048 } | 2238 } |
2049 } } // namespace v8::internal | 2239 } } // namespace v8::internal |
OLD | NEW |