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

Side by Side Diff: src/ic.cc

Issue 136643008: A64: Synchronize with r18256. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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.h ('k') | src/isolate.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 // 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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/isolate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698