Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Side by Side Diff: src/ppc/builtins-ppc.cc

Issue 1327093002: PPC: [builtins] Unify the various versions of [[Call]] with a Call builtin. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/ppc/code-stubs-ppc.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/ppc/code-stubs-ppc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698