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

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

Issue 1328963004: Revert of [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/arm/code-stubs-arm.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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_ARM 5 #if V8_TARGET_ARCH_ARM
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 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1249 __ CallRuntime(Runtime::kStackGuard, 0); 1249 __ CallRuntime(Runtime::kStackGuard, 0);
1250 } 1250 }
1251 __ Jump(masm->isolate()->builtins()->OnStackReplacement(), 1251 __ Jump(masm->isolate()->builtins()->OnStackReplacement(),
1252 RelocInfo::CODE_TARGET); 1252 RelocInfo::CODE_TARGET);
1253 1253
1254 __ bind(&ok); 1254 __ bind(&ok);
1255 __ Ret(); 1255 __ Ret();
1256 } 1256 }
1257 1257
1258 1258
1259 // static
1260 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { 1259 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
1261 // 1. Make sure we have at least one argument. 1260 // 1. Make sure we have at least one argument.
1262 // r0: actual number of arguments 1261 // r0: actual number of arguments
1263 { 1262 { Label done;
1264 Label done;
1265 __ cmp(r0, Operand::Zero()); 1263 __ cmp(r0, Operand::Zero());
1266 __ b(ne, &done); 1264 __ b(ne, &done);
1267 __ PushRoot(Heap::kUndefinedValueRootIndex); 1265 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
1266 __ push(r2);
1268 __ add(r0, r0, Operand(1)); 1267 __ add(r0, r0, Operand(1));
1269 __ bind(&done); 1268 __ bind(&done);
1270 } 1269 }
1271 1270
1272 // 2. Get the callable to call (passed as receiver) from the stack. 1271 // 2. Get the function to call (passed as receiver) from the stack, check
1272 // if it is a function.
1273 // r0: actual number of arguments 1273 // r0: actual number of arguments
1274 Label slow, non_function;
1274 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); 1275 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
1276 __ JumpIfSmi(r1, &non_function);
1277 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1278 __ b(ne, &slow);
1275 1279
1276 // 3. Shift arguments and return address one slot down on the stack 1280 // 3a. Patch the first argument if necessary when calling a function.
1281 // r0: actual number of arguments
1282 // r1: function
1283 Label shift_arguments;
1284 __ mov(r4, Operand::Zero()); // indicate regular JS_FUNCTION
1285 { Label convert_to_object, use_global_proxy, patch_receiver;
1286 // Change context eagerly in case we need the global receiver.
1287 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1288
1289 // Do not transform the receiver for strict mode functions.
1290 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1291 __ ldr(r3, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset));
1292 __ tst(r3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1293 kSmiTagSize)));
1294 __ b(ne, &shift_arguments);
1295
1296 // Do not transform the receiver for native (Compilerhints already in r3).
1297 __ tst(r3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1298 __ b(ne, &shift_arguments);
1299
1300 // Compute the receiver in sloppy mode.
1301 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1302 __ ldr(r2, MemOperand(r2, -kPointerSize));
1303 // r0: actual number of arguments
1304 // r1: function
1305 // r2: first argument
1306 __ JumpIfSmi(r2, &convert_to_object);
1307
1308 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
1309 __ cmp(r2, r3);
1310 __ b(eq, &use_global_proxy);
1311 __ LoadRoot(r3, Heap::kNullValueRootIndex);
1312 __ cmp(r2, r3);
1313 __ b(eq, &use_global_proxy);
1314
1315 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1316 __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE);
1317 __ b(ge, &shift_arguments);
1318
1319 __ bind(&convert_to_object);
1320
1321 {
1322 // Enter an internal frame in order to preserve argument count.
1323 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
1324 __ SmiTag(r0);
1325 __ push(r0);
1326
1327 __ mov(r0, r2);
1328 ToObjectStub stub(masm->isolate());
1329 __ CallStub(&stub);
1330 __ mov(r2, r0);
1331
1332 __ pop(r0);
1333 __ SmiUntag(r0);
1334
1335 // Exit the internal frame.
1336 }
1337
1338 // Restore the function to r1, and the flag to r4.
1339 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
1340 __ mov(r4, Operand::Zero());
1341 __ jmp(&patch_receiver);
1342
1343 __ bind(&use_global_proxy);
1344 __ ldr(r2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
1345 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalProxyOffset));
1346
1347 __ bind(&patch_receiver);
1348 __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
1349 __ str(r2, MemOperand(r3, -kPointerSize));
1350
1351 __ jmp(&shift_arguments);
1352 }
1353
1354 // 3b. Check for function proxy.
1355 __ bind(&slow);
1356 __ mov(r4, Operand(1, RelocInfo::NONE32)); // indicate function proxy
1357 __ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE));
1358 __ b(eq, &shift_arguments);
1359 __ bind(&non_function);
1360 __ mov(r4, Operand(2, RelocInfo::NONE32)); // indicate non-function
1361
1362 // 3c. Patch the first argument when calling a non-function. The
1363 // CALL_NON_FUNCTION builtin expects the non-function callee as
1364 // receiver, so overwrite the first argument which will ultimately
1365 // become the receiver.
1366 // r0: actual number of arguments
1367 // r1: function
1368 // r4: call type (0: JS function, 1: function proxy, 2: non-function)
1369 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1370 __ str(r1, MemOperand(r2, -kPointerSize));
1371
1372 // 4. Shift arguments and return address one slot down on the stack
1277 // (overwriting the original receiver). Adjust argument count to make 1373 // (overwriting the original receiver). Adjust argument count to make
1278 // the original first argument the new receiver. 1374 // the original first argument the new receiver.
1279 // r0: actual number of arguments 1375 // r0: actual number of arguments
1280 // r1: callable 1376 // r1: function
1281 { 1377 // r4: call type (0: JS function, 1: function proxy, 2: non-function)
1282 Label loop; 1378 __ bind(&shift_arguments);
1379 { Label loop;
1283 // Calculate the copy start address (destination). Copy end address is sp. 1380 // Calculate the copy start address (destination). Copy end address is sp.
1284 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 1381 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1285 1382
1286 __ bind(&loop); 1383 __ bind(&loop);
1287 __ ldr(ip, MemOperand(r2, -kPointerSize)); 1384 __ ldr(ip, MemOperand(r2, -kPointerSize));
1288 __ str(ip, MemOperand(r2)); 1385 __ str(ip, MemOperand(r2));
1289 __ sub(r2, r2, Operand(kPointerSize)); 1386 __ sub(r2, r2, Operand(kPointerSize));
1290 __ cmp(r2, sp); 1387 __ cmp(r2, sp);
1291 __ b(ne, &loop); 1388 __ b(ne, &loop);
1292 // Adjust the actual number of arguments and remove the top element 1389 // Adjust the actual number of arguments and remove the top element
1293 // (which is a copy of the last argument). 1390 // (which is a copy of the last argument).
1294 __ sub(r0, r0, Operand(1)); 1391 __ sub(r0, r0, Operand(1));
1295 __ pop(); 1392 __ pop();
1296 } 1393 }
1297 1394
1298 // 4. Call the callable. 1395 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
1299 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 1396 // or a function proxy via CALL_FUNCTION_PROXY.
1397 // r0: actual number of arguments
1398 // r1: function
1399 // r4: call type (0: JS function, 1: function proxy, 2: non-function)
1400 { Label function, non_proxy;
1401 __ tst(r4, r4);
1402 __ b(eq, &function);
1403 // Expected number of arguments is 0 for CALL_NON_FUNCTION.
1404 __ mov(r2, Operand::Zero());
1405 __ cmp(r4, Operand(1));
1406 __ b(ne, &non_proxy);
1407
1408 __ push(r1); // re-add proxy object as additional argument
1409 __ add(r0, r0, Operand(1));
1410 __ GetBuiltinFunction(r1, Context::CALL_FUNCTION_PROXY_BUILTIN_INDEX);
1411 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1412 RelocInfo::CODE_TARGET);
1413
1414 __ bind(&non_proxy);
1415 __ GetBuiltinFunction(r1, Context::CALL_NON_FUNCTION_BUILTIN_INDEX);
1416 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1417 RelocInfo::CODE_TARGET);
1418 __ bind(&function);
1419 }
1420
1421 // 5b. Get the code to call from the function and check that the number of
1422 // expected arguments matches what we're providing. If so, jump
1423 // (tail-call) to the code in register edx without checking arguments.
1424 // r0: actual number of arguments
1425 // r1: function
1426 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1427 __ ldr(r2,
1428 FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
1429 __ SmiUntag(r2);
1430 __ cmp(r2, r0); // Check formal and actual parameter counts.
1431 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1432 RelocInfo::CODE_TARGET,
1433 ne);
1434
1435 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
1436 ParameterCount expected(0);
1437 __ InvokeCode(r3, expected, expected, JUMP_FUNCTION, NullCallWrapper());
1300 } 1438 }
1301 1439
1302 1440
1303 static void Generate_PushAppliedArguments(MacroAssembler* masm, 1441 static void Generate_PushAppliedArguments(MacroAssembler* masm,
1304 const int argumentsOffset, 1442 const int argumentsOffset,
1305 const int indexOffset, 1443 const int indexOffset,
1306 const int limitOffset) { 1444 const int limitOffset) {
1307 Label entry, loop; 1445 Label entry, loop;
1308 Register receiver = LoadDescriptor::ReceiverRegister(); 1446 Register receiver = LoadDescriptor::ReceiverRegister();
1309 Register key = LoadDescriptor::NameRegister(); 1447 Register key = LoadDescriptor::NameRegister();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1354 const int kFormalParameters = targetIsArgument ? 3 : 2; 1492 const int kFormalParameters = targetIsArgument ? 3 : 2;
1355 const int kStackSize = kFormalParameters + 1; 1493 const int kStackSize = kFormalParameters + 1;
1356 1494
1357 { 1495 {
1358 FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); 1496 FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
1359 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; 1497 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1360 const int kReceiverOffset = kArgumentsOffset + kPointerSize; 1498 const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1361 const int kFunctionOffset = kReceiverOffset + kPointerSize; 1499 const int kFunctionOffset = kReceiverOffset + kPointerSize;
1362 1500
1363 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function 1501 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function
1364 __ ldr(r1, MemOperand(fp, kArgumentsOffset)); // get the args array 1502 __ push(r0);
1365 __ Push(r0, r1); 1503 __ ldr(r0, MemOperand(fp, kArgumentsOffset)); // get the args array
1504 __ push(r0);
1366 if (targetIsArgument) { 1505 if (targetIsArgument) {
1367 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, 1506 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX,
1368 CALL_FUNCTION); 1507 CALL_FUNCTION);
1369 } else { 1508 } else {
1370 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); 1509 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION);
1371 } 1510 }
1372 1511
1373 Generate_CheckStackOverflow(masm, kFunctionOffset, r0, kArgcIsSmiTagged); 1512 Generate_CheckStackOverflow(masm, kFunctionOffset, r0, kArgcIsSmiTagged);
1374 1513
1375 // Push current limit and index. 1514 // Push current limit and index.
1376 const int kIndexOffset = 1515 const int kIndexOffset =
1377 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); 1516 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
1378 const int kLimitOffset = 1517 const int kLimitOffset =
1379 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); 1518 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
1380 __ mov(r1, Operand::Zero()); 1519 __ push(r0); // limit
1381 __ ldr(r2, MemOperand(fp, kReceiverOffset)); 1520 __ mov(r1, Operand::Zero()); // initial index
1382 __ Push(r0, r1, r2); // limit, initial index and receiver. 1521 __ push(r1);
1522
1523 // Get the receiver.
1524 __ ldr(r0, MemOperand(fp, kReceiverOffset));
1525
1526 // Check that the function is a JS function (otherwise it must be a proxy).
1527 Label push_receiver;
1528 __ ldr(r1, MemOperand(fp, kFunctionOffset));
1529 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1530 __ b(ne, &push_receiver);
1531
1532 // Change context eagerly to get the right global object if necessary.
1533 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1534 // Load the shared function info while the function is still in r1.
1535 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1536
1537 // Compute the receiver.
1538 // Do not transform the receiver for strict mode functions.
1539 Label call_to_object, use_global_proxy;
1540 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset));
1541 __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1542 kSmiTagSize)));
1543 __ b(ne, &push_receiver);
1544
1545 // Do not transform the receiver for strict mode functions.
1546 __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1547 __ b(ne, &push_receiver);
1548
1549 // Compute the receiver in sloppy mode.
1550 __ JumpIfSmi(r0, &call_to_object);
1551 __ LoadRoot(r1, Heap::kNullValueRootIndex);
1552 __ cmp(r0, r1);
1553 __ b(eq, &use_global_proxy);
1554 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
1555 __ cmp(r0, r1);
1556 __ b(eq, &use_global_proxy);
1557
1558 // Check if the receiver is already a JavaScript object.
1559 // r0: receiver
1560 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1561 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
1562 __ b(ge, &push_receiver);
1563
1564 // Convert the receiver to a regular object.
1565 // r0: receiver
1566 __ bind(&call_to_object);
1567 ToObjectStub stub(masm->isolate());
1568 __ CallStub(&stub);
1569 __ b(&push_receiver);
1570
1571 __ bind(&use_global_proxy);
1572 __ ldr(r0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
1573 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalProxyOffset));
1574
1575 // Push the receiver.
1576 // r0: receiver
1577 __ bind(&push_receiver);
1578 __ push(r0);
1383 1579
1384 // Copy all arguments from the array to the stack. 1580 // Copy all arguments from the array to the stack.
1385 Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset, 1581 Generate_PushAppliedArguments(
1386 kLimitOffset); 1582 masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
1387 1583
1388 // Call the callable. 1584 // Call the function.
1389 // TODO(bmeurer): This should be a tail call according to ES6. 1585 Label call_proxy;
1586 ParameterCount actual(r0);
1390 __ ldr(r1, MemOperand(fp, kFunctionOffset)); 1587 __ ldr(r1, MemOperand(fp, kFunctionOffset));
1391 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 1588 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1589 __ b(ne, &call_proxy);
1590 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper());
1591
1592 frame_scope.GenerateLeaveFrame();
1593 __ add(sp, sp, Operand(kStackSize * kPointerSize));
1594 __ Jump(lr);
1595
1596 // Call the function proxy.
1597 __ bind(&call_proxy);
1598 __ push(r1); // add function proxy as last argument
1599 __ add(r0, r0, Operand(1));
1600 __ mov(r2, Operand::Zero());
1601 __ GetBuiltinFunction(r1, Context::CALL_FUNCTION_PROXY_BUILTIN_INDEX);
1602 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1603 RelocInfo::CODE_TARGET);
1392 1604
1393 // Tear down the internal frame and remove function, receiver and args. 1605 // Tear down the internal frame and remove function, receiver and args.
1394 } 1606 }
1395 __ add(sp, sp, Operand(kStackSize * kPointerSize)); 1607 __ add(sp, sp, Operand(kStackSize * kPointerSize));
1396 __ Jump(lr); 1608 __ Jump(lr);
1397 } 1609 }
1398 1610
1399 1611
1400 static void Generate_ConstructHelper(MacroAssembler* masm) { 1612 static void Generate_ConstructHelper(MacroAssembler* masm) {
1401 const int kFormalParameters = 3; 1613 const int kFormalParameters = 3;
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1514 // then tear down the parameters. 1726 // then tear down the parameters.
1515 __ ldr(r1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + 1727 __ ldr(r1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp +
1516 kPointerSize))); 1728 kPointerSize)));
1517 1729
1518 __ LeaveFrame(StackFrame::ARGUMENTS_ADAPTOR); 1730 __ LeaveFrame(StackFrame::ARGUMENTS_ADAPTOR);
1519 __ add(sp, sp, Operand::PointerOffsetFromSmiKey(r1)); 1731 __ add(sp, sp, Operand::PointerOffsetFromSmiKey(r1));
1520 __ add(sp, sp, Operand(kPointerSize)); // adjust for receiver 1732 __ add(sp, sp, Operand(kPointerSize)); // adjust for receiver
1521 } 1733 }
1522 1734
1523 1735
1524 // static
1525 void Builtins::Generate_CallFunction(MacroAssembler* masm) {
1526 // ----------- S t a t e -------------
1527 // -- r0 : the number of arguments (not including the receiver)
1528 // -- r1 : the function to call (checked to be a JSFunction)
1529 // -----------------------------------
1530
1531 Label convert, convert_global_proxy, convert_to_object, done_convert;
1532 __ AssertFunction(r1);
1533 // TODO(bmeurer): Throw a TypeError if function's [[FunctionKind]] internal
1534 // slot is "classConstructor".
1535 // Enter the context of the function; ToObject has to run in the function
1536 // context, and we also need to take the global proxy from the function
1537 // context in case of conversion.
1538 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
1539 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset ==
1540 SharedFunctionInfo::kStrictModeByteOffset);
1541 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1542 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1543 // We need to convert the receiver for non-native sloppy mode functions.
1544 __ ldrb(r3, FieldMemOperand(r2, SharedFunctionInfo::kNativeByteOffset));
1545 __ tst(r3, Operand((1 << SharedFunctionInfo::kNativeBitWithinByte) |
1546 (1 << SharedFunctionInfo::kStrictModeBitWithinByte)));
1547 __ b(ne, &done_convert);
1548 {
1549 __ ldr(r3, MemOperand(sp, r0, LSL, kPointerSizeLog2));
1550
1551 // ----------- S t a t e -------------
1552 // -- r0 : the number of arguments (not including the receiver)
1553 // -- r1 : the function to call (checked to be a JSFunction)
1554 // -- r2 : the shared function info.
1555 // -- r3 : the receiver
1556 // -- cp : the function context.
1557 // -----------------------------------
1558
1559 Label convert_receiver;
1560 __ JumpIfSmi(r3, &convert_to_object);
1561 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
1562 __ CompareObjectType(r3, r4, r4, FIRST_JS_RECEIVER_TYPE);
1563 __ b(hs, &done_convert);
1564 __ JumpIfRoot(r3, Heap::kUndefinedValueRootIndex, &convert_global_proxy);
1565 __ JumpIfNotRoot(r3, Heap::kNullValueRootIndex, &convert_to_object);
1566 __ bind(&convert_global_proxy);
1567 {
1568 // Patch receiver to global proxy.
1569 __ LoadGlobalProxy(r3);
1570 }
1571 __ b(&convert_receiver);
1572 __ bind(&convert_to_object);
1573 {
1574 // Convert receiver using ToObject.
1575 // TODO(bmeurer): Inline the allocation here to avoid building the frame
1576 // in the fast case? (fall back to AllocateInNewSpace?)
1577 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
1578 __ SmiTag(r0);
1579 __ Push(r0, r1);
1580 __ mov(r0, r3);
1581 ToObjectStub stub(masm->isolate());
1582 __ CallStub(&stub);
1583 __ mov(r3, r0);
1584 __ Pop(r0, r1);
1585 __ SmiUntag(r0);
1586 }
1587 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1588 __ bind(&convert_receiver);
1589 __ str(r3, MemOperand(sp, r0, LSL, kPointerSizeLog2));
1590 }
1591 __ bind(&done_convert);
1592
1593 // ----------- S t a t e -------------
1594 // -- r0 : the number of arguments (not including the receiver)
1595 // -- r1 : the function to call (checked to be a JSFunction)
1596 // -- r2 : the shared function info.
1597 // -- cp : the function context.
1598 // -----------------------------------
1599
1600 __ ldr(r2,
1601 FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset));
1602 __ SmiUntag(r2);
1603 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
1604 ParameterCount actual(r0);
1605 ParameterCount expected(r2);
1606 __ InvokeCode(r3, expected, actual, JUMP_FUNCTION, NullCallWrapper());
1607 }
1608
1609
1610 // static
1611 void Builtins::Generate_Call(MacroAssembler* masm) {
1612 // ----------- S t a t e -------------
1613 // -- r0 : the number of arguments (not including the receiver)
1614 // -- r1 : the target to call (can be any Object).
1615 // -----------------------------------
1616
1617 Label non_smi, non_function;
1618 __ JumpIfSmi(r1, &non_function);
1619 __ bind(&non_smi);
1620 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1621 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET,
1622 eq);
1623 __ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE));
1624 __ b(ne, &non_function);
1625
1626 // 1. Call to function proxy.
1627 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies.
1628 __ ldr(r1, FieldMemOperand(r1, JSFunctionProxy::kCallTrapOffset));
1629 __ AssertNotSmi(r1);
1630 __ b(&non_smi);
1631
1632 // 2. Call to something else, which might have a [[Call]] internal method (if
1633 // not we raise an exception).
1634 __ bind(&non_function);
1635 // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could
1636 // be awesome instead; i.e. a trivial improvement would be to call into the
1637 // runtime and just deal with the API function there instead of returning a
1638 // delegate from a runtime call that just jumps back to the runtime once
1639 // called. Or, bonus points, call directly into the C API function here, as
1640 // we do in some Crankshaft fast cases.
1641 // Overwrite the original receiver with the (original) target.
1642 __ str(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
1643 {
1644 // Determine the delegate for the target (if any).
1645 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
1646 __ SmiTag(r0);
1647 __ Push(r0, r1);
1648 __ CallRuntime(Runtime::kGetFunctionDelegate, 1);
1649 __ mov(r1, r0);
1650 __ Pop(r0);
1651 __ SmiUntag(r0);
1652 }
1653 // The delegate is always a regular function.
1654 __ AssertFunction(r1);
1655 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
1656 }
1657
1658
1659 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 1736 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1660 // ----------- S t a t e ------------- 1737 // ----------- S t a t e -------------
1661 // -- r0 : actual number of arguments 1738 // -- r0 : actual number of arguments
1662 // -- r1 : function (passed through to callee) 1739 // -- r1 : function (passed through to callee)
1663 // -- r2 : expected number of arguments 1740 // -- r2 : expected number of arguments
1664 // ----------------------------------- 1741 // -----------------------------------
1665 1742
1666 Label stack_overflow; 1743 Label stack_overflow;
1667 ArgumentAdaptorStackCheck(masm, &stack_overflow); 1744 ArgumentAdaptorStackCheck(masm, &stack_overflow);
1668 Label invoke, dont_adapt_arguments; 1745 Label invoke, dont_adapt_arguments;
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1799 } 1876 }
1800 } 1877 }
1801 1878
1802 1879
1803 #undef __ 1880 #undef __
1804 1881
1805 } // namespace internal 1882 } // namespace internal
1806 } // namespace v8 1883 } // namespace v8
1807 1884
1808 #endif // V8_TARGET_ARCH_ARM 1885 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/arm/code-stubs-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698