Chromium Code Reviews| 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 r0, untagged | |
|
paul.l...
2015/03/19 22:35:40
nit: regname a0
akos.palfi.imgtec
2015/03/20 00:07:24
Done.
| |
| 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(a0); // 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 |