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 }; |
1293 Register argc = x0; | 1298 Register argc = x0; |
1294 Register function = x1; | 1299 Register function = x1; |
| 1300 Register call_type = x4; |
1295 Register scratch1 = x10; | 1301 Register scratch1 = x10; |
1296 Register scratch2 = x11; | 1302 Register scratch2 = x11; |
| 1303 Register receiver_type = x13; |
1297 | 1304 |
1298 ASM_LOCATION("Builtins::Generate_FunctionCall"); | 1305 ASM_LOCATION("Builtins::Generate_FunctionCall"); |
1299 // 1. Make sure we have at least one argument. | 1306 // 1. Make sure we have at least one argument. |
1300 { | 1307 { Label done; |
1301 Label done; | |
1302 __ Cbnz(argc, &done); | 1308 __ Cbnz(argc, &done); |
1303 __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); | 1309 __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); |
1304 __ Push(scratch1); | 1310 __ Push(scratch1); |
1305 __ Mov(argc, 1); | 1311 __ Mov(argc, 1); |
1306 __ Bind(&done); | 1312 __ Bind(&done); |
1307 } | 1313 } |
1308 | 1314 |
1309 // 2. Get the callable to call (passed as receiver) from the stack. | 1315 // 2. Get the function to call (passed as receiver) from the stack, check |
| 1316 // if it is a function. |
| 1317 Label slow, non_function; |
1310 __ Peek(function, Operand(argc, LSL, kXRegSizeLog2)); | 1318 __ Peek(function, Operand(argc, LSL, kXRegSizeLog2)); |
| 1319 __ JumpIfSmi(function, &non_function); |
| 1320 __ JumpIfNotObjectType(function, scratch1, receiver_type, |
| 1321 JS_FUNCTION_TYPE, &slow); |
1311 | 1322 |
1312 // 3. Shift arguments and return address one slot down on the stack | 1323 // 3a. Patch the first argument if necessary when calling a function. |
| 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 |
1313 // (overwriting the original receiver). Adjust argument count to make | 1411 // (overwriting the original receiver). Adjust argument count to make |
1314 // the original first argument the new receiver. | 1412 // the original first argument the new receiver. |
1315 { | 1413 // call type (0: JS function, 1: function proxy, 2: non-function) |
1316 Label loop; | 1414 __ Bind(&shift_arguments); |
| 1415 { Label loop; |
1317 // Calculate the copy start address (destination). Copy end address is jssp. | 1416 // Calculate the copy start address (destination). Copy end address is jssp. |
1318 __ Add(scratch2, jssp, Operand(argc, LSL, kPointerSizeLog2)); | 1417 __ Add(scratch2, jssp, Operand(argc, LSL, kPointerSizeLog2)); |
1319 __ Sub(scratch1, scratch2, kPointerSize); | 1418 __ Sub(scratch1, scratch2, kPointerSize); |
1320 | 1419 |
1321 __ Bind(&loop); | 1420 __ Bind(&loop); |
1322 __ Ldr(x12, MemOperand(scratch1, -kPointerSize, PostIndex)); | 1421 __ Ldr(x12, MemOperand(scratch1, -kPointerSize, PostIndex)); |
1323 __ Str(x12, MemOperand(scratch2, -kPointerSize, PostIndex)); | 1422 __ Str(x12, MemOperand(scratch2, -kPointerSize, PostIndex)); |
1324 __ Cmp(scratch1, jssp); | 1423 __ Cmp(scratch1, jssp); |
1325 __ B(ge, &loop); | 1424 __ B(ge, &loop); |
1326 // Adjust the actual number of arguments and remove the top element | 1425 // Adjust the actual number of arguments and remove the top element |
1327 // (which is a copy of the last argument). | 1426 // (which is a copy of the last argument). |
1328 __ Sub(argc, argc, 1); | 1427 __ Sub(argc, argc, 1); |
1329 __ Drop(1); | 1428 __ Drop(1); |
1330 } | 1429 } |
1331 | 1430 |
1332 // 4. Call the callable. | 1431 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, |
1333 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1432 // or a function proxy via CALL_FUNCTION_PROXY. |
| 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()); |
1334 } | 1471 } |
1335 | 1472 |
1336 | 1473 |
1337 static void Generate_PushAppliedArguments(MacroAssembler* masm, | 1474 static void Generate_PushAppliedArguments(MacroAssembler* masm, |
1338 const int argumentsOffset, | 1475 const int argumentsOffset, |
1339 const int indexOffset, | 1476 const int indexOffset, |
1340 const int limitOffset) { | 1477 const int limitOffset) { |
1341 Label entry, loop; | 1478 Label entry, loop; |
1342 Register receiver = LoadDescriptor::ReceiverRegister(); | 1479 Register receiver = LoadDescriptor::ReceiverRegister(); |
1343 Register key = LoadDescriptor::NameRegister(); | 1480 Register key = LoadDescriptor::NameRegister(); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1409 if (targetIsArgument) { | 1546 if (targetIsArgument) { |
1410 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, | 1547 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, |
1411 CALL_FUNCTION); | 1548 CALL_FUNCTION); |
1412 } else { | 1549 } else { |
1413 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); | 1550 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); |
1414 } | 1551 } |
1415 Register argc = x0; | 1552 Register argc = x0; |
1416 | 1553 |
1417 Generate_CheckStackOverflow(masm, kFunctionOffset, argc, kArgcIsSmiTagged); | 1554 Generate_CheckStackOverflow(masm, kFunctionOffset, argc, kArgcIsSmiTagged); |
1418 | 1555 |
1419 // Push current limit, index and receiver. | 1556 // Push current limit and index. |
1420 __ Mov(x1, 0); // Initial index. | 1557 __ Mov(x1, 0); // Initial index. |
| 1558 __ Push(argc, x1); |
| 1559 |
| 1560 Label push_receiver; |
1421 __ Ldr(receiver, MemOperand(fp, kReceiverOffset)); | 1561 __ Ldr(receiver, MemOperand(fp, kReceiverOffset)); |
1422 __ Push(argc, x1, receiver); | 1562 |
| 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); |
1423 | 1608 |
1424 // Copy all arguments from the array to the stack. | 1609 // Copy all arguments from the array to the stack. |
1425 Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset, | 1610 Generate_PushAppliedArguments( |
1426 kLimitOffset); | 1611 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); |
1427 | 1612 |
1428 // At the end of the loop, the number of arguments is stored in x0, untagged | 1613 // At the end of the loop, the number of arguments is stored in 'current', |
| 1614 // represented as a smi. |
1429 | 1615 |
1430 // Call the callable. | 1616 function = x1; // From now on we want the function to be kept in x1; |
1431 // TODO(bmeurer): This should be a tail call according to ES6. | 1617 __ Ldr(function, MemOperand(fp, kFunctionOffset)); |
1432 __ Ldr(x1, MemOperand(fp, kFunctionOffset)); | 1618 |
1433 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1619 // Call the function. |
| 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); |
1434 } | 1638 } |
1435 __ Drop(kStackSize); | 1639 __ Drop(kStackSize); |
1436 __ Ret(); | 1640 __ Ret(); |
1437 } | 1641 } |
1438 | 1642 |
1439 | 1643 |
1440 static void Generate_ConstructHelper(MacroAssembler* masm) { | 1644 static void Generate_ConstructHelper(MacroAssembler* masm) { |
1441 const int kFormalParameters = 3; | 1645 const int kFormalParameters = 3; |
1442 const int kStackSize = kFormalParameters + 1; | 1646 const int kStackSize = kFormalParameters + 1; |
1443 | 1647 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1559 // then drop the parameters and the receiver. | 1763 // then drop the parameters and the receiver. |
1560 __ Ldr(x10, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + | 1764 __ Ldr(x10, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + |
1561 kPointerSize))); | 1765 kPointerSize))); |
1562 __ Mov(jssp, fp); | 1766 __ Mov(jssp, fp); |
1563 __ Pop(fp, lr); | 1767 __ Pop(fp, lr); |
1564 __ DropBySMI(x10, kXRegSize); | 1768 __ DropBySMI(x10, kXRegSize); |
1565 __ Drop(1); | 1769 __ Drop(1); |
1566 } | 1770 } |
1567 | 1771 |
1568 | 1772 |
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 | |
1703 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { | 1773 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { |
1704 ASM_LOCATION("Builtins::Generate_ArgumentsAdaptorTrampoline"); | 1774 ASM_LOCATION("Builtins::Generate_ArgumentsAdaptorTrampoline"); |
1705 // ----------- S t a t e ------------- | 1775 // ----------- S t a t e ------------- |
1706 // -- x0 : actual number of arguments | 1776 // -- x0 : actual number of arguments |
1707 // -- x1 : function (passed through to callee) | 1777 // -- x1 : function (passed through to callee) |
1708 // -- x2 : expected number of arguments | 1778 // -- x2 : expected number of arguments |
1709 // ----------------------------------- | 1779 // ----------------------------------- |
1710 | 1780 |
1711 Label stack_overflow; | 1781 Label stack_overflow; |
1712 ArgumentAdaptorStackCheck(masm, &stack_overflow); | 1782 ArgumentAdaptorStackCheck(masm, &stack_overflow); |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1868 } | 1938 } |
1869 } | 1939 } |
1870 | 1940 |
1871 | 1941 |
1872 #undef __ | 1942 #undef __ |
1873 | 1943 |
1874 } // namespace internal | 1944 } // namespace internal |
1875 } // namespace v8 | 1945 } // namespace v8 |
1876 | 1946 |
1877 #endif // V8_TARGET_ARCH_ARM | 1947 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |