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