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 1803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1933 template <> | 1913 template <> |
1934 HValue* CodeStubGraphBuilder<ToObjectStub>::BuildCodeStub() { | 1914 HValue* CodeStubGraphBuilder<ToObjectStub>::BuildCodeStub() { |
1935 HValue* receiver = GetParameter(TypeConversionDescriptor::kArgumentIndex); | 1915 HValue* receiver = GetParameter(TypeConversionDescriptor::kArgumentIndex); |
1936 return BuildToObject(receiver); | 1916 return BuildToObject(receiver); |
1937 } | 1917 } |
1938 | 1918 |
1939 | 1919 |
1940 Handle<Code> ToObjectStub::GenerateCode() { return DoGenerateCode(this); } | 1920 Handle<Code> ToObjectStub::GenerateCode() { return DoGenerateCode(this); } |
1941 | 1921 |
1942 | 1922 |
1943 void CodeStubGraphBuilderBase::BuildCheckAndInstallOptimizedCode( | |
1944 HValue* js_function, | |
1945 HValue* native_context, | |
1946 IfBuilder* builder, | |
1947 HValue* optimized_map, | |
1948 HValue* map_index) { | |
1949 HValue* osr_ast_id_none = Add<HConstant>(BailoutId::None().ToInt()); | |
1950 HValue* context_slot = LoadFromOptimizedCodeMap( | |
1951 optimized_map, map_index, SharedFunctionInfo::kContextOffset); | |
1952 context_slot = Add<HLoadNamedField>(context_slot, nullptr, | |
1953 HObjectAccess::ForWeakCellValue()); | |
1954 HValue* osr_ast_slot = LoadFromOptimizedCodeMap( | |
1955 optimized_map, map_index, SharedFunctionInfo::kOsrAstIdOffset); | |
1956 HValue* code_object = LoadFromOptimizedCodeMap( | |
1957 optimized_map, map_index, SharedFunctionInfo::kCachedCodeOffset); | |
1958 code_object = Add<HLoadNamedField>(code_object, nullptr, | |
1959 HObjectAccess::ForWeakCellValue()); | |
1960 builder->If<HCompareObjectEqAndBranch>(native_context, | |
1961 context_slot); | |
1962 builder->AndIf<HCompareObjectEqAndBranch>(osr_ast_slot, osr_ast_id_none); | |
1963 builder->And(); | |
1964 builder->IfNot<HCompareObjectEqAndBranch>(code_object, | |
1965 graph()->GetConstant0()); | |
1966 builder->Then(); | |
1967 HValue* literals = LoadFromOptimizedCodeMap(optimized_map, | |
1968 map_index, SharedFunctionInfo::kLiteralsOffset); | |
1969 literals = Add<HLoadNamedField>(literals, nullptr, | |
1970 HObjectAccess::ForWeakCellValue()); | |
1971 IfBuilder maybe_deopt(this); | |
1972 maybe_deopt.If<HCompareObjectEqAndBranch>(literals, graph()->GetConstant0()); | |
1973 maybe_deopt.ThenDeopt(Deoptimizer::kLiteralsWereDisposed); | |
1974 maybe_deopt.End(); | |
1975 | |
1976 BuildInstallOptimizedCode(js_function, native_context, code_object, literals); | |
1977 | |
1978 // The builder continues in the "then" after this function. | |
1979 } | |
1980 | |
1981 | |
1982 void CodeStubGraphBuilderBase::BuildInstallOptimizedCode(HValue* js_function, | |
1983 HValue* native_context, | |
1984 HValue* code_object, | |
1985 HValue* literals) { | |
1986 Counters* counters = isolate()->counters(); | |
1987 AddIncrementCounter(counters->fast_new_closure_install_optimized()); | |
1988 | |
1989 // TODO(fschneider): Idea: store proper code pointers in the optimized code | |
1990 // map and either unmangle them on marking or do nothing as the whole map is | |
1991 // discarded on major GC anyway. | |
1992 Add<HStoreCodeEntry>(js_function, code_object); | |
1993 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), | |
1994 literals); | |
1995 | |
1996 // Now link a function into a list of optimized functions. | |
1997 HValue* optimized_functions_list = Add<HLoadNamedField>( | |
1998 native_context, nullptr, | |
1999 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST)); | |
2000 Add<HStoreNamedField>(js_function, | |
2001 HObjectAccess::ForNextFunctionLinkPointer(), | |
2002 optimized_functions_list); | |
2003 | |
2004 // This store is the only one that should have a write barrier. | |
2005 Add<HStoreNamedField>(native_context, | |
2006 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST), | |
2007 js_function); | |
2008 } | |
2009 | |
2010 | |
2011 void CodeStubGraphBuilderBase::BuildInstallCode(HValue* js_function, | |
2012 HValue* shared_info) { | |
2013 Add<HStoreNamedField>(js_function, | |
2014 HObjectAccess::ForNextFunctionLinkPointer(), | |
2015 graph()->GetConstantUndefined()); | |
2016 HValue* code_object = Add<HLoadNamedField>(shared_info, nullptr, | |
2017 HObjectAccess::ForCodeOffset()); | |
2018 Add<HStoreCodeEntry>(js_function, code_object); | |
2019 } | |
2020 | |
2021 | |
2022 HInstruction* CodeStubGraphBuilderBase::LoadFromOptimizedCodeMap( | |
2023 HValue* optimized_map, | |
2024 HValue* iterator, | |
2025 int field_offset) { | |
2026 // By making sure to express these loads in the form [<hvalue> + constant] | |
2027 // the keyed load can be hoisted. | |
2028 DCHECK(field_offset >= 0 && field_offset < SharedFunctionInfo::kEntryLength); | |
2029 HValue* field_slot = iterator; | |
2030 if (field_offset > 0) { | |
2031 HValue* field_offset_value = Add<HConstant>(field_offset); | |
2032 field_slot = AddUncasted<HAdd>(iterator, field_offset_value); | |
2033 } | |
2034 HInstruction* field_entry = Add<HLoadKeyed>(optimized_map, field_slot, | |
2035 nullptr, nullptr, FAST_ELEMENTS); | |
2036 return field_entry; | |
2037 } | |
2038 | |
2039 | |
2040 void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( | |
2041 HValue* js_function, | |
2042 HValue* shared_info, | |
2043 HValue* native_context) { | |
2044 Counters* counters = isolate()->counters(); | |
2045 Factory* factory = isolate()->factory(); | |
2046 IfBuilder is_optimized(this); | |
2047 HInstruction* optimized_map = Add<HLoadNamedField>( | |
2048 shared_info, nullptr, HObjectAccess::ForOptimizedCodeMap()); | |
2049 HValue* null_constant = Add<HConstant>(0); | |
2050 is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant); | |
2051 is_optimized.Then(); | |
2052 { | |
2053 BuildInstallCode(js_function, shared_info); | |
2054 } | |
2055 is_optimized.Else(); | |
2056 { | |
2057 AddIncrementCounter(counters->fast_new_closure_try_optimized()); | |
2058 // The {optimized_map} points to fixed array of 4-element entries: | |
2059 // (native context, optimized code, literals, ast-id). | |
2060 // Iterate through the {optimized_map} backwards. After the loop, if no | |
2061 // matching optimized code was found, install unoptimized code. | |
2062 // for(i = map.length() - SharedFunctionInfo::kEntryLength; | |
2063 // i >= SharedFunctionInfo::kEntriesStart; | |
2064 // i -= SharedFunctionInfo::kEntryLength) { ... } | |
2065 HValue* first_entry_index = | |
2066 Add<HConstant>(SharedFunctionInfo::kEntriesStart); | |
2067 HValue* shared_function_entry_length = | |
2068 Add<HConstant>(SharedFunctionInfo::kEntryLength); | |
2069 LoopBuilder loop_builder(this, context(), LoopBuilder::kPostDecrement, | |
2070 shared_function_entry_length); | |
2071 HValue* array_length = Add<HLoadNamedField>( | |
2072 optimized_map, nullptr, HObjectAccess::ForFixedArrayLength()); | |
2073 HValue* start_pos = | |
2074 AddUncasted<HSub>(array_length, shared_function_entry_length); | |
2075 HValue* slot_iterator = | |
2076 loop_builder.BeginBody(start_pos, first_entry_index, Token::GTE); | |
2077 { | |
2078 IfBuilder done_check(this); | |
2079 BuildCheckAndInstallOptimizedCode(js_function, native_context, | |
2080 &done_check, optimized_map, | |
2081 slot_iterator); | |
2082 // Fall out of the loop | |
2083 loop_builder.Break(); | |
2084 } | |
2085 loop_builder.EndBody(); | |
2086 | |
2087 // If {slot_iterator} is less than the first entry index, then we failed to | |
2088 // find a context-dependent code and try context-independent code next. | |
2089 IfBuilder no_optimized_code_check(this); | |
2090 no_optimized_code_check.If<HCompareNumericAndBranch>( | |
2091 slot_iterator, first_entry_index, Token::LT); | |
2092 no_optimized_code_check.Then(); | |
2093 { | |
2094 IfBuilder shared_code_check(this); | |
2095 HValue* shared_code = | |
2096 Add<HLoadNamedField>(optimized_map, nullptr, | |
2097 HObjectAccess::ForOptimizedCodeMapSharedCode()); | |
2098 shared_code = Add<HLoadNamedField>(shared_code, nullptr, | |
2099 HObjectAccess::ForWeakCellValue()); | |
2100 shared_code_check.IfNot<HCompareObjectEqAndBranch>( | |
2101 shared_code, graph()->GetConstant0()); | |
2102 shared_code_check.Then(); | |
2103 { | |
2104 // Store the context-independent optimized code. | |
2105 HValue* literals = Add<HConstant>(factory->empty_fixed_array()); | |
2106 BuildInstallOptimizedCode(js_function, native_context, shared_code, | |
2107 literals); | |
2108 } | |
2109 shared_code_check.Else(); | |
2110 { | |
2111 // Store the unoptimized code. | |
2112 BuildInstallCode(js_function, shared_info); | |
2113 } | |
2114 } | |
2115 } | |
2116 } | |
2117 | |
2118 | |
2119 template<> | 1923 template<> |
2120 HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() { | 1924 HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() { |
2121 Counters* counters = isolate()->counters(); | 1925 Counters* counters = isolate()->counters(); |
2122 Factory* factory = isolate()->factory(); | 1926 Factory* factory = isolate()->factory(); |
2123 HInstruction* empty_fixed_array = | 1927 HInstruction* empty_fixed_array = |
2124 Add<HConstant>(factory->empty_fixed_array()); | 1928 Add<HConstant>(factory->empty_fixed_array()); |
2125 HValue* shared_info = GetParameter(0); | 1929 HValue* shared_info = GetParameter(0); |
2126 | 1930 |
2127 AddIncrementCounter(counters->fast_new_closure_total()); | 1931 AddIncrementCounter(counters->fast_new_closure_total()); |
2128 | 1932 |
(...skipping 19 matching lines...) Expand all Loading... |
2148 empty_fixed_array); | 1952 empty_fixed_array); |
2149 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), | 1953 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), |
2150 empty_fixed_array); | 1954 empty_fixed_array); |
2151 Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(), | 1955 Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(), |
2152 graph()->GetConstantHole()); | 1956 graph()->GetConstantHole()); |
2153 Add<HStoreNamedField>( | 1957 Add<HStoreNamedField>( |
2154 js_function, HObjectAccess::ForSharedFunctionInfoPointer(), shared_info); | 1958 js_function, HObjectAccess::ForSharedFunctionInfoPointer(), shared_info); |
2155 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(), | 1959 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(), |
2156 context()); | 1960 context()); |
2157 | 1961 |
2158 // Initialize the code pointer in the function to be the one found in the | 1962 Handle<Code> lazy_builtin( |
2159 // shared function info object. But first check if there is an optimized | 1963 isolate()->builtins()->builtin(Builtins::kCompileLazy)); |
2160 // version for our context. | 1964 HConstant* lazy = Add<HConstant>(lazy_builtin); |
2161 BuildInstallFromOptimizedCodeMap(js_function, shared_info, native_context); | 1965 Add<HStoreCodeEntry>(js_function, lazy); |
| 1966 Add<HStoreNamedField>(js_function, |
| 1967 HObjectAccess::ForNextFunctionLinkPointer(), |
| 1968 graph()->GetConstantUndefined()); |
2162 | 1969 |
2163 return js_function; | 1970 return js_function; |
2164 } | 1971 } |
2165 | 1972 |
2166 | 1973 |
2167 Handle<Code> FastNewClosureStub::GenerateCode() { | 1974 Handle<Code> FastNewClosureStub::GenerateCode() { |
2168 return DoGenerateCode(this); | 1975 return DoGenerateCode(this); |
2169 } | 1976 } |
2170 | 1977 |
2171 | 1978 |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2501 return Pop(); | 2308 return Pop(); |
2502 } | 2309 } |
2503 | 2310 |
2504 | 2311 |
2505 Handle<Code> KeyedLoadGenericStub::GenerateCode() { | 2312 Handle<Code> KeyedLoadGenericStub::GenerateCode() { |
2506 return DoGenerateCode(this); | 2313 return DoGenerateCode(this); |
2507 } | 2314 } |
2508 | 2315 |
2509 } // namespace internal | 2316 } // namespace internal |
2510 } // namespace v8 | 2317 } // namespace v8 |
OLD | NEW |