| OLD | NEW | 
|     1 // Copyright 2013 the V8 project authors. All rights reserved. |     1 // Copyright 2013 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_ARM64 |     7 #if V8_TARGET_ARCH_ARM64 | 
|     8  |     8  | 
|     9 #include "src/codegen.h" |     9 #include "src/codegen.h" | 
|    10 #include "src/debug.h" |    10 #include "src/debug.h" | 
| (...skipping 1306 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1317   __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |  1317   __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 
|  1318           RelocInfo::CODE_TARGET); |  1318           RelocInfo::CODE_TARGET); | 
|  1319   __ Bind(&dont_adapt_args); |  1319   __ Bind(&dont_adapt_args); | 
|  1320  |  1320  | 
|  1321   __ Ldr(x3, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); |  1321   __ Ldr(x3, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); | 
|  1322   ParameterCount expected(0); |  1322   ParameterCount expected(0); | 
|  1323   __ InvokeCode(x3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); |  1323   __ InvokeCode(x3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); | 
|  1324 } |  1324 } | 
|  1325  |  1325  | 
|  1326  |  1326  | 
|  1327 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |  1327 static void Generate_CheckStackOverflow(MacroAssembler* masm, | 
|  1328   ASM_LOCATION("Builtins::Generate_FunctionApply"); |  1328                                         const int calleeOffset) { | 
|  1329   const int kIndexOffset    = |  1329   Register argc = x0; | 
|  1330       StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); |  1330   Register receiver = x14; | 
|  1331   const int kLimitOffset    = |  1331   Register function = x15; | 
|  1332       StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); |  1332  | 
|  1333   const int kArgsOffset     =  2 * kPointerSize; |  1333   // Check the stack for overflow. | 
|  1334   const int kReceiverOffset =  3 * kPointerSize; |  1334   // We are not trying to catch interruptions (e.g. debug break and | 
|  1335   const int kFunctionOffset =  4 * kPointerSize; |  1335   // preemption) here, so the "real stack limit" is checked. | 
 |  1336   Label enough_stack_space; | 
 |  1337   __ LoadRoot(x10, Heap::kRealStackLimitRootIndex); | 
 |  1338   __ Ldr(function, MemOperand(fp, calleeOffset)); | 
 |  1339   // Make x10 the space we have left. The stack might already be overflowed | 
 |  1340   // here which will cause x10 to become negative. | 
 |  1341   // TODO(jbramley): Check that the stack usage here is safe. | 
 |  1342   __ Sub(x10, jssp, x10); | 
 |  1343   // Check if the arguments will overflow the stack. | 
 |  1344   __ Cmp(x10, Operand::UntagSmiAndScale(argc, kPointerSizeLog2)); | 
 |  1345   __ B(gt, &enough_stack_space); | 
 |  1346   // There is not enough stack space, so use a builtin to throw an appropriate | 
 |  1347   // error. | 
 |  1348   __ Push(function, argc); | 
 |  1349   __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); | 
 |  1350   // We should never return from the APPLY_OVERFLOW builtin. | 
 |  1351   if (__ emit_debug_code()) { | 
 |  1352     __ Unreachable(); | 
 |  1353   } | 
 |  1354  | 
 |  1355   __ Bind(&enough_stack_space); | 
 |  1356 } | 
 |  1357  | 
 |  1358  | 
 |  1359 static void Generate_PushAppliedArguments(MacroAssembler* masm, | 
 |  1360                                           const int argumentsOffset, | 
 |  1361                                           const int indexOffset, | 
 |  1362                                           const int limitOffset) { | 
 |  1363   Label entry, loop; | 
 |  1364   Register current = x0; | 
 |  1365   __ Ldr(current, MemOperand(fp, indexOffset)); | 
 |  1366   __ B(&entry); | 
 |  1367  | 
 |  1368   __ Bind(&loop); | 
 |  1369   // Load the current argument from the arguments array and push it. | 
 |  1370   // TODO(all): Couldn't we optimize this for JS arrays? | 
 |  1371  | 
 |  1372   __ Ldr(x1, MemOperand(fp, argumentsOffset)); | 
 |  1373   __ Push(x1, current); | 
 |  1374  | 
 |  1375   // Call the runtime to access the property in the arguments array. | 
 |  1376   __ CallRuntime(Runtime::kGetProperty, 2); | 
 |  1377   __ Push(x0); | 
 |  1378  | 
 |  1379   // Use inline caching to access the arguments. | 
 |  1380   __ Ldr(current, MemOperand(fp, indexOffset)); | 
 |  1381   __ Add(current, current, Smi::FromInt(1)); | 
 |  1382   __ Str(current, MemOperand(fp, indexOffset)); | 
 |  1383  | 
 |  1384   // Test if the copy loop has finished copying all the elements from the | 
 |  1385   // arguments object. | 
 |  1386   __ Bind(&entry); | 
 |  1387   __ Ldr(x1, MemOperand(fp, limitOffset)); | 
 |  1388   __ Cmp(current, x1); | 
 |  1389   __ B(ne, &loop); | 
 |  1390  | 
 |  1391   // On exit, the pushed arguments count is in x0, untagged | 
 |  1392   __ SmiUntag(current); | 
 |  1393 } | 
 |  1394  | 
 |  1395  | 
 |  1396 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { | 
 |  1397   const int kFormalParameters = targetIsArgument ? 3 : 2; | 
 |  1398   const int kStackSize = kFormalParameters + 1; | 
|  1336  |  1399  | 
|  1337   { |  1400   { | 
|  1338     FrameScope frame_scope(masm, StackFrame::INTERNAL); |  1401     FrameScope frame_scope(masm, StackFrame::INTERNAL); | 
|  1339  |  1402  | 
 |  1403     const int kArgumentsOffset =  kFPOnStackSize + kPCOnStackSize; | 
 |  1404     const int kReceiverOffset = kArgumentsOffset + kPointerSize; | 
 |  1405     const int kFunctionOffset = kReceiverOffset + kPointerSize; | 
 |  1406     const int kIndexOffset    = | 
 |  1407         StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); | 
 |  1408     const int kLimitOffset    = | 
 |  1409         StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); | 
 |  1410  | 
|  1340     Register args = x12; |  1411     Register args = x12; | 
|  1341     Register receiver = x14; |  1412     Register receiver = x14; | 
|  1342     Register function = x15; |  1413     Register function = x15; | 
|  1343  |  1414  | 
|  1344     // Get the length of the arguments via a builtin call. |  1415     // Get the length of the arguments via a builtin call. | 
|  1345     __ Ldr(function, MemOperand(fp, kFunctionOffset)); |  1416     __ Ldr(function, MemOperand(fp, kFunctionOffset)); | 
|  1346     __ Ldr(args, MemOperand(fp, kArgsOffset)); |  1417     __ Ldr(args, MemOperand(fp, kArgumentsOffset)); | 
|  1347     __ Push(function, args); |  1418     __ Push(function, args); | 
|  1348     __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); |  1419     if (targetIsArgument) { | 
 |  1420       __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION); | 
 |  1421     } else { | 
 |  1422       __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); | 
 |  1423     } | 
|  1349     Register argc = x0; |  1424     Register argc = x0; | 
|  1350  |  1425  | 
|  1351     // Check the stack for overflow. |  1426     Generate_CheckStackOverflow(masm, kFunctionOffset); | 
|  1352     // We are not trying to catch interruptions (e.g. debug break and |  | 
|  1353     // preemption) here, so the "real stack limit" is checked. |  | 
|  1354     Label enough_stack_space; |  | 
|  1355     __ LoadRoot(x10, Heap::kRealStackLimitRootIndex); |  | 
|  1356     __ Ldr(function, MemOperand(fp, kFunctionOffset)); |  | 
|  1357     // Make x10 the space we have left. The stack might already be overflowed |  | 
|  1358     // here which will cause x10 to become negative. |  | 
|  1359     // TODO(jbramley): Check that the stack usage here is safe. |  | 
|  1360     __ Sub(x10, jssp, x10); |  | 
|  1361     // Check if the arguments will overflow the stack. |  | 
|  1362     __ Cmp(x10, Operand::UntagSmiAndScale(argc, kPointerSizeLog2)); |  | 
|  1363     __ B(gt, &enough_stack_space); |  | 
|  1364     // There is not enough stack space, so use a builtin to throw an appropriate |  | 
|  1365     // error. |  | 
|  1366     __ Push(function, argc); |  | 
|  1367     __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); |  | 
|  1368     // We should never return from the APPLY_OVERFLOW builtin. |  | 
|  1369     if (__ emit_debug_code()) { |  | 
|  1370       __ Unreachable(); |  | 
|  1371     } |  | 
|  1372  |  1427  | 
|  1373     __ Bind(&enough_stack_space); |  | 
|  1374     // Push current limit and index. |  1428     // Push current limit and index. | 
|  1375     __ Mov(x1, 0);  // Initial index. |  1429     __ Mov(x1, 0);  // Initial index. | 
|  1376     __ Push(argc, x1); |  1430     __ Push(argc, x1); | 
|  1377  |  1431  | 
|  1378     Label push_receiver; |  1432     Label push_receiver; | 
|  1379     __ Ldr(receiver, MemOperand(fp, kReceiverOffset)); |  1433     __ Ldr(receiver, MemOperand(fp, kReceiverOffset)); | 
|  1380  |  1434  | 
|  1381     // Check that the function is a JS function. Otherwise it must be a proxy. |  1435     // Check that the function is a JS function. Otherwise it must be a proxy. | 
|  1382     // When it is not the function proxy will be invoked later. |  1436     // When it is not the function proxy will be invoked later. | 
|  1383     __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE, |  1437     __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE, | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1417  |  1471  | 
|  1418     __ Bind(&use_global_proxy); |  1472     __ Bind(&use_global_proxy); | 
|  1419     __ Ldr(x10, GlobalObjectMemOperand()); |  1473     __ Ldr(x10, GlobalObjectMemOperand()); | 
|  1420     __ Ldr(receiver, FieldMemOperand(x10, GlobalObject::kGlobalProxyOffset)); |  1474     __ Ldr(receiver, FieldMemOperand(x10, GlobalObject::kGlobalProxyOffset)); | 
|  1421  |  1475  | 
|  1422     // Push the receiver |  1476     // Push the receiver | 
|  1423     __ Bind(&push_receiver); |  1477     __ Bind(&push_receiver); | 
|  1424     __ Push(receiver); |  1478     __ Push(receiver); | 
|  1425  |  1479  | 
|  1426     // Copy all arguments from the array to the stack. |  1480     // Copy all arguments from the array to the stack. | 
|  1427     Label entry, loop; |  1481     Generate_PushAppliedArguments( | 
|  1428     Register current = x0; |  1482         masm, kArgumentsOffset, kIndexOffset, kLimitOffset); | 
|  1429     __ Ldr(current, MemOperand(fp, kIndexOffset)); |  | 
|  1430     __ B(&entry); |  | 
|  1431  |  | 
|  1432     __ Bind(&loop); |  | 
|  1433     // Load the current argument from the arguments array and push it. |  | 
|  1434     // TODO(all): Couldn't we optimize this for JS arrays? |  | 
|  1435  |  | 
|  1436     __ Ldr(x1, MemOperand(fp, kArgsOffset)); |  | 
|  1437     __ Push(x1, current); |  | 
|  1438  |  | 
|  1439     // Call the runtime to access the property in the arguments array. |  | 
|  1440     __ CallRuntime(Runtime::kGetProperty, 2); |  | 
|  1441     __ Push(x0); |  | 
|  1442  |  | 
|  1443     // Use inline caching to access the arguments. |  | 
|  1444     __ Ldr(current, MemOperand(fp, kIndexOffset)); |  | 
|  1445     __ Add(current, current, Smi::FromInt(1)); |  | 
|  1446     __ Str(current, MemOperand(fp, kIndexOffset)); |  | 
|  1447  |  | 
|  1448     // Test if the copy loop has finished copying all the elements from the |  | 
|  1449     // arguments object. |  | 
|  1450     __ Bind(&entry); |  | 
|  1451     __ Ldr(x1, MemOperand(fp, kLimitOffset)); |  | 
|  1452     __ Cmp(current, x1); |  | 
|  1453     __ B(ne, &loop); |  | 
|  1454  |  1483  | 
|  1455     // At the end of the loop, the number of arguments is stored in 'current', |  1484     // At the end of the loop, the number of arguments is stored in 'current', | 
|  1456     // represented as a smi. |  1485     // represented as a smi. | 
|  1457  |  1486  | 
|  1458     function = x1;  // From now on we want the function to be kept in x1; |  1487     function = x1;  // From now on we want the function to be kept in x1; | 
|  1459     __ Ldr(function, MemOperand(fp, kFunctionOffset)); |  1488     __ Ldr(function, MemOperand(fp, kFunctionOffset)); | 
|  1460  |  1489  | 
|  1461     // Call the function. |  1490     // Call the function. | 
|  1462     Label call_proxy; |  1491     Label call_proxy; | 
|  1463     ParameterCount actual(current); |  1492     ParameterCount actual(x0); | 
|  1464     __ SmiUntag(current); |  | 
|  1465     __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE, &call_proxy); |  1493     __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE, &call_proxy); | 
|  1466     __ InvokeFunction(function, actual, CALL_FUNCTION, NullCallWrapper()); |  1494     __ InvokeFunction(function, actual, CALL_FUNCTION, NullCallWrapper()); | 
|  1467     frame_scope.GenerateLeaveFrame(); |  1495     frame_scope.GenerateLeaveFrame(); | 
|  1468     __ Drop(3); |  1496     __ Drop(kStackSize); | 
|  1469     __ Ret(); |  1497     __ Ret(); | 
|  1470  |  1498  | 
|  1471     // Call the function proxy. |  1499     // Call the function proxy. | 
|  1472     __ Bind(&call_proxy); |  1500     __ Bind(&call_proxy); | 
|  1473     // x0 : argc |  1501     // x0 : argc | 
|  1474     // x1 : function |  1502     // x1 : function | 
|  1475     __ Push(function);  // Add function proxy as last argument. |  1503     __ Push(function);  // Add function proxy as last argument. | 
|  1476     __ Add(x0, x0, 1); |  1504     __ Add(x0, x0, 1); | 
|  1477     __ Mov(x2, 0); |  1505     __ Mov(x2, 0); | 
|  1478     __ GetBuiltinFunction(x1, Builtins::CALL_FUNCTION_PROXY); |  1506     __ GetBuiltinFunction(x1, Builtins::CALL_FUNCTION_PROXY); | 
|  1479     __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |  1507     __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 
|  1480             RelocInfo::CODE_TARGET); |  1508             RelocInfo::CODE_TARGET); | 
|  1481   } |  1509   } | 
|  1482   __ Drop(3); |  1510   __ Drop(kStackSize); | 
|  1483   __ Ret(); |  1511   __ Ret(); | 
|  1484 } |  1512 } | 
|  1485  |  1513  | 
|  1486  |  1514  | 
 |  1515 static void Generate_ConstructHelper(MacroAssembler* masm) { | 
 |  1516   const int kFormalParameters = 3; | 
 |  1517   const int kStackSize = kFormalParameters + 1; | 
 |  1518  | 
 |  1519   { | 
 |  1520     FrameScope frame_scope(masm, StackFrame::INTERNAL); | 
 |  1521  | 
 |  1522     const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; | 
 |  1523     const int kArgumentsOffset =  kNewTargetOffset + kPointerSize; | 
 |  1524     const int kFunctionOffset = kArgumentsOffset + kPointerSize; | 
 |  1525  | 
 |  1526     const int kIndexOffset    = | 
 |  1527         StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); | 
 |  1528     const int kLimitOffset    = | 
 |  1529         StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); | 
 |  1530  | 
 |  1531     // Is x11 safe to use? | 
 |  1532     Register newTarget = x11; | 
 |  1533     Register args = x12; | 
 |  1534     Register receiver = x14; | 
 |  1535     Register function = x15; | 
 |  1536  | 
 |  1537     // If newTarget is not supplied, set it to constructor | 
 |  1538     Label validate_arguments; | 
 |  1539     __ Ldr(x0, MemOperand(fp, kNewTargetOffset)); | 
 |  1540     __ CompareRoot(x0, Heap::kUndefinedValueRootIndex); | 
 |  1541     __ B(ne, &validate_arguments); | 
 |  1542     __ Ldr(x0, MemOperand(fp, kFunctionOffset)); | 
 |  1543     __ Str(x0, MemOperand(fp, kNewTargetOffset)); | 
 |  1544  | 
 |  1545     // Validate arguments | 
 |  1546     __ Bind(&validate_arguments); | 
 |  1547     __ Ldr(function, MemOperand(fp, kFunctionOffset)); | 
 |  1548     __ Ldr(args, MemOperand(fp, kArgumentsOffset)); | 
 |  1549     __ Ldr(newTarget, MemOperand(fp, kNewTargetOffset)); | 
 |  1550     __ Push(function, args, newTarget); | 
 |  1551     __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION); | 
 |  1552     Register argc = x0; | 
 |  1553  | 
 |  1554     Generate_CheckStackOverflow(masm, kFunctionOffset); | 
 |  1555  | 
 |  1556     // Push current limit and index, constructor & newTarget | 
 |  1557     __ Mov(x1, 0);  // Initial index. | 
 |  1558     __ Ldr(newTarget, MemOperand(fp, kNewTargetOffset)); | 
 |  1559     __ Push(argc, x1, newTarget, function); | 
 |  1560  | 
 |  1561     // Copy all arguments from the array to the stack. | 
 |  1562     Generate_PushAppliedArguments( | 
 |  1563         masm, kArgumentsOffset, kIndexOffset, kLimitOffset); | 
 |  1564  | 
 |  1565     __ Ldr(x1, MemOperand(fp, kFunctionOffset)); | 
 |  1566     // Use undefined feedback vector | 
 |  1567     __ LoadRoot(x2, Heap::kUndefinedValueRootIndex); | 
 |  1568  | 
 |  1569     // Call the function. | 
 |  1570     CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL); | 
 |  1571     __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 
 |  1572  | 
 |  1573     __ Drop(1); | 
 |  1574   } | 
 |  1575   __ Drop(kStackSize); | 
 |  1576   __ Ret(); | 
 |  1577 } | 
 |  1578  | 
 |  1579  | 
 |  1580 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 
 |  1581   ASM_LOCATION("Builtins::Generate_FunctionApply"); | 
 |  1582   Generate_ApplyHelper(masm, false); | 
 |  1583 } | 
 |  1584  | 
 |  1585  | 
 |  1586 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { | 
 |  1587   ASM_LOCATION("Builtins::Generate_ReflectApply"); | 
 |  1588   Generate_ApplyHelper(masm, true); | 
 |  1589 } | 
 |  1590  | 
 |  1591  | 
 |  1592 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { | 
 |  1593   ASM_LOCATION("Builtins::Generate_ReflectConstruct"); | 
 |  1594   Generate_ConstructHelper(masm); | 
 |  1595 } | 
 |  1596  | 
 |  1597  | 
