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

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 2325083003: Record call counts also for megamorphic calls. (Closed)
Patch Set: Code comments. Created 4 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
« no previous file with comments | « src/arm64/code-stubs-arm64.cc ('k') | src/interpreter/interpreter-assembler.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 #if V8_TARGET_ARCH_IA32 5 #if V8_TARGET_ARCH_IA32
6 6
7 #include "src/code-stubs.h" 7 #include "src/code-stubs.h"
8 #include "src/api-arguments.h" 8 #include "src/api-arguments.h"
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 1413 matching lines...) Expand 10 before | Expand all | Expand 10 after
1424 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 1424 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1425 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); 1425 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset));
1426 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 1426 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
1427 __ jmp(ecx); 1427 __ jmp(ecx);
1428 1428
1429 __ bind(&non_function); 1429 __ bind(&non_function);
1430 __ mov(edx, edi); 1430 __ mov(edx, edi);
1431 __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 1431 __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
1432 } 1432 }
1433 1433
1434 static void IncrementCallCount(MacroAssembler* masm, Register feedback_vector,
1435 Register slot) {
1436 __ add(FieldOperand(feedback_vector, slot, times_half_pointer_size,
1437 FixedArray::kHeaderSize + kPointerSize),
1438 Immediate(Smi::FromInt(1)));
1439 }
1434 1440
1435 void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { 1441 void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
1436 // edi - function 1442 // edi - function
1437 // edx - slot id 1443 // edx - slot id
1438 // ebx - vector 1444 // ebx - vector
1439 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); 1445 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx);
1440 __ cmp(edi, ecx); 1446 __ cmp(edi, ecx);
1441 __ j(not_equal, miss); 1447 __ j(not_equal, miss);
1442 1448
1443 __ mov(eax, arg_count()); 1449 __ mov(eax, arg_count());
1444 // Reload ecx. 1450 // Reload ecx.
1445 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, 1451 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
1446 FixedArray::kHeaderSize)); 1452 FixedArray::kHeaderSize));
1447 1453
1448 // Increment the call count for monomorphic function calls. 1454 // Increment the call count for monomorphic function calls.
1449 __ add(FieldOperand(ebx, edx, times_half_pointer_size, 1455 IncrementCallCount(masm, ebx, edx);
1450 FixedArray::kHeaderSize + kPointerSize),
1451 Immediate(Smi::FromInt(1)));
1452 1456
1453 __ mov(ebx, ecx); 1457 __ mov(ebx, ecx);
1454 __ mov(edx, edi); 1458 __ mov(edx, edi);
1455 ArrayConstructorStub stub(masm->isolate(), arg_count()); 1459 ArrayConstructorStub stub(masm->isolate(), arg_count());
1456 __ TailCallStub(&stub); 1460 __ TailCallStub(&stub);
1457 1461
1458 // Unreachable. 1462 // Unreachable.
1459 } 1463 }
1460 1464
1461 1465
1462 void CallICStub::Generate(MacroAssembler* masm) { 1466 void CallICStub::Generate(MacroAssembler* masm) {
1463 // edi - function 1467 // edi - function
1464 // edx - slot id 1468 // edx - slot id
1465 // ebx - vector 1469 // ebx - vector
1466 Isolate* isolate = masm->isolate(); 1470 Isolate* isolate = masm->isolate();
1467 Label extra_checks_or_miss, call, call_function; 1471 Label extra_checks_or_miss, call, call_function, call_count_incremented;
1468 int argc = arg_count(); 1472 int argc = arg_count();
1469 ParameterCount actual(argc); 1473 ParameterCount actual(argc);
1470 1474
1471 // The checks. First, does edi match the recorded monomorphic target? 1475 // The checks. First, does edi match the recorded monomorphic target?
1472 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, 1476 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
1473 FixedArray::kHeaderSize)); 1477 FixedArray::kHeaderSize));
1474 1478
1475 // We don't know that we have a weak cell. We might have a private symbol 1479 // We don't know that we have a weak cell. We might have a private symbol
1476 // or an AllocationSite, but the memory is safe to examine. 1480 // or an AllocationSite, but the memory is safe to examine.
1477 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to 1481 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to
1478 // FixedArray. 1482 // FixedArray.
1479 // WeakCell::kValueOffset - contains a JSFunction or Smi(0) 1483 // WeakCell::kValueOffset - contains a JSFunction or Smi(0)
1480 // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not 1484 // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not
1481 // computed, meaning that it can't appear to be a pointer. If the low bit is 1485 // computed, meaning that it can't appear to be a pointer. If the low bit is
1482 // 0, then hash is computed, but the 0 bit prevents the field from appearing 1486 // 0, then hash is computed, but the 0 bit prevents the field from appearing
1483 // to be a pointer. 1487 // to be a pointer.
1484 STATIC_ASSERT(WeakCell::kSize >= kPointerSize); 1488 STATIC_ASSERT(WeakCell::kSize >= kPointerSize);
1485 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == 1489 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset ==
1486 WeakCell::kValueOffset && 1490 WeakCell::kValueOffset &&
1487 WeakCell::kValueOffset == Symbol::kHashFieldSlot); 1491 WeakCell::kValueOffset == Symbol::kHashFieldSlot);
1488 1492
1489 __ cmp(edi, FieldOperand(ecx, WeakCell::kValueOffset)); 1493 __ cmp(edi, FieldOperand(ecx, WeakCell::kValueOffset));
1490 __ j(not_equal, &extra_checks_or_miss); 1494 __ j(not_equal, &extra_checks_or_miss);
1491 1495
1492 // The compare above could have been a SMI/SMI comparison. Guard against this 1496 // The compare above could have been a SMI/SMI comparison. Guard against this
1493 // convincing us that we have a monomorphic JSFunction. 1497 // convincing us that we have a monomorphic JSFunction.
1494 __ JumpIfSmi(edi, &extra_checks_or_miss); 1498 __ JumpIfSmi(edi, &extra_checks_or_miss);
1495 1499
1500 __ bind(&call_function);
1501
1496 // Increment the call count for monomorphic function calls. 1502 // Increment the call count for monomorphic function calls.
1497 __ add(FieldOperand(ebx, edx, times_half_pointer_size, 1503 IncrementCallCount(masm, ebx, edx);
1498 FixedArray::kHeaderSize + kPointerSize),
1499 Immediate(Smi::FromInt(1)));
1500 1504
1501 __ bind(&call_function);
1502 __ Set(eax, argc); 1505 __ Set(eax, argc);
1503 __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(), 1506 __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
1504 tail_call_mode()), 1507 tail_call_mode()),
1505 RelocInfo::CODE_TARGET); 1508 RelocInfo::CODE_TARGET);
1506 1509
1507 __ bind(&extra_checks_or_miss); 1510 __ bind(&extra_checks_or_miss);
1508 Label uninitialized, miss, not_allocation_site; 1511 Label uninitialized, miss, not_allocation_site;
1509 1512
1510 __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); 1513 __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate)));
1511 __ j(equal, &call); 1514 __ j(equal, &call);
(...skipping 20 matching lines...) Expand all
1532 // We are going megamorphic. If the feedback is a JSFunction, it is fine 1535 // We are going megamorphic. If the feedback is a JSFunction, it is fine
1533 // to handle it here. More complex cases are dealt with in the runtime. 1536 // to handle it here. More complex cases are dealt with in the runtime.
1534 __ AssertNotSmi(ecx); 1537 __ AssertNotSmi(ecx);
1535 __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx); 1538 __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx);
1536 __ j(not_equal, &miss); 1539 __ j(not_equal, &miss);
1537 __ mov( 1540 __ mov(
1538 FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize), 1541 FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize),
1539 Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); 1542 Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate)));
1540 1543
1541 __ bind(&call); 1544 __ bind(&call);
1545
1546 // Increment the call count for megamorphic function calls.
1547 IncrementCallCount(masm, ebx, edx);
1548
1549 __ bind(&call_count_incremented);
1550
1542 __ Set(eax, argc); 1551 __ Set(eax, argc);
1543 __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()), 1552 __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
1544 RelocInfo::CODE_TARGET); 1553 RelocInfo::CODE_TARGET);
1545 1554
1546 __ bind(&uninitialized); 1555 __ bind(&uninitialized);
1547 1556
1548 // We are going monomorphic, provided we actually have a JSFunction. 1557 // We are going monomorphic, provided we actually have a JSFunction.
1549 __ JumpIfSmi(edi, &miss); 1558 __ JumpIfSmi(edi, &miss);
1550 1559
1551 // Goto miss case if we do not have a function. 1560 // Goto miss case if we do not have a function.
1552 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 1561 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
1553 __ j(not_equal, &miss); 1562 __ j(not_equal, &miss);
1554 1563
1555 // Make sure the function is not the Array() function, which requires special 1564 // Make sure the function is not the Array() function, which requires special
1556 // behavior on MISS. 1565 // behavior on MISS.
1557 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); 1566 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx);
1558 __ cmp(edi, ecx); 1567 __ cmp(edi, ecx);
1559 __ j(equal, &miss); 1568 __ j(equal, &miss);
1560 1569
1561 // Make sure the function belongs to the same native context. 1570 // Make sure the function belongs to the same native context.
1562 __ mov(ecx, FieldOperand(edi, JSFunction::kContextOffset)); 1571 __ mov(ecx, FieldOperand(edi, JSFunction::kContextOffset));
1563 __ mov(ecx, ContextOperand(ecx, Context::NATIVE_CONTEXT_INDEX)); 1572 __ mov(ecx, ContextOperand(ecx, Context::NATIVE_CONTEXT_INDEX));
1564 __ cmp(ecx, NativeContextOperand()); 1573 __ cmp(ecx, NativeContextOperand());
1565 __ j(not_equal, &miss); 1574 __ j(not_equal, &miss);
1566 1575
1567 // Initialize the call counter.
1568 __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
1569 FixedArray::kHeaderSize + kPointerSize),
1570 Immediate(Smi::FromInt(1)));
1571
1572 // Store the function. Use a stub since we need a frame for allocation. 1576 // Store the function. Use a stub since we need a frame for allocation.
1573 // ebx - vector 1577 // ebx - vector
1574 // edx - slot 1578 // edx - slot
1575 // edi - function 1579 // edi - function
1576 { 1580 {
1577 FrameScope scope(masm, StackFrame::INTERNAL); 1581 FrameScope scope(masm, StackFrame::INTERNAL);
1578 CreateWeakCellStub create_stub(isolate); 1582 CreateWeakCellStub create_stub(isolate);
1583 __ push(ebx);
1584 __ push(edx);
1579 __ push(edi); 1585 __ push(edi);
1580 __ push(esi); 1586 __ push(esi);
1581 __ CallStub(&create_stub); 1587 __ CallStub(&create_stub);
1582 __ pop(esi); 1588 __ pop(esi);
1583 __ pop(edi); 1589 __ pop(edi);
1590 __ pop(edx);
1591 __ pop(ebx);
1584 } 1592 }
1585 1593
1586 __ jmp(&call_function); 1594 __ jmp(&call_function);
1587 1595
1588 // We are here because tracing is on or we encountered a MISS case we can't 1596 // We are here because tracing is on or we encountered a MISS case we can't
1589 // handle here. 1597 // handle here.
1590 __ bind(&miss); 1598 __ bind(&miss);
1591 GenerateMiss(masm); 1599 GenerateMiss(masm);
1592 1600
1593 __ jmp(&call); 1601 __ jmp(&call_count_incremented);
1594 1602
1595 // Unreachable 1603 // Unreachable
1596 __ int3(); 1604 __ int3();
1597 } 1605 }
1598 1606
1599 1607
1600 void CallICStub::GenerateMiss(MacroAssembler* masm) { 1608 void CallICStub::GenerateMiss(MacroAssembler* masm) {
1601 FrameScope scope(masm, StackFrame::INTERNAL); 1609 FrameScope scope(masm, StackFrame::INTERNAL);
1602 1610
1603 // Push the function and feedback info. 1611 // Push the function and feedback info.
(...skipping 3846 matching lines...) Expand 10 before | Expand all | Expand 10 after
5450 kStackUnwindSpace, nullptr, return_value_operand, 5458 kStackUnwindSpace, nullptr, return_value_operand,
5451 NULL); 5459 NULL);
5452 } 5460 }
5453 5461
5454 #undef __ 5462 #undef __
5455 5463
5456 } // namespace internal 5464 } // namespace internal
5457 } // namespace v8 5465 } // namespace v8
5458 5466
5459 #endif // V8_TARGET_ARCH_IA32 5467 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/arm64/code-stubs-arm64.cc ('k') | src/interpreter/interpreter-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698