| 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 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); |
| 1356 | 1414 |
| 1357 // Check the stack for overflow. We are not trying to catch | 1415 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 | 1416 |
| 1375 // Push current limit and index. | 1417 // Push current limit and index. |
| 1376 __ bind(&okay); | 1418 const int kIndexOffset = |
| 1419 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); |
| 1420 const int kLimitOffset = |
| 1421 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); |
| 1377 __ push(r0); // limit | 1422 __ push(r0); // limit |
| 1378 __ mov(r1, Operand::Zero()); // initial index | 1423 __ mov(r1, Operand::Zero()); // initial index |
| 1379 __ push(r1); | 1424 __ push(r1); |
| 1380 | 1425 |
| 1381 // Get the receiver. | 1426 // Get the receiver. |
| 1382 __ ldr(r0, MemOperand(fp, kRecvOffset)); | 1427 __ ldr(r0, MemOperand(fp, kReceiverOffset)); |
| 1383 | 1428 |
| 1384 // Check that the function is a JS function (otherwise it must be a proxy). | 1429 // Check that the function is a JS function (otherwise it must be a proxy). |
| 1385 Label push_receiver; | 1430 Label push_receiver; |
| 1386 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | 1431 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
| 1387 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 1432 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
| 1388 __ b(ne, &push_receiver); | 1433 __ b(ne, &push_receiver); |
| 1389 | 1434 |
| 1390 // Change context eagerly to get the right global object if necessary. | 1435 // Change context eagerly to get the right global object if necessary. |
| 1391 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1436 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 1392 // Load the shared function info while the function is still in r1. | 1437 // 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); | 1474 __ bind(&use_global_proxy); |
| 1430 __ ldr(r0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | 1475 __ ldr(r0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); |
| 1431 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalProxyOffset)); | 1476 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalProxyOffset)); |
| 1432 | 1477 |
| 1433 // Push the receiver. | 1478 // Push the receiver. |
| 1434 // r0: receiver | 1479 // r0: receiver |
| 1435 __ bind(&push_receiver); | 1480 __ bind(&push_receiver); |
| 1436 __ push(r0); | 1481 __ push(r0); |
| 1437 | 1482 |
| 1438 // Copy all arguments from the array to the stack. | 1483 // Copy all arguments from the array to the stack. |
| 1439 Label entry, loop; | 1484 Generate_PushAppliedArguments( |
| 1440 __ ldr(r0, MemOperand(fp, kIndexOffset)); | 1485 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 | 1486 |
| 1466 // Call the function. | 1487 // Call the function. |
| 1467 Label call_proxy; | 1488 Label call_proxy; |
| 1468 ParameterCount actual(r0); | 1489 ParameterCount actual(r0); |
| 1469 __ SmiUntag(r0); | |
| 1470 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | 1490 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
| 1471 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 1491 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
| 1472 __ b(ne, &call_proxy); | 1492 __ b(ne, &call_proxy); |
| 1473 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); | 1493 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); |
| 1474 | 1494 |
| 1475 frame_scope.GenerateLeaveFrame(); | 1495 frame_scope.GenerateLeaveFrame(); |
| 1476 __ add(sp, sp, Operand(3 * kPointerSize)); | 1496 __ add(sp, sp, Operand(kStackSize * kPointerSize)); |
| 1477 __ Jump(lr); | 1497 __ Jump(lr); |
| 1478 | 1498 |
| 1479 // Call the function proxy. | 1499 // Call the function proxy. |
| 1480 __ bind(&call_proxy); | 1500 __ bind(&call_proxy); |
| 1481 __ push(r1); // add function proxy as last argument | 1501 __ push(r1); // add function proxy as last argument |
| 1482 __ add(r0, r0, Operand(1)); | 1502 __ add(r0, r0, Operand(1)); |
| 1483 __ mov(r2, Operand::Zero()); | 1503 __ mov(r2, Operand::Zero()); |
| 1484 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY); | 1504 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY); |
| 1485 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1505 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 1486 RelocInfo::CODE_TARGET); | 1506 RelocInfo::CODE_TARGET); |
| 1487 | 1507 |
| 1488 // Tear down the internal frame and remove function, receiver and args. | 1508 // Tear down the internal frame and remove function, receiver and args. |
| 1489 } | 1509 } |
| 1490 __ add(sp, sp, Operand(3 * kPointerSize)); | 1510 __ add(sp, sp, Operand(kStackSize * kPointerSize)); |
| 1491 __ Jump(lr); | 1511 __ Jump(lr); |
| 1492 } | 1512 } |
| 1493 | 1513 |
| 1494 | 1514 |
| 1515 static void Generate_ConstructHelper(MacroAssembler* masm) { |
| 1516 const int kFormalParameters = 3; |
| 1517 const int kStackSize = kFormalParameters + 1; |
| 1518 |
| 1519 { |
| 1520 FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); |
| 1521 const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; |
| 1522 const int kArgumentsOffset = kNewTargetOffset + kPointerSize; |
| 1523 const int kFunctionOffset = kArgumentsOffset + kPointerSize; |
| 1524 |
| 1525 // If newTarget is not supplied, set it to constructor |
| 1526 Label validate_arguments; |
| 1527 __ ldr(r0, MemOperand(fp, kNewTargetOffset)); |
| 1528 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); |
| 1529 __ b(ne, &validate_arguments); |
| 1530 __ ldr(r0, MemOperand(fp, kFunctionOffset)); |
| 1531 __ str(r0, MemOperand(fp, kNewTargetOffset)); |
| 1532 |
| 1533 // Validate arguments |
| 1534 __ bind(&validate_arguments); |
| 1535 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function |
| 1536 __ push(r0); |
| 1537 __ ldr(r0, MemOperand(fp, kArgumentsOffset)); // get the args array |
| 1538 __ push(r0); |
| 1539 __ ldr(r0, MemOperand(fp, kNewTargetOffset)); // get the new.target |
| 1540 __ push(r0); |
| 1541 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION); |
| 1542 |
| 1543 Generate_CheckStackOverflow(masm, kFunctionOffset); |
| 1544 |
| 1545 // Push current limit and index. |
| 1546 const int kIndexOffset = |
| 1547 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); |
| 1548 const int kLimitOffset = |
| 1549 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); |
| 1550 __ push(r0); // limit |
| 1551 __ mov(r1, Operand::Zero()); // initial index |
| 1552 __ push(r1); |
| 1553 // Push newTarget and callee functions |
| 1554 __ ldr(r0, MemOperand(fp, kNewTargetOffset)); |
| 1555 __ push(r0); |
| 1556 __ ldr(r0, MemOperand(fp, kFunctionOffset)); |
| 1557 __ push(r0); |
| 1558 |
| 1559 // Copy all arguments from the array to the stack. |
| 1560 Generate_PushAppliedArguments( |
| 1561 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); |
| 1562 |
| 1563 // Use undefined feedback vector |
| 1564 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
| 1565 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
| 1566 |
| 1567 // Call the function. |
| 1568 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL); |
| 1569 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
| 1570 |
| 1571 __ Drop(1); |
| 1572 |
| 1573 // Leave internal frame. |
| 1574 } |
| 1575 __ add(sp, sp, Operand(kStackSize * kPointerSize)); |
| 1576 __ Jump(lr); |
| 1577 } |
| 1578 |
| 1579 |
| 1580 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
| 1581 Generate_ApplyHelper(masm, false); |
| 1582 } |
| 1583 |
| 1584 |
| 1585 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { |
| 1586 Generate_ApplyHelper(masm, true); |
| 1587 } |
| 1588 |
| 1589 |
| 1590 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { |
| 1591 Generate_ConstructHelper(masm); |
| 1592 } |
| 1593 |
| 1594 |
| 1495 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, | 1595 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, |
| 1496 Label* stack_overflow) { | 1596 Label* stack_overflow) { |
| 1497 // ----------- S t a t e ------------- | 1597 // ----------- S t a t e ------------- |
| 1498 // -- r0 : actual number of arguments | 1598 // -- r0 : actual number of arguments |
| 1499 // -- r1 : function (passed through to callee) | 1599 // -- r1 : function (passed through to callee) |
| 1500 // -- r2 : expected number of arguments | 1600 // -- r2 : expected number of arguments |
| 1501 // ----------------------------------- | 1601 // ----------------------------------- |
| 1502 // Check the stack for overflow. We are not trying to catch | 1602 // Check the stack for overflow. We are not trying to catch |
| 1503 // interruptions (e.g. debug break and preemption) here, so the "real stack | 1603 // interruptions (e.g. debug break and preemption) here, so the "real stack |
| 1504 // limit" is checked. | 1604 // limit" is checked. |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 __ bkpt(0); | 1755 __ bkpt(0); |
| 1656 } | 1756 } |
| 1657 } | 1757 } |
| 1658 | 1758 |
| 1659 | 1759 |
| 1660 #undef __ | 1760 #undef __ |
| 1661 | 1761 |
| 1662 } } // namespace v8::internal | 1762 } } // namespace v8::internal |
| 1663 | 1763 |
| 1664 #endif // V8_TARGET_ARCH_ARM | 1764 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |