| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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_PPC | 5 #if V8_TARGET_ARCH_PPC |
| 6 | 6 |
| 7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
| 8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
| 9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
| 10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
| (...skipping 1245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1256 __ CallRuntime(Runtime::kStackGuard, 0); | 1256 __ CallRuntime(Runtime::kStackGuard, 0); |
| 1257 } | 1257 } |
| 1258 __ Jump(masm->isolate()->builtins()->OnStackReplacement(), | 1258 __ Jump(masm->isolate()->builtins()->OnStackReplacement(), |
| 1259 RelocInfo::CODE_TARGET); | 1259 RelocInfo::CODE_TARGET); |
| 1260 | 1260 |
| 1261 __ bind(&ok); | 1261 __ bind(&ok); |
| 1262 __ Ret(); | 1262 __ Ret(); |
| 1263 } | 1263 } |
| 1264 | 1264 |
| 1265 | 1265 |
| 1266 // static |
| 1266 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { | 1267 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { |
| 1267 // 1. Make sure we have at least one argument. | 1268 // 1. Make sure we have at least one argument. |
| 1268 // r3: actual number of arguments | 1269 // r3: actual number of arguments |
| 1269 { | 1270 { |
| 1270 Label done; | 1271 Label done; |
| 1271 __ cmpi(r3, Operand::Zero()); | 1272 __ cmpi(r3, Operand::Zero()); |
| 1272 __ bne(&done); | 1273 __ bne(&done); |
| 1273 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); | 1274 __ PushRoot(Heap::kUndefinedValueRootIndex); |
| 1274 __ push(r5); | |
| 1275 __ addi(r3, r3, Operand(1)); | 1275 __ addi(r3, r3, Operand(1)); |
| 1276 __ bind(&done); | 1276 __ bind(&done); |
| 1277 } | 1277 } |
| 1278 | 1278 |
| 1279 // 2. Get the function to call (passed as receiver) from the stack, check | 1279 // 2. Get the callable to call (passed as receiver) from the stack. |
| 1280 // if it is a function. | |
| 1281 // r3: actual number of arguments | 1280 // r3: actual number of arguments |
| 1282 Label slow, non_function; | 1281 __ ShiftLeftImm(r5, r3, Operand(kPointerSizeLog2)); |
| 1283 __ ShiftLeftImm(r4, r3, Operand(kPointerSizeLog2)); | 1282 __ LoadPX(r4, MemOperand(sp, r5)); |
| 1284 __ add(r4, sp, r4); | |
| 1285 __ LoadP(r4, MemOperand(r4)); | |
| 1286 __ JumpIfSmi(r4, &non_function); | |
| 1287 __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE); | |
| 1288 __ bne(&slow); | |
| 1289 | 1283 |
| 1290 // 3a. Patch the first argument if necessary when calling a function. | 1284 // 3. Shift arguments and return address one slot down on the stack |
| 1291 // r3: actual number of arguments | |
| 1292 // r4: function | |
| 1293 Label shift_arguments; | |
| 1294 __ li(r7, Operand::Zero()); // indicate regular JS_FUNCTION | |
| 1295 { | |
| 1296 Label convert_to_object, use_global_proxy, patch_receiver; | |
| 1297 // Change context eagerly in case we need the global receiver. | |
| 1298 __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); | |
| 1299 | |
| 1300 // Do not transform the receiver for strict mode functions. | |
| 1301 __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); | |
| 1302 __ lwz(r6, FieldMemOperand(r5, SharedFunctionInfo::kCompilerHintsOffset)); | |
| 1303 __ TestBit(r6, | |
| 1304 #if V8_TARGET_ARCH_PPC64 | |
| 1305 SharedFunctionInfo::kStrictModeFunction, | |
| 1306 #else | |
| 1307 SharedFunctionInfo::kStrictModeFunction + kSmiTagSize, | |
| 1308 #endif | |
| 1309 r0); | |
| 1310 __ bne(&shift_arguments, cr0); | |
| 1311 | |
| 1312 // Do not transform the receiver for native (Compilerhints already in r6). | |
| 1313 __ TestBit(r6, | |
| 1314 #if V8_TARGET_ARCH_PPC64 | |
| 1315 SharedFunctionInfo::kNative, | |
| 1316 #else | |
| 1317 SharedFunctionInfo::kNative + kSmiTagSize, | |
| 1318 #endif | |
| 1319 r0); | |
| 1320 __ bne(&shift_arguments, cr0); | |
| 1321 | |
| 1322 // Compute the receiver in sloppy mode. | |
| 1323 __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2)); | |
| 1324 __ add(r5, sp, ip); | |
| 1325 __ LoadP(r5, MemOperand(r5, -kPointerSize)); | |
| 1326 // r3: actual number of arguments | |
| 1327 // r4: function | |
| 1328 // r5: first argument | |
| 1329 __ JumpIfSmi(r5, &convert_to_object); | |
| 1330 | |
| 1331 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex); | |
| 1332 __ cmp(r5, r6); | |
| 1333 __ beq(&use_global_proxy); | |
| 1334 __ LoadRoot(r6, Heap::kNullValueRootIndex); | |
| 1335 __ cmp(r5, r6); | |
| 1336 __ beq(&use_global_proxy); | |
| 1337 | |
| 1338 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | |
| 1339 __ CompareObjectType(r5, r6, r6, FIRST_SPEC_OBJECT_TYPE); | |
| 1340 __ bge(&shift_arguments); | |
| 1341 | |
| 1342 __ bind(&convert_to_object); | |
| 1343 | |
| 1344 { | |
| 1345 // Enter an internal frame in order to preserve argument count. | |
| 1346 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | |
| 1347 __ SmiTag(r3); | |
| 1348 __ Push(r3); | |
| 1349 __ mr(r3, r5); | |
| 1350 ToObjectStub stub(masm->isolate()); | |
| 1351 __ CallStub(&stub); | |
| 1352 __ mr(r5, r3); | |
| 1353 | |
| 1354 __ pop(r3); | |
| 1355 __ SmiUntag(r3); | |
| 1356 | |
| 1357 // Exit the internal frame. | |
| 1358 } | |
| 1359 | |
| 1360 // Restore the function to r4, and the flag to r7. | |
| 1361 __ ShiftLeftImm(r7, r3, Operand(kPointerSizeLog2)); | |
| 1362 __ add(r7, sp, r7); | |
| 1363 __ LoadP(r4, MemOperand(r7)); | |
| 1364 __ li(r7, Operand::Zero()); | |
| 1365 __ b(&patch_receiver); | |
| 1366 | |
| 1367 __ bind(&use_global_proxy); | |
| 1368 __ LoadP(r5, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | |
| 1369 __ LoadP(r5, FieldMemOperand(r5, GlobalObject::kGlobalProxyOffset)); | |
| 1370 | |
| 1371 __ bind(&patch_receiver); | |
| 1372 __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2)); | |
| 1373 __ add(r6, sp, ip); | |
| 1374 __ StoreP(r5, MemOperand(r6, -kPointerSize)); | |
| 1375 | |
| 1376 __ b(&shift_arguments); | |
| 1377 } | |
| 1378 | |
| 1379 // 3b. Check for function proxy. | |
| 1380 __ bind(&slow); | |
| 1381 __ li(r7, Operand(1, RelocInfo::NONE32)); // indicate function proxy | |
| 1382 __ cmpi(r5, Operand(JS_FUNCTION_PROXY_TYPE)); | |
| 1383 __ beq(&shift_arguments); | |
| 1384 __ bind(&non_function); | |
| 1385 __ li(r7, Operand(2, RelocInfo::NONE32)); // indicate non-function | |
| 1386 | |
| 1387 // 3c. Patch the first argument when calling a non-function. The | |
| 1388 // CALL_NON_FUNCTION builtin expects the non-function callee as | |
| 1389 // receiver, so overwrite the first argument which will ultimately | |
| 1390 // become the receiver. | |
| 1391 // r3: actual number of arguments | |
| 1392 // r4: function | |
| 1393 // r7: call type (0: JS function, 1: function proxy, 2: non-function) | |
| 1394 __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2)); | |
| 1395 __ add(r5, sp, ip); | |
| 1396 __ StoreP(r4, MemOperand(r5, -kPointerSize)); | |
| 1397 | |
| 1398 // 4. Shift arguments and return address one slot down on the stack | |
| 1399 // (overwriting the original receiver). Adjust argument count to make | 1285 // (overwriting the original receiver). Adjust argument count to make |
| 1400 // the original first argument the new receiver. | 1286 // the original first argument the new receiver. |
| 1401 // r3: actual number of arguments | 1287 // r3: actual number of arguments |
| 1402 // r4: function | 1288 // r4: callable |
| 1403 // r7: call type (0: JS function, 1: function proxy, 2: non-function) | |
| 1404 __ bind(&shift_arguments); | |
| 1405 { | 1289 { |
| 1406 Label loop; | 1290 Label loop; |
| 1407 // Calculate the copy start address (destination). Copy end address is sp. | 1291 // Calculate the copy start address (destination). Copy end address is sp. |
| 1408 __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2)); | 1292 __ add(r5, sp, r5); |
| 1409 __ add(r5, sp, ip); | |
| 1410 | 1293 |
| 1294 |
| 1295 __ mtctr(r3); |
| 1411 __ bind(&loop); | 1296 __ bind(&loop); |
| 1412 __ LoadP(ip, MemOperand(r5, -kPointerSize)); | 1297 __ LoadP(ip, MemOperand(r5, -kPointerSize)); |
| 1413 __ StoreP(ip, MemOperand(r5)); | 1298 __ StoreP(ip, MemOperand(r5)); |
| 1414 __ subi(r5, r5, Operand(kPointerSize)); | 1299 __ subi(r5, r5, Operand(kPointerSize)); |
| 1415 __ cmp(r5, sp); | 1300 __ bdnz(&loop); |
| 1416 __ bne(&loop); | |
| 1417 // Adjust the actual number of arguments and remove the top element | 1301 // Adjust the actual number of arguments and remove the top element |
| 1418 // (which is a copy of the last argument). | 1302 // (which is a copy of the last argument). |
| 1419 __ subi(r3, r3, Operand(1)); | 1303 __ subi(r3, r3, Operand(1)); |
| 1420 __ pop(); | 1304 __ pop(); |
| 1421 } | 1305 } |
| 1422 | 1306 |
| 1423 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, | 1307 // 4. Call the callable. |
| 1424 // or a function proxy via CALL_FUNCTION_PROXY. | 1308 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1425 // r3: actual number of arguments | |
| 1426 // r4: function | |
| 1427 // r7: call type (0: JS function, 1: function proxy, 2: non-function) | |
| 1428 { | |
| 1429 Label function, non_proxy; | |
| 1430 __ cmpi(r7, Operand::Zero()); | |
| 1431 __ beq(&function); | |
| 1432 // Expected number of arguments is 0 for CALL_NON_FUNCTION. | |
| 1433 __ li(r5, Operand::Zero()); | |
| 1434 __ cmpi(r7, Operand(1)); | |
| 1435 __ bne(&non_proxy); | |
| 1436 | |
| 1437 __ push(r4); // re-add proxy object as additional argument | |
| 1438 __ addi(r3, r3, Operand(1)); | |
| 1439 __ GetBuiltinFunction(r4, Context::CALL_FUNCTION_PROXY_BUILTIN_INDEX); | |
| 1440 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | |
| 1441 RelocInfo::CODE_TARGET); | |
| 1442 | |
| 1443 __ bind(&non_proxy); | |
| 1444 __ GetBuiltinFunction(r4, Context::CALL_NON_FUNCTION_BUILTIN_INDEX); | |
| 1445 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | |
| 1446 RelocInfo::CODE_TARGET); | |
| 1447 __ bind(&function); | |
| 1448 } | |
| 1449 | |
| 1450 // 5b. Get the code to call from the function and check that the number of | |
| 1451 // expected arguments matches what we're providing. If so, jump | |
| 1452 // (tail-call) to the code in register ip without checking arguments. | |
| 1453 // r3: actual number of arguments | |
| 1454 // r4: function | |
| 1455 __ LoadP(r6, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); | |
| 1456 __ LoadWordArith( | |
| 1457 r5, FieldMemOperand(r6, SharedFunctionInfo::kFormalParameterCountOffset)); | |
| 1458 #if !V8_TARGET_ARCH_PPC64 | |
| 1459 __ SmiUntag(r5); | |
| 1460 #endif | |
| 1461 __ cmp(r5, r3); // Check formal and actual parameter counts. | |
| 1462 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | |
| 1463 RelocInfo::CODE_TARGET, ne); | |
| 1464 | |
| 1465 __ LoadP(ip, FieldMemOperand(r4, JSFunction::kCodeEntryOffset)); | |
| 1466 ParameterCount expected(0); | |
| 1467 __ InvokeCode(ip, expected, expected, JUMP_FUNCTION, NullCallWrapper()); | |
| 1468 } | 1309 } |
| 1469 | 1310 |
| 1470 | 1311 |
| 1471 static void Generate_PushAppliedArguments(MacroAssembler* masm, | 1312 static void Generate_PushAppliedArguments(MacroAssembler* masm, |
| 1472 const int argumentsOffset, | 1313 const int argumentsOffset, |
| 1473 const int indexOffset, | 1314 const int indexOffset, |
| 1474 const int limitOffset) { | 1315 const int limitOffset) { |
| 1475 Register receiver = LoadDescriptor::ReceiverRegister(); | 1316 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 1476 Register key = LoadDescriptor::NameRegister(); | 1317 Register key = LoadDescriptor::NameRegister(); |
| 1477 Register slot = LoadDescriptor::SlotRegister(); | 1318 Register slot = LoadDescriptor::SlotRegister(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1521 const int kFormalParameters = targetIsArgument ? 3 : 2; | 1362 const int kFormalParameters = targetIsArgument ? 3 : 2; |
| 1522 const int kStackSize = kFormalParameters + 1; | 1363 const int kStackSize = kFormalParameters + 1; |
| 1523 | 1364 |
| 1524 { | 1365 { |
| 1525 FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); | 1366 FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); |
| 1526 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; | 1367 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; |
| 1527 const int kReceiverOffset = kArgumentsOffset + kPointerSize; | 1368 const int kReceiverOffset = kArgumentsOffset + kPointerSize; |
| 1528 const int kFunctionOffset = kReceiverOffset + kPointerSize; | 1369 const int kFunctionOffset = kReceiverOffset + kPointerSize; |
| 1529 | 1370 |
| 1530 __ LoadP(r3, MemOperand(fp, kFunctionOffset)); // get the function | 1371 __ LoadP(r3, MemOperand(fp, kFunctionOffset)); // get the function |
| 1531 __ push(r3); | 1372 __ LoadP(r4, MemOperand(fp, kArgumentsOffset)); // get the args array |
| 1532 __ LoadP(r3, MemOperand(fp, kArgumentsOffset)); // get the args array | 1373 __ Push(r3, r4); |
| 1533 __ push(r3); | |
| 1534 if (targetIsArgument) { | 1374 if (targetIsArgument) { |
| 1535 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, | 1375 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, |
| 1536 CALL_FUNCTION); | 1376 CALL_FUNCTION); |
| 1537 } else { | 1377 } else { |
| 1538 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); | 1378 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); |
| 1539 } | 1379 } |
| 1540 | 1380 |
| 1541 Generate_CheckStackOverflow(masm, kFunctionOffset, r3, kArgcIsSmiTagged); | 1381 Generate_CheckStackOverflow(masm, kFunctionOffset, r3, kArgcIsSmiTagged); |
| 1542 | 1382 |
| 1543 // Push current limit and index. | 1383 // Push current limit and index. |
| 1544 const int kIndexOffset = | 1384 const int kIndexOffset = |
| 1545 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); | 1385 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); |
| 1546 const int kLimitOffset = | 1386 const int kLimitOffset = |
| 1547 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); | 1387 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); |
| 1548 __ li(r4, Operand::Zero()); | 1388 __ li(r4, Operand::Zero()); |
| 1549 __ Push(r3, r4); // limit and initial index. | 1389 __ LoadP(r5, MemOperand(fp, kReceiverOffset)); |
| 1550 | 1390 __ Push(r3, r4, r5); // limit, initial index and receiver. |
| 1551 // Get the receiver. | |
| 1552 __ LoadP(r3, MemOperand(fp, kReceiverOffset)); | |
| 1553 | |
| 1554 // Check that the function is a JS function (otherwise it must be a proxy). | |
| 1555 Label push_receiver; | |
| 1556 __ LoadP(r4, MemOperand(fp, kFunctionOffset)); | |
| 1557 __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE); | |
| 1558 __ bne(&push_receiver); | |
| 1559 | |
| 1560 // Change context eagerly to get the right global object if necessary. | |
| 1561 __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); | |
| 1562 // Load the shared function info while the function is still in r4. | |
| 1563 __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); | |
| 1564 | |
| 1565 // Compute the receiver. | |
| 1566 // Do not transform the receiver for strict mode functions. | |
| 1567 Label call_to_object, use_global_proxy; | |
| 1568 __ lwz(r5, FieldMemOperand(r5, SharedFunctionInfo::kCompilerHintsOffset)); | |
| 1569 __ TestBit(r5, | |
| 1570 #if V8_TARGET_ARCH_PPC64 | |
| 1571 SharedFunctionInfo::kStrictModeFunction, | |
| 1572 #else | |
| 1573 SharedFunctionInfo::kStrictModeFunction + kSmiTagSize, | |
| 1574 #endif | |
| 1575 r0); | |
| 1576 __ bne(&push_receiver, cr0); | |
| 1577 | |
| 1578 // Do not transform the receiver for strict mode functions. | |
| 1579 __ TestBit(r5, | |
| 1580 #if V8_TARGET_ARCH_PPC64 | |
| 1581 SharedFunctionInfo::kNative, | |
| 1582 #else | |
| 1583 SharedFunctionInfo::kNative + kSmiTagSize, | |
| 1584 #endif | |
| 1585 r0); | |
| 1586 __ bne(&push_receiver, cr0); | |
| 1587 | |
| 1588 // Compute the receiver in sloppy mode. | |
| 1589 __ JumpIfSmi(r3, &call_to_object); | |
| 1590 __ LoadRoot(r4, Heap::kNullValueRootIndex); | |
| 1591 __ cmp(r3, r4); | |
| 1592 __ beq(&use_global_proxy); | |
| 1593 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); | |
| 1594 __ cmp(r3, r4); | |
| 1595 __ beq(&use_global_proxy); | |
| 1596 | |
| 1597 // Check if the receiver is already a JavaScript object. | |
| 1598 // r3: receiver | |
| 1599 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | |
| 1600 __ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE); | |
| 1601 __ bge(&push_receiver); | |
| 1602 | |
| 1603 // Convert the receiver to a regular object. | |
| 1604 // r3: receiver | |
| 1605 __ bind(&call_to_object); | |
| 1606 ToObjectStub stub(masm->isolate()); | |
| 1607 __ CallStub(&stub); | |
| 1608 __ b(&push_receiver); | |
| 1609 | |
| 1610 __ bind(&use_global_proxy); | |
| 1611 __ LoadP(r3, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | |
| 1612 __ LoadP(r3, FieldMemOperand(r3, GlobalObject::kGlobalProxyOffset)); | |
| 1613 | |
| 1614 // Push the receiver. | |
| 1615 // r3: receiver | |
| 1616 __ bind(&push_receiver); | |
| 1617 __ push(r3); | |
| 1618 | 1391 |
| 1619 // Copy all arguments from the array to the stack. | 1392 // Copy all arguments from the array to the stack. |
| 1620 Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset, | 1393 Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset, |
| 1621 kLimitOffset); | 1394 kLimitOffset); |
| 1622 | 1395 |
| 1623 // Call the function. | 1396 // Call the callable. |
| 1624 Label call_proxy; | 1397 // TODO(bmeurer): This should be a tail call according to ES6. |
| 1625 ParameterCount actual(r3); | |
| 1626 __ LoadP(r4, MemOperand(fp, kFunctionOffset)); | 1398 __ LoadP(r4, MemOperand(fp, kFunctionOffset)); |
| 1627 __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE); | 1399 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1628 __ bne(&call_proxy); | |
| 1629 __ InvokeFunction(r4, actual, CALL_FUNCTION, NullCallWrapper()); | |
| 1630 | |
| 1631 __ LeaveFrame(StackFrame::INTERNAL, kStackSize * kPointerSize); | |
| 1632 __ blr(); | |
| 1633 | |
| 1634 // Call the function proxy. | |
| 1635 __ bind(&call_proxy); | |
| 1636 __ push(r4); // add function proxy as last argument | |
| 1637 __ addi(r3, r3, Operand(1)); | |
| 1638 __ li(r5, Operand::Zero()); | |
| 1639 __ GetBuiltinFunction(r4, Context::CALL_FUNCTION_PROXY_BUILTIN_INDEX); | |
| 1640 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | |
| 1641 RelocInfo::CODE_TARGET); | |
| 1642 | 1400 |
| 1643 // Tear down the internal frame and remove function, receiver and args. | 1401 // Tear down the internal frame and remove function, receiver and args. |
| 1644 } | 1402 } |
| 1645 __ addi(sp, sp, Operand(kStackSize * kPointerSize)); | 1403 __ addi(sp, sp, Operand(kStackSize * kPointerSize)); |
| 1646 __ blr(); | 1404 __ blr(); |
| 1647 } | 1405 } |
| 1648 | 1406 |
| 1649 | 1407 |
| 1650 static void Generate_ConstructHelper(MacroAssembler* masm) { | 1408 static void Generate_ConstructHelper(MacroAssembler* masm) { |
| 1651 const int kFormalParameters = 3; | 1409 const int kFormalParameters = 3; |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1768 // then tear down the parameters. | 1526 // then tear down the parameters. |
| 1769 __ LoadP(r4, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + | 1527 __ LoadP(r4, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + |
| 1770 kPointerSize))); | 1528 kPointerSize))); |
| 1771 int stack_adjustment = kPointerSize; // adjust for receiver | 1529 int stack_adjustment = kPointerSize; // adjust for receiver |
| 1772 __ LeaveFrame(StackFrame::ARGUMENTS_ADAPTOR, stack_adjustment); | 1530 __ LeaveFrame(StackFrame::ARGUMENTS_ADAPTOR, stack_adjustment); |
| 1773 __ SmiToPtrArrayOffset(r0, r4); | 1531 __ SmiToPtrArrayOffset(r0, r4); |
| 1774 __ add(sp, sp, r0); | 1532 __ add(sp, sp, r0); |
| 1775 } | 1533 } |
| 1776 | 1534 |
| 1777 | 1535 |
| 1536 // static |
| 1537 void Builtins::Generate_CallFunction(MacroAssembler* masm) { |
| 1538 // ----------- S t a t e ------------- |
| 1539 // -- r3 : the number of arguments (not including the receiver) |
| 1540 // -- r4 : the function to call (checked to be a JSFunction) |
| 1541 // ----------------------------------- |
| 1542 |
| 1543 Label convert, convert_global_proxy, convert_to_object, done_convert; |
| 1544 __ AssertFunction(r4); |
| 1545 // TODO(bmeurer): Throw a TypeError if function's [[FunctionKind]] internal |
| 1546 // slot is "classConstructor". |
| 1547 // Enter the context of the function; ToObject has to run in the function |
| 1548 // context, and we also need to take the global proxy from the function |
| 1549 // context in case of conversion. |
| 1550 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) |
| 1551 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset == |
| 1552 SharedFunctionInfo::kStrictModeByteOffset); |
| 1553 __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); |
| 1554 __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); |
| 1555 // We need to convert the receiver for non-native sloppy mode functions. |
| 1556 __ lbz(r6, FieldMemOperand(r5, SharedFunctionInfo::kNativeByteOffset)); |
| 1557 __ andi(r0, r6, Operand((1 << SharedFunctionInfo::kNativeBitWithinByte) | |
| 1558 (1 << SharedFunctionInfo::kStrictModeBitWithinByte))); |
| 1559 __ bne(&done_convert, cr0); |
| 1560 { |
| 1561 __ ShiftLeftImm(r6, r3, Operand(kPointerSizeLog2)); |
| 1562 __ LoadPX(r6, MemOperand(sp, r6)); |
| 1563 |
| 1564 // ----------- S t a t e ------------- |
| 1565 // -- r3 : the number of arguments (not including the receiver) |
| 1566 // -- r4 : the function to call (checked to be a JSFunction) |
| 1567 // -- r5 : the shared function info. |
| 1568 // -- r6 : the receiver |
| 1569 // -- cp : the function context. |
| 1570 // ----------------------------------- |
| 1571 |
| 1572 Label convert_receiver; |
| 1573 __ JumpIfSmi(r6, &convert_to_object); |
| 1574 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 1575 __ CompareObjectType(r6, r7, r7, FIRST_JS_RECEIVER_TYPE); |
| 1576 __ bge(&done_convert); |
| 1577 __ JumpIfRoot(r6, Heap::kUndefinedValueRootIndex, &convert_global_proxy); |
| 1578 __ JumpIfNotRoot(r6, Heap::kNullValueRootIndex, &convert_to_object); |
| 1579 __ bind(&convert_global_proxy); |
| 1580 { |
| 1581 // Patch receiver to global proxy. |
| 1582 __ LoadGlobalProxy(r6); |
| 1583 } |
| 1584 __ b(&convert_receiver); |
| 1585 __ bind(&convert_to_object); |
| 1586 { |
| 1587 // Convert receiver using ToObject. |
| 1588 // TODO(bmeurer): Inline the allocation here to avoid building the frame |
| 1589 // in the fast case? (fall back to AllocateInNewSpace?) |
| 1590 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 1591 __ SmiTag(r3); |
| 1592 __ Push(r3, r4); |
| 1593 __ mr(r3, r6); |
| 1594 ToObjectStub stub(masm->isolate()); |
| 1595 __ CallStub(&stub); |
| 1596 __ mr(r6, r3); |
| 1597 __ Pop(r3, r4); |
| 1598 __ SmiUntag(r3); |
| 1599 } |
| 1600 __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); |
| 1601 __ bind(&convert_receiver); |
| 1602 __ ShiftLeftImm(r7, r3, Operand(kPointerSizeLog2)); |
| 1603 __ StorePX(r6, MemOperand(sp, r7)); |
| 1604 } |
| 1605 __ bind(&done_convert); |
| 1606 |
| 1607 // ----------- S t a t e ------------- |
| 1608 // -- r3 : the number of arguments (not including the receiver) |
| 1609 // -- r4 : the function to call (checked to be a JSFunction) |
| 1610 // -- r5 : the shared function info. |
| 1611 // -- cp : the function context. |
| 1612 // ----------------------------------- |
| 1613 |
| 1614 __ LoadWordArith( |
| 1615 r5, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset)); |
| 1616 #if !V8_TARGET_ARCH_PPC64 |
| 1617 __ SmiUntag(r5); |
| 1618 #endif |
| 1619 __ LoadP(r6, FieldMemOperand(r4, JSFunction::kCodeEntryOffset)); |
| 1620 ParameterCount actual(r3); |
| 1621 ParameterCount expected(r5); |
| 1622 __ InvokeCode(r6, expected, actual, JUMP_FUNCTION, NullCallWrapper()); |
| 1623 } |
| 1624 |
| 1625 |
| 1626 // static |
| 1627 void Builtins::Generate_Call(MacroAssembler* masm) { |
| 1628 // ----------- S t a t e ------------- |
| 1629 // -- r3 : the number of arguments (not including the receiver) |
| 1630 // -- r4 : the target to call (can be any Object). |
| 1631 // ----------------------------------- |
| 1632 |
| 1633 Label non_smi, non_function; |
| 1634 __ JumpIfSmi(r4, &non_function); |
| 1635 __ bind(&non_smi); |
| 1636 __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE); |
| 1637 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET, |
| 1638 eq); |
| 1639 __ cmpi(r5, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 1640 __ bne(&non_function); |
| 1641 |
| 1642 // 1. Call to function proxy. |
| 1643 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies. |
| 1644 __ LoadP(r4, FieldMemOperand(r4, JSFunctionProxy::kCallTrapOffset)); |
| 1645 __ AssertNotSmi(r4); |
| 1646 __ b(&non_smi); |
| 1647 |
| 1648 // 2. Call to something else, which might have a [[Call]] internal method (if |
| 1649 // not we raise an exception). |
| 1650 __ bind(&non_function); |
| 1651 // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could |
| 1652 // be awesome instead; i.e. a trivial improvement would be to call into the |
| 1653 // runtime and just deal with the API function there instead of returning a |
| 1654 // delegate from a runtime call that just jumps back to the runtime once |
| 1655 // called. Or, bonus points, call directly into the C API function here, as |
| 1656 // we do in some Crankshaft fast cases. |
| 1657 // Overwrite the original receiver with the (original) target. |
| 1658 __ ShiftLeftImm(r5, r3, Operand(kPointerSizeLog2)); |
| 1659 __ StorePX(r4, MemOperand(sp, r5)); |
| 1660 { |
| 1661 // Determine the delegate for the target (if any). |
| 1662 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 1663 __ SmiTag(r3); |
| 1664 __ Push(r3, r4); |
| 1665 __ CallRuntime(Runtime::kGetFunctionDelegate, 1); |
| 1666 __ mr(r4, r3); |
| 1667 __ Pop(r3); |
| 1668 __ SmiUntag(r3); |
| 1669 } |
| 1670 // The delegate is always a regular function. |
| 1671 __ AssertFunction(r4); |
| 1672 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); |
| 1673 } |
| 1674 |
| 1675 |
| 1778 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { | 1676 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { |
| 1779 // ----------- S t a t e ------------- | 1677 // ----------- S t a t e ------------- |
| 1780 // -- r3 : actual number of arguments | 1678 // -- r3 : actual number of arguments |
| 1781 // -- r4 : function (passed through to callee) | 1679 // -- r4 : function (passed through to callee) |
| 1782 // -- r5 : expected number of arguments | 1680 // -- r5 : expected number of arguments |
| 1783 // ----------------------------------- | 1681 // ----------------------------------- |
| 1784 | 1682 |
| 1785 Label stack_overflow; | 1683 Label stack_overflow; |
| 1786 ArgumentAdaptorStackCheck(masm, &stack_overflow); | 1684 ArgumentAdaptorStackCheck(masm, &stack_overflow); |
| 1787 Label invoke, dont_adapt_arguments; | 1685 Label invoke, dont_adapt_arguments; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1932 __ bkpt(0); | 1830 __ bkpt(0); |
| 1933 } | 1831 } |
| 1934 } | 1832 } |
| 1935 | 1833 |
| 1936 | 1834 |
| 1937 #undef __ | 1835 #undef __ |
| 1938 } // namespace internal | 1836 } // namespace internal |
| 1939 } // namespace v8 | 1837 } // namespace v8 |
| 1940 | 1838 |
| 1941 #endif // V8_TARGET_ARCH_PPC | 1839 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |