OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |