| 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/debug.h" | 10 #include "src/debug.h" |
| (...skipping 1318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1329 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1329 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 1330 RelocInfo::CODE_TARGET, | 1330 RelocInfo::CODE_TARGET, |
| 1331 ne); | 1331 ne); |
| 1332 | 1332 |
| 1333 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 1333 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
| 1334 ParameterCount expected(0); | 1334 ParameterCount expected(0); |
| 1335 __ InvokeCode(r3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); | 1335 __ InvokeCode(r3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); |
| 1336 } | 1336 } |
| 1337 | 1337 |
| 1338 | 1338 |
| 1339 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 1339 static void Generate_CheckStackOverflow(MacroAssembler* masm, |
| 1340 const int kIndexOffset = | 1340 const int calleeOffset) { |
| 1341 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); | 1341 // Check the stack for overflow. We are not trying to catch |
| 1342 const int kLimitOffset = | 1342 // interruptions (e.g. debug break and preemption) here, so the "real stack |
| 1343 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); | 1343 // limit" is checked. |
| 1344 const int kArgsOffset = 2 * kPointerSize; | 1344 Label okay; |
| 1345 const int kRecvOffset = 3 * kPointerSize; | 1345 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); |
| 1346 const int kFunctionOffset = 4 * kPointerSize; | 1346 // Make r2 the space we have left. The stack might already be overflowed |
| 1347 // here which will cause r2 to become negative. |
| 1348 __ sub(r2, sp, r2); |
| 1349 // Check if the arguments will overflow the stack. |
| 1350 __ cmp(r2, Operand::PointerOffsetFromSmiKey(r0)); |
| 1351 __ b(gt, &okay); // Signed comparison. |
| 1352 |
| 1353 // Out of stack space. |
| 1354 __ ldr(r1, MemOperand(fp, calleeOffset)); |
| 1355 __ Push(r1, r0); |
| 1356 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); |
| 1357 |
| 1358 __ bind(&okay); |
| 1359 } |
| 1360 |
| 1361 |
| 1362 static void Generate_PushAppliedArguments(MacroAssembler* masm, |
| 1363 const int argumentsOffset, |
| 1364 const int indexOffset, |
| 1365 const int limitOffset) { |
| 1366 Label entry, loop; |
| 1367 __ ldr(r0, MemOperand(fp, indexOffset)); |
| 1368 __ b(&entry); |
| 1369 |
| 1370 // Load the current argument from the arguments array and push it to the |
| 1371 // stack. |
| 1372 // r0: current argument index |
| 1373 __ bind(&loop); |
| 1374 __ ldr(r1, MemOperand(fp, argumentsOffset)); |
| 1375 __ Push(r1, r0); |
| 1376 |
| 1377 // Call the runtime to access the property in the arguments array. |
| 1378 __ CallRuntime(Runtime::kGetProperty, 2); |
| 1379 __ push(r0); |
| 1380 |
| 1381 // Use inline caching to access the arguments. |
| 1382 __ ldr(r0, MemOperand(fp, indexOffset)); |
| 1383 __ add(r0, r0, Operand(1 << kSmiTagSize)); |
| 1384 __ str(r0, MemOperand(fp, indexOffset)); |
| 1385 |
| 1386 // Test if the copy loop has finished copying all the elements from the |
| 1387 // arguments object. |
| 1388 __ bind(&entry); |
| 1389 __ ldr(r1, MemOperand(fp, limitOffset)); |
| 1390 __ cmp(r0, r1); |
| 1391 __ b(ne, &loop); |
| 1392 |
| 1393 // On exit, the pushed arguments count is in r0, untagged |
| 1394 __ SmiUntag(r0); |
| 1395 } |
| 1396 |
| 1397 |
| 1398 // Used by FunctionApply and ReflectApply |
| 1399 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { |
| 1400 const int kFormalParameters = targetIsArgument ? 3 : 2; |
| 1401 const int kStackSize = kFormalParameters + 1; |
| 1347 | 1402 |
| 1348 { | 1403 { |
| 1349 FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); | 1404 FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); |
| 1405 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; |
| 1406 const int kReceiverOffset = kArgumentsOffset + kPointerSize; |
| 1407 const int kFunctionOffset = kReceiverOffset + kPointerSize; |
| 1350 | 1408 |
| 1351 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function | 1409 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function |
| 1352 __ push(r0); | 1410 __ push(r0); |
| 1353 __ ldr(r0, MemOperand(fp, kArgsOffset)); // get the args array | 1411 __ ldr(r0, MemOperand(fp, kArgumentsOffset)); // get the args array |
| 1354 __ push(r0); | 1412 __ push(r0); |
| 1355 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); | 1413 if (targetIsArgument) { |
| 1414 __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION); |
| 1415 } else { |
| 1416 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); |
| 1417 } |
| 1356 | 1418 |
| 1357 // Check the stack for overflow. We are not trying to catch | 1419 Generate_CheckStackOverflow(masm, kFunctionOffset); |
| 1358 // interruptions (e.g. debug break and preemption) here, so the "real stack | |
| 1359 // limit" is checked. | |
| 1360 Label okay; | |
| 1361 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); | |
| 1362 // Make r2 the space we have left. The stack might already be overflowed | |
| 1363 // here which will cause r2 to become negative. | |
| 1364 __ sub(r2, sp, r2); | |
| 1365 // Check if the arguments will overflow the stack. | |
| 1366 __ cmp(r2, Operand::PointerOffsetFromSmiKey(r0)); | |
| 1367 __ b(gt, &okay); // Signed comparison. | |
| 1368 | |
| 1369 // Out of stack space. | |
| 1370 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | |
| 1371 __ Push(r1, r0); | |
| 1372 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); | |
| 1373 // End of stack check. | |
| 1374 | 1420 |
| 1375 // Push current limit and index. | 1421 // Push current limit and index. |
| 1376 __ bind(&okay); | 1422 const int kIndexOffset = |
| 1423 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); |
| 1424 const int kLimitOffset = |
| 1425 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); |
| 1377 __ push(r0); // limit | 1426 __ push(r0); // limit |
| 1378 __ mov(r1, Operand::Zero()); // initial index | 1427 __ mov(r1, Operand::Zero()); // initial index |
| 1379 __ push(r1); | 1428 __ push(r1); |
| 1380 | 1429 |
| 1381 // Get the receiver. | 1430 // Get the receiver. |
| 1382 __ ldr(r0, MemOperand(fp, kRecvOffset)); | 1431 __ ldr(r0, MemOperand(fp, kReceiverOffset)); |
| 1383 | 1432 |
| 1384 // Check that the function is a JS function (otherwise it must be a proxy). | 1433 // Check that the function is a JS function (otherwise it must be a proxy). |
| 1385 Label push_receiver; | 1434 Label push_receiver; |
| 1386 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | 1435 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
| 1387 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 1436 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
| 1388 __ b(ne, &push_receiver); | 1437 __ b(ne, &push_receiver); |
| 1389 | 1438 |
| 1390 // Change context eagerly to get the right global object if necessary. | 1439 // Change context eagerly to get the right global object if necessary. |
| 1391 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1440 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 1392 // Load the shared function info while the function is still in r1. | 1441 // Load the shared function info while the function is still in r1. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1429 __ bind(&use_global_proxy); | 1478 __ bind(&use_global_proxy); |
| 1430 __ ldr(r0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | 1479 __ ldr(r0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); |
| 1431 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalProxyOffset)); | 1480 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalProxyOffset)); |
| 1432 | 1481 |
| 1433 // Push the receiver. | 1482 // Push the receiver. |
| 1434 // r0: receiver | 1483 // r0: receiver |
| 1435 __ bind(&push_receiver); | 1484 __ bind(&push_receiver); |
| 1436 __ push(r0); | 1485 __ push(r0); |
| 1437 | 1486 |
| 1438 // Copy all arguments from the array to the stack. | 1487 // Copy all arguments from the array to the stack. |
| 1439 Label entry, loop; | 1488 Generate_PushAppliedArguments( |
| 1440 __ ldr(r0, MemOperand(fp, kIndexOffset)); | 1489 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); |
| 1441 __ b(&entry); | |
| 1442 | |
| 1443 // Load the current argument from the arguments array and push it to the | |
| 1444 // stack. | |
| 1445 // r0: current argument index | |
| 1446 __ bind(&loop); | |
| 1447 __ ldr(r1, MemOperand(fp, kArgsOffset)); | |
| 1448 __ Push(r1, r0); | |
| 1449 | |
| 1450 // Call the runtime to access the property in the arguments array. | |
| 1451 __ CallRuntime(Runtime::kGetProperty, 2); | |
| 1452 __ push(r0); | |
| 1453 | |
| 1454 // Use inline caching to access the arguments. | |
| 1455 __ ldr(r0, MemOperand(fp, kIndexOffset)); | |
| 1456 __ add(r0, r0, Operand(1 << kSmiTagSize)); | |
| 1457 __ str(r0, MemOperand(fp, kIndexOffset)); | |
| 1458 | |
| 1459 // Test if the copy loop has finished copying all the elements from the | |
| 1460 // arguments object. | |
| 1461 __ bind(&entry); | |
| 1462 __ ldr(r1, MemOperand(fp, kLimitOffset)); | |
| 1463 __ cmp(r0, r1); | |
| 1464 __ b(ne, &loop); | |
| 1465 | 1490 |
| 1466 // Call the function. | 1491 // Call the function. |
| 1467 Label call_proxy; | 1492 Label call_proxy; |
| 1468 ParameterCount actual(r0); | 1493 ParameterCount actual(r0); |
| 1469 __ SmiUntag(r0); | |
| 1470 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | 1494 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
| 1471 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 1495 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
| 1472 __ b(ne, &call_proxy); | 1496 __ b(ne, &call_proxy); |
| 1473 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); | 1497 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); |
| 1474 | 1498 |
| 1475 frame_scope.GenerateLeaveFrame(); | 1499 frame_scope.GenerateLeaveFrame(); |
| 1476 __ add(sp, sp, Operand(3 * kPointerSize)); | 1500 __ add(sp, sp, Operand(kStackSize * kPointerSize)); |
| 1477 __ Jump(lr); | 1501 __ Jump(lr); |
| 1478 | 1502 |
| 1479 // Call the function proxy. | 1503 // Call the function proxy. |
| 1480 __ bind(&call_proxy); | 1504 __ bind(&call_proxy); |
| 1481 __ push(r1); // add function proxy as last argument | 1505 __ push(r1); // add function proxy as last argument |
| 1482 __ add(r0, r0, Operand(1)); | 1506 __ add(r0, r0, Operand(1)); |
| 1483 __ mov(r2, Operand::Zero()); | 1507 __ mov(r2, Operand::Zero()); |
| 1484 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY); | 1508 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY); |
| 1485 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1509 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 1486 RelocInfo::CODE_TARGET); | 1510 RelocInfo::CODE_TARGET); |
| 1487 | 1511 |
| 1488 // Tear down the internal frame and remove function, receiver and args. | 1512 // Tear down the internal frame and remove function, receiver and args. |
| 1489 } | 1513 } |
| 1490 __ add(sp, sp, Operand(3 * kPointerSize)); | 1514 __ add(sp, sp, Operand(kStackSize * kPointerSize)); |
| 1491 __ Jump(lr); | 1515 __ Jump(lr); |
| 1492 } | 1516 } |
| 1493 | 1517 |
| 1494 | 1518 |
| 1519 static void Generate_ConstructHelper(MacroAssembler* masm) { |
| 1520 const int kFormalParameters = 3; |
| 1521 const int kStackSize = kFormalParameters + 1; |
| 1522 |
| 1523 { |
| 1524 FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); |
| 1525 const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; |
| 1526 const int kArgumentsOffset = kNewTargetOffset + kPointerSize; |
| 1527 const int kFunctionOffset = kArgumentsOffset + kPointerSize; |
| 1528 |
| 1529 // If newTarget is not supplied, set it to constructor |
| 1530 Label validate_arguments; |
| 1531 __ ldr(r0, MemOperand(fp, kNewTargetOffset)); |
| 1532 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); |
| 1533 __ b(ne, &validate_arguments); |
| 1534 __ ldr(r0, MemOperand(fp, kFunctionOffset)); |
| 1535 __ str(r0, MemOperand(fp, kNewTargetOffset)); |
| 1536 |
| 1537 // Validate arguments |
| 1538 __ bind(&validate_arguments); |
| 1539 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function |
| 1540 __ push(r0); |
| 1541 __ ldr(r0, MemOperand(fp, kArgumentsOffset)); // get the args array |
| 1542 __ push(r0); |
| 1543 __ ldr(r0, MemOperand(fp, kNewTargetOffset)); // get the new.target |
| 1544 __ push(r0); |
| 1545 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION); |
| 1546 |
| 1547 Generate_CheckStackOverflow(masm, kFunctionOffset); |
| 1548 |
| 1549 // Push current limit and index. |
| 1550 const int kIndexOffset = |
| 1551 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); |
| 1552 const int kLimitOffset = |
| 1553 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); |
| 1554 __ push(r0); // limit |
| 1555 __ mov(r1, Operand::Zero()); // initial index |
| 1556 __ push(r1); |
| 1557 // Push newTarget and callee functions |
| 1558 __ ldr(r0, MemOperand(fp, kNewTargetOffset)); |
| 1559 __ push(r0); |
| 1560 __ ldr(r0, MemOperand(fp, kFunctionOffset)); |
| 1561 __ push(r0); |
| 1562 |
| 1563 // Copy all arguments from the array to the stack. |
| 1564 Generate_PushAppliedArguments( |
| 1565 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); |
| 1566 |
| 1567 // Use undefined feedback vector |
| 1568 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
| 1569 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
| 1570 |
| 1571 // Call the function. |
| 1572 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL); |
| 1573 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
| 1574 |
| 1575 __ Drop(1); |
| 1576 |
| 1577 // Leave internal frame. |
| 1578 } |
| 1579 __ add(sp, sp, Operand(kStackSize * kPointerSize)); |
| 1580 __ Jump(lr); |
| 1581 } |
| 1582 |
| 1583 |
| 1584 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
| 1585 Generate_ApplyHelper(masm, false); |
| 1586 } |
| 1587 |
| 1588 |
| 1589 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { |
| 1590 Generate_ApplyHelper(masm, true); |
| 1591 } |
| 1592 |
| 1593 |
| 1594 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { |
| 1595 Generate_ConstructHelper(masm); |
| 1596 } |
| 1597 |
| 1598 |
| 1495 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, | 1599 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, |
| 1496 Label* stack_overflow) { | 1600 Label* stack_overflow) { |
| 1497 // ----------- S t a t e ------------- | 1601 // ----------- S t a t e ------------- |
| 1498 // -- r0 : actual number of arguments | 1602 // -- r0 : actual number of arguments |
| 1499 // -- r1 : function (passed through to callee) | 1603 // -- r1 : function (passed through to callee) |
| 1500 // -- r2 : expected number of arguments | 1604 // -- r2 : expected number of arguments |
| 1501 // ----------------------------------- | 1605 // ----------------------------------- |
| 1502 // Check the stack for overflow. We are not trying to catch | 1606 // Check the stack for overflow. We are not trying to catch |
| 1503 // interruptions (e.g. debug break and preemption) here, so the "real stack | 1607 // interruptions (e.g. debug break and preemption) here, so the "real stack |
| 1504 // limit" is checked. | 1608 // limit" is checked. |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 __ bkpt(0); | 1759 __ bkpt(0); |
| 1656 } | 1760 } |
| 1657 } | 1761 } |
| 1658 | 1762 |
| 1659 | 1763 |
| 1660 #undef __ | 1764 #undef __ |
| 1661 | 1765 |
| 1662 } } // namespace v8::internal | 1766 } } // namespace v8::internal |
| 1663 | 1767 |
| 1664 #endif // V8_TARGET_ARCH_ARM | 1768 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |