Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/ic/ic.cc

Issue 565873002: Removing ic.h from code-stubs.h (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: REBASE and mips. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic/ic.h ('k') | src/ic/ic-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/accessors.h" 7 #include "src/accessors.h"
8 #include "src/api.h" 8 #include "src/api.h"
9 #include "src/arguments.h" 9 #include "src/arguments.h"
10 #include "src/base/bits.h" 10 #include "src/base/bits.h"
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 isolate, StoreIC::GetStrictMode(target->extra_ic_state())), 545 isolate, StoreIC::GetStrictMode(target->extra_ic_state())),
546 constant_pool); 546 constant_pool);
547 } 547 }
548 548
549 549
550 void CompareIC::Clear(Isolate* isolate, Address address, Code* target, 550 void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
551 ConstantPoolArray* constant_pool) { 551 ConstantPoolArray* constant_pool) {
552 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC); 552 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC);
553 CompareICStub stub(target->stub_key(), isolate); 553 CompareICStub stub(target->stub_key(), isolate);
554 // Only clear CompareICs that can retain objects. 554 // Only clear CompareICs that can retain objects.
555 if (stub.state() != KNOWN_OBJECT) return; 555 if (stub.state() != CompareICState::KNOWN_OBJECT) return;
556 SetTargetAtAddress(address, GetRawUninitialized(isolate, stub.op()), 556 SetTargetAtAddress(address, GetRawUninitialized(isolate, stub.op()),
557 constant_pool); 557 constant_pool);
558 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); 558 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK);
559 } 559 }
560 560
561 561
562 // static 562 // static
563 Handle<Code> KeyedLoadIC::generic_stub(Isolate* isolate) { 563 Handle<Code> KeyedLoadIC::generic_stub(Isolate* isolate) {
564 if (FLAG_compiled_keyed_generic_loads) { 564 if (FLAG_compiled_keyed_generic_loads) {
565 return KeyedLoadGenericStub(isolate).GetCode(); 565 return KeyedLoadGenericStub(isolate).GetCode();
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
808 808
809 809
810 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, 810 Handle<Code> LoadIC::initialize_stub(Isolate* isolate,
811 ExtraICState extra_state) { 811 ExtraICState extra_state) {
812 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); 812 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state);
813 } 813 }
814 814
815 815
816 Handle<Code> LoadIC::megamorphic_stub() { 816 Handle<Code> LoadIC::megamorphic_stub() {
817 if (kind() == Code::LOAD_IC) { 817 if (kind() == Code::LOAD_IC) {
818 MegamorphicLoadStub stub(isolate(), State(extra_ic_state())); 818 MegamorphicLoadStub stub(isolate(), LoadICState(extra_ic_state()));
819 return stub.GetCode(); 819 return stub.GetCode();
820 } else { 820 } else {
821 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); 821 DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
822 return KeyedLoadIC::generic_stub(isolate()); 822 return KeyedLoadIC::generic_stub(isolate());
823 } 823 }
824 } 824 }
825 825
826 826
827 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, 827 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate,
828 ExtraICState extra_state) { 828 ExtraICState extra_state) {
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after
1332 1332
1333 // Set the property. 1333 // Set the property.
1334 Handle<Object> result; 1334 Handle<Object> result;
1335 ASSIGN_RETURN_ON_EXCEPTION( 1335 ASSIGN_RETURN_ON_EXCEPTION(
1336 isolate(), result, 1336 isolate(), result,
1337 Object::SetProperty(&it, value, strict_mode(), store_mode), Object); 1337 Object::SetProperty(&it, value, strict_mode(), store_mode), Object);
1338 return result; 1338 return result;
1339 } 1339 }
1340 1340
1341 1341
1342 OStream& operator<<(OStream& os, const CallIC::State& s) {
1343 return os << "(args(" << s.arg_count() << "), "
1344 << (s.call_type() == CallIC::METHOD ? "METHOD" : "FUNCTION")
1345 << ", ";
1346 }
1347
1348
1349 Handle<Code> CallIC::initialize_stub(Isolate* isolate, int argc, 1342 Handle<Code> CallIC::initialize_stub(Isolate* isolate, int argc,
1350 CallType call_type) { 1343 CallICState::CallType call_type) {
1351 CallICStub stub(isolate, State(argc, call_type)); 1344 CallICStub stub(isolate, CallICState(argc, call_type));
1352 Handle<Code> code = stub.GetCode(); 1345 Handle<Code> code = stub.GetCode();
1353 return code; 1346 return code;
1354 } 1347 }
1355 1348
1356 1349
1357 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, 1350 Handle<Code> StoreIC::initialize_stub(Isolate* isolate,
1358 StrictMode strict_mode) { 1351 StrictMode strict_mode) {
1359 ExtraICState extra_state = ComputeExtraICState(strict_mode); 1352 ExtraICState extra_state = ComputeExtraICState(strict_mode);
1360 Handle<Code> ic = 1353 Handle<Code> ic =
1361 PropertyICCompiler::ComputeStore(isolate, UNINITIALIZED, extra_state); 1354 PropertyICCompiler::ComputeStore(isolate, UNINITIALIZED, extra_state);
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after
1829 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); 1822 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
1830 } 1823 }
1831 DCHECK(!stub.is_null()); 1824 DCHECK(!stub.is_null());
1832 set_target(*stub); 1825 set_target(*stub);
1833 TRACE_IC("StoreIC", key); 1826 TRACE_IC("StoreIC", key);
1834 1827
1835 return store_handle; 1828 return store_handle;
1836 } 1829 }
1837 1830
1838 1831
1839 CallIC::State::State(ExtraICState extra_ic_state)
1840 : argc_(ArgcBits::decode(extra_ic_state)),
1841 call_type_(CallTypeBits::decode(extra_ic_state)) {}
1842
1843
1844 ExtraICState CallIC::State::GetExtraICState() const {
1845 ExtraICState extra_ic_state =
1846 ArgcBits::encode(argc_) | CallTypeBits::encode(call_type_);
1847 return extra_ic_state;
1848 }
1849
1850
1851 bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function, 1832 bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function,
1852 Handle<FixedArray> vector, Handle<Smi> slot, 1833 Handle<FixedArray> vector, Handle<Smi> slot,
1853 const State& state) { 1834 const CallICState& state) {
1854 DCHECK(FLAG_use_ic && function->IsJSFunction()); 1835 DCHECK(FLAG_use_ic && function->IsJSFunction());
1855 1836
1856 // Are we the array function? 1837 // Are we the array function?
1857 Handle<JSFunction> array_function = 1838 Handle<JSFunction> array_function =
1858 Handle<JSFunction>(isolate()->native_context()->array_function()); 1839 Handle<JSFunction>(isolate()->native_context()->array_function());
1859 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) { 1840 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) {
1860 // Alter the slot. 1841 // Alter the slot.
1861 IC::State old_state = FeedbackToState(vector, slot); 1842 IC::State old_state = FeedbackToState(vector, slot);
1862 Object* feedback = vector->get(slot->value()); 1843 Object* feedback = vector->get(slot->value());
1863 if (!feedback->IsAllocationSite()) { 1844 if (!feedback->IsAllocationSite()) {
(...skipping 14 matching lines...) Expand all
1878 OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true); 1859 OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
1879 TRACE_VECTOR_IC("CallIC (custom handler)", name, old_state, new_state); 1860 TRACE_VECTOR_IC("CallIC (custom handler)", name, old_state, new_state);
1880 return true; 1861 return true;
1881 } 1862 }
1882 return false; 1863 return false;
1883 } 1864 }
1884 1865
1885 1866
1886 void CallIC::PatchMegamorphic(Handle<Object> function, 1867 void CallIC::PatchMegamorphic(Handle<Object> function,
1887 Handle<FixedArray> vector, Handle<Smi> slot) { 1868 Handle<FixedArray> vector, Handle<Smi> slot) {
1888 State state(target()->extra_ic_state()); 1869 CallICState state(target()->extra_ic_state());
1889 IC::State old_state = FeedbackToState(vector, slot); 1870 IC::State old_state = FeedbackToState(vector, slot);
1890 1871
1891 // We are going generic. 1872 // We are going generic.
1892 vector->set(slot->value(), *TypeFeedbackInfo::MegamorphicSentinel(isolate()), 1873 vector->set(slot->value(), *TypeFeedbackInfo::MegamorphicSentinel(isolate()),
1893 SKIP_WRITE_BARRIER); 1874 SKIP_WRITE_BARRIER);
1894 1875
1895 CallICStub stub(isolate(), state); 1876 CallICStub stub(isolate(), state);
1896 Handle<Code> code = stub.GetCode(); 1877 Handle<Code> code = stub.GetCode();
1897 set_target(*code); 1878 set_target(*code);
1898 1879
1899 Handle<Object> name = isolate()->factory()->empty_string(); 1880 Handle<Object> name = isolate()->factory()->empty_string();
1900 if (function->IsJSFunction()) { 1881 if (function->IsJSFunction()) {
1901 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); 1882 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
1902 name = handle(js_function->shared()->name(), isolate()); 1883 name = handle(js_function->shared()->name(), isolate());
1903 } 1884 }
1904 1885
1905 IC::State new_state = FeedbackToState(vector, slot); 1886 IC::State new_state = FeedbackToState(vector, slot);
1906 OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true); 1887 OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
1907 TRACE_VECTOR_IC("CallIC", name, old_state, new_state); 1888 TRACE_VECTOR_IC("CallIC", name, old_state, new_state);
1908 } 1889 }
1909 1890
1910 1891
1911 void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function, 1892 void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function,
1912 Handle<FixedArray> vector, Handle<Smi> slot) { 1893 Handle<FixedArray> vector, Handle<Smi> slot) {
1913 State state(target()->extra_ic_state()); 1894 CallICState state(target()->extra_ic_state());
1914 IC::State old_state = FeedbackToState(vector, slot); 1895 IC::State old_state = FeedbackToState(vector, slot);
1915 Handle<Object> name = isolate()->factory()->empty_string(); 1896 Handle<Object> name = isolate()->factory()->empty_string();
1916 Object* feedback = vector->get(slot->value()); 1897 Object* feedback = vector->get(slot->value());
1917 1898
1918 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. 1899 // Hand-coded MISS handling is easier if CallIC slots don't contain smis.
1919 DCHECK(!feedback->IsSmi()); 1900 DCHECK(!feedback->IsSmi());
1920 1901
1921 if (feedback->IsJSFunction() || !function->IsJSFunction()) { 1902 if (feedback->IsJSFunction() || !function->IsJSFunction()) {
1922 // We are going generic. 1903 // We are going generic.
1923 vector->set(slot->value(), 1904 vector->set(slot->value(),
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
2166 map->elements_kind()); 2147 map->elements_kind());
2167 } 2148 }
2168 Handle<Object> result; 2149 Handle<Object> result;
2169 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2150 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2170 isolate, result, 2151 isolate, result,
2171 Runtime::SetObjectProperty(isolate, object, key, value, strict_mode)); 2152 Runtime::SetObjectProperty(isolate, object, key, value, strict_mode));
2172 return *result; 2153 return *result;
2173 } 2154 }
2174 2155
2175 2156
2176 BinaryOpIC::State::State(Isolate* isolate, ExtraICState extra_ic_state)
2177 : isolate_(isolate) {
2178 op_ =
2179 static_cast<Token::Value>(FIRST_TOKEN + OpField::decode(extra_ic_state));
2180 mode_ = OverwriteModeField::decode(extra_ic_state);
2181 fixed_right_arg_ =
2182 Maybe<int>(HasFixedRightArgField::decode(extra_ic_state),
2183 1 << FixedRightArgValueField::decode(extra_ic_state));
2184 left_kind_ = LeftKindField::decode(extra_ic_state);
2185 if (fixed_right_arg_.has_value) {
2186 right_kind_ = Smi::IsValid(fixed_right_arg_.value) ? SMI : INT32;
2187 } else {
2188 right_kind_ = RightKindField::decode(extra_ic_state);
2189 }
2190 result_kind_ = ResultKindField::decode(extra_ic_state);
2191 DCHECK_LE(FIRST_TOKEN, op_);
2192 DCHECK_LE(op_, LAST_TOKEN);
2193 }
2194
2195
2196 ExtraICState BinaryOpIC::State::GetExtraICState() const {
2197 ExtraICState extra_ic_state =
2198 OpField::encode(op_ - FIRST_TOKEN) | OverwriteModeField::encode(mode_) |
2199 LeftKindField::encode(left_kind_) |
2200 ResultKindField::encode(result_kind_) |
2201 HasFixedRightArgField::encode(fixed_right_arg_.has_value);
2202 if (fixed_right_arg_.has_value) {
2203 extra_ic_state = FixedRightArgValueField::update(
2204 extra_ic_state, WhichPowerOf2(fixed_right_arg_.value));
2205 } else {
2206 extra_ic_state = RightKindField::update(extra_ic_state, right_kind_);
2207 }
2208 return extra_ic_state;
2209 }
2210
2211
2212 // static
2213 void BinaryOpIC::State::GenerateAheadOfTime(Isolate* isolate,
2214 void (*Generate)(Isolate*,
2215 const State&)) {
2216 // TODO(olivf) We should investigate why adding stubs to the snapshot is so
2217 // expensive at runtime. When solved we should be able to add most binops to
2218 // the snapshot instead of hand-picking them.
2219 // Generated list of commonly used stubs
2220 #define GENERATE(op, left_kind, right_kind, result_kind, mode) \
2221 do { \
2222 State state(isolate, op, mode); \
2223 state.left_kind_ = left_kind; \
2224 state.fixed_right_arg_.has_value = false; \
2225 state.right_kind_ = right_kind; \
2226 state.result_kind_ = result_kind; \
2227 Generate(isolate, state); \
2228 } while (false)
2229 GENERATE(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE);
2230 GENERATE(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT);
2231 GENERATE(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE);
2232 GENERATE(Token::ADD, INT32, INT32, NUMBER, OVERWRITE_LEFT);
2233 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, NO_OVERWRITE);
2234 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
2235 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT);
2236 GENERATE(Token::ADD, INT32, SMI, INT32, NO_OVERWRITE);
2237 GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_LEFT);
2238 GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_RIGHT);
2239 GENERATE(Token::ADD, NUMBER, INT32, NUMBER, NO_OVERWRITE);
2240 GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
2241 GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT);
2242 GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
2243 GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
2244 GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
2245 GENERATE(Token::ADD, NUMBER, SMI, NUMBER, NO_OVERWRITE);
2246 GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2247 GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
2248 GENERATE(Token::ADD, SMI, INT32, INT32, NO_OVERWRITE);
2249 GENERATE(Token::ADD, SMI, INT32, INT32, OVERWRITE_LEFT);
2250 GENERATE(Token::ADD, SMI, INT32, NUMBER, NO_OVERWRITE);
2251 GENERATE(Token::ADD, SMI, NUMBER, NUMBER, NO_OVERWRITE);
2252 GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
2253 GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
2254 GENERATE(Token::ADD, SMI, SMI, INT32, OVERWRITE_LEFT);
2255 GENERATE(Token::ADD, SMI, SMI, SMI, OVERWRITE_RIGHT);
2256 GENERATE(Token::BIT_AND, INT32, INT32, INT32, NO_OVERWRITE);
2257 GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_LEFT);
2258 GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_RIGHT);
2259 GENERATE(Token::BIT_AND, INT32, INT32, SMI, NO_OVERWRITE);
2260 GENERATE(Token::BIT_AND, INT32, INT32, SMI, OVERWRITE_RIGHT);
2261 GENERATE(Token::BIT_AND, INT32, SMI, INT32, NO_OVERWRITE);
2262 GENERATE(Token::BIT_AND, INT32, SMI, INT32, OVERWRITE_RIGHT);
2263 GENERATE(Token::BIT_AND, INT32, SMI, SMI, NO_OVERWRITE);
2264 GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_LEFT);
2265 GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_RIGHT);
2266 GENERATE(Token::BIT_AND, NUMBER, INT32, INT32, OVERWRITE_RIGHT);
2267 GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, NO_OVERWRITE);
2268 GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
2269 GENERATE(Token::BIT_AND, SMI, INT32, INT32, NO_OVERWRITE);
2270 GENERATE(Token::BIT_AND, SMI, INT32, SMI, OVERWRITE_RIGHT);
2271 GENERATE(Token::BIT_AND, SMI, NUMBER, SMI, OVERWRITE_RIGHT);
2272 GENERATE(Token::BIT_AND, SMI, SMI, SMI, NO_OVERWRITE);
2273 GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_LEFT);
2274 GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_RIGHT);
2275 GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_LEFT);
2276 GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_RIGHT);
2277 GENERATE(Token::BIT_OR, INT32, INT32, SMI, OVERWRITE_LEFT);
2278 GENERATE(Token::BIT_OR, INT32, SMI, INT32, NO_OVERWRITE);
2279 GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_LEFT);
2280 GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_RIGHT);
2281 GENERATE(Token::BIT_OR, INT32, SMI, SMI, NO_OVERWRITE);
2282 GENERATE(Token::BIT_OR, INT32, SMI, SMI, OVERWRITE_RIGHT);
2283 GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, NO_OVERWRITE);
2284 GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_LEFT);
2285 GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_RIGHT);
2286 GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, NO_OVERWRITE);
2287 GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, OVERWRITE_LEFT);
2288 GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_LEFT);
2289 GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_RIGHT);
2290 GENERATE(Token::BIT_OR, SMI, INT32, SMI, OVERWRITE_RIGHT);
2291 GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_LEFT);
2292 GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_RIGHT);
2293 GENERATE(Token::BIT_XOR, INT32, INT32, INT32, NO_OVERWRITE);
2294 GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_LEFT);
2295 GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_RIGHT);
2296 GENERATE(Token::BIT_XOR, INT32, INT32, SMI, NO_OVERWRITE);
2297 GENERATE(Token::BIT_XOR, INT32, INT32, SMI, OVERWRITE_LEFT);
2298 GENERATE(Token::BIT_XOR, INT32, NUMBER, SMI, NO_OVERWRITE);
2299 GENERATE(Token::BIT_XOR, INT32, SMI, INT32, NO_OVERWRITE);
2300 GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_LEFT);
2301 GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_RIGHT);
2302 GENERATE(Token::BIT_XOR, NUMBER, INT32, INT32, NO_OVERWRITE);
2303 GENERATE(Token::BIT_XOR, NUMBER, SMI, INT32, NO_OVERWRITE);
2304 GENERATE(Token::BIT_XOR, NUMBER, SMI, SMI, NO_OVERWRITE);
2305 GENERATE(Token::BIT_XOR, SMI, INT32, INT32, NO_OVERWRITE);
2306 GENERATE(Token::BIT_XOR, SMI, INT32, INT32, OVERWRITE_LEFT);
2307 GENERATE(Token::BIT_XOR, SMI, INT32, SMI, OVERWRITE_LEFT);
2308 GENERATE(Token::BIT_XOR, SMI, SMI, SMI, NO_OVERWRITE);
2309 GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_LEFT);
2310 GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_RIGHT);
2311 GENERATE(Token::DIV, INT32, INT32, INT32, NO_OVERWRITE);
2312 GENERATE(Token::DIV, INT32, INT32, NUMBER, NO_OVERWRITE);
2313 GENERATE(Token::DIV, INT32, NUMBER, NUMBER, NO_OVERWRITE);
2314 GENERATE(Token::DIV, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
2315 GENERATE(Token::DIV, INT32, SMI, INT32, NO_OVERWRITE);
2316 GENERATE(Token::DIV, INT32, SMI, NUMBER, NO_OVERWRITE);
2317 GENERATE(Token::DIV, NUMBER, INT32, NUMBER, NO_OVERWRITE);
2318 GENERATE(Token::DIV, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
2319 GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
2320 GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
2321 GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
2322 GENERATE(Token::DIV, NUMBER, SMI, NUMBER, NO_OVERWRITE);
2323 GENERATE(Token::DIV, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2324 GENERATE(Token::DIV, SMI, INT32, INT32, NO_OVERWRITE);
2325 GENERATE(Token::DIV, SMI, INT32, NUMBER, NO_OVERWRITE);
2326 GENERATE(Token::DIV, SMI, INT32, NUMBER, OVERWRITE_LEFT);
2327 GENERATE(Token::DIV, SMI, NUMBER, NUMBER, NO_OVERWRITE);
2328 GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
2329 GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
2330 GENERATE(Token::DIV, SMI, SMI, NUMBER, NO_OVERWRITE);
2331 GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_LEFT);
2332 GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_RIGHT);
2333 GENERATE(Token::DIV, SMI, SMI, SMI, NO_OVERWRITE);
2334 GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_LEFT);
2335 GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_RIGHT);
2336 GENERATE(Token::MOD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2337 GENERATE(Token::MOD, SMI, SMI, SMI, NO_OVERWRITE);
2338 GENERATE(Token::MOD, SMI, SMI, SMI, OVERWRITE_LEFT);
2339 GENERATE(Token::MUL, INT32, INT32, INT32, NO_OVERWRITE);
2340 GENERATE(Token::MUL, INT32, INT32, NUMBER, NO_OVERWRITE);
2341 GENERATE(Token::MUL, INT32, NUMBER, NUMBER, NO_OVERWRITE);
2342 GENERATE(Token::MUL, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
2343 GENERATE(Token::MUL, INT32, SMI, INT32, NO_OVERWRITE);
2344 GENERATE(Token::MUL, INT32, SMI, INT32, OVERWRITE_LEFT);
2345 GENERATE(Token::MUL, INT32, SMI, NUMBER, NO_OVERWRITE);
2346 GENERATE(Token::MUL, NUMBER, INT32, NUMBER, NO_OVERWRITE);
2347 GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
2348 GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT);
2349 GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
2350 GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
2351 GENERATE(Token::MUL, NUMBER, SMI, NUMBER, NO_OVERWRITE);
2352 GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2353 GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
2354 GENERATE(Token::MUL, SMI, INT32, INT32, NO_OVERWRITE);
2355 GENERATE(Token::MUL, SMI, INT32, INT32, OVERWRITE_LEFT);
2356 GENERATE(Token::MUL, SMI, INT32, NUMBER, NO_OVERWRITE);
2357 GENERATE(Token::MUL, SMI, NUMBER, NUMBER, NO_OVERWRITE);
2358 GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
2359 GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
2360 GENERATE(Token::MUL, SMI, SMI, INT32, NO_OVERWRITE);
2361 GENERATE(Token::MUL, SMI, SMI, NUMBER, NO_OVERWRITE);
2362 GENERATE(Token::MUL, SMI, SMI, NUMBER, OVERWRITE_LEFT);
2363 GENERATE(Token::MUL, SMI, SMI, SMI, NO_OVERWRITE);
2364 GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_LEFT);
2365 GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_RIGHT);
2366 GENERATE(Token::SAR, INT32, SMI, INT32, OVERWRITE_RIGHT);
2367 GENERATE(Token::SAR, INT32, SMI, SMI, NO_OVERWRITE);
2368 GENERATE(Token::SAR, INT32, SMI, SMI, OVERWRITE_RIGHT);
2369 GENERATE(Token::SAR, NUMBER, SMI, SMI, NO_OVERWRITE);
2370 GENERATE(Token::SAR, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
2371 GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_LEFT);
2372 GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_RIGHT);
2373 GENERATE(Token::SHL, INT32, SMI, INT32, NO_OVERWRITE);
2374 GENERATE(Token::SHL, INT32, SMI, INT32, OVERWRITE_RIGHT);
2375 GENERATE(Token::SHL, INT32, SMI, SMI, NO_OVERWRITE);
2376 GENERATE(Token::SHL, INT32, SMI, SMI, OVERWRITE_RIGHT);
2377 GENERATE(Token::SHL, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
2378 GENERATE(Token::SHL, SMI, SMI, INT32, NO_OVERWRITE);
2379 GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_LEFT);
2380 GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_RIGHT);
2381 GENERATE(Token::SHL, SMI, SMI, SMI, NO_OVERWRITE);
2382 GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_LEFT);
2383 GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_RIGHT);
2384 GENERATE(Token::SHR, INT32, SMI, SMI, NO_OVERWRITE);
2385 GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_LEFT);
2386 GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_RIGHT);
2387 GENERATE(Token::SHR, NUMBER, SMI, SMI, NO_OVERWRITE);
2388 GENERATE(Token::SHR, NUMBER, SMI, SMI, OVERWRITE_LEFT);
2389 GENERATE(Token::SHR, NUMBER, SMI, INT32, OVERWRITE_RIGHT);
2390 GENERATE(Token::SHR, SMI, SMI, SMI, NO_OVERWRITE);
2391 GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_LEFT);
2392 GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_RIGHT);
2393 GENERATE(Token::SUB, INT32, INT32, INT32, NO_OVERWRITE);
2394 GENERATE(Token::SUB, INT32, INT32, INT32, OVERWRITE_LEFT);
2395 GENERATE(Token::SUB, INT32, NUMBER, NUMBER, NO_OVERWRITE);
2396 GENERATE(Token::SUB, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT);
2397 GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_LEFT);
2398 GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_RIGHT);
2399 GENERATE(Token::SUB, NUMBER, INT32, NUMBER, NO_OVERWRITE);
2400 GENERATE(Token::SUB, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
2401 GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
2402 GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
2403 GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
2404 GENERATE(Token::SUB, NUMBER, SMI, NUMBER, NO_OVERWRITE);
2405 GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2406 GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
2407 GENERATE(Token::SUB, SMI, INT32, INT32, NO_OVERWRITE);
2408 GENERATE(Token::SUB, SMI, NUMBER, NUMBER, NO_OVERWRITE);
2409 GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
2410 GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
2411 GENERATE(Token::SUB, SMI, SMI, SMI, NO_OVERWRITE);
2412 GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_LEFT);
2413 GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_RIGHT);
2414 #undef GENERATE
2415 #define GENERATE(op, left_kind, fixed_right_arg_value, result_kind, mode) \
2416 do { \
2417 State state(isolate, op, mode); \
2418 state.left_kind_ = left_kind; \
2419 state.fixed_right_arg_.has_value = true; \
2420 state.fixed_right_arg_.value = fixed_right_arg_value; \
2421 state.right_kind_ = SMI; \
2422 state.result_kind_ = result_kind; \
2423 Generate(isolate, state); \
2424 } while (false)
2425 GENERATE(Token::MOD, SMI, 2, SMI, NO_OVERWRITE);
2426 GENERATE(Token::MOD, SMI, 4, SMI, NO_OVERWRITE);
2427 GENERATE(Token::MOD, SMI, 4, SMI, OVERWRITE_LEFT);
2428 GENERATE(Token::MOD, SMI, 8, SMI, NO_OVERWRITE);
2429 GENERATE(Token::MOD, SMI, 16, SMI, OVERWRITE_LEFT);
2430 GENERATE(Token::MOD, SMI, 32, SMI, NO_OVERWRITE);
2431 GENERATE(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE);
2432 #undef GENERATE
2433 }
2434
2435
2436 Type* BinaryOpIC::State::GetResultType(Zone* zone) const {
2437 Kind result_kind = result_kind_;
2438 if (HasSideEffects()) {
2439 result_kind = NONE;
2440 } else if (result_kind == GENERIC && op_ == Token::ADD) {
2441 return Type::Union(Type::Number(zone), Type::String(zone), zone);
2442 } else if (result_kind == NUMBER && op_ == Token::SHR) {
2443 return Type::Unsigned32(zone);
2444 }
2445 DCHECK_NE(GENERIC, result_kind);
2446 return KindToType(result_kind, zone);
2447 }
2448
2449
2450 OStream& operator<<(OStream& os, const BinaryOpIC::State& s) {
2451 os << "(" << Token::Name(s.op_);
2452 if (s.mode_ == OVERWRITE_LEFT)
2453 os << "_ReuseLeft";
2454 else if (s.mode_ == OVERWRITE_RIGHT)
2455 os << "_ReuseRight";
2456 if (s.CouldCreateAllocationMementos()) os << "_CreateAllocationMementos";
2457 os << ":" << BinaryOpIC::State::KindToString(s.left_kind_) << "*";
2458 if (s.fixed_right_arg_.has_value) {
2459 os << s.fixed_right_arg_.value;
2460 } else {
2461 os << BinaryOpIC::State::KindToString(s.right_kind_);
2462 }
2463 return os << "->" << BinaryOpIC::State::KindToString(s.result_kind_) << ")";
2464 }
2465
2466
2467 void BinaryOpIC::State::Update(Handle<Object> left, Handle<Object> right,
2468 Handle<Object> result) {
2469 ExtraICState old_extra_ic_state = GetExtraICState();
2470
2471 left_kind_ = UpdateKind(left, left_kind_);
2472 right_kind_ = UpdateKind(right, right_kind_);
2473
2474 int32_t fixed_right_arg_value = 0;
2475 bool has_fixed_right_arg =
2476 op_ == Token::MOD && right->ToInt32(&fixed_right_arg_value) &&
2477 fixed_right_arg_value > 0 &&
2478 base::bits::IsPowerOfTwo32(fixed_right_arg_value) &&
2479 FixedRightArgValueField::is_valid(WhichPowerOf2(fixed_right_arg_value)) &&
2480 (left_kind_ == SMI || left_kind_ == INT32) &&
2481 (result_kind_ == NONE || !fixed_right_arg_.has_value);
2482 fixed_right_arg_ = Maybe<int32_t>(has_fixed_right_arg, fixed_right_arg_value);
2483
2484 result_kind_ = UpdateKind(result, result_kind_);
2485
2486 if (!Token::IsTruncatingBinaryOp(op_)) {
2487 Kind input_kind = Max(left_kind_, right_kind_);
2488 if (result_kind_ < input_kind && input_kind <= NUMBER) {
2489 result_kind_ = input_kind;
2490 }
2491 }
2492
2493 // We don't want to distinguish INT32 and NUMBER for string add (because
2494 // NumberToString can't make use of this anyway).
2495 if (left_kind_ == STRING && right_kind_ == INT32) {
2496 DCHECK_EQ(STRING, result_kind_);
2497 DCHECK_EQ(Token::ADD, op_);
2498 right_kind_ = NUMBER;
2499 } else if (right_kind_ == STRING && left_kind_ == INT32) {
2500 DCHECK_EQ(STRING, result_kind_);
2501 DCHECK_EQ(Token::ADD, op_);
2502 left_kind_ = NUMBER;
2503 }
2504
2505 // Reset overwrite mode unless we can actually make use of it, or may be able
2506 // to make use of it at some point in the future.
2507 if ((mode_ == OVERWRITE_LEFT && left_kind_ > NUMBER) ||
2508 (mode_ == OVERWRITE_RIGHT && right_kind_ > NUMBER) ||
2509 result_kind_ > NUMBER) {
2510 mode_ = NO_OVERWRITE;
2511 }
2512
2513 if (old_extra_ic_state == GetExtraICState()) {
2514 // Tagged operations can lead to non-truncating HChanges
2515 if (left->IsUndefined() || left->IsBoolean()) {
2516 left_kind_ = GENERIC;
2517 } else {
2518 DCHECK(right->IsUndefined() || right->IsBoolean());
2519 right_kind_ = GENERIC;
2520 }
2521 }
2522 }
2523
2524
2525 BinaryOpIC::State::Kind BinaryOpIC::State::UpdateKind(Handle<Object> object,
2526 Kind kind) const {
2527 Kind new_kind = GENERIC;
2528 bool is_truncating = Token::IsTruncatingBinaryOp(op());
2529 if (object->IsBoolean() && is_truncating) {
2530 // Booleans will be automatically truncated by HChange.
2531 new_kind = INT32;
2532 } else if (object->IsUndefined()) {
2533 // Undefined will be automatically truncated by HChange.
2534 new_kind = is_truncating ? INT32 : NUMBER;
2535 } else if (object->IsSmi()) {
2536 new_kind = SMI;
2537 } else if (object->IsHeapNumber()) {
2538 double value = Handle<HeapNumber>::cast(object)->value();
2539 new_kind = IsInt32Double(value) ? INT32 : NUMBER;
2540 } else if (object->IsString() && op() == Token::ADD) {
2541 new_kind = STRING;
2542 }
2543 if (new_kind == INT32 && SmiValuesAre32Bits()) {
2544 new_kind = NUMBER;
2545 }
2546 if (kind != NONE && ((new_kind <= NUMBER && kind > NUMBER) ||
2547 (new_kind > NUMBER && kind <= NUMBER))) {
2548 new_kind = GENERIC;
2549 }
2550 return Max(kind, new_kind);
2551 }
2552
2553
2554 // static
2555 const char* BinaryOpIC::State::KindToString(Kind kind) {
2556 switch (kind) {
2557 case NONE:
2558 return "None";
2559 case SMI:
2560 return "Smi";
2561 case INT32:
2562 return "Int32";
2563 case NUMBER:
2564 return "Number";
2565 case STRING:
2566 return "String";
2567 case GENERIC:
2568 return "Generic";
2569 }
2570 UNREACHABLE();
2571 return NULL;
2572 }
2573
2574
2575 // static
2576 Type* BinaryOpIC::State::KindToType(Kind kind, Zone* zone) {
2577 switch (kind) {
2578 case NONE:
2579 return Type::None(zone);
2580 case SMI:
2581 return Type::SignedSmall(zone);
2582 case INT32:
2583 return Type::Signed32(zone);
2584 case NUMBER:
2585 return Type::Number(zone);
2586 case STRING:
2587 return Type::String(zone);
2588 case GENERIC:
2589 return Type::Any(zone);
2590 }
2591 UNREACHABLE();
2592 return NULL;
2593 }
2594
2595
2596 MaybeHandle<Object> BinaryOpIC::Transition( 2157 MaybeHandle<Object> BinaryOpIC::Transition(
2597 Handle<AllocationSite> allocation_site, Handle<Object> left, 2158 Handle<AllocationSite> allocation_site, Handle<Object> left,
2598 Handle<Object> right) { 2159 Handle<Object> right) {
2599 State state(isolate(), target()->extra_ic_state()); 2160 BinaryOpICState state(isolate(), target()->extra_ic_state());
2600 2161
2601 // Compute the actual result using the builtin for the binary operation. 2162 // Compute the actual result using the builtin for the binary operation.
2602 Object* builtin = isolate()->js_builtins_object()->javascript_builtin( 2163 Object* builtin = isolate()->js_builtins_object()->javascript_builtin(
2603 TokenToJSBuiltin(state.op())); 2164 TokenToJSBuiltin(state.op()));
2604 Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate()); 2165 Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate());
2605 Handle<Object> result; 2166 Handle<Object> result;
2606 ASSIGN_RETURN_ON_EXCEPTION( 2167 ASSIGN_RETURN_ON_EXCEPTION(
2607 isolate(), result, Execution::Call(isolate(), function, left, 1, &right), 2168 isolate(), result, Execution::Call(isolate(), function, left, 1, &right),
2608 Object); 2169 Object);
2609 2170
2610 // Execution::Call can execute arbitrary JavaScript, hence potentially 2171 // Execution::Call can execute arbitrary JavaScript, hence potentially
2611 // update the state of this very IC, so we must update the stored state. 2172 // update the state of this very IC, so we must update the stored state.
2612 UpdateTarget(); 2173 UpdateTarget();
2613 // Compute the new state. 2174 // Compute the new state.
2614 State old_state(isolate(), target()->extra_ic_state()); 2175 BinaryOpICState old_state(isolate(), target()->extra_ic_state());
2615 state.Update(left, right, result); 2176 state.Update(left, right, result);
2616 2177
2617 // Check if we have a string operation here. 2178 // Check if we have a string operation here.
2618 Handle<Code> target; 2179 Handle<Code> target;
2619 if (!allocation_site.is_null() || state.ShouldCreateAllocationMementos()) { 2180 if (!allocation_site.is_null() || state.ShouldCreateAllocationMementos()) {
2620 // Setup the allocation site on-demand. 2181 // Setup the allocation site on-demand.
2621 if (allocation_site.is_null()) { 2182 if (allocation_site.is_null()) {
2622 allocation_site = isolate()->factory()->NewAllocationSite(); 2183 allocation_site = isolate()->factory()->NewAllocationSite();
2623 } 2184 }
2624 2185
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2686 args.at<Object>(BinaryOpWithAllocationSiteStub::kRight); 2247 args.at<Object>(BinaryOpWithAllocationSiteStub::kRight);
2687 BinaryOpIC ic(isolate); 2248 BinaryOpIC ic(isolate);
2688 Handle<Object> result; 2249 Handle<Object> result;
2689 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2250 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2690 isolate, result, ic.Transition(allocation_site, left, right)); 2251 isolate, result, ic.Transition(allocation_site, left, right));
2691 return *result; 2252 return *result;
2692 } 2253 }
2693 2254
2694 2255
2695 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { 2256 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
2696 CompareICStub stub(isolate, op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); 2257 CompareICStub stub(isolate, op, CompareICState::UNINITIALIZED,
2258 CompareICState::UNINITIALIZED,
2259 CompareICState::UNINITIALIZED);
2697 Code* code = NULL; 2260 Code* code = NULL;
2698 CHECK(stub.FindCodeInCache(&code)); 2261 CHECK(stub.FindCodeInCache(&code));
2699 return code; 2262 return code;
2700 } 2263 }
2701 2264
2702 2265
2703 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { 2266 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) {
2704 CompareICStub stub(isolate, op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); 2267 CompareICStub stub(isolate, op, CompareICState::UNINITIALIZED,
2268 CompareICState::UNINITIALIZED,
2269 CompareICState::UNINITIALIZED);
2705 return stub.GetCode(); 2270 return stub.GetCode();
2706 } 2271 }
2707 2272
2708 2273
2709 const char* CompareIC::GetStateName(State state) {
2710 switch (state) {
2711 case UNINITIALIZED:
2712 return "UNINITIALIZED";
2713 case SMI:
2714 return "SMI";
2715 case NUMBER:
2716 return "NUMBER";
2717 case INTERNALIZED_STRING:
2718 return "INTERNALIZED_STRING";
2719 case STRING:
2720 return "STRING";
2721 case UNIQUE_NAME:
2722 return "UNIQUE_NAME";
2723 case OBJECT:
2724 return "OBJECT";
2725 case KNOWN_OBJECT:
2726 return "KNOWN_OBJECT";
2727 case GENERIC:
2728 return "GENERIC";
2729 }
2730 UNREACHABLE();
2731 return NULL;
2732 }
2733
2734
2735 Type* CompareIC::StateToType(Zone* zone, CompareIC::State state,
2736 Handle<Map> map) {
2737 switch (state) {
2738 case CompareIC::UNINITIALIZED:
2739 return Type::None(zone);
2740 case CompareIC::SMI:
2741 return Type::SignedSmall(zone);
2742 case CompareIC::NUMBER:
2743 return Type::Number(zone);
2744 case CompareIC::STRING:
2745 return Type::String(zone);
2746 case CompareIC::INTERNALIZED_STRING:
2747 return Type::InternalizedString(zone);
2748 case CompareIC::UNIQUE_NAME:
2749 return Type::UniqueName(zone);
2750 case CompareIC::OBJECT:
2751 return Type::Receiver(zone);
2752 case CompareIC::KNOWN_OBJECT:
2753 return map.is_null() ? Type::Receiver(zone) : Type::Class(map, zone);
2754 case CompareIC::GENERIC:
2755 return Type::Any(zone);
2756 }
2757 UNREACHABLE();
2758 return NULL;
2759 }
2760
2761
2762 CompareIC::State CompareIC::NewInputState(State old_state,
2763 Handle<Object> value) {
2764 switch (old_state) {
2765 case UNINITIALIZED:
2766 if (value->IsSmi()) return SMI;
2767 if (value->IsHeapNumber()) return NUMBER;
2768 if (value->IsInternalizedString()) return INTERNALIZED_STRING;
2769 if (value->IsString()) return STRING;
2770 if (value->IsSymbol()) return UNIQUE_NAME;
2771 if (value->IsJSObject()) return OBJECT;
2772 break;
2773 case SMI:
2774 if (value->IsSmi()) return SMI;
2775 if (value->IsHeapNumber()) return NUMBER;
2776 break;
2777 case NUMBER:
2778 if (value->IsNumber()) return NUMBER;
2779 break;
2780 case INTERNALIZED_STRING:
2781 if (value->IsInternalizedString()) return INTERNALIZED_STRING;
2782 if (value->IsString()) return STRING;
2783 if (value->IsSymbol()) return UNIQUE_NAME;
2784 break;
2785 case STRING:
2786 if (value->IsString()) return STRING;
2787 break;
2788 case UNIQUE_NAME:
2789 if (value->IsUniqueName()) return UNIQUE_NAME;
2790 break;
2791 case OBJECT:
2792 if (value->IsJSObject()) return OBJECT;
2793 break;
2794 case GENERIC:
2795 break;
2796 case KNOWN_OBJECT:
2797 UNREACHABLE();
2798 break;
2799 }
2800 return GENERIC;
2801 }
2802
2803
2804 CompareIC::State CompareIC::TargetState(State old_state, State old_left,
2805 State old_right,
2806 bool has_inlined_smi_code,
2807 Handle<Object> x, Handle<Object> y) {
2808 switch (old_state) {
2809 case UNINITIALIZED:
2810 if (x->IsSmi() && y->IsSmi()) return SMI;
2811 if (x->IsNumber() && y->IsNumber()) return NUMBER;
2812 if (Token::IsOrderedRelationalCompareOp(op_)) {
2813 // Ordered comparisons treat undefined as NaN, so the
2814 // NUMBER stub will do the right thing.
2815 if ((x->IsNumber() && y->IsUndefined()) ||
2816 (y->IsNumber() && x->IsUndefined())) {
2817 return NUMBER;
2818 }
2819 }
2820 if (x->IsInternalizedString() && y->IsInternalizedString()) {
2821 // We compare internalized strings as plain ones if we need to determine
2822 // the order in a non-equality compare.
2823 return Token::IsEqualityOp(op_) ? INTERNALIZED_STRING : STRING;
2824 }
2825 if (x->IsString() && y->IsString()) return STRING;
2826 if (!Token::IsEqualityOp(op_)) return GENERIC;
2827 if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
2828 if (x->IsJSObject() && y->IsJSObject()) {
2829 if (Handle<JSObject>::cast(x)->map() ==
2830 Handle<JSObject>::cast(y)->map()) {
2831 return KNOWN_OBJECT;
2832 } else {
2833 return OBJECT;
2834 }
2835 }
2836 return GENERIC;
2837 case SMI:
2838 return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC;
2839 case INTERNALIZED_STRING:
2840 DCHECK(Token::IsEqualityOp(op_));
2841 if (x->IsString() && y->IsString()) return STRING;
2842 if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
2843 return GENERIC;
2844 case NUMBER:
2845 // If the failure was due to one side changing from smi to heap number,
2846 // then keep the state (if other changed at the same time, we will get
2847 // a second miss and then go to generic).
2848 if (old_left == SMI && x->IsHeapNumber()) return NUMBER;
2849 if (old_right == SMI && y->IsHeapNumber()) return NUMBER;
2850 return GENERIC;
2851 case KNOWN_OBJECT:
2852 DCHECK(Token::IsEqualityOp(op_));
2853 if (x->IsJSObject() && y->IsJSObject()) return OBJECT;
2854 return GENERIC;
2855 case STRING:
2856 case UNIQUE_NAME:
2857 case OBJECT:
2858 case GENERIC:
2859 return GENERIC;
2860 }
2861 UNREACHABLE();
2862 return GENERIC; // Make the compiler happy.
2863 }
2864
2865
2866 Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { 2274 Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
2867 HandleScope scope(isolate()); 2275 HandleScope scope(isolate());
2868 CompareICStub old_stub(target()->stub_key(), isolate()); 2276 CompareICStub old_stub(target()->stub_key(), isolate());
2869 State new_left = NewInputState(old_stub.left(), x); 2277 CompareICState::State new_left =
2870 State new_right = NewInputState(old_stub.right(), y); 2278 CompareICState::NewInputState(old_stub.left(), x);
2871 State state = TargetState(old_stub.state(), old_stub.left(), old_stub.right(), 2279 CompareICState::State new_right =
2872 HasInlinedSmiCode(address()), x, y); 2280 CompareICState::NewInputState(old_stub.right(), y);
2281 CompareICState::State state = CompareICState::TargetState(
2282 old_stub.state(), old_stub.left(), old_stub.right(), op_,
2283 HasInlinedSmiCode(address()), x, y);
2873 CompareICStub stub(isolate(), op_, new_left, new_right, state); 2284 CompareICStub stub(isolate(), op_, new_left, new_right, state);
2874 if (state == KNOWN_OBJECT) { 2285 if (state == CompareICState::KNOWN_OBJECT) {
2875 stub.set_known_map( 2286 stub.set_known_map(
2876 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); 2287 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate()));
2877 } 2288 }
2878 Handle<Code> new_target = stub.GetCode(); 2289 Handle<Code> new_target = stub.GetCode();
2879 set_target(*new_target); 2290 set_target(*new_target);
2880 2291
2881 if (FLAG_trace_ic) { 2292 if (FLAG_trace_ic) {
2882 PrintF("[CompareIC in "); 2293 PrintF("[CompareIC in ");
2883 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); 2294 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2884 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", 2295 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n",
2885 GetStateName(old_stub.left()), GetStateName(old_stub.right()), 2296 CompareICState::GetStateName(old_stub.left()),
2886 GetStateName(old_stub.state()), GetStateName(new_left), 2297 CompareICState::GetStateName(old_stub.right()),
2887 GetStateName(new_right), GetStateName(state), Token::Name(op_), 2298 CompareICState::GetStateName(old_stub.state()),
2299 CompareICState::GetStateName(new_left),
2300 CompareICState::GetStateName(new_right),
2301 CompareICState::GetStateName(state), Token::Name(op_),
2888 static_cast<void*>(*stub.GetCode())); 2302 static_cast<void*>(*stub.GetCode()));
2889 } 2303 }
2890 2304
2891 // Activate inlined smi code. 2305 // Activate inlined smi code.
2892 if (old_stub.state() == UNINITIALIZED) { 2306 if (old_stub.state() == CompareICState::UNINITIALIZED) {
2893 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); 2307 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2894 } 2308 }
2895 2309
2896 return *new_target; 2310 return *new_target;
2897 } 2311 }
2898 2312
2899 2313
2900 // Used from CompareICStub::GenerateMiss in code-stubs-<arch>.cc. 2314 // Used from CompareICStub::GenerateMiss in code-stubs-<arch>.cc.
2901 RUNTIME_FUNCTION(CompareIC_Miss) { 2315 RUNTIME_FUNCTION(CompareIC_Miss) {
2902 TimerEventScope<TimerEventIcMiss> timer(isolate); 2316 TimerEventScope<TimerEventIcMiss> timer(isolate);
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
3205 static const Address IC_utilities[] = { 2619 static const Address IC_utilities[] = {
3206 #define ADDR(name) FUNCTION_ADDR(name), 2620 #define ADDR(name) FUNCTION_ADDR(name),
3207 IC_UTIL_LIST(ADDR) NULL 2621 IC_UTIL_LIST(ADDR) NULL
3208 #undef ADDR 2622 #undef ADDR
3209 }; 2623 };
3210 2624
3211 2625
3212 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } 2626 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; }
3213 } 2627 }
3214 } // namespace v8::internal 2628 } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic/ic.h ('k') | src/ic/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698