| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 1187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1198 Handle<String> name, | 1198 Handle<String> name, |
| 1199 Handle<Object> unused, | 1199 Handle<Object> unused, |
| 1200 InlineCacheHolderFlag cache_holder) { | 1200 InlineCacheHolderFlag cache_holder) { |
| 1201 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) { | 1201 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) { |
| 1202 int length_index = String::kLengthOffset / kPointerSize; | 1202 int length_index = String::kLengthOffset / kPointerSize; |
| 1203 return SimpleFieldLoad(length_index); | 1203 return SimpleFieldLoad(length_index); |
| 1204 } | 1204 } |
| 1205 | 1205 |
| 1206 Handle<Type> type = CurrentTypeOf(object, isolate()); | 1206 Handle<Type> type = CurrentTypeOf(object, isolate()); |
| 1207 Handle<JSObject> holder(lookup->holder()); | 1207 Handle<JSObject> holder(lookup->holder()); |
| 1208 LoadStubCompiler compiler(isolate(), cache_holder, kind()); | 1208 LoadStubCompiler compiler(isolate(), kNoExtraICState, cache_holder, kind()); |
| 1209 | 1209 |
| 1210 switch (lookup->type()) { | 1210 switch (lookup->type()) { |
| 1211 case FIELD: { | 1211 case FIELD: { |
| 1212 PropertyIndex field = lookup->GetFieldIndex(); | 1212 PropertyIndex field = lookup->GetFieldIndex(); |
| 1213 if (object.is_identical_to(holder)) { | 1213 if (object.is_identical_to(holder)) { |
| 1214 return SimpleFieldLoad(field.translate(holder), | 1214 return SimpleFieldLoad(field.translate(holder), |
| 1215 field.is_inobject(holder), | 1215 field.is_inobject(holder), |
| 1216 lookup->representation()); | 1216 lookup->representation()); |
| 1217 } | 1217 } |
| 1218 return compiler.CompileLoadField( | 1218 return compiler.CompileLoadField( |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1447 receiver->LocalLookupRealNamedProperty(*name, lookup); | 1447 receiver->LocalLookupRealNamedProperty(*name, lookup); |
| 1448 return lookup->IsFound() && | 1448 return lookup->IsFound() && |
| 1449 !lookup->IsReadOnly() && | 1449 !lookup->IsReadOnly() && |
| 1450 lookup->CanHoldValue(value) && | 1450 lookup->CanHoldValue(value) && |
| 1451 lookup->IsCacheable(); | 1451 lookup->IsCacheable(); |
| 1452 } | 1452 } |
| 1453 return lookup->CanHoldValue(value); | 1453 return lookup->CanHoldValue(value); |
| 1454 } | 1454 } |
| 1455 | 1455 |
| 1456 if (lookup->IsPropertyCallbacks()) return true; | 1456 if (lookup->IsPropertyCallbacks()) return true; |
| 1457 | 1457 // JSGlobalProxy always goes via the runtime, so it's safe to cache. |
| 1458 if (receiver->IsJSGlobalProxy()) return true; |
| 1458 // Currently normal holders in the prototype chain are not supported. They | 1459 // Currently normal holders in the prototype chain are not supported. They |
| 1459 // would require a runtime positive lookup and verification that the details | 1460 // would require a runtime positive lookup and verification that the details |
| 1460 // have not changed. | 1461 // have not changed. |
| 1461 if (lookup->IsInterceptor() || lookup->IsNormal()) return false; | 1462 if (lookup->IsInterceptor() || lookup->IsNormal()) return false; |
| 1462 holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); | 1463 holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); |
| 1463 } | 1464 } |
| 1464 | 1465 |
| 1465 // While normally LookupTransition gets passed the receiver, in this case we | 1466 // While normally LookupTransition gets passed the receiver, in this case we |
| 1466 // pass the holder of the property that we overwrite. This keeps the holder in | 1467 // pass the holder of the property that we overwrite. This keeps the holder in |
| 1467 // the LookupResult intact so we can later use it to generate a prototype | 1468 // the LookupResult intact so we can later use it to generate a prototype |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1554 Handle<Code> stub = | 1555 Handle<Code> stub = |
| 1555 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); | 1556 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); |
| 1556 set_target(*stub); | 1557 set_target(*stub); |
| 1557 TRACE_IC("StoreIC", name); | 1558 TRACE_IC("StoreIC", name); |
| 1558 Handle<Object> result = JSReceiver::SetProperty( | 1559 Handle<Object> result = JSReceiver::SetProperty( |
| 1559 receiver, name, value, NONE, strict_mode(), store_mode); | 1560 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1560 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1561 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1561 return *result; | 1562 return *result; |
| 1562 } | 1563 } |
| 1563 | 1564 |
| 1564 if (receiver->IsJSGlobalProxy()) { | |
| 1565 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { | |
| 1566 // Generate a generic stub that goes to the runtime when we see a global | |
| 1567 // proxy as receiver. | |
| 1568 Handle<Code> stub = global_proxy_stub(); | |
| 1569 set_target(*stub); | |
| 1570 TRACE_IC("StoreIC", name); | |
| 1571 } | |
| 1572 Handle<Object> result = JSReceiver::SetProperty( | |
| 1573 receiver, name, value, NONE, strict_mode(), store_mode); | |
| 1574 RETURN_IF_EMPTY_HANDLE(isolate(), result); | |
| 1575 return *result; | |
| 1576 } | |
| 1577 | |
| 1578 LookupResult lookup(isolate()); | 1565 LookupResult lookup(isolate()); |
| 1579 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); | 1566 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); |
| 1580 if (!can_store && | 1567 if (!can_store && |
| 1581 strict_mode() == kStrictMode && | 1568 strict_mode() == kStrictMode && |
| 1582 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1569 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
| 1583 IsUndeclaredGlobal(object)) { | 1570 IsUndeclaredGlobal(object)) { |
| 1584 // Strict mode doesn't allow setting non-existent global property. | 1571 // Strict mode doesn't allow setting non-existent global property. |
| 1585 return ReferenceError("not_defined", name); | 1572 return ReferenceError("not_defined", name); |
| 1586 } | 1573 } |
| 1587 if (FLAG_use_ic) { | 1574 if (FLAG_use_ic) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1604 receiver, name, value, NONE, strict_mode(), store_mode); | 1591 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1605 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1592 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1606 return *result; | 1593 return *result; |
| 1607 } | 1594 } |
| 1608 | 1595 |
| 1609 | 1596 |
| 1610 void StoreIC::UpdateCaches(LookupResult* lookup, | 1597 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1611 Handle<JSObject> receiver, | 1598 Handle<JSObject> receiver, |
| 1612 Handle<String> name, | 1599 Handle<String> name, |
| 1613 Handle<Object> value) { | 1600 Handle<Object> value) { |
| 1614 ASSERT(!receiver->IsJSGlobalProxy()); | |
| 1615 ASSERT(lookup->IsFound()); | 1601 ASSERT(lookup->IsFound()); |
| 1616 | 1602 |
| 1617 // These are not cacheable, so we never see such LookupResults here. | 1603 // These are not cacheable, so we never see such LookupResults here. |
| 1618 ASSERT(!lookup->IsHandler()); | 1604 ASSERT(!lookup->IsHandler()); |
| 1619 | 1605 |
| 1620 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); | 1606 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); |
| 1621 | 1607 |
| 1622 PatchCache(CurrentTypeOf(receiver, isolate()), name, code); | 1608 PatchCache(CurrentTypeOf(receiver, isolate()), name, code); |
| 1623 TRACE_IC("StoreIC", name); | 1609 TRACE_IC("StoreIC", name); |
| 1624 } | 1610 } |
| 1625 | 1611 |
| 1626 | 1612 |
| 1627 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, | 1613 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, |
| 1628 Handle<Object> object, | 1614 Handle<Object> object, |
| 1629 Handle<String> name, | 1615 Handle<String> name, |
| 1630 Handle<Object> value, | 1616 Handle<Object> value, |
| 1631 InlineCacheHolderFlag cache_holder) { | 1617 InlineCacheHolderFlag cache_holder) { |
| 1618 if (object->IsJSGlobalProxy()) return slow_stub(); |
| 1632 ASSERT(cache_holder == OWN_MAP); | 1619 ASSERT(cache_holder == OWN_MAP); |
| 1633 // This is currently guaranteed by checks in StoreIC::Store. | 1620 // This is currently guaranteed by checks in StoreIC::Store. |
| 1634 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1621 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1635 | 1622 |
| 1636 Handle<JSObject> holder(lookup->holder()); | 1623 Handle<JSObject> holder(lookup->holder()); |
| 1637 // Handlers do not use strict mode. | 1624 // Handlers do not use strict mode. |
| 1638 StoreStubCompiler compiler(isolate(), kNonStrictMode, kind()); | 1625 StoreStubCompiler compiler(isolate(), kNonStrictMode, kind()); |
| 1639 switch (lookup->type()) { | 1626 switch (lookup->type()) { |
| 1640 case FIELD: | 1627 case FIELD: |
| 1641 return compiler.CompileStoreField(receiver, lookup, name); | 1628 return compiler.CompileStoreField(receiver, lookup, name); |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2323 } | 2310 } |
| 2324 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key, | 2311 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key, |
| 2325 value, | 2312 value, |
| 2326 NONE, | 2313 NONE, |
| 2327 strict_mode); | 2314 strict_mode); |
| 2328 RETURN_IF_EMPTY_HANDLE(isolate, result); | 2315 RETURN_IF_EMPTY_HANDLE(isolate, result); |
| 2329 return *result; | 2316 return *result; |
| 2330 } | 2317 } |
| 2331 | 2318 |
| 2332 | 2319 |
| 2333 const char* BinaryOpIC::GetName(TypeInfo type_info) { | 2320 BinaryOpIC::State::State(ExtraICState extra_ic_state) { |
| 2334 switch (type_info) { | 2321 // We don't deserialize the SSE2 Field, since this is only used to be able |
| 2335 case UNINITIALIZED: return "Uninitialized"; | 2322 // to include SSE2 as well as non-SSE2 versions in the snapshot. For code |
| 2323 // generation we always want it to reflect the current state. |
| 2324 op_ = static_cast<Token::Value>( |
| 2325 FIRST_TOKEN + OpField::decode(extra_ic_state)); |
| 2326 mode_ = OverwriteModeField::decode(extra_ic_state); |
| 2327 fixed_right_arg_ = Maybe<int>( |
| 2328 HasFixedRightArgField::decode(extra_ic_state), |
| 2329 1 << FixedRightArgValueField::decode(extra_ic_state)); |
| 2330 left_kind_ = LeftKindField::decode(extra_ic_state); |
| 2331 if (fixed_right_arg_.has_value) { |
| 2332 right_kind_ = Smi::IsValid(fixed_right_arg_.value) ? SMI : INT32; |
| 2333 } else { |
| 2334 right_kind_ = RightKindField::decode(extra_ic_state); |
| 2335 } |
| 2336 result_kind_ = ResultKindField::decode(extra_ic_state); |
| 2337 ASSERT_LE(FIRST_TOKEN, op_); |
| 2338 ASSERT_LE(op_, LAST_TOKEN); |
| 2339 } |
| 2340 |
| 2341 |
| 2342 ExtraICState BinaryOpIC::State::GetExtraICState() const { |
| 2343 bool sse2 = (Max(result_kind_, Max(left_kind_, right_kind_)) > SMI && |
| 2344 CpuFeatures::IsSafeForSnapshot(SSE2)); |
| 2345 ExtraICState extra_ic_state = |
| 2346 SSE2Field::encode(sse2) | |
| 2347 OpField::encode(op_ - FIRST_TOKEN) | |
| 2348 OverwriteModeField::encode(mode_) | |
| 2349 LeftKindField::encode(left_kind_) | |
| 2350 ResultKindField::encode(result_kind_) | |
| 2351 HasFixedRightArgField::encode(fixed_right_arg_.has_value); |
| 2352 if (fixed_right_arg_.has_value) { |
| 2353 extra_ic_state = FixedRightArgValueField::update( |
| 2354 extra_ic_state, WhichPowerOf2(fixed_right_arg_.value)); |
| 2355 } else { |
| 2356 extra_ic_state = RightKindField::update(extra_ic_state, right_kind_); |
| 2357 } |
| 2358 return extra_ic_state; |
| 2359 } |
| 2360 |
| 2361 |
| 2362 // static |
| 2363 void BinaryOpIC::State::GenerateAheadOfTime( |
| 2364 Isolate* isolate, void (*Generate)(Isolate*, const State&)) { |
| 2365 // TODO(olivf) We should investigate why adding stubs to the snapshot is so |
| 2366 // expensive at runtime. When solved we should be able to add most binops to |
| 2367 // the snapshot instead of hand-picking them. |
| 2368 // Generated list of commonly used stubs |
| 2369 #define GENERATE(op, left_kind, right_kind, result_kind, mode) \ |
| 2370 do { \ |
| 2371 State state(op, mode); \ |
| 2372 state.left_kind_ = left_kind; \ |
| 2373 state.fixed_right_arg_.has_value = false; \ |
| 2374 state.right_kind_ = right_kind; \ |
| 2375 state.result_kind_ = result_kind; \ |
| 2376 Generate(isolate, state); \ |
| 2377 } while (false) |
| 2378 GENERATE(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE); |
| 2379 GENERATE(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT); |
| 2380 GENERATE(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE); |
| 2381 GENERATE(Token::ADD, INT32, INT32, NUMBER, OVERWRITE_LEFT); |
| 2382 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, NO_OVERWRITE); |
| 2383 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_LEFT); |
| 2384 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT); |
| 2385 GENERATE(Token::ADD, INT32, SMI, INT32, NO_OVERWRITE); |
| 2386 GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_LEFT); |
| 2387 GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_RIGHT); |
| 2388 GENERATE(Token::ADD, NUMBER, INT32, NUMBER, NO_OVERWRITE); |
| 2389 GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_LEFT); |
| 2390 GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT); |
| 2391 GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, NO_OVERWRITE); |
| 2392 GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT); |
| 2393 GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT); |
| 2394 GENERATE(Token::ADD, NUMBER, SMI, NUMBER, NO_OVERWRITE); |
| 2395 GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT); |
| 2396 GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT); |
| 2397 GENERATE(Token::ADD, SMI, INT32, INT32, NO_OVERWRITE); |
| 2398 GENERATE(Token::ADD, SMI, INT32, INT32, OVERWRITE_LEFT); |
| 2399 GENERATE(Token::ADD, SMI, INT32, NUMBER, NO_OVERWRITE); |
| 2400 GENERATE(Token::ADD, SMI, NUMBER, NUMBER, NO_OVERWRITE); |
| 2401 GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_LEFT); |
| 2402 GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT); |
| 2403 GENERATE(Token::ADD, SMI, SMI, INT32, OVERWRITE_LEFT); |
| 2404 GENERATE(Token::ADD, SMI, SMI, SMI, OVERWRITE_RIGHT); |
| 2405 GENERATE(Token::BIT_AND, INT32, INT32, INT32, NO_OVERWRITE); |
| 2406 GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_LEFT); |
| 2407 GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_RIGHT); |
| 2408 GENERATE(Token::BIT_AND, INT32, INT32, SMI, NO_OVERWRITE); |
| 2409 GENERATE(Token::BIT_AND, INT32, INT32, SMI, OVERWRITE_RIGHT); |
| 2410 GENERATE(Token::BIT_AND, INT32, SMI, INT32, NO_OVERWRITE); |
| 2411 GENERATE(Token::BIT_AND, INT32, SMI, INT32, OVERWRITE_RIGHT); |
| 2412 GENERATE(Token::BIT_AND, INT32, SMI, SMI, NO_OVERWRITE); |
| 2413 GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_LEFT); |
| 2414 GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_RIGHT); |
| 2415 GENERATE(Token::BIT_AND, NUMBER, INT32, INT32, OVERWRITE_RIGHT); |
| 2416 GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, NO_OVERWRITE); |
| 2417 GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, OVERWRITE_RIGHT); |
| 2418 GENERATE(Token::BIT_AND, SMI, INT32, INT32, NO_OVERWRITE); |
| 2419 GENERATE(Token::BIT_AND, SMI, INT32, SMI, OVERWRITE_RIGHT); |
| 2420 GENERATE(Token::BIT_AND, SMI, NUMBER, SMI, OVERWRITE_RIGHT); |
| 2421 GENERATE(Token::BIT_AND, SMI, SMI, SMI, NO_OVERWRITE); |
| 2422 GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_LEFT); |
| 2423 GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_RIGHT); |
| 2424 GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_LEFT); |
| 2425 GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_RIGHT); |
| 2426 GENERATE(Token::BIT_OR, INT32, INT32, SMI, OVERWRITE_LEFT); |
| 2427 GENERATE(Token::BIT_OR, INT32, SMI, INT32, NO_OVERWRITE); |
| 2428 GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_LEFT); |
| 2429 GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_RIGHT); |
| 2430 GENERATE(Token::BIT_OR, INT32, SMI, SMI, NO_OVERWRITE); |
| 2431 GENERATE(Token::BIT_OR, INT32, SMI, SMI, OVERWRITE_RIGHT); |
| 2432 GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, NO_OVERWRITE); |
| 2433 GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_LEFT); |
| 2434 GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_RIGHT); |
| 2435 GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, NO_OVERWRITE); |
| 2436 GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, OVERWRITE_LEFT); |
| 2437 GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_LEFT); |
| 2438 GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_RIGHT); |
| 2439 GENERATE(Token::BIT_OR, SMI, INT32, SMI, OVERWRITE_RIGHT); |
| 2440 GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_LEFT); |
| 2441 GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_RIGHT); |
| 2442 GENERATE(Token::BIT_XOR, INT32, INT32, INT32, NO_OVERWRITE); |
| 2443 GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_LEFT); |
| 2444 GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_RIGHT); |
| 2445 GENERATE(Token::BIT_XOR, INT32, INT32, SMI, NO_OVERWRITE); |
| 2446 GENERATE(Token::BIT_XOR, INT32, INT32, SMI, OVERWRITE_LEFT); |
| 2447 GENERATE(Token::BIT_XOR, INT32, NUMBER, SMI, NO_OVERWRITE); |
| 2448 GENERATE(Token::BIT_XOR, INT32, SMI, INT32, NO_OVERWRITE); |
| 2449 GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_LEFT); |
| 2450 GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_RIGHT); |
| 2451 GENERATE(Token::BIT_XOR, NUMBER, INT32, INT32, NO_OVERWRITE); |
| 2452 GENERATE(Token::BIT_XOR, NUMBER, SMI, INT32, NO_OVERWRITE); |
| 2453 GENERATE(Token::BIT_XOR, NUMBER, SMI, SMI, NO_OVERWRITE); |
| 2454 GENERATE(Token::BIT_XOR, SMI, INT32, INT32, NO_OVERWRITE); |
| 2455 GENERATE(Token::BIT_XOR, SMI, INT32, INT32, OVERWRITE_LEFT); |
| 2456 GENERATE(Token::BIT_XOR, SMI, INT32, SMI, OVERWRITE_LEFT); |
| 2457 GENERATE(Token::BIT_XOR, SMI, SMI, SMI, NO_OVERWRITE); |
| 2458 GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_LEFT); |
| 2459 GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_RIGHT); |
| 2460 GENERATE(Token::DIV, INT32, INT32, INT32, NO_OVERWRITE); |
| 2461 GENERATE(Token::DIV, INT32, INT32, NUMBER, NO_OVERWRITE); |
| 2462 GENERATE(Token::DIV, INT32, NUMBER, NUMBER, NO_OVERWRITE); |
| 2463 GENERATE(Token::DIV, INT32, NUMBER, NUMBER, OVERWRITE_LEFT); |
| 2464 GENERATE(Token::DIV, INT32, SMI, INT32, NO_OVERWRITE); |
| 2465 GENERATE(Token::DIV, INT32, SMI, NUMBER, NO_OVERWRITE); |
| 2466 GENERATE(Token::DIV, NUMBER, INT32, NUMBER, NO_OVERWRITE); |
| 2467 GENERATE(Token::DIV, NUMBER, INT32, NUMBER, OVERWRITE_LEFT); |
| 2468 GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, NO_OVERWRITE); |
| 2469 GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT); |
| 2470 GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT); |
| 2471 GENERATE(Token::DIV, NUMBER, SMI, NUMBER, NO_OVERWRITE); |
| 2472 GENERATE(Token::DIV, NUMBER, SMI, NUMBER, OVERWRITE_LEFT); |
| 2473 GENERATE(Token::DIV, SMI, INT32, INT32, NO_OVERWRITE); |
| 2474 GENERATE(Token::DIV, SMI, INT32, NUMBER, NO_OVERWRITE); |
| 2475 GENERATE(Token::DIV, SMI, INT32, NUMBER, OVERWRITE_LEFT); |
| 2476 GENERATE(Token::DIV, SMI, NUMBER, NUMBER, NO_OVERWRITE); |
| 2477 GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_LEFT); |
| 2478 GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT); |
| 2479 GENERATE(Token::DIV, SMI, SMI, NUMBER, NO_OVERWRITE); |
| 2480 GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_LEFT); |
| 2481 GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_RIGHT); |
| 2482 GENERATE(Token::DIV, SMI, SMI, SMI, NO_OVERWRITE); |
| 2483 GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_LEFT); |
| 2484 GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_RIGHT); |
| 2485 GENERATE(Token::MOD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT); |
| 2486 GENERATE(Token::MOD, SMI, SMI, SMI, NO_OVERWRITE); |
| 2487 GENERATE(Token::MOD, SMI, SMI, SMI, OVERWRITE_LEFT); |
| 2488 GENERATE(Token::MUL, INT32, INT32, INT32, NO_OVERWRITE); |
| 2489 GENERATE(Token::MUL, INT32, INT32, NUMBER, NO_OVERWRITE); |
| 2490 GENERATE(Token::MUL, INT32, NUMBER, NUMBER, NO_OVERWRITE); |
| 2491 GENERATE(Token::MUL, INT32, NUMBER, NUMBER, OVERWRITE_LEFT); |
| 2492 GENERATE(Token::MUL, INT32, SMI, INT32, NO_OVERWRITE); |
| 2493 GENERATE(Token::MUL, INT32, SMI, INT32, OVERWRITE_LEFT); |
| 2494 GENERATE(Token::MUL, INT32, SMI, NUMBER, NO_OVERWRITE); |
| 2495 GENERATE(Token::MUL, NUMBER, INT32, NUMBER, NO_OVERWRITE); |
| 2496 GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_LEFT); |
| 2497 GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT); |
| 2498 GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, NO_OVERWRITE); |
| 2499 GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT); |
| 2500 GENERATE(Token::MUL, NUMBER, SMI, NUMBER, NO_OVERWRITE); |
| 2501 GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_LEFT); |
| 2502 GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT); |
| 2503 GENERATE(Token::MUL, SMI, INT32, INT32, NO_OVERWRITE); |
| 2504 GENERATE(Token::MUL, SMI, INT32, INT32, OVERWRITE_LEFT); |
| 2505 GENERATE(Token::MUL, SMI, INT32, NUMBER, NO_OVERWRITE); |
| 2506 GENERATE(Token::MUL, SMI, NUMBER, NUMBER, NO_OVERWRITE); |
| 2507 GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_LEFT); |
| 2508 GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT); |
| 2509 GENERATE(Token::MUL, SMI, SMI, INT32, NO_OVERWRITE); |
| 2510 GENERATE(Token::MUL, SMI, SMI, NUMBER, NO_OVERWRITE); |
| 2511 GENERATE(Token::MUL, SMI, SMI, NUMBER, OVERWRITE_LEFT); |
| 2512 GENERATE(Token::MUL, SMI, SMI, SMI, NO_OVERWRITE); |
| 2513 GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_LEFT); |
| 2514 GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_RIGHT); |
| 2515 GENERATE(Token::SAR, INT32, SMI, INT32, OVERWRITE_RIGHT); |
| 2516 GENERATE(Token::SAR, INT32, SMI, SMI, NO_OVERWRITE); |
| 2517 GENERATE(Token::SAR, INT32, SMI, SMI, OVERWRITE_RIGHT); |
| 2518 GENERATE(Token::SAR, NUMBER, SMI, SMI, NO_OVERWRITE); |
| 2519 GENERATE(Token::SAR, NUMBER, SMI, SMI, OVERWRITE_RIGHT); |
| 2520 GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_LEFT); |
| 2521 GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_RIGHT); |
| 2522 GENERATE(Token::SHL, INT32, SMI, INT32, NO_OVERWRITE); |
| 2523 GENERATE(Token::SHL, INT32, SMI, INT32, OVERWRITE_RIGHT); |
| 2524 GENERATE(Token::SHL, INT32, SMI, SMI, NO_OVERWRITE); |
| 2525 GENERATE(Token::SHL, INT32, SMI, SMI, OVERWRITE_RIGHT); |
| 2526 GENERATE(Token::SHL, NUMBER, SMI, SMI, OVERWRITE_RIGHT); |
| 2527 GENERATE(Token::SHL, SMI, SMI, INT32, NO_OVERWRITE); |
| 2528 GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_LEFT); |
| 2529 GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_RIGHT); |
| 2530 GENERATE(Token::SHL, SMI, SMI, SMI, NO_OVERWRITE); |
| 2531 GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_LEFT); |
| 2532 GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_RIGHT); |
| 2533 GENERATE(Token::SHR, INT32, SMI, SMI, NO_OVERWRITE); |
| 2534 GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_LEFT); |
| 2535 GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_RIGHT); |
| 2536 GENERATE(Token::SHR, NUMBER, SMI, SMI, NO_OVERWRITE); |
| 2537 GENERATE(Token::SHR, NUMBER, SMI, SMI, OVERWRITE_LEFT); |
| 2538 GENERATE(Token::SHR, NUMBER, SMI, INT32, OVERWRITE_RIGHT); |
| 2539 GENERATE(Token::SHR, SMI, SMI, SMI, NO_OVERWRITE); |
| 2540 GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_LEFT); |
| 2541 GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_RIGHT); |
| 2542 GENERATE(Token::SUB, INT32, INT32, INT32, NO_OVERWRITE); |
| 2543 GENERATE(Token::SUB, INT32, INT32, INT32, OVERWRITE_LEFT); |
| 2544 GENERATE(Token::SUB, INT32, NUMBER, NUMBER, NO_OVERWRITE); |
| 2545 GENERATE(Token::SUB, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT); |
| 2546 GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_LEFT); |
| 2547 GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_RIGHT); |
| 2548 GENERATE(Token::SUB, NUMBER, INT32, NUMBER, NO_OVERWRITE); |
| 2549 GENERATE(Token::SUB, NUMBER, INT32, NUMBER, OVERWRITE_LEFT); |
| 2550 GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, NO_OVERWRITE); |
| 2551 GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT); |
| 2552 GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT); |
| 2553 GENERATE(Token::SUB, NUMBER, SMI, NUMBER, NO_OVERWRITE); |
| 2554 GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_LEFT); |
| 2555 GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT); |
| 2556 GENERATE(Token::SUB, SMI, INT32, INT32, NO_OVERWRITE); |
| 2557 GENERATE(Token::SUB, SMI, NUMBER, NUMBER, NO_OVERWRITE); |
| 2558 GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_LEFT); |
| 2559 GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT); |
| 2560 GENERATE(Token::SUB, SMI, SMI, SMI, NO_OVERWRITE); |
| 2561 GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_LEFT); |
| 2562 GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_RIGHT); |
| 2563 #undef GENERATE |
| 2564 #define GENERATE(op, left_kind, fixed_right_arg_value, result_kind, mode) \ |
| 2565 do { \ |
| 2566 State state(op, mode); \ |
| 2567 state.left_kind_ = left_kind; \ |
| 2568 state.fixed_right_arg_.has_value = true; \ |
| 2569 state.fixed_right_arg_.value = fixed_right_arg_value; \ |
| 2570 state.right_kind_ = SMI; \ |
| 2571 state.result_kind_ = result_kind; \ |
| 2572 Generate(isolate, state); \ |
| 2573 } while (false) |
| 2574 GENERATE(Token::MOD, SMI, 2, SMI, NO_OVERWRITE); |
| 2575 GENERATE(Token::MOD, SMI, 4, SMI, NO_OVERWRITE); |
| 2576 GENERATE(Token::MOD, SMI, 4, SMI, OVERWRITE_LEFT); |
| 2577 GENERATE(Token::MOD, SMI, 8, SMI, NO_OVERWRITE); |
| 2578 GENERATE(Token::MOD, SMI, 16, SMI, OVERWRITE_LEFT); |
| 2579 GENERATE(Token::MOD, SMI, 32, SMI, NO_OVERWRITE); |
| 2580 GENERATE(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE); |
| 2581 #undef GENERATE |
| 2582 } |
| 2583 |
| 2584 |
| 2585 Handle<Type> BinaryOpIC::State::GetResultType(Isolate* isolate) const { |
| 2586 Kind result_kind = result_kind_; |
| 2587 if (HasSideEffects()) { |
| 2588 result_kind = NONE; |
| 2589 } else if (result_kind == GENERIC && op_ == Token::ADD) { |
| 2590 return handle(Type::Union(handle(Type::Number(), isolate), |
| 2591 handle(Type::String(), isolate)), isolate); |
| 2592 } else if (result_kind == NUMBER && op_ == Token::SHR) { |
| 2593 return handle(Type::Unsigned32(), isolate); |
| 2594 } |
| 2595 ASSERT_NE(GENERIC, result_kind); |
| 2596 return KindToType(result_kind, isolate); |
| 2597 } |
| 2598 |
| 2599 |
| 2600 void BinaryOpIC::State::Print(StringStream* stream) const { |
| 2601 stream->Add("(%s", Token::Name(op_)); |
| 2602 if (mode_ == OVERWRITE_LEFT) stream->Add("_ReuseLeft"); |
| 2603 else if (mode_ == OVERWRITE_RIGHT) stream->Add("_ReuseRight"); |
| 2604 stream->Add(":%s*", KindToString(left_kind_)); |
| 2605 if (fixed_right_arg_.has_value) { |
| 2606 stream->Add("%d", fixed_right_arg_.value); |
| 2607 } else { |
| 2608 stream->Add("%s", KindToString(right_kind_)); |
| 2609 } |
| 2610 stream->Add("->%s)", KindToString(result_kind_)); |
| 2611 } |
| 2612 |
| 2613 |
| 2614 void BinaryOpIC::State::Update(Handle<Object> left, |
| 2615 Handle<Object> right, |
| 2616 Handle<Object> result) { |
| 2617 ExtraICState old_extra_ic_state = GetExtraICState(); |
| 2618 |
| 2619 left_kind_ = UpdateKind(left, left_kind_); |
| 2620 right_kind_ = UpdateKind(right, right_kind_); |
| 2621 |
| 2622 int32_t fixed_right_arg_value = 0; |
| 2623 bool has_fixed_right_arg = |
| 2624 op_ == Token::MOD && |
| 2625 right->ToInt32(&fixed_right_arg_value) && |
| 2626 fixed_right_arg_value > 0 && |
| 2627 IsPowerOf2(fixed_right_arg_value) && |
| 2628 FixedRightArgValueField::is_valid(WhichPowerOf2(fixed_right_arg_value)) && |
| 2629 (left_kind_ == SMI || left_kind_ == INT32) && |
| 2630 (result_kind_ == NONE || !fixed_right_arg_.has_value); |
| 2631 fixed_right_arg_ = Maybe<int32_t>(has_fixed_right_arg, |
| 2632 fixed_right_arg_value); |
| 2633 |
| 2634 result_kind_ = UpdateKind(result, result_kind_); |
| 2635 |
| 2636 if (!Token::IsTruncatingBinaryOp(op_)) { |
| 2637 Kind input_kind = Max(left_kind_, right_kind_); |
| 2638 if (result_kind_ < input_kind && input_kind <= NUMBER) { |
| 2639 result_kind_ = input_kind; |
| 2640 } |
| 2641 } |
| 2642 |
| 2643 // Reset overwrite mode unless we can actually make use of it, or may be able |
| 2644 // to make use of it at some point in the future. |
| 2645 if ((mode_ == OVERWRITE_LEFT && left_kind_ > NUMBER) || |
| 2646 (mode_ == OVERWRITE_RIGHT && right_kind_ > NUMBER) || |
| 2647 result_kind_ > NUMBER) { |
| 2648 mode_ = NO_OVERWRITE; |
| 2649 } |
| 2650 |
| 2651 if (old_extra_ic_state == GetExtraICState()) { |
| 2652 // Tagged operations can lead to non-truncating HChanges |
| 2653 if (left->IsUndefined() || left->IsBoolean()) { |
| 2654 left_kind_ = GENERIC; |
| 2655 } else if (right->IsUndefined() || right->IsBoolean()) { |
| 2656 right_kind_ = GENERIC; |
| 2657 } else { |
| 2658 // Since the X87 is too precise, we might bail out on numbers which |
| 2659 // actually would truncate with 64 bit precision. |
| 2660 ASSERT(!CpuFeatures::IsSupported(SSE2)); |
| 2661 ASSERT(result_kind_ < NUMBER); |
| 2662 result_kind_ = NUMBER; |
| 2663 } |
| 2664 } |
| 2665 } |
| 2666 |
| 2667 |
| 2668 BinaryOpIC::State::Kind BinaryOpIC::State::UpdateKind(Handle<Object> object, |
| 2669 Kind kind) const { |
| 2670 Kind new_kind = GENERIC; |
| 2671 bool is_truncating = Token::IsTruncatingBinaryOp(op()); |
| 2672 if (object->IsBoolean() && is_truncating) { |
| 2673 // Booleans will be automatically truncated by HChange. |
| 2674 new_kind = INT32; |
| 2675 } else if (object->IsUndefined()) { |
| 2676 // Undefined will be automatically truncated by HChange. |
| 2677 new_kind = is_truncating ? INT32 : NUMBER; |
| 2678 } else if (object->IsSmi()) { |
| 2679 new_kind = SMI; |
| 2680 } else if (object->IsHeapNumber()) { |
| 2681 double value = Handle<HeapNumber>::cast(object)->value(); |
| 2682 new_kind = TypeInfo::IsInt32Double(value) ? INT32 : NUMBER; |
| 2683 } else if (object->IsString() && op() == Token::ADD) { |
| 2684 new_kind = STRING; |
| 2685 } |
| 2686 if (new_kind == INT32 && SmiValuesAre32Bits()) { |
| 2687 new_kind = NUMBER; |
| 2688 } |
| 2689 if (kind != NONE && |
| 2690 ((new_kind <= NUMBER && kind > NUMBER) || |
| 2691 (new_kind > NUMBER && kind <= NUMBER))) { |
| 2692 new_kind = GENERIC; |
| 2693 } |
| 2694 return Max(kind, new_kind); |
| 2695 } |
| 2696 |
| 2697 |
| 2698 // static |
| 2699 const char* BinaryOpIC::State::KindToString(Kind kind) { |
| 2700 switch (kind) { |
| 2701 case NONE: return "None"; |
| 2336 case SMI: return "Smi"; | 2702 case SMI: return "Smi"; |
| 2337 case INT32: return "Int32"; | 2703 case INT32: return "Int32"; |
| 2338 case NUMBER: return "Number"; | 2704 case NUMBER: return "Number"; |
| 2339 case ODDBALL: return "Oddball"; | |
| 2340 case STRING: return "String"; | 2705 case STRING: return "String"; |
| 2341 case GENERIC: return "Generic"; | 2706 case GENERIC: return "Generic"; |
| 2342 default: return "Invalid"; | 2707 } |
| 2343 } | 2708 UNREACHABLE(); |
| 2709 return NULL; |
| 2710 } |
| 2711 |
| 2712 |
| 2713 // static |
| 2714 Handle<Type> BinaryOpIC::State::KindToType(Kind kind, Isolate* isolate) { |
| 2715 Type* type = NULL; |
| 2716 switch (kind) { |
| 2717 case NONE: type = Type::None(); break; |
| 2718 case SMI: type = Type::Smi(); break; |
| 2719 case INT32: type = Type::Signed32(); break; |
| 2720 case NUMBER: type = Type::Number(); break; |
| 2721 case STRING: type = Type::String(); break; |
| 2722 case GENERIC: type = Type::Any(); break; |
| 2723 } |
| 2724 return handle(type, isolate); |
| 2344 } | 2725 } |
| 2345 | 2726 |
| 2346 | 2727 |
| 2347 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) { | 2728 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) { |
| 2348 ExtraICState extra_ic_state = target()->extended_extra_ic_state(); | 2729 State state(target()->extended_extra_ic_state()); |
| 2349 BinaryOpStub stub(extra_ic_state); | 2730 |
| 2350 | 2731 // Compute the actual result using the builtin for the binary operation. |
| 2351 Handle<Type> left_type = stub.GetLeftType(isolate()); | 2732 Object* builtin = isolate()->js_builtins_object()->javascript_builtin( |
| 2352 Handle<Type> right_type = stub.GetRightType(isolate()); | 2733 TokenToJSBuiltin(state.op())); |
| 2353 bool smi_was_enabled = left_type->Maybe(Type::Smi()) && | 2734 Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate()); |
| 2354 right_type->Maybe(Type::Smi()); | 2735 bool caught_exception; |
| 2355 | 2736 Handle<Object> result = Execution::Call( |
| 2356 Maybe<Handle<Object> > result = stub.Result(left, right, isolate()); | 2737 isolate(), function, left, 1, &right, &caught_exception); |
| 2357 if (!result.has_value) return Failure::Exception(); | 2738 if (caught_exception) return Failure::Exception(); |
| 2739 |
| 2740 // Compute the new state. |
| 2741 State old_state = state; |
| 2742 state.Update(left, right, result); |
| 2743 |
| 2744 // Install the new stub. |
| 2745 BinaryOpICStub stub(state); |
| 2746 set_target(*stub.GetCode(isolate())); |
| 2358 | 2747 |
| 2359 if (FLAG_trace_ic) { | 2748 if (FLAG_trace_ic) { |
| 2360 char buffer[100]; | 2749 char buffer[150]; |
| 2361 NoAllocationStringAllocator allocator(buffer, | 2750 NoAllocationStringAllocator allocator( |
| 2362 static_cast<unsigned>(sizeof(buffer))); | 2751 buffer, static_cast<unsigned>(sizeof(buffer))); |
| 2363 StringStream stream(&allocator); | 2752 StringStream stream(&allocator); |
| 2364 stream.Add("["); | 2753 stream.Add("[BinaryOpIC"); |
| 2365 stub.PrintName(&stream); | 2754 old_state.Print(&stream); |
| 2366 | |
| 2367 stub.UpdateStatus(left, right, result); | |
| 2368 | |
| 2369 stream.Add(" => "); | 2755 stream.Add(" => "); |
| 2370 stub.PrintState(&stream); | 2756 state.Print(&stream); |
| 2371 stream.Add(" "); | 2757 stream.Add(" @ %p <- ", static_cast<void*>(*target())); |
| 2372 stream.OutputToStdOut(); | 2758 stream.OutputToStdOut(); |
| 2373 PrintF(" @ %p <- ", static_cast<void*>(*stub.GetCode(isolate()))); | |
| 2374 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 2759 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
| 2375 PrintF("]\n"); | 2760 PrintF("]\n"); |
| 2376 } else { | 2761 } |
| 2377 stub.UpdateStatus(left, right, result); | 2762 |
| 2378 } | 2763 // Patch the inlined smi code as necessary. |
| 2379 | 2764 if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) { |
| 2380 Handle<Code> code = stub.GetCode(isolate()); | |
| 2381 set_target(*code); | |
| 2382 | |
| 2383 left_type = stub.GetLeftType(isolate()); | |
| 2384 right_type = stub.GetRightType(isolate()); | |
| 2385 bool enable_smi = left_type->Maybe(Type::Smi()) && | |
| 2386 right_type->Maybe(Type::Smi()); | |
| 2387 | |
| 2388 if (!smi_was_enabled && enable_smi) { | |
| 2389 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); | 2765 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); |
| 2390 } else if (smi_was_enabled && !enable_smi) { | 2766 } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) { |
| 2391 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK); | 2767 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK); |
| 2392 } | 2768 } |
| 2393 | 2769 |
| 2394 ASSERT(result.has_value); | 2770 return *result; |
| 2395 return static_cast<MaybeObject*>(*result.value); | |
| 2396 } | 2771 } |
| 2397 | 2772 |
| 2398 | 2773 |
| 2399 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) { | 2774 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) { |
| 2400 HandleScope scope(isolate); | 2775 HandleScope scope(isolate); |
| 2401 Handle<Object> left = args.at<Object>(0); | 2776 Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft); |
| 2402 Handle<Object> right = args.at<Object>(1); | 2777 Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight); |
| 2403 BinaryOpIC ic(isolate); | 2778 BinaryOpIC ic(isolate); |
| 2404 return ic.Transition(left, right); | 2779 return ic.Transition(left, right); |
| 2405 } | 2780 } |
| 2406 | 2781 |
| 2407 | 2782 |
| 2408 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { | 2783 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { |
| 2409 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); | 2784 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); |
| 2410 Code* code = NULL; | 2785 Code* code = NULL; |
| 2411 CHECK(stub.FindCodeInCache(&code, isolate)); | 2786 CHECK(stub.FindCodeInCache(&code, isolate)); |
| 2412 return code; | 2787 return code; |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2768 #undef ADDR | 3143 #undef ADDR |
| 2769 }; | 3144 }; |
| 2770 | 3145 |
| 2771 | 3146 |
| 2772 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3147 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2773 return IC_utilities[id]; | 3148 return IC_utilities[id]; |
| 2774 } | 3149 } |
| 2775 | 3150 |
| 2776 | 3151 |
| 2777 } } // namespace v8::internal | 3152 } } // namespace v8::internal |
| OLD | NEW |