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 | 5 |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #if V8_TARGET_ARCH_MIPS64 | 9 #if V8_TARGET_ARCH_MIPS64 |
10 | 10 |
(...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1352 // Check formal and actual parameter counts. | 1352 // Check formal and actual parameter counts. |
1353 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1353 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1354 RelocInfo::CODE_TARGET, ne, a2, Operand(a0)); | 1354 RelocInfo::CODE_TARGET, ne, a2, Operand(a0)); |
1355 | 1355 |
1356 __ ld(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 1356 __ ld(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
1357 ParameterCount expected(0); | 1357 ParameterCount expected(0); |
1358 __ InvokeCode(a3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); | 1358 __ InvokeCode(a3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); |
1359 } | 1359 } |
1360 | 1360 |
1361 | 1361 |
1362 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 1362 static void Generate_CheckStackOverflow(MacroAssembler* masm, |
1363 const int kIndexOffset = | 1363 const int calleeOffset) { |
1364 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); | 1364 // Check the stack for overflow. We are not trying to catch |
1365 const int kLimitOffset = | 1365 // interruptions (e.g. debug break and preemption) here, so the "real stack |
1366 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); | 1366 // limit" is checked. |
1367 const int kArgsOffset = 2 * kPointerSize; | 1367 Label okay; |
1368 const int kRecvOffset = 3 * kPointerSize; | 1368 __ LoadRoot(a2, Heap::kRealStackLimitRootIndex); |
1369 const int kFunctionOffset = 4 * kPointerSize; | 1369 // Make a2 the space we have left. The stack might already be overflowed |
| 1370 // here which will cause a2 to become negative. |
| 1371 __ dsubu(a2, sp, a2); |
| 1372 // Check if the arguments will overflow the stack. |
| 1373 __ SmiScale(a7, v0, kPointerSizeLog2); |
| 1374 __ Branch(&okay, gt, a2, Operand(a7)); // Signed comparison. |
| 1375 |
| 1376 // Out of stack space. |
| 1377 __ ld(a1, MemOperand(fp, calleeOffset)); |
| 1378 __ Push(a1, v0); |
| 1379 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); |
| 1380 |
| 1381 __ bind(&okay); |
| 1382 } |
| 1383 |
| 1384 |
| 1385 static void Generate_PushAppliedArguments(MacroAssembler* masm, |
| 1386 const int argumentsOffset, |
| 1387 const int indexOffset, |
| 1388 const int limitOffset) { |
| 1389 Label entry, loop; |
| 1390 __ ld(a0, MemOperand(fp, indexOffset)); |
| 1391 __ Branch(&entry); |
| 1392 |
| 1393 // Load the current argument from the arguments array and push it to the |
| 1394 // stack. |
| 1395 // a0: current argument index |
| 1396 __ bind(&loop); |
| 1397 __ ld(a1, MemOperand(fp, argumentsOffset)); |
| 1398 __ Push(a1, a0); |
| 1399 |
| 1400 // Call the runtime to access the property in the arguments array. |
| 1401 __ CallRuntime(Runtime::kGetProperty, 2); |
| 1402 __ push(v0); |
| 1403 |
| 1404 // Use inline caching to access the arguments. |
| 1405 __ ld(a0, MemOperand(fp, indexOffset)); |
| 1406 __ Daddu(a0, a0, Operand(Smi::FromInt(1))); |
| 1407 __ sd(a0, MemOperand(fp, indexOffset)); |
| 1408 |
| 1409 // Test if the copy loop has finished copying all the elements from the |
| 1410 // arguments object. |
| 1411 __ bind(&entry); |
| 1412 __ ld(a1, MemOperand(fp, limitOffset)); |
| 1413 __ Branch(&loop, ne, a0, Operand(a1)); |
| 1414 |
| 1415 // On exit, the pushed arguments count is in a0, untagged |
| 1416 __ SmiUntag(a0); |
| 1417 } |
| 1418 |
| 1419 |
| 1420 // Used by FunctionApply and ReflectApply |
| 1421 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { |
| 1422 const int kFormalParameters = targetIsArgument ? 3 : 2; |
| 1423 const int kStackSize = kFormalParameters + 1; |
1370 | 1424 |
1371 { | 1425 { |
1372 FrameScope frame_scope(masm, StackFrame::INTERNAL); | 1426 FrameScope frame_scope(masm, StackFrame::INTERNAL); |
| 1427 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; |
| 1428 const int kReceiverOffset = kArgumentsOffset + kPointerSize; |
| 1429 const int kFunctionOffset = kReceiverOffset + kPointerSize; |
| 1430 |
1373 __ ld(a0, MemOperand(fp, kFunctionOffset)); // Get the function. | 1431 __ ld(a0, MemOperand(fp, kFunctionOffset)); // Get the function. |
1374 __ push(a0); | 1432 __ push(a0); |
1375 __ ld(a0, MemOperand(fp, kArgsOffset)); // Get the args array. | 1433 __ ld(a0, MemOperand(fp, kArgumentsOffset)); // Get the args array. |
1376 __ push(a0); | 1434 __ push(a0); |
| 1435 |
1377 // Returns (in v0) number of arguments to copy to stack as Smi. | 1436 // Returns (in v0) number of arguments to copy to stack as Smi. |
1378 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); | 1437 if (targetIsArgument) { |
| 1438 __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION); |
| 1439 } else { |
| 1440 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); |
| 1441 } |
1379 | 1442 |
1380 // Check the stack for overflow. We are not trying to catch | 1443 Generate_CheckStackOverflow(masm, kFunctionOffset); |
1381 // interruptions (e.g. debug break and preemption) here, so the "real stack | |
1382 // limit" is checked. | |
1383 Label okay; | |
1384 __ LoadRoot(a2, Heap::kRealStackLimitRootIndex); | |
1385 // Make a2 the space we have left. The stack might already be overflowed | |
1386 // here which will cause a2 to become negative. | |
1387 __ dsubu(a2, sp, a2); | |
1388 // Check if the arguments will overflow the stack. | |
1389 __ SmiScale(a7, v0, kPointerSizeLog2); | |
1390 __ Branch(&okay, gt, a2, Operand(a7)); // Signed comparison. | |
1391 | |
1392 // Out of stack space. | |
1393 __ ld(a1, MemOperand(fp, kFunctionOffset)); | |
1394 __ Push(a1, v0); | |
1395 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); | |
1396 // End of stack check. | |
1397 | 1444 |
1398 // Push current limit and index. | 1445 // Push current limit and index. |
1399 __ bind(&okay); | 1446 const int kIndexOffset = |
| 1447 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); |
| 1448 const int kLimitOffset = |
| 1449 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); |
1400 __ mov(a1, zero_reg); | 1450 __ mov(a1, zero_reg); |
1401 __ Push(v0, a1); // Limit and initial index. | 1451 __ Push(v0, a1); // Limit and initial index. |
1402 | 1452 |
1403 // Get the receiver. | 1453 // Get the receiver. |
1404 __ ld(a0, MemOperand(fp, kRecvOffset)); | 1454 __ ld(a0, MemOperand(fp, kReceiverOffset)); |
1405 | 1455 |
1406 // Check that the function is a JS function (otherwise it must be a proxy). | 1456 // Check that the function is a JS function (otherwise it must be a proxy). |
1407 Label push_receiver; | 1457 Label push_receiver; |
1408 __ ld(a1, MemOperand(fp, kFunctionOffset)); | 1458 __ ld(a1, MemOperand(fp, kFunctionOffset)); |
1409 __ GetObjectType(a1, a2, a2); | 1459 __ GetObjectType(a1, a2, a2); |
1410 __ Branch(&push_receiver, ne, a2, Operand(JS_FUNCTION_TYPE)); | 1460 __ Branch(&push_receiver, ne, a2, Operand(JS_FUNCTION_TYPE)); |
1411 | 1461 |
1412 // Change context eagerly to get the right global object if necessary. | 1462 // Change context eagerly to get the right global object if necessary. |
1413 __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 1463 __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
1414 // Load the shared function info while the function is still in a1. | 1464 // Load the shared function info while the function is still in a1. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1450 __ bind(&use_global_proxy); | 1500 __ bind(&use_global_proxy); |
1451 __ ld(a0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | 1501 __ ld(a0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); |
1452 __ ld(a0, FieldMemOperand(a0, GlobalObject::kGlobalProxyOffset)); | 1502 __ ld(a0, FieldMemOperand(a0, GlobalObject::kGlobalProxyOffset)); |
1453 | 1503 |
1454 // Push the receiver. | 1504 // Push the receiver. |
1455 // a0: receiver | 1505 // a0: receiver |
1456 __ bind(&push_receiver); | 1506 __ bind(&push_receiver); |
1457 __ push(a0); | 1507 __ push(a0); |
1458 | 1508 |
1459 // Copy all arguments from the array to the stack. | 1509 // Copy all arguments from the array to the stack. |
1460 Label entry, loop; | 1510 Generate_PushAppliedArguments( |
1461 __ ld(a0, MemOperand(fp, kIndexOffset)); | 1511 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); |
1462 __ Branch(&entry); | |
1463 | |
1464 // Load the current argument from the arguments array and push it to the | |
1465 // stack. | |
1466 // a0: current argument index | |
1467 __ bind(&loop); | |
1468 __ ld(a1, MemOperand(fp, kArgsOffset)); | |
1469 __ Push(a1, a0); | |
1470 | |
1471 // Call the runtime to access the property in the arguments array. | |
1472 __ CallRuntime(Runtime::kGetProperty, 2); | |
1473 __ push(v0); | |
1474 | |
1475 // Use inline caching to access the arguments. | |
1476 __ ld(a0, MemOperand(fp, kIndexOffset)); | |
1477 __ Daddu(a0, a0, Operand(Smi::FromInt(1))); | |
1478 __ sd(a0, MemOperand(fp, kIndexOffset)); | |
1479 | |
1480 // Test if the copy loop has finished copying all the elements from the | |
1481 // arguments object. | |
1482 __ bind(&entry); | |
1483 __ ld(a1, MemOperand(fp, kLimitOffset)); | |
1484 __ Branch(&loop, ne, a0, Operand(a1)); | |
1485 | 1512 |
1486 // Call the function. | 1513 // Call the function. |
1487 Label call_proxy; | 1514 Label call_proxy; |
1488 ParameterCount actual(a0); | 1515 ParameterCount actual(a0); |
1489 __ SmiUntag(a0); | |
1490 __ ld(a1, MemOperand(fp, kFunctionOffset)); | 1516 __ ld(a1, MemOperand(fp, kFunctionOffset)); |
1491 __ GetObjectType(a1, a2, a2); | 1517 __ GetObjectType(a1, a2, a2); |
1492 __ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE)); | 1518 __ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE)); |
1493 | 1519 |
1494 __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper()); | 1520 __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper()); |
1495 | 1521 |
1496 frame_scope.GenerateLeaveFrame(); | 1522 frame_scope.GenerateLeaveFrame(); |
1497 __ Ret(USE_DELAY_SLOT); | 1523 __ Ret(USE_DELAY_SLOT); |
1498 __ Daddu(sp, sp, Operand(3 * kPointerSize)); // In delay slot. | 1524 __ Daddu(sp, sp, Operand(kStackSize * kPointerSize)); // In delay slot. |
1499 | 1525 |
1500 // Call the function proxy. | 1526 // Call the function proxy. |
1501 __ bind(&call_proxy); | 1527 __ bind(&call_proxy); |
1502 __ push(a1); // Add function proxy as last argument. | 1528 __ push(a1); // Add function proxy as last argument. |
1503 __ Daddu(a0, a0, Operand(1)); | 1529 __ Daddu(a0, a0, Operand(1)); |
1504 __ li(a2, Operand(0, RelocInfo::NONE32)); | 1530 __ li(a2, Operand(0, RelocInfo::NONE32)); |
1505 __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY); | 1531 __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY); |
1506 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1532 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1507 RelocInfo::CODE_TARGET); | 1533 RelocInfo::CODE_TARGET); |
1508 // Tear down the internal frame and remove function, receiver and args. | 1534 // Tear down the internal frame and remove function, receiver and args. |
1509 } | 1535 } |
1510 | 1536 |
1511 __ Ret(USE_DELAY_SLOT); | 1537 __ Ret(USE_DELAY_SLOT); |
1512 __ Daddu(sp, sp, Operand(3 * kPointerSize)); // In delay slot. | 1538 __ Daddu(sp, sp, Operand(kStackSize * kPointerSize)); // In delay slot. |
1513 } | 1539 } |
1514 | 1540 |
1515 | 1541 |
| 1542 static void Generate_ConstructHelper(MacroAssembler* masm) { |
| 1543 const int kFormalParameters = 3; |
| 1544 const int kStackSize = kFormalParameters + 1; |
| 1545 |
| 1546 { |
| 1547 FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); |
| 1548 const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; |
| 1549 const int kArgumentsOffset = kNewTargetOffset + kPointerSize; |
| 1550 const int kFunctionOffset = kArgumentsOffset + kPointerSize; |
| 1551 |
| 1552 // If newTarget is not supplied, set it to constructor |
| 1553 Label validate_arguments; |
| 1554 __ ld(a0, MemOperand(fp, kNewTargetOffset)); |
| 1555 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 1556 __ Branch(&validate_arguments, ne, a0, Operand(at)); |
| 1557 __ ld(a0, MemOperand(fp, kFunctionOffset)); |
| 1558 __ sd(a0, MemOperand(fp, kNewTargetOffset)); |
| 1559 |
| 1560 // Validate arguments |
| 1561 __ bind(&validate_arguments); |
| 1562 __ ld(a0, MemOperand(fp, kFunctionOffset)); // get the function |
| 1563 __ push(a0); |
| 1564 __ ld(a0, MemOperand(fp, kArgumentsOffset)); // get the args array |
| 1565 __ push(a0); |
| 1566 __ ld(a0, MemOperand(fp, kNewTargetOffset)); // get the new.target |
| 1567 __ push(a0); |
| 1568 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION); |
| 1569 |
| 1570 Generate_CheckStackOverflow(masm, kFunctionOffset); |
| 1571 |
| 1572 // Push current limit and index. |
| 1573 const int kIndexOffset = |
| 1574 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); |
| 1575 const int kLimitOffset = |
| 1576 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); |
| 1577 __ push(v0); // limit |
| 1578 __ mov(a1, zero_reg); // initial index |
| 1579 __ push(a1); |
| 1580 // Push newTarget and callee functions |
| 1581 __ ld(a0, MemOperand(fp, kNewTargetOffset)); |
| 1582 __ push(a0); |
| 1583 __ ld(a0, MemOperand(fp, kFunctionOffset)); |
| 1584 __ push(a0); |
| 1585 |
| 1586 // Copy all arguments from the array to the stack. |
| 1587 Generate_PushAppliedArguments( |
| 1588 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); |
| 1589 |
| 1590 // Use undefined feedback vector |
| 1591 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); |
| 1592 __ ld(a1, MemOperand(fp, kFunctionOffset)); |
| 1593 |
| 1594 // Call the function. |
| 1595 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL); |
| 1596 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
| 1597 |
| 1598 __ Drop(1); |
| 1599 |
| 1600 // Leave internal frame. |
| 1601 } |
| 1602 __ Daddu(sp, sp, Operand(kStackSize * kPointerSize)); |
| 1603 __ Jump(ra); |
| 1604 } |
| 1605 |
| 1606 |
| 1607 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
| 1608 Generate_ApplyHelper(masm, false); |
| 1609 } |
| 1610 |
| 1611 |
| 1612 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { |
| 1613 Generate_ApplyHelper(masm, true); |
| 1614 } |
| 1615 |
| 1616 |
| 1617 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { |
| 1618 Generate_ConstructHelper(masm); |
| 1619 } |
| 1620 |
| 1621 |
1516 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, | 1622 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, |
1517 Label* stack_overflow) { | 1623 Label* stack_overflow) { |
1518 // ----------- S t a t e ------------- | 1624 // ----------- S t a t e ------------- |
1519 // -- a0 : actual number of arguments | 1625 // -- a0 : actual number of arguments |
1520 // -- a1 : function (passed through to callee) | 1626 // -- a1 : function (passed through to callee) |
1521 // -- a2 : expected number of arguments | 1627 // -- a2 : expected number of arguments |
1522 // ----------------------------------- | 1628 // ----------------------------------- |
1523 // Check the stack for overflow. We are not trying to catch | 1629 // Check the stack for overflow. We are not trying to catch |
1524 // interruptions (e.g. debug break and preemption) here, so the "real stack | 1630 // interruptions (e.g. debug break and preemption) here, so the "real stack |
1525 // limit" is checked. | 1631 // limit" is checked. |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1688 __ break_(0xCC); | 1794 __ break_(0xCC); |
1689 } | 1795 } |
1690 } | 1796 } |
1691 | 1797 |
1692 | 1798 |
1693 #undef __ | 1799 #undef __ |
1694 | 1800 |
1695 } } // namespace v8::internal | 1801 } } // namespace v8::internal |
1696 | 1802 |
1697 #endif // V8_TARGET_ARCH_MIPS64 | 1803 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |