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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
6 | 6 |
7 #include "src/arm64/frames-arm64.h" | 7 #include "src/arm64/frames-arm64.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/debug/debug.h" | 9 #include "src/debug/debug.h" |
10 #include "src/deoptimizer.h" | 10 #include "src/deoptimizer.h" |
(...skipping 1272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1283 } | 1283 } |
1284 __ Jump(masm->isolate()->builtins()->OnStackReplacement(), | 1284 __ Jump(masm->isolate()->builtins()->OnStackReplacement(), |
1285 RelocInfo::CODE_TARGET); | 1285 RelocInfo::CODE_TARGET); |
1286 | 1286 |
1287 __ Bind(&ok); | 1287 __ Bind(&ok); |
1288 __ Ret(); | 1288 __ Ret(); |
1289 } | 1289 } |
1290 | 1290 |
1291 | 1291 |
1292 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { | 1292 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { |
1293 enum { | |
1294 call_type_JS_func = 0, | |
1295 call_type_func_proxy = 1, | |
1296 call_type_non_func = 2 | |
1297 }; | |
1298 Register argc = x0; | 1293 Register argc = x0; |
1299 Register function = x1; | 1294 Register function = x1; |
1300 Register call_type = x4; | |
1301 Register scratch1 = x10; | 1295 Register scratch1 = x10; |
1302 Register scratch2 = x11; | 1296 Register scratch2 = x11; |
1303 Register receiver_type = x13; | |
1304 | 1297 |
1305 ASM_LOCATION("Builtins::Generate_FunctionCall"); | 1298 ASM_LOCATION("Builtins::Generate_FunctionCall"); |
1306 // 1. Make sure we have at least one argument. | 1299 // 1. Make sure we have at least one argument. |
1307 { Label done; | 1300 { |
| 1301 Label done; |
1308 __ Cbnz(argc, &done); | 1302 __ Cbnz(argc, &done); |
1309 __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); | 1303 __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); |
1310 __ Push(scratch1); | 1304 __ Push(scratch1); |
1311 __ Mov(argc, 1); | 1305 __ Mov(argc, 1); |
1312 __ Bind(&done); | 1306 __ Bind(&done); |
1313 } | 1307 } |
1314 | 1308 |
1315 // 2. Get the function to call (passed as receiver) from the stack, check | 1309 // 2. Get the callable to call (passed as receiver) from the stack. |
1316 // if it is a function. | |
1317 Label slow, non_function; | |
1318 __ Peek(function, Operand(argc, LSL, kXRegSizeLog2)); | 1310 __ Peek(function, Operand(argc, LSL, kXRegSizeLog2)); |
1319 __ JumpIfSmi(function, &non_function); | |
1320 __ JumpIfNotObjectType(function, scratch1, receiver_type, | |
1321 JS_FUNCTION_TYPE, &slow); | |
1322 | 1311 |
1323 // 3a. Patch the first argument if necessary when calling a function. | 1312 // 3. Shift arguments and return address one slot down on the stack |
1324 Label shift_arguments; | |
1325 __ Mov(call_type, static_cast<int>(call_type_JS_func)); | |
1326 { Label convert_to_object, use_global_proxy, patch_receiver; | |
1327 // Change context eagerly in case we need the global receiver. | |
1328 __ Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); | |
1329 | |
1330 // Do not transform the receiver for strict mode functions. | |
1331 // Also do not transform the receiver for native (Compilerhints already in | |
1332 // x3). | |
1333 __ Ldr(scratch1, | |
1334 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); | |
1335 __ Ldr(scratch2.W(), | |
1336 FieldMemOperand(scratch1, SharedFunctionInfo::kCompilerHintsOffset)); | |
1337 __ TestAndBranchIfAnySet( | |
1338 scratch2.W(), | |
1339 (1 << SharedFunctionInfo::kStrictModeFunction) | | |
1340 (1 << SharedFunctionInfo::kNative), | |
1341 &shift_arguments); | |
1342 | |
1343 // Compute the receiver in sloppy mode. | |
1344 Register receiver = x2; | |
1345 __ Sub(scratch1, argc, 1); | |
1346 __ Peek(receiver, Operand(scratch1, LSL, kXRegSizeLog2)); | |
1347 __ JumpIfSmi(receiver, &convert_to_object); | |
1348 | |
1349 __ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex, | |
1350 &use_global_proxy); | |
1351 __ JumpIfRoot(receiver, Heap::kNullValueRootIndex, &use_global_proxy); | |
1352 | |
1353 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | |
1354 __ JumpIfObjectType(receiver, scratch1, scratch2, | |
1355 FIRST_SPEC_OBJECT_TYPE, &shift_arguments, ge); | |
1356 | |
1357 __ Bind(&convert_to_object); | |
1358 | |
1359 { | |
1360 // Enter an internal frame in order to preserve argument count. | |
1361 FrameScope scope(masm, StackFrame::INTERNAL); | |
1362 __ SmiTag(argc); | |
1363 | |
1364 __ Push(argc); | |
1365 __ Mov(x0, receiver); | |
1366 ToObjectStub stub(masm->isolate()); | |
1367 __ CallStub(&stub); | |
1368 __ Mov(receiver, x0); | |
1369 | |
1370 __ Pop(argc); | |
1371 __ SmiUntag(argc); | |
1372 | |
1373 // Exit the internal frame. | |
1374 } | |
1375 | |
1376 // Restore the function and flag in the registers. | |
1377 __ Peek(function, Operand(argc, LSL, kXRegSizeLog2)); | |
1378 __ Mov(call_type, static_cast<int>(call_type_JS_func)); | |
1379 __ B(&patch_receiver); | |
1380 | |
1381 __ Bind(&use_global_proxy); | |
1382 __ Ldr(receiver, GlobalObjectMemOperand()); | |
1383 __ Ldr(receiver, | |
1384 FieldMemOperand(receiver, GlobalObject::kGlobalProxyOffset)); | |
1385 | |
1386 | |
1387 __ Bind(&patch_receiver); | |
1388 __ Sub(scratch1, argc, 1); | |
1389 __ Poke(receiver, Operand(scratch1, LSL, kXRegSizeLog2)); | |
1390 | |
1391 __ B(&shift_arguments); | |
1392 } | |
1393 | |
1394 // 3b. Check for function proxy. | |
1395 __ Bind(&slow); | |
1396 __ Mov(call_type, static_cast<int>(call_type_func_proxy)); | |
1397 __ Cmp(receiver_type, JS_FUNCTION_PROXY_TYPE); | |
1398 __ B(eq, &shift_arguments); | |
1399 __ Bind(&non_function); | |
1400 __ Mov(call_type, static_cast<int>(call_type_non_func)); | |
1401 | |
1402 // 3c. Patch the first argument when calling a non-function. The | |
1403 // CALL_NON_FUNCTION builtin expects the non-function callee as | |
1404 // receiver, so overwrite the first argument which will ultimately | |
1405 // become the receiver. | |
1406 // call type (0: JS function, 1: function proxy, 2: non-function) | |
1407 __ Sub(scratch1, argc, 1); | |
1408 __ Poke(function, Operand(scratch1, LSL, kXRegSizeLog2)); | |
1409 | |
1410 // 4. Shift arguments and return address one slot down on the stack | |
1411 // (overwriting the original receiver). Adjust argument count to make | 1313 // (overwriting the original receiver). Adjust argument count to make |
1412 // the original first argument the new receiver. | 1314 // the original first argument the new receiver. |
1413 // call type (0: JS function, 1: function proxy, 2: non-function) | 1315 { |
1414 __ Bind(&shift_arguments); | 1316 Label loop; |
1415 { Label loop; | |
1416 // Calculate the copy start address (destination). Copy end address is jssp. | 1317 // Calculate the copy start address (destination). Copy end address is jssp. |
1417 __ Add(scratch2, jssp, Operand(argc, LSL, kPointerSizeLog2)); | 1318 __ Add(scratch2, jssp, Operand(argc, LSL, kPointerSizeLog2)); |
1418 __ Sub(scratch1, scratch2, kPointerSize); | 1319 __ Sub(scratch1, scratch2, kPointerSize); |
1419 | 1320 |
1420 __ Bind(&loop); | 1321 __ Bind(&loop); |
1421 __ Ldr(x12, MemOperand(scratch1, -kPointerSize, PostIndex)); | 1322 __ Ldr(x12, MemOperand(scratch1, -kPointerSize, PostIndex)); |
1422 __ Str(x12, MemOperand(scratch2, -kPointerSize, PostIndex)); | 1323 __ Str(x12, MemOperand(scratch2, -kPointerSize, PostIndex)); |
1423 __ Cmp(scratch1, jssp); | 1324 __ Cmp(scratch1, jssp); |
1424 __ B(ge, &loop); | 1325 __ B(ge, &loop); |
1425 // Adjust the actual number of arguments and remove the top element | 1326 // Adjust the actual number of arguments and remove the top element |
1426 // (which is a copy of the last argument). | 1327 // (which is a copy of the last argument). |
1427 __ Sub(argc, argc, 1); | 1328 __ Sub(argc, argc, 1); |
1428 __ Drop(1); | 1329 __ Drop(1); |
1429 } | 1330 } |
1430 | 1331 |
1431 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, | 1332 // 4. Call the callable. |
1432 // or a function proxy via CALL_FUNCTION_PROXY. | 1333 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
1433 // call type (0: JS function, 1: function proxy, 2: non-function) | |
1434 { Label js_function, non_proxy; | |
1435 __ Cbz(call_type, &js_function); | |
1436 // Expected number of arguments is 0 for CALL_NON_FUNCTION. | |
1437 __ Mov(x2, 0); | |
1438 __ Cmp(call_type, static_cast<int>(call_type_func_proxy)); | |
1439 __ B(ne, &non_proxy); | |
1440 | |
1441 __ Push(function); // Re-add proxy object as additional argument. | |
1442 __ Add(argc, argc, 1); | |
1443 __ GetBuiltinFunction(function, Context::CALL_FUNCTION_PROXY_BUILTIN_INDEX); | |
1444 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | |
1445 RelocInfo::CODE_TARGET); | |
1446 | |
1447 __ Bind(&non_proxy); | |
1448 __ GetBuiltinFunction(function, Context::CALL_NON_FUNCTION_BUILTIN_INDEX); | |
1449 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | |
1450 RelocInfo::CODE_TARGET); | |
1451 __ Bind(&js_function); | |
1452 } | |
1453 | |
1454 // 5b. Get the code to call from the function and check that the number of | |
1455 // expected arguments matches what we're providing. If so, jump | |
1456 // (tail-call) to the code in register edx without checking arguments. | |
1457 __ Ldr(x3, FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); | |
1458 __ Ldrsw(x2, | |
1459 FieldMemOperand(x3, | |
1460 SharedFunctionInfo::kFormalParameterCountOffset)); | |
1461 Label dont_adapt_args; | |
1462 __ Cmp(x2, argc); // Check formal and actual parameter counts. | |
1463 __ B(eq, &dont_adapt_args); | |
1464 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | |
1465 RelocInfo::CODE_TARGET); | |
1466 __ Bind(&dont_adapt_args); | |
1467 | |
1468 __ Ldr(x3, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); | |
1469 ParameterCount expected(0); | |
1470 __ InvokeCode(x3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); | |
1471 } | 1334 } |
1472 | 1335 |
1473 | 1336 |
1474 static void Generate_PushAppliedArguments(MacroAssembler* masm, | 1337 static void Generate_PushAppliedArguments(MacroAssembler* masm, |
1475 const int argumentsOffset, | 1338 const int argumentsOffset, |
1476 const int indexOffset, | 1339 const int indexOffset, |
1477 const int limitOffset) { | 1340 const int limitOffset) { |
1478 Label entry, loop; | 1341 Label entry, loop; |
1479 Register receiver = LoadDescriptor::ReceiverRegister(); | 1342 Register receiver = LoadDescriptor::ReceiverRegister(); |
1480 Register key = LoadDescriptor::NameRegister(); | 1343 Register key = LoadDescriptor::NameRegister(); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1546 if (targetIsArgument) { | 1409 if (targetIsArgument) { |
1547 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, | 1410 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, |
1548 CALL_FUNCTION); | 1411 CALL_FUNCTION); |
1549 } else { | 1412 } else { |
1550 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); | 1413 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); |
1551 } | 1414 } |
1552 Register argc = x0; | 1415 Register argc = x0; |
1553 | 1416 |
1554 Generate_CheckStackOverflow(masm, kFunctionOffset, argc, kArgcIsSmiTagged); | 1417 Generate_CheckStackOverflow(masm, kFunctionOffset, argc, kArgcIsSmiTagged); |
1555 | 1418 |
1556 // Push current limit and index. | 1419 // Push current limit, index and receiver. |
1557 __ Mov(x1, 0); // Initial index. | 1420 __ Mov(x1, 0); // Initial index. |
1558 __ Push(argc, x1); | |
1559 | |
1560 Label push_receiver; | |
1561 __ Ldr(receiver, MemOperand(fp, kReceiverOffset)); | 1421 __ Ldr(receiver, MemOperand(fp, kReceiverOffset)); |
1562 | 1422 __ Push(argc, x1, receiver); |
1563 // Check that the function is a JS function. Otherwise it must be a proxy. | |
1564 // When it is not the function proxy will be invoked later. | |
1565 __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE, | |
1566 &push_receiver); | |
1567 | |
1568 // Change context eagerly to get the right global object if necessary. | |
1569 __ Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); | |
1570 // Load the shared function info. | |
1571 __ Ldr(x2, FieldMemOperand(function, | |
1572 JSFunction::kSharedFunctionInfoOffset)); | |
1573 | |
1574 // Compute and push the receiver. | |
1575 // Do not transform the receiver for strict mode functions. | |
1576 Label convert_receiver_to_object, use_global_proxy; | |
1577 __ Ldr(w10, FieldMemOperand(x2, SharedFunctionInfo::kCompilerHintsOffset)); | |
1578 __ Tbnz(x10, SharedFunctionInfo::kStrictModeFunction, &push_receiver); | |
1579 // Do not transform the receiver for native functions. | |
1580 __ Tbnz(x10, SharedFunctionInfo::kNative, &push_receiver); | |
1581 | |
1582 // Compute the receiver in sloppy mode. | |
1583 __ JumpIfSmi(receiver, &convert_receiver_to_object); | |
1584 __ JumpIfRoot(receiver, Heap::kNullValueRootIndex, &use_global_proxy); | |
1585 __ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex, | |
1586 &use_global_proxy); | |
1587 | |
1588 // Check if the receiver is already a JavaScript object. | |
1589 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | |
1590 __ JumpIfObjectType(receiver, x10, x11, FIRST_SPEC_OBJECT_TYPE, | |
1591 &push_receiver, ge); | |
1592 | |
1593 // Call a builtin to convert the receiver to a regular object. | |
1594 __ Bind(&convert_receiver_to_object); | |
1595 __ Mov(x0, receiver); | |
1596 ToObjectStub stub(masm->isolate()); | |
1597 __ CallStub(&stub); | |
1598 __ Mov(receiver, x0); | |
1599 __ B(&push_receiver); | |
1600 | |
1601 __ Bind(&use_global_proxy); | |
1602 __ Ldr(x10, GlobalObjectMemOperand()); | |
1603 __ Ldr(receiver, FieldMemOperand(x10, GlobalObject::kGlobalProxyOffset)); | |
1604 | |
1605 // Push the receiver | |
1606 __ Bind(&push_receiver); | |
1607 __ Push(receiver); | |
1608 | 1423 |
1609 // Copy all arguments from the array to the stack. | 1424 // Copy all arguments from the array to the stack. |
1610 Generate_PushAppliedArguments( | 1425 Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset, |
1611 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); | 1426 kLimitOffset); |
1612 | 1427 |
1613 // At the end of the loop, the number of arguments is stored in 'current', | 1428 // At the end of the loop, the number of arguments is stored in x0, untagged |
1614 // represented as a smi. | |
1615 | 1429 |
1616 function = x1; // From now on we want the function to be kept in x1; | 1430 // Call the callable. |
1617 __ Ldr(function, MemOperand(fp, kFunctionOffset)); | 1431 // TODO(bmeurer): This should be a tail call according to ES6. |
1618 | 1432 __ Ldr(x1, MemOperand(fp, kFunctionOffset)); |
1619 // Call the function. | 1433 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
1620 Label call_proxy; | |
1621 ParameterCount actual(x0); | |
1622 __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE, &call_proxy); | |
1623 __ InvokeFunction(function, actual, CALL_FUNCTION, NullCallWrapper()); | |
1624 frame_scope.GenerateLeaveFrame(); | |
1625 __ Drop(kStackSize); | |
1626 __ Ret(); | |
1627 | |
1628 // Call the function proxy. | |
1629 __ Bind(&call_proxy); | |
1630 // x0 : argc | |
1631 // x1 : function | |
1632 __ Push(function); // Add function proxy as last argument. | |
1633 __ Add(x0, x0, 1); | |
1634 __ Mov(x2, 0); | |
1635 __ GetBuiltinFunction(x1, Context::CALL_FUNCTION_PROXY_BUILTIN_INDEX); | |
1636 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | |
1637 RelocInfo::CODE_TARGET); | |
1638 } | 1434 } |
1639 __ Drop(kStackSize); | 1435 __ Drop(kStackSize); |
1640 __ Ret(); | 1436 __ Ret(); |
1641 } | 1437 } |
1642 | 1438 |
1643 | 1439 |
1644 static void Generate_ConstructHelper(MacroAssembler* masm) { | 1440 static void Generate_ConstructHelper(MacroAssembler* masm) { |
1645 const int kFormalParameters = 3; | 1441 const int kFormalParameters = 3; |
1646 const int kStackSize = kFormalParameters + 1; | 1442 const int kStackSize = kFormalParameters + 1; |
1647 | 1443 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1763 // then drop the parameters and the receiver. | 1559 // then drop the parameters and the receiver. |
1764 __ Ldr(x10, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + | 1560 __ Ldr(x10, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + |
1765 kPointerSize))); | 1561 kPointerSize))); |
1766 __ Mov(jssp, fp); | 1562 __ Mov(jssp, fp); |
1767 __ Pop(fp, lr); | 1563 __ Pop(fp, lr); |
1768 __ DropBySMI(x10, kXRegSize); | 1564 __ DropBySMI(x10, kXRegSize); |
1769 __ Drop(1); | 1565 __ Drop(1); |
1770 } | 1566 } |
1771 | 1567 |
1772 | 1568 |
| 1569 // static |
| 1570 void Builtins::Generate_CallFunction(MacroAssembler* masm) { |
| 1571 // ----------- S t a t e ------------- |
| 1572 // -- x0 : the number of arguments (not including the receiver) |
| 1573 // -- x1 : the function to call (checked to be a JSFunction) |
| 1574 // ----------------------------------- |
| 1575 |
| 1576 Label convert, convert_global_proxy, convert_to_object, done_convert; |
| 1577 __ AssertFunction(x1); |
| 1578 // TODO(bmeurer): Throw a TypeError if function's [[FunctionKind]] internal |
| 1579 // slot is "classConstructor". |
| 1580 // Enter the context of the function; ToObject has to run in the function |
| 1581 // context, and we also need to take the global proxy from the function |
| 1582 // context in case of conversion. |
| 1583 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) |
| 1584 __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset)); |
| 1585 __ Ldr(x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); |
| 1586 // We need to convert the receiver for non-native sloppy mode functions. |
| 1587 __ Ldr(w3, FieldMemOperand(x2, SharedFunctionInfo::kCompilerHintsOffset)); |
| 1588 __ TestAndBranchIfAnySet(w3, |
| 1589 (1 << SharedFunctionInfo::kNative) | |
| 1590 (1 << SharedFunctionInfo::kStrictModeFunction), |
| 1591 &done_convert); |
| 1592 { |
| 1593 __ Peek(x3, Operand(x0, LSL, kXRegSizeLog2)); |
| 1594 |
| 1595 // ----------- S t a t e ------------- |
| 1596 // -- x0 : the number of arguments (not including the receiver) |
| 1597 // -- x1 : the function to call (checked to be a JSFunction) |
| 1598 // -- x2 : the shared function info. |
| 1599 // -- x3 : the receiver |
| 1600 // -- cp : the function context. |
| 1601 // ----------------------------------- |
| 1602 |
| 1603 Label convert_receiver; |
| 1604 __ JumpIfSmi(x3, &convert_to_object); |
| 1605 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 1606 __ CompareObjectType(x3, x4, x4, FIRST_JS_RECEIVER_TYPE); |
| 1607 __ B(hs, &done_convert); |
| 1608 __ JumpIfRoot(x3, Heap::kUndefinedValueRootIndex, &convert_global_proxy); |
| 1609 __ JumpIfNotRoot(x3, Heap::kNullValueRootIndex, &convert_to_object); |
| 1610 __ Bind(&convert_global_proxy); |
| 1611 { |
| 1612 // Patch receiver to global proxy. |
| 1613 __ LoadGlobalProxy(x3); |
| 1614 } |
| 1615 __ B(&convert_receiver); |
| 1616 __ Bind(&convert_to_object); |
| 1617 { |
| 1618 // Convert receiver using ToObject. |
| 1619 // TODO(bmeurer): Inline the allocation here to avoid building the frame |
| 1620 // in the fast case? (fall back to AllocateInNewSpace?) |
| 1621 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1622 __ SmiTag(x0); |
| 1623 __ Push(x0, x1); |
| 1624 __ Mov(x0, x3); |
| 1625 ToObjectStub stub(masm->isolate()); |
| 1626 __ CallStub(&stub); |
| 1627 __ Mov(x3, x0); |
| 1628 __ Pop(x1, x0); |
| 1629 __ SmiUntag(x0); |
| 1630 } |
| 1631 __ Ldr(x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); |
| 1632 __ Bind(&convert_receiver); |
| 1633 __ Poke(x3, Operand(x0, LSL, kXRegSizeLog2)); |
| 1634 } |
| 1635 __ Bind(&done_convert); |
| 1636 |
| 1637 // ----------- S t a t e ------------- |
| 1638 // -- x0 : the number of arguments (not including the receiver) |
| 1639 // -- x1 : the function to call (checked to be a JSFunction) |
| 1640 // -- x2 : the shared function info. |
| 1641 // -- cp : the function context. |
| 1642 // ----------------------------------- |
| 1643 |
| 1644 __ Ldrsw( |
| 1645 x2, FieldMemOperand(x2, SharedFunctionInfo::kFormalParameterCountOffset)); |
| 1646 __ Ldr(x3, FieldMemOperand(x1, JSFunction::kCodeEntryOffset)); |
| 1647 ParameterCount actual(x0); |
| 1648 ParameterCount expected(x2); |
| 1649 __ InvokeCode(x3, expected, actual, JUMP_FUNCTION, NullCallWrapper()); |
| 1650 } |
| 1651 |
| 1652 |
| 1653 // static |
| 1654 void Builtins::Generate_Call(MacroAssembler* masm) { |
| 1655 // ----------- S t a t e ------------- |
| 1656 // -- x0 : the number of arguments (not including the receiver) |
| 1657 // -- x1 : the target to call (can be any Object). |
| 1658 // ----------------------------------- |
| 1659 |
| 1660 Label non_smi, non_jsfunction, non_function; |
| 1661 __ JumpIfSmi(x1, &non_function); |
| 1662 __ Bind(&non_smi); |
| 1663 __ CompareObjectType(x1, x2, x2, JS_FUNCTION_TYPE); |
| 1664 __ B(ne, &non_jsfunction); |
| 1665 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); |
| 1666 __ Bind(&non_jsfunction); |
| 1667 __ Cmp(x2, JS_FUNCTION_PROXY_TYPE); |
| 1668 __ B(ne, &non_function); |
| 1669 |
| 1670 // 1. Call to function proxy. |
| 1671 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies. |
| 1672 __ Ldr(x1, FieldMemOperand(x1, JSFunctionProxy::kCallTrapOffset)); |
| 1673 __ AssertNotSmi(x1); |
| 1674 __ B(&non_smi); |
| 1675 |
| 1676 // 2. Call to something else, which might have a [[Call]] internal method (if |
| 1677 // not we raise an exception). |
| 1678 __ Bind(&non_function); |
| 1679 // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could |
| 1680 // be awesome instead; i.e. a trivial improvement would be to call into the |
| 1681 // runtime and just deal with the API function there instead of returning a |
| 1682 // delegate from a runtime call that just jumps back to the runtime once |
| 1683 // called. Or, bonus points, call directly into the C API function here, as |
| 1684 // we do in some Crankshaft fast cases. |
| 1685 // Overwrite the original receiver with the (original) target. |
| 1686 __ Poke(x1, Operand(x0, LSL, kXRegSizeLog2)); |
| 1687 { |
| 1688 // Determine the delegate for the target (if any). |
| 1689 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1690 __ SmiTag(x0); |
| 1691 __ Push(x0, x1); |
| 1692 __ CallRuntime(Runtime::kGetFunctionDelegate, 1); |
| 1693 __ Mov(x1, x0); |
| 1694 __ Pop(x0); |
| 1695 __ SmiUntag(x0); |
| 1696 } |
| 1697 // The delegate is always a regular function. |
| 1698 __ AssertFunction(x1); |
| 1699 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); |
| 1700 } |
| 1701 |
| 1702 |
1773 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { | 1703 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { |
1774 ASM_LOCATION("Builtins::Generate_ArgumentsAdaptorTrampoline"); | 1704 ASM_LOCATION("Builtins::Generate_ArgumentsAdaptorTrampoline"); |
1775 // ----------- S t a t e ------------- | 1705 // ----------- S t a t e ------------- |
1776 // -- x0 : actual number of arguments | 1706 // -- x0 : actual number of arguments |
1777 // -- x1 : function (passed through to callee) | 1707 // -- x1 : function (passed through to callee) |
1778 // -- x2 : expected number of arguments | 1708 // -- x2 : expected number of arguments |
1779 // ----------------------------------- | 1709 // ----------------------------------- |
1780 | 1710 |
1781 Label stack_overflow; | 1711 Label stack_overflow; |
1782 ArgumentAdaptorStackCheck(masm, &stack_overflow); | 1712 ArgumentAdaptorStackCheck(masm, &stack_overflow); |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1938 } | 1868 } |
1939 } | 1869 } |
1940 | 1870 |
1941 | 1871 |
1942 #undef __ | 1872 #undef __ |
1943 | 1873 |
1944 } // namespace internal | 1874 } // namespace internal |
1945 } // namespace v8 | 1875 } // namespace v8 |
1946 | 1876 |
1947 #endif // V8_TARGET_ARCH_ARM | 1877 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |