| 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 |