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/code-stubs.h" | 5 #include "src/code-stubs.h" |
6 | 6 |
7 #include "src/bailout-reason.h" | 7 #include "src/bailout-reason.h" |
8 #include "src/crankshaft/hydrogen.h" | 8 #include "src/crankshaft/hydrogen.h" |
9 #include "src/crankshaft/lithium.h" | 9 #include "src/crankshaft/lithium.h" |
10 #include "src/field-index.h" | 10 #include "src/field-index.h" |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 HValue* UnmappedCase(HValue* elements, HValue* key, HValue* value); | 90 HValue* UnmappedCase(HValue* elements, HValue* key, HValue* value); |
91 HValue* EmitKeyedSloppyArguments(HValue* receiver, HValue* key, | 91 HValue* EmitKeyedSloppyArguments(HValue* receiver, HValue* key, |
92 HValue* value); | 92 HValue* value); |
93 | 93 |
94 HValue* BuildArrayConstructor(ElementsKind kind, | 94 HValue* BuildArrayConstructor(ElementsKind kind, |
95 AllocationSiteOverrideMode override_mode, | 95 AllocationSiteOverrideMode override_mode, |
96 ArgumentClass argument_class); | 96 ArgumentClass argument_class); |
97 HValue* BuildInternalArrayConstructor(ElementsKind kind, | 97 HValue* BuildInternalArrayConstructor(ElementsKind kind, |
98 ArgumentClass argument_class); | 98 ArgumentClass argument_class); |
99 | 99 |
| 100 // BuildCheckAndInstallOptimizedCode emits code to install the optimized |
| 101 // function found in the optimized code map at map_index in js_function, if |
| 102 // the function at map_index matches the given native_context. Builder is |
| 103 // left in the "Then()" state after the install. |
| 104 void BuildCheckAndInstallOptimizedCode(HValue* js_function, |
| 105 HValue* native_context, |
| 106 IfBuilder* builder, |
| 107 HValue* optimized_map, |
| 108 HValue* map_index); |
| 109 void BuildInstallOptimizedCode(HValue* js_function, HValue* native_context, |
| 110 HValue* code_object, HValue* literals); |
| 111 void BuildInstallCode(HValue* js_function, HValue* shared_info); |
| 112 |
| 113 HInstruction* LoadFromOptimizedCodeMap(HValue* optimized_map, |
| 114 HValue* iterator, |
| 115 int field_offset); |
| 116 void BuildInstallFromOptimizedCodeMap(HValue* js_function, |
| 117 HValue* shared_info, |
| 118 HValue* native_context); |
| 119 |
100 HValue* BuildToString(HValue* input, bool convert); | 120 HValue* BuildToString(HValue* input, bool convert); |
101 HValue* BuildToPrimitive(HValue* input, HValue* input_map); | 121 HValue* BuildToPrimitive(HValue* input, HValue* input_map); |
102 | 122 |
103 private: | 123 private: |
104 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); | 124 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); |
105 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, | 125 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, |
106 ElementsKind kind); | 126 ElementsKind kind); |
107 | 127 |
108 base::SmartArrayPointer<HParameter*> parameters_; | 128 base::SmartArrayPointer<HParameter*> parameters_; |
109 HValue* arguments_length_; | 129 HValue* arguments_length_; |
(...skipping 1876 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1986 template <> | 2006 template <> |
1987 HValue* CodeStubGraphBuilder<ToObjectStub>::BuildCodeStub() { | 2007 HValue* CodeStubGraphBuilder<ToObjectStub>::BuildCodeStub() { |
1988 HValue* receiver = GetParameter(TypeConversionDescriptor::kArgumentIndex); | 2008 HValue* receiver = GetParameter(TypeConversionDescriptor::kArgumentIndex); |
1989 return BuildToObject(receiver); | 2009 return BuildToObject(receiver); |
1990 } | 2010 } |
1991 | 2011 |
1992 | 2012 |
1993 Handle<Code> ToObjectStub::GenerateCode() { return DoGenerateCode(this); } | 2013 Handle<Code> ToObjectStub::GenerateCode() { return DoGenerateCode(this); } |
1994 | 2014 |
1995 | 2015 |
| 2016 void CodeStubGraphBuilderBase::BuildCheckAndInstallOptimizedCode( |
| 2017 HValue* js_function, |
| 2018 HValue* native_context, |
| 2019 IfBuilder* builder, |
| 2020 HValue* optimized_map, |
| 2021 HValue* map_index) { |
| 2022 HValue* osr_ast_id_none = Add<HConstant>(BailoutId::None().ToInt()); |
| 2023 HValue* context_slot = LoadFromOptimizedCodeMap( |
| 2024 optimized_map, map_index, SharedFunctionInfo::kContextOffset); |
| 2025 context_slot = Add<HLoadNamedField>(context_slot, nullptr, |
| 2026 HObjectAccess::ForWeakCellValue()); |
| 2027 HValue* osr_ast_slot = LoadFromOptimizedCodeMap( |
| 2028 optimized_map, map_index, SharedFunctionInfo::kOsrAstIdOffset); |
| 2029 HValue* code_object = LoadFromOptimizedCodeMap( |
| 2030 optimized_map, map_index, SharedFunctionInfo::kCachedCodeOffset); |
| 2031 code_object = Add<HLoadNamedField>(code_object, nullptr, |
| 2032 HObjectAccess::ForWeakCellValue()); |
| 2033 builder->If<HCompareObjectEqAndBranch>(native_context, |
| 2034 context_slot); |
| 2035 builder->AndIf<HCompareObjectEqAndBranch>(osr_ast_slot, osr_ast_id_none); |
| 2036 builder->And(); |
| 2037 builder->IfNot<HCompareObjectEqAndBranch>(code_object, |
| 2038 graph()->GetConstant0()); |
| 2039 builder->Then(); |
| 2040 HValue* literals = LoadFromOptimizedCodeMap(optimized_map, |
| 2041 map_index, SharedFunctionInfo::kLiteralsOffset); |
| 2042 literals = Add<HLoadNamedField>(literals, nullptr, |
| 2043 HObjectAccess::ForWeakCellValue()); |
| 2044 IfBuilder maybe_deopt(this); |
| 2045 maybe_deopt.If<HCompareObjectEqAndBranch>(literals, graph()->GetConstant0()); |
| 2046 maybe_deopt.ThenDeopt(Deoptimizer::kLiteralsWereDisposed); |
| 2047 maybe_deopt.End(); |
| 2048 |
| 2049 BuildInstallOptimizedCode(js_function, native_context, code_object, literals); |
| 2050 |
| 2051 // The builder continues in the "then" after this function. |
| 2052 } |
| 2053 |
| 2054 |
| 2055 void CodeStubGraphBuilderBase::BuildInstallOptimizedCode(HValue* js_function, |
| 2056 HValue* native_context, |
| 2057 HValue* code_object, |
| 2058 HValue* literals) { |
| 2059 Counters* counters = isolate()->counters(); |
| 2060 AddIncrementCounter(counters->fast_new_closure_install_optimized()); |
| 2061 |
| 2062 // TODO(fschneider): Idea: store proper code pointers in the optimized code |
| 2063 // map and either unmangle them on marking or do nothing as the whole map is |
| 2064 // discarded on major GC anyway. |
| 2065 Add<HStoreCodeEntry>(js_function, code_object); |
| 2066 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), |
| 2067 literals); |
| 2068 |
| 2069 // Now link a function into a list of optimized functions. |
| 2070 HValue* optimized_functions_list = Add<HLoadNamedField>( |
| 2071 native_context, nullptr, |
| 2072 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST)); |
| 2073 Add<HStoreNamedField>(js_function, |
| 2074 HObjectAccess::ForNextFunctionLinkPointer(), |
| 2075 optimized_functions_list); |
| 2076 |
| 2077 // This store is the only one that should have a write barrier. |
| 2078 Add<HStoreNamedField>(native_context, |
| 2079 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST), |
| 2080 js_function); |
| 2081 } |
| 2082 |
| 2083 |
| 2084 void CodeStubGraphBuilderBase::BuildInstallCode(HValue* js_function, |
| 2085 HValue* shared_info) { |
| 2086 Add<HStoreNamedField>(js_function, |
| 2087 HObjectAccess::ForNextFunctionLinkPointer(), |
| 2088 graph()->GetConstantUndefined()); |
| 2089 HValue* code_object = Add<HLoadNamedField>(shared_info, nullptr, |
| 2090 HObjectAccess::ForCodeOffset()); |
| 2091 Add<HStoreCodeEntry>(js_function, code_object); |
| 2092 } |
| 2093 |
| 2094 |
| 2095 HInstruction* CodeStubGraphBuilderBase::LoadFromOptimizedCodeMap( |
| 2096 HValue* optimized_map, |
| 2097 HValue* iterator, |
| 2098 int field_offset) { |
| 2099 // By making sure to express these loads in the form [<hvalue> + constant] |
| 2100 // the keyed load can be hoisted. |
| 2101 DCHECK(field_offset >= 0 && field_offset < SharedFunctionInfo::kEntryLength); |
| 2102 HValue* field_slot = iterator; |
| 2103 if (field_offset > 0) { |
| 2104 HValue* field_offset_value = Add<HConstant>(field_offset); |
| 2105 field_slot = AddUncasted<HAdd>(iterator, field_offset_value); |
| 2106 } |
| 2107 HInstruction* field_entry = Add<HLoadKeyed>(optimized_map, field_slot, |
| 2108 nullptr, nullptr, FAST_ELEMENTS); |
| 2109 return field_entry; |
| 2110 } |
| 2111 |
| 2112 |
| 2113 void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( |
| 2114 HValue* js_function, |
| 2115 HValue* shared_info, |
| 2116 HValue* native_context) { |
| 2117 Counters* counters = isolate()->counters(); |
| 2118 Factory* factory = isolate()->factory(); |
| 2119 IfBuilder is_optimized(this); |
| 2120 HInstruction* optimized_map = Add<HLoadNamedField>( |
| 2121 shared_info, nullptr, HObjectAccess::ForOptimizedCodeMap()); |
| 2122 HValue* null_constant = Add<HConstant>(0); |
| 2123 is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant); |
| 2124 is_optimized.Then(); |
| 2125 { |
| 2126 BuildInstallCode(js_function, shared_info); |
| 2127 } |
| 2128 is_optimized.Else(); |
| 2129 { |
| 2130 AddIncrementCounter(counters->fast_new_closure_try_optimized()); |
| 2131 // The {optimized_map} points to fixed array of 4-element entries: |
| 2132 // (native context, optimized code, literals, ast-id). |
| 2133 // Iterate through the {optimized_map} backwards. After the loop, if no |
| 2134 // matching optimized code was found, install unoptimized code. |
| 2135 // for(i = map.length() - SharedFunctionInfo::kEntryLength; |
| 2136 // i >= SharedFunctionInfo::kEntriesStart; |
| 2137 // i -= SharedFunctionInfo::kEntryLength) { ... } |
| 2138 HValue* first_entry_index = |
| 2139 Add<HConstant>(SharedFunctionInfo::kEntriesStart); |
| 2140 HValue* shared_function_entry_length = |
| 2141 Add<HConstant>(SharedFunctionInfo::kEntryLength); |
| 2142 LoopBuilder loop_builder(this, context(), LoopBuilder::kPostDecrement, |
| 2143 shared_function_entry_length); |
| 2144 HValue* array_length = Add<HLoadNamedField>( |
| 2145 optimized_map, nullptr, HObjectAccess::ForFixedArrayLength()); |
| 2146 HValue* start_pos = |
| 2147 AddUncasted<HSub>(array_length, shared_function_entry_length); |
| 2148 HValue* slot_iterator = |
| 2149 loop_builder.BeginBody(start_pos, first_entry_index, Token::GTE); |
| 2150 { |
| 2151 IfBuilder done_check(this); |
| 2152 BuildCheckAndInstallOptimizedCode(js_function, native_context, |
| 2153 &done_check, optimized_map, |
| 2154 slot_iterator); |
| 2155 // Fall out of the loop |
| 2156 loop_builder.Break(); |
| 2157 } |
| 2158 loop_builder.EndBody(); |
| 2159 |
| 2160 // If {slot_iterator} is less than the first entry index, then we failed to |
| 2161 // find a context-dependent code and try context-independent code next. |
| 2162 IfBuilder no_optimized_code_check(this); |
| 2163 no_optimized_code_check.If<HCompareNumericAndBranch>( |
| 2164 slot_iterator, first_entry_index, Token::LT); |
| 2165 no_optimized_code_check.Then(); |
| 2166 { |
| 2167 IfBuilder shared_code_check(this); |
| 2168 HValue* shared_code = |
| 2169 Add<HLoadNamedField>(optimized_map, nullptr, |
| 2170 HObjectAccess::ForOptimizedCodeMapSharedCode()); |
| 2171 shared_code = Add<HLoadNamedField>(shared_code, nullptr, |
| 2172 HObjectAccess::ForWeakCellValue()); |
| 2173 shared_code_check.IfNot<HCompareObjectEqAndBranch>( |
| 2174 shared_code, graph()->GetConstant0()); |
| 2175 shared_code_check.Then(); |
| 2176 { |
| 2177 // Store the context-independent optimized code. |
| 2178 HValue* literals = Add<HConstant>(factory->empty_fixed_array()); |
| 2179 BuildInstallOptimizedCode(js_function, native_context, shared_code, |
| 2180 literals); |
| 2181 } |
| 2182 shared_code_check.Else(); |
| 2183 { |
| 2184 // Store the unoptimized code. |
| 2185 BuildInstallCode(js_function, shared_info); |
| 2186 } |
| 2187 } |
| 2188 } |
| 2189 } |
| 2190 |
| 2191 |
1996 template<> | 2192 template<> |
1997 HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() { | 2193 HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() { |
1998 Counters* counters = isolate()->counters(); | 2194 Counters* counters = isolate()->counters(); |
1999 Factory* factory = isolate()->factory(); | 2195 Factory* factory = isolate()->factory(); |
2000 HInstruction* empty_fixed_array = | 2196 HInstruction* empty_fixed_array = |
2001 Add<HConstant>(factory->empty_fixed_array()); | 2197 Add<HConstant>(factory->empty_fixed_array()); |
2002 HValue* shared_info = GetParameter(0); | 2198 HValue* shared_info = GetParameter(0); |
2003 | 2199 |
2004 AddIncrementCounter(counters->fast_new_closure_total()); | 2200 AddIncrementCounter(counters->fast_new_closure_total()); |
2005 | 2201 |
(...skipping 19 matching lines...) Expand all Loading... |
2025 empty_fixed_array); | 2221 empty_fixed_array); |
2026 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), | 2222 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), |
2027 empty_fixed_array); | 2223 empty_fixed_array); |
2028 Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(), | 2224 Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(), |
2029 graph()->GetConstantHole()); | 2225 graph()->GetConstantHole()); |
2030 Add<HStoreNamedField>( | 2226 Add<HStoreNamedField>( |
2031 js_function, HObjectAccess::ForSharedFunctionInfoPointer(), shared_info); | 2227 js_function, HObjectAccess::ForSharedFunctionInfoPointer(), shared_info); |
2032 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(), | 2228 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(), |
2033 context()); | 2229 context()); |
2034 | 2230 |
2035 Handle<Code> lazy_builtin( | 2231 // Initialize the code pointer in the function to be the one found in the |
2036 isolate()->builtins()->builtin(Builtins::kCompileLazy)); | 2232 // shared function info object. But first check if there is an optimized |
2037 HConstant* lazy = Add<HConstant>(lazy_builtin); | 2233 // version for our context. |
2038 Add<HStoreCodeEntry>(js_function, lazy); | 2234 BuildInstallFromOptimizedCodeMap(js_function, shared_info, native_context); |
2039 Add<HStoreNamedField>(js_function, | |
2040 HObjectAccess::ForNextFunctionLinkPointer(), | |
2041 graph()->GetConstantUndefined()); | |
2042 | 2235 |
2043 return js_function; | 2236 return js_function; |
2044 } | 2237 } |
2045 | 2238 |
2046 | 2239 |
2047 Handle<Code> FastNewClosureStub::GenerateCode() { | 2240 Handle<Code> FastNewClosureStub::GenerateCode() { |
2048 return DoGenerateCode(this); | 2241 return DoGenerateCode(this); |
2049 } | 2242 } |
2050 | 2243 |
2051 | 2244 |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2381 return Pop(); | 2574 return Pop(); |
2382 } | 2575 } |
2383 | 2576 |
2384 | 2577 |
2385 Handle<Code> KeyedLoadGenericStub::GenerateCode() { | 2578 Handle<Code> KeyedLoadGenericStub::GenerateCode() { |
2386 return DoGenerateCode(this); | 2579 return DoGenerateCode(this); |
2387 } | 2580 } |
2388 | 2581 |
2389 } // namespace internal | 2582 } // namespace internal |
2390 } // namespace v8 | 2583 } // namespace v8 |
OLD | NEW |