| 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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 HValue* UnmappedCase(HValue* elements, HValue* key, HValue* value); | 86 HValue* UnmappedCase(HValue* elements, HValue* key, HValue* value); |
| 87 HValue* EmitKeyedSloppyArguments(HValue* receiver, HValue* key, | 87 HValue* EmitKeyedSloppyArguments(HValue* receiver, HValue* key, |
| 88 HValue* value); | 88 HValue* value); |
| 89 | 89 |
| 90 HValue* BuildArrayConstructor(ElementsKind kind, | 90 HValue* BuildArrayConstructor(ElementsKind kind, |
| 91 AllocationSiteOverrideMode override_mode, | 91 AllocationSiteOverrideMode override_mode, |
| 92 ArgumentClass argument_class); | 92 ArgumentClass argument_class); |
| 93 HValue* BuildInternalArrayConstructor(ElementsKind kind, | 93 HValue* BuildInternalArrayConstructor(ElementsKind kind, |
| 94 ArgumentClass argument_class); | 94 ArgumentClass argument_class); |
| 95 | 95 |
| 96 // BuildCheckAndInstallOptimizedCode emits code to install the optimized | |
| 97 // function found in the optimized code map at map_index in js_function, if | |
| 98 // the function at map_index matches the given native_context. Builder is | |
| 99 // left in the "Then()" state after the install. | |
| 100 void BuildCheckAndInstallOptimizedCode(HValue* js_function, | |
| 101 HValue* native_context, | |
| 102 IfBuilder* builder, | |
| 103 HValue* optimized_map, | |
| 104 HValue* map_index); | |
| 105 void BuildInstallOptimizedCode(HValue* js_function, HValue* native_context, | |
| 106 HValue* code_object, HValue* literals); | |
| 107 void BuildInstallCode(HValue* js_function, HValue* shared_info); | |
| 108 | |
| 109 HInstruction* LoadFromOptimizedCodeMap(HValue* optimized_map, | |
| 110 HValue* iterator, | |
| 111 int field_offset); | |
| 112 void BuildInstallFromOptimizedCodeMap(HValue* js_function, | |
| 113 HValue* shared_info, | |
| 114 HValue* native_context); | |
| 115 | |
| 116 HValue* BuildToString(HValue* input, bool convert); | 96 HValue* BuildToString(HValue* input, bool convert); |
| 117 HValue* BuildToPrimitive(HValue* input, HValue* input_map); | 97 HValue* BuildToPrimitive(HValue* input, HValue* input_map); |
| 118 | 98 |
| 119 private: | 99 private: |
| 120 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); | 100 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); |
| 121 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, | 101 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, |
| 122 ElementsKind kind); | 102 ElementsKind kind); |
| 123 | 103 |
| 124 base::SmartArrayPointer<HParameter*> parameters_; | 104 base::SmartArrayPointer<HParameter*> parameters_; |
| 125 HValue* arguments_length_; | 105 HValue* arguments_length_; |
| (...skipping 1727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1853 template <> | 1833 template <> |
| 1854 HValue* CodeStubGraphBuilder<ToObjectStub>::BuildCodeStub() { | 1834 HValue* CodeStubGraphBuilder<ToObjectStub>::BuildCodeStub() { |
| 1855 HValue* receiver = GetParameter(ToObjectDescriptor::kReceiverIndex); | 1835 HValue* receiver = GetParameter(ToObjectDescriptor::kReceiverIndex); |
| 1856 return BuildToObject(receiver); | 1836 return BuildToObject(receiver); |
| 1857 } | 1837 } |
| 1858 | 1838 |
| 1859 | 1839 |
| 1860 Handle<Code> ToObjectStub::GenerateCode() { return DoGenerateCode(this); } | 1840 Handle<Code> ToObjectStub::GenerateCode() { return DoGenerateCode(this); } |
| 1861 | 1841 |
| 1862 | 1842 |
| 1863 void CodeStubGraphBuilderBase::BuildCheckAndInstallOptimizedCode( | |
| 1864 HValue* js_function, | |
| 1865 HValue* native_context, | |
| 1866 IfBuilder* builder, | |
| 1867 HValue* optimized_map, | |
| 1868 HValue* map_index) { | |
| 1869 HValue* osr_ast_id_none = Add<HConstant>(BailoutId::None().ToInt()); | |
| 1870 HValue* context_slot = LoadFromOptimizedCodeMap( | |
| 1871 optimized_map, map_index, SharedFunctionInfo::kContextOffset); | |
| 1872 context_slot = Add<HLoadNamedField>(context_slot, nullptr, | |
| 1873 HObjectAccess::ForWeakCellValue()); | |
| 1874 HValue* osr_ast_slot = LoadFromOptimizedCodeMap( | |
| 1875 optimized_map, map_index, SharedFunctionInfo::kOsrAstIdOffset); | |
| 1876 HValue* code_object = LoadFromOptimizedCodeMap( | |
| 1877 optimized_map, map_index, SharedFunctionInfo::kCachedCodeOffset); | |
| 1878 code_object = Add<HLoadNamedField>(code_object, nullptr, | |
| 1879 HObjectAccess::ForWeakCellValue()); | |
| 1880 builder->If<HCompareObjectEqAndBranch>(native_context, | |
| 1881 context_slot); | |
| 1882 builder->AndIf<HCompareObjectEqAndBranch>(osr_ast_slot, osr_ast_id_none); | |
| 1883 builder->And(); | |
| 1884 builder->IfNot<HCompareObjectEqAndBranch>(code_object, | |
| 1885 graph()->GetConstant0()); | |
| 1886 builder->Then(); | |
| 1887 HValue* literals = LoadFromOptimizedCodeMap(optimized_map, | |
| 1888 map_index, SharedFunctionInfo::kLiteralsOffset); | |
| 1889 literals = Add<HLoadNamedField>(literals, nullptr, | |
| 1890 HObjectAccess::ForWeakCellValue()); | |
| 1891 IfBuilder maybe_deopt(this); | |
| 1892 maybe_deopt.If<HCompareObjectEqAndBranch>(literals, graph()->GetConstant0()); | |
| 1893 maybe_deopt.ThenDeopt(Deoptimizer::kLiteralsWereDisposed); | |
| 1894 maybe_deopt.End(); | |
| 1895 | |
| 1896 BuildInstallOptimizedCode(js_function, native_context, code_object, literals); | |
| 1897 | |
| 1898 // The builder continues in the "then" after this function. | |
| 1899 } | |
| 1900 | |
| 1901 | |
| 1902 void CodeStubGraphBuilderBase::BuildInstallOptimizedCode(HValue* js_function, | |
| 1903 HValue* native_context, | |
| 1904 HValue* code_object, | |
| 1905 HValue* literals) { | |
| 1906 Counters* counters = isolate()->counters(); | |
| 1907 AddIncrementCounter(counters->fast_new_closure_install_optimized()); | |
| 1908 | |
| 1909 // TODO(fschneider): Idea: store proper code pointers in the optimized code | |
| 1910 // map and either unmangle them on marking or do nothing as the whole map is | |
| 1911 // discarded on major GC anyway. | |
| 1912 Add<HStoreCodeEntry>(js_function, code_object); | |
| 1913 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), | |
| 1914 literals); | |
| 1915 | |
| 1916 // Now link a function into a list of optimized functions. | |
| 1917 HValue* optimized_functions_list = Add<HLoadNamedField>( | |
| 1918 native_context, nullptr, | |
| 1919 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST)); | |
| 1920 Add<HStoreNamedField>(js_function, | |
| 1921 HObjectAccess::ForNextFunctionLinkPointer(), | |
| 1922 optimized_functions_list); | |
| 1923 | |
| 1924 // This store is the only one that should have a write barrier. | |
| 1925 Add<HStoreNamedField>(native_context, | |
| 1926 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST), | |
| 1927 js_function); | |
| 1928 } | |
| 1929 | |
| 1930 | |
| 1931 void CodeStubGraphBuilderBase::BuildInstallCode(HValue* js_function, | |
| 1932 HValue* shared_info) { | |
| 1933 Add<HStoreNamedField>(js_function, | |
| 1934 HObjectAccess::ForNextFunctionLinkPointer(), | |
| 1935 graph()->GetConstantUndefined()); | |
| 1936 HValue* code_object = Add<HLoadNamedField>(shared_info, nullptr, | |
| 1937 HObjectAccess::ForCodeOffset()); | |
| 1938 Add<HStoreCodeEntry>(js_function, code_object); | |
| 1939 } | |
| 1940 | |
| 1941 | |
| 1942 HInstruction* CodeStubGraphBuilderBase::LoadFromOptimizedCodeMap( | |
| 1943 HValue* optimized_map, | |
| 1944 HValue* iterator, | |
| 1945 int field_offset) { | |
| 1946 // By making sure to express these loads in the form [<hvalue> + constant] | |
| 1947 // the keyed load can be hoisted. | |
| 1948 DCHECK(field_offset >= 0 && field_offset < SharedFunctionInfo::kEntryLength); | |
| 1949 HValue* field_slot = iterator; | |
| 1950 if (field_offset > 0) { | |
| 1951 HValue* field_offset_value = Add<HConstant>(field_offset); | |
| 1952 field_slot = AddUncasted<HAdd>(iterator, field_offset_value); | |
| 1953 } | |
| 1954 HInstruction* field_entry = Add<HLoadKeyed>(optimized_map, field_slot, | |
| 1955 nullptr, nullptr, FAST_ELEMENTS); | |
| 1956 return field_entry; | |
| 1957 } | |
| 1958 | |
| 1959 | |
| 1960 void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( | |
| 1961 HValue* js_function, | |
| 1962 HValue* shared_info, | |
| 1963 HValue* native_context) { | |
| 1964 Counters* counters = isolate()->counters(); | |
| 1965 Factory* factory = isolate()->factory(); | |
| 1966 IfBuilder is_optimized(this); | |
| 1967 HInstruction* optimized_map = Add<HLoadNamedField>( | |
| 1968 shared_info, nullptr, HObjectAccess::ForOptimizedCodeMap()); | |
| 1969 HValue* null_constant = Add<HConstant>(0); | |
| 1970 is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant); | |
| 1971 is_optimized.Then(); | |
| 1972 { | |
| 1973 BuildInstallCode(js_function, shared_info); | |
| 1974 } | |
| 1975 is_optimized.Else(); | |
| 1976 { | |
| 1977 AddIncrementCounter(counters->fast_new_closure_try_optimized()); | |
| 1978 // The {optimized_map} points to fixed array of 4-element entries: | |
| 1979 // (native context, optimized code, literals, ast-id). | |
| 1980 // Iterate through the {optimized_map} backwards. After the loop, if no | |
| 1981 // matching optimized code was found, install unoptimized code. | |
| 1982 // for(i = map.length() - SharedFunctionInfo::kEntryLength; | |
| 1983 // i >= SharedFunctionInfo::kEntriesStart; | |
| 1984 // i -= SharedFunctionInfo::kEntryLength) { ... } | |
| 1985 HValue* first_entry_index = | |
| 1986 Add<HConstant>(SharedFunctionInfo::kEntriesStart); | |
| 1987 HValue* shared_function_entry_length = | |
| 1988 Add<HConstant>(SharedFunctionInfo::kEntryLength); | |
| 1989 LoopBuilder loop_builder(this, context(), LoopBuilder::kPostDecrement, | |
| 1990 shared_function_entry_length); | |
| 1991 HValue* array_length = Add<HLoadNamedField>( | |
| 1992 optimized_map, nullptr, HObjectAccess::ForFixedArrayLength()); | |
| 1993 HValue* start_pos = | |
| 1994 AddUncasted<HSub>(array_length, shared_function_entry_length); | |
| 1995 HValue* slot_iterator = | |
| 1996 loop_builder.BeginBody(start_pos, first_entry_index, Token::GTE); | |
| 1997 { | |
| 1998 IfBuilder done_check(this); | |
| 1999 BuildCheckAndInstallOptimizedCode(js_function, native_context, | |
| 2000 &done_check, optimized_map, | |
| 2001 slot_iterator); | |
| 2002 // Fall out of the loop | |
| 2003 loop_builder.Break(); | |
| 2004 } | |
| 2005 loop_builder.EndBody(); | |
| 2006 | |
| 2007 // If {slot_iterator} is less than the first entry index, then we failed to | |
| 2008 // find a context-dependent code and try context-independent code next. | |
| 2009 IfBuilder no_optimized_code_check(this); | |
| 2010 no_optimized_code_check.If<HCompareNumericAndBranch>( | |
| 2011 slot_iterator, first_entry_index, Token::LT); | |
| 2012 no_optimized_code_check.Then(); | |
| 2013 { | |
| 2014 IfBuilder shared_code_check(this); | |
| 2015 HValue* shared_code = | |
| 2016 Add<HLoadNamedField>(optimized_map, nullptr, | |
| 2017 HObjectAccess::ForOptimizedCodeMapSharedCode()); | |
| 2018 shared_code = Add<HLoadNamedField>(shared_code, nullptr, | |
| 2019 HObjectAccess::ForWeakCellValue()); | |
| 2020 shared_code_check.IfNot<HCompareObjectEqAndBranch>( | |
| 2021 shared_code, graph()->GetConstant0()); | |
| 2022 shared_code_check.Then(); | |
| 2023 { | |
| 2024 // Store the context-independent optimized code. | |
| 2025 HValue* literals = Add<HConstant>(factory->empty_fixed_array()); | |
| 2026 BuildInstallOptimizedCode(js_function, native_context, shared_code, | |
| 2027 literals); | |
| 2028 } | |
| 2029 shared_code_check.Else(); | |
| 2030 { | |
| 2031 // Store the unoptimized code. | |
| 2032 BuildInstallCode(js_function, shared_info); | |
| 2033 } | |
| 2034 } | |
| 2035 } | |
| 2036 } | |
| 2037 | |
| 2038 | |
| 2039 template<> | 1843 template<> |
| 2040 HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() { | 1844 HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() { |
| 2041 Counters* counters = isolate()->counters(); | 1845 Counters* counters = isolate()->counters(); |
| 2042 Factory* factory = isolate()->factory(); | 1846 Factory* factory = isolate()->factory(); |
| 2043 HInstruction* empty_fixed_array = | 1847 HInstruction* empty_fixed_array = |
| 2044 Add<HConstant>(factory->empty_fixed_array()); | 1848 Add<HConstant>(factory->empty_fixed_array()); |
| 1849 HInstruction* empty_literals_array = |
| 1850 Add<HConstant>(factory->empty_literals_array()); |
| 2045 HValue* shared_info = GetParameter(0); | 1851 HValue* shared_info = GetParameter(0); |
| 2046 | 1852 |
| 2047 AddIncrementCounter(counters->fast_new_closure_total()); | 1853 AddIncrementCounter(counters->fast_new_closure_total()); |
| 2048 | 1854 |
| 2049 // Create a new closure from the given function info in new space | 1855 // Create a new closure from the given function info in new space |
| 2050 HValue* size = Add<HConstant>(JSFunction::kSize); | 1856 HValue* size = Add<HConstant>(JSFunction::kSize); |
| 2051 HInstruction* js_function = | 1857 HInstruction* js_function = |
| 2052 Add<HAllocate>(size, HType::JSObject(), NOT_TENURED, JS_FUNCTION_TYPE); | 1858 Add<HAllocate>(size, HType::JSObject(), NOT_TENURED, JS_FUNCTION_TYPE); |
| 2053 | 1859 |
| 2054 int map_index = Context::FunctionMapIndex(casted_stub()->language_mode(), | 1860 int map_index = Context::FunctionMapIndex(casted_stub()->language_mode(), |
| 2055 casted_stub()->kind()); | 1861 casted_stub()->kind()); |
| 2056 | 1862 |
| 2057 // Compute the function map in the current native context and set that | 1863 // Compute the function map in the current native context and set that |
| 2058 // as the map of the allocated object. | 1864 // as the map of the allocated object. |
| 2059 HInstruction* native_context = BuildGetNativeContext(); | 1865 HInstruction* native_context = BuildGetNativeContext(); |
| 2060 HInstruction* map_slot_value = Add<HLoadNamedField>( | 1866 HInstruction* map_slot_value = Add<HLoadNamedField>( |
| 2061 native_context, nullptr, HObjectAccess::ForContextSlot(map_index)); | 1867 native_context, nullptr, HObjectAccess::ForContextSlot(map_index)); |
| 2062 Add<HStoreNamedField>(js_function, HObjectAccess::ForMap(), map_slot_value); | 1868 Add<HStoreNamedField>(js_function, HObjectAccess::ForMap(), map_slot_value); |
| 2063 | 1869 |
| 2064 // Initialize the rest of the function. | 1870 // Initialize the rest of the function. |
| 2065 Add<HStoreNamedField>(js_function, HObjectAccess::ForPropertiesPointer(), | 1871 Add<HStoreNamedField>(js_function, HObjectAccess::ForPropertiesPointer(), |
| 2066 empty_fixed_array); | 1872 empty_fixed_array); |
| 2067 Add<HStoreNamedField>(js_function, HObjectAccess::ForElementsPointer(), | 1873 Add<HStoreNamedField>(js_function, HObjectAccess::ForElementsPointer(), |
| 2068 empty_fixed_array); | 1874 empty_fixed_array); |
| 2069 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), | 1875 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), |
| 2070 empty_fixed_array); | 1876 empty_literals_array); |
| 2071 Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(), | 1877 Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(), |
| 2072 graph()->GetConstantHole()); | 1878 graph()->GetConstantHole()); |
| 2073 Add<HStoreNamedField>( | 1879 Add<HStoreNamedField>( |
| 2074 js_function, HObjectAccess::ForSharedFunctionInfoPointer(), shared_info); | 1880 js_function, HObjectAccess::ForSharedFunctionInfoPointer(), shared_info); |
| 2075 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(), | 1881 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(), |
| 2076 context()); | 1882 context()); |
| 2077 | 1883 Handle<Code> lazy_builtin( |
| 2078 // Initialize the code pointer in the function to be the one found in the | 1884 isolate()->builtins()->builtin(Builtins::kCompileLazy)); |
| 2079 // shared function info object. But first check if there is an optimized | 1885 HConstant* lazy = Add<HConstant>(lazy_builtin); |
| 2080 // version for our context. | 1886 Add<HStoreCodeEntry>(js_function, lazy); |
| 2081 BuildInstallFromOptimizedCodeMap(js_function, shared_info, native_context); | 1887 Add<HStoreNamedField>(js_function, |
| 2082 | 1888 HObjectAccess::ForNextFunctionLinkPointer(), |
| 1889 graph()->GetConstantUndefined()); |
| 2083 return js_function; | 1890 return js_function; |
| 2084 } | 1891 } |
| 2085 | 1892 |
| 2086 | 1893 |
| 2087 Handle<Code> FastNewClosureStub::GenerateCode() { | 1894 Handle<Code> FastNewClosureStub::GenerateCode() { |
| 2088 return DoGenerateCode(this); | 1895 return DoGenerateCode(this); |
| 2089 } | 1896 } |
| 2090 | 1897 |
| 2091 | 1898 |
| 2092 template<> | 1899 template<> |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2426 return Pop(); | 2233 return Pop(); |
| 2427 } | 2234 } |
| 2428 | 2235 |
| 2429 | 2236 |
| 2430 Handle<Code> KeyedLoadGenericStub::GenerateCode() { | 2237 Handle<Code> KeyedLoadGenericStub::GenerateCode() { |
| 2431 return DoGenerateCode(this); | 2238 return DoGenerateCode(this); |
| 2432 } | 2239 } |
| 2433 | 2240 |
| 2434 } // namespace internal | 2241 } // namespace internal |
| 2435 } // namespace v8 | 2242 } // namespace v8 |
| OLD | NEW |