|  1487 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, |  1598 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, | 
|  1488                                       Label* stack_overflow) { |  1599                                       Label* stack_overflow) { | 
|  1489   // ----------- S t a t e ------------- |  1600   // ----------- S t a t e ------------- | 
|  1490   //  -- x0 : actual number of arguments |  1601   //  -- x0 : actual number of arguments | 
|  1491   //  -- x1 : function (passed through to callee) |  1602   //  -- x1 : function (passed through to callee) | 
|  1492   //  -- x2 : expected number of arguments |  1603   //  -- x2 : expected number of arguments | 
|  1493   // ----------------------------------- |  1604   // ----------------------------------- | 
|  1494   // Check the stack for overflow. |  1605   // Check the stack for overflow. | 
|  1495   // We are not trying to catch interruptions (e.g. debug break and |  1606   // We are not trying to catch interruptions (e.g. debug break and | 
|  1496   // preemption) here, so the "real stack limit" is checked. |  1607   // preemption) here, so the "real stack limit" is checked. | 
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1669     __ Unreachable(); |  1780     __ Unreachable(); | 
|  1670   } |  1781   } | 
|  1671 } |  1782 } | 
|  1672  |  1783  | 
|  1673  |  1784  | 
|  1674 #undef __ |  1785 #undef __ | 
|  1675  |  1786  | 
|  1676 } }  // namespace v8::internal |  1787 } }  // namespace v8::internal | 
|  1677  |  1788  | 
|  1678 #endif  // V8_TARGET_ARCH_ARM |  1789 #endif  // V8_TARGET_ARCH_ARM | 
| OLD | NEW |