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

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

Issue 913073003: [es6] implement Reflect.apply() & Reflect.construct() (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix arm Created 5 years, 9 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 | « src/arm/builtins-arm.cc ('k') | src/bootstrapper.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 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 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_ARM64 7 #if V8_TARGET_ARCH_ARM64
8 8
9 #include "src/codegen.h" 9 #include "src/codegen.h"
10 #include "src/debug.h" 10 #include "src/debug.h"
(...skipping 1306 matching lines...) Expand 10 before | Expand all | Expand 10 after
1317 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1317 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1318 RelocInfo::CODE_TARGET); 1318 RelocInfo::CODE_TARGET);
1319 __ Bind(&dont_adapt_args); 1319 __ Bind(&dont_adapt_args);
1320 1320
1321 __ Ldr(x3, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); 1321 __ Ldr(x3, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
1322 ParameterCount expected(0); 1322 ParameterCount expected(0);
1323 __ InvokeCode(x3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); 1323 __ InvokeCode(x3, expected, expected, JUMP_FUNCTION, NullCallWrapper());
1324 } 1324 }
1325 1325
1326 1326
1327 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { 1327 static void Generate_CheckStackOverflow(MacroAssembler* masm,
1328 ASM_LOCATION("Builtins::Generate_FunctionApply"); 1328 const int calleeOffset) {
1329 const int kIndexOffset = 1329 Register argc = x0;
1330 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); 1330 Register receiver = x14;
1331 const int kLimitOffset = 1331 Register function = x15;
1332 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); 1332
1333 const int kArgsOffset = 2 * kPointerSize; 1333 // Check the stack for overflow.
1334 const int kReceiverOffset = 3 * kPointerSize; 1334 // We are not trying to catch interruptions (e.g. debug break and
1335 const int kFunctionOffset = 4 * kPointerSize; 1335 // preemption) here, so the "real stack limit" is checked.
1336 Label enough_stack_space;
1337 __ LoadRoot(x10, Heap::kRealStackLimitRootIndex);
1338 __ Ldr(function, MemOperand(fp, calleeOffset));
1339 // Make x10 the space we have left. The stack might already be overflowed
1340 // here which will cause x10 to become negative.
1341 // TODO(jbramley): Check that the stack usage here is safe.
1342 __ Sub(x10, jssp, x10);
1343 // Check if the arguments will overflow the stack.
1344 __ Cmp(x10, Operand::UntagSmiAndScale(argc, kPointerSizeLog2));
1345 __ B(gt, &enough_stack_space);
1346 // There is not enough stack space, so use a builtin to throw an appropriate
1347 // error.
1348 __ Push(function, argc);
1349 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1350 // We should never return from the APPLY_OVERFLOW builtin.
1351 if (__ emit_debug_code()) {
1352 __ Unreachable();
1353 }
1354
1355 __ Bind(&enough_stack_space);
1356 }
1357
1358
1359 static void Generate_PushAppliedArguments(MacroAssembler* masm,
1360 const int argumentsOffset,
1361 const int indexOffset,
1362 const int limitOffset) {
1363 Label entry, loop;
1364 Register current = x0;
1365 __ Ldr(current, MemOperand(fp, indexOffset));
1366 __ B(&entry);
1367
1368 __ Bind(&loop);
1369 // Load the current argument from the arguments array and push it.
1370 // TODO(all): Couldn't we optimize this for JS arrays?
1371
1372 __ Ldr(x1, MemOperand(fp, argumentsOffset));
1373 __ Push(x1, current);
1374
1375 // Call the runtime to access the property in the arguments array.
1376 __ CallRuntime(Runtime::kGetProperty, 2);
1377 __ Push(x0);
1378
1379 // Use inline caching to access the arguments.
1380 __ Ldr(current, MemOperand(fp, indexOffset));
1381 __ Add(current, current, Smi::FromInt(1));
1382 __ Str(current, MemOperand(fp, indexOffset));
1383
1384 // Test if the copy loop has finished copying all the elements from the
1385 // arguments object.
1386 __ Bind(&entry);
1387 __ Ldr(x1, MemOperand(fp, limitOffset));
1388 __ Cmp(current, x1);
1389 __ B(ne, &loop);
1390
1391 // On exit, the pushed arguments count is in x0, untagged
1392 __ SmiUntag(current);
1393 }
1394
1395
1396 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
1397 const int kFormalParameters = targetIsArgument ? 3 : 2;
1398 const int kStackSize = kFormalParameters + 1;
1336 1399
1337 { 1400 {
1338 FrameScope frame_scope(masm, StackFrame::INTERNAL); 1401 FrameScope frame_scope(masm, StackFrame::INTERNAL);
1339 1402
1403 const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1404 const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1405 const int kFunctionOffset = kReceiverOffset + kPointerSize;
1406 const int kIndexOffset =
1407 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
1408 const int kLimitOffset =
1409 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
1410
1340 Register args = x12; 1411 Register args = x12;
1341 Register receiver = x14; 1412 Register receiver = x14;
1342 Register function = x15; 1413 Register function = x15;
1343 1414
1344 // Get the length of the arguments via a builtin call. 1415 // Get the length of the arguments via a builtin call.
1345 __ Ldr(function, MemOperand(fp, kFunctionOffset)); 1416 __ Ldr(function, MemOperand(fp, kFunctionOffset));
1346 __ Ldr(args, MemOperand(fp, kArgsOffset)); 1417 __ Ldr(args, MemOperand(fp, kArgumentsOffset));
1347 __ Push(function, args); 1418 __ Push(function, args);
1348 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 1419 if (targetIsArgument) {
1420 __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION);
1421 } else {
1422 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1423 }
1349 Register argc = x0; 1424 Register argc = x0;
1350 1425
1351 // Check the stack for overflow. 1426 Generate_CheckStackOverflow(masm, kFunctionOffset);
1352 // We are not trying to catch interruptions (e.g. debug break and
1353 // preemption) here, so the "real stack limit" is checked.
1354 Label enough_stack_space;
1355 __ LoadRoot(x10, Heap::kRealStackLimitRootIndex);
1356 __ Ldr(function, MemOperand(fp, kFunctionOffset));
1357 // Make x10 the space we have left. The stack might already be overflowed
1358 // here which will cause x10 to become negative.
1359 // TODO(jbramley): Check that the stack usage here is safe.
1360 __ Sub(x10, jssp, x10);
1361 // Check if the arguments will overflow the stack.
1362 __ Cmp(x10, Operand::UntagSmiAndScale(argc, kPointerSizeLog2));
1363 __ B(gt, &enough_stack_space);
1364 // There is not enough stack space, so use a builtin to throw an appropriate
1365 // error.
1366 __ Push(function, argc);
1367 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1368 // We should never return from the APPLY_OVERFLOW builtin.
1369 if (__ emit_debug_code()) {
1370 __ Unreachable();
1371 }
1372 1427
1373 __ Bind(&enough_stack_space);
1374 // Push current limit and index. 1428 // Push current limit and index.
1375 __ Mov(x1, 0); // Initial index. 1429 __ Mov(x1, 0); // Initial index.
1376 __ Push(argc, x1); 1430 __ Push(argc, x1);
1377 1431
1378 Label push_receiver; 1432 Label push_receiver;
1379 __ Ldr(receiver, MemOperand(fp, kReceiverOffset)); 1433 __ Ldr(receiver, MemOperand(fp, kReceiverOffset));
1380 1434
1381 // Check that the function is a JS function. Otherwise it must be a proxy. 1435 // Check that the function is a JS function. Otherwise it must be a proxy.
1382 // When it is not the function proxy will be invoked later. 1436 // When it is not the function proxy will be invoked later.
1383 __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE, 1437 __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1417 1471
1418 __ Bind(&use_global_proxy); 1472 __ Bind(&use_global_proxy);
1419 __ Ldr(x10, GlobalObjectMemOperand()); 1473 __ Ldr(x10, GlobalObjectMemOperand());
1420 __ Ldr(receiver, FieldMemOperand(x10, GlobalObject::kGlobalProxyOffset)); 1474 __ Ldr(receiver, FieldMemOperand(x10, GlobalObject::kGlobalProxyOffset));
1421 1475
1422 // Push the receiver 1476 // Push the receiver
1423 __ Bind(&push_receiver); 1477 __ Bind(&push_receiver);
1424 __ Push(receiver); 1478 __ Push(receiver);
1425 1479
1426 // Copy all arguments from the array to the stack. 1480 // Copy all arguments from the array to the stack.
1427 Label entry, loop; 1481 Generate_PushAppliedArguments(
1428 Register current = x0; 1482 masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
1429 __ Ldr(current, MemOperand(fp, kIndexOffset));
1430 __ B(&entry);
1431
1432 __ Bind(&loop);
1433 // Load the current argument from the arguments array and push it.
1434 // TODO(all): Couldn't we optimize this for JS arrays?
1435
1436 __ Ldr(x1, MemOperand(fp, kArgsOffset));
1437 __ Push(x1, current);
1438
1439 // Call the runtime to access the property in the arguments array.
1440 __ CallRuntime(Runtime::kGetProperty, 2);
1441 __ Push(x0);
1442
1443 // Use inline caching to access the arguments.
1444 __ Ldr(current, MemOperand(fp, kIndexOffset));
1445 __ Add(current, current, Smi::FromInt(1));
1446 __ Str(current, MemOperand(fp, kIndexOffset));
1447
1448 // Test if the copy loop has finished copying all the elements from the
1449 // arguments object.
1450 __ Bind(&entry);
1451 __ Ldr(x1, MemOperand(fp, kLimitOffset));
1452 __ Cmp(current, x1);
1453 __ B(ne, &loop);
1454 1483
1455 // At the end of the loop, the number of arguments is stored in 'current', 1484 // At the end of the loop, the number of arguments is stored in 'current',
1456 // represented as a smi. 1485 // represented as a smi.
1457 1486
1458 function = x1; // From now on we want the function to be kept in x1; 1487 function = x1; // From now on we want the function to be kept in x1;
1459 __ Ldr(function, MemOperand(fp, kFunctionOffset)); 1488 __ Ldr(function, MemOperand(fp, kFunctionOffset));
1460 1489
1461 // Call the function. 1490 // Call the function.
1462 Label call_proxy; 1491 Label call_proxy;
1463 ParameterCount actual(current); 1492 ParameterCount actual(x0);
1464 __ SmiUntag(current);
1465 __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE, &call_proxy); 1493 __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE, &call_proxy);
1466 __ InvokeFunction(function, actual, CALL_FUNCTION, NullCallWrapper()); 1494 __ InvokeFunction(function, actual, CALL_FUNCTION, NullCallWrapper());
1467 frame_scope.GenerateLeaveFrame(); 1495 frame_scope.GenerateLeaveFrame();
1468 __ Drop(3); 1496 __ Drop(kStackSize);
1469 __ Ret(); 1497 __ Ret();
1470 1498
1471 // Call the function proxy. 1499 // Call the function proxy.
1472 __ Bind(&call_proxy); 1500 __ Bind(&call_proxy);
1473 // x0 : argc 1501 // x0 : argc
1474 // x1 : function 1502 // x1 : function
1475 __ Push(function); // Add function proxy as last argument. 1503 __ Push(function); // Add function proxy as last argument.
1476 __ Add(x0, x0, 1); 1504 __ Add(x0, x0, 1);
1477 __ Mov(x2, 0); 1505 __ Mov(x2, 0);
1478 __ GetBuiltinFunction(x1, Builtins::CALL_FUNCTION_PROXY); 1506 __ GetBuiltinFunction(x1, Builtins::CALL_FUNCTION_PROXY);
1479 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1507 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1480 RelocInfo::CODE_TARGET); 1508 RelocInfo::CODE_TARGET);
1481 } 1509 }
1482 __ Drop(3); 1510 __ Drop(kStackSize);
1483 __ Ret(); 1511 __ Ret();
1484 } 1512 }
1485 1513
1486 1514
1515 static void Generate_ConstructHelper(MacroAssembler* masm) {
1516 const int kFormalParameters = 3;
1517 const int kStackSize = kFormalParameters + 1;
1518
1519 {
1520 FrameScope frame_scope(masm, StackFrame::INTERNAL);
1521
1522 const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
1523 const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
1524 const int kFunctionOffset = kArgumentsOffset + kPointerSize;
1525
1526 const int kIndexOffset =
1527 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
1528 const int kLimitOffset =
1529 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
1530
1531 // Is x11 safe to use?
1532 Register newTarget = x11;
1533 Register args = x12;
1534 Register receiver = x14;
1535 Register function = x15;
1536
1537 // If newTarget is not supplied, set it to constructor
1538 Label validate_arguments;
1539 __ Ldr(x0, MemOperand(fp, kNewTargetOffset));
1540 __ CompareRoot(x0, Heap::kUndefinedValueRootIndex);
1541 __ B(ne, &validate_arguments);
1542 __ Ldr(x0, MemOperand(fp, kFunctionOffset));
1543 __ Str(x0, MemOperand(fp, kNewTargetOffset));
1544
1545 // Validate arguments
1546 __ Bind(&validate_arguments);
1547 __ Ldr(function, MemOperand(fp, kFunctionOffset));
1548 __ Ldr(args, MemOperand(fp, kArgumentsOffset));
1549 __ Ldr(newTarget, MemOperand(fp, kNewTargetOffset));
1550 __ Push(function, args, newTarget);
1551 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION);
1552 Register argc = x0;
1553
1554 Generate_CheckStackOverflow(masm, kFunctionOffset);
1555
1556 // Push current limit and index, constructor & newTarget
1557 __ Mov(x1, 0); // Initial index.
1558 __ Ldr(newTarget, MemOperand(fp, kNewTargetOffset));
1559 __ Push(argc, x1, newTarget, function);
1560
1561 // Copy all arguments from the array to the stack.
1562 Generate_PushAppliedArguments(
1563 masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
1564
1565 __ Ldr(x1, MemOperand(fp, kFunctionOffset));
1566 // Use undefined feedback vector
1567 __ LoadRoot(x2, Heap::kUndefinedValueRootIndex);
1568
1569 // Call the function.
1570 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL);
1571 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
1572
1573 __ Drop(1);
1574 }
1575 __ Drop(kStackSize);
1576 __ Ret();
1577 }
1578
1579
1580 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1581 ASM_LOCATION("Builtins::Generate_FunctionApply");
1582 Generate_ApplyHelper(masm, false);
1583 }
1584
1585
1586 void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
1587 ASM_LOCATION("Builtins::Generate_ReflectApply");
1588 Generate_ApplyHelper(masm, true);
1589 }
1590
1591
1592 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
1593 ASM_LOCATION("Builtins::Generate_ReflectConstruct");
1594 Generate_ConstructHelper(masm);
1595 }
1596
1597
1487 static void ArgumentAdaptorStackCheck(MacroAssembler* masm, 1598 static void ArgumentAdaptorStackCheck(MacroAssembler* masm,
1488 Label* stack_overflow) { 1599 Label* stack_overflow) {
1489 // ----------- S t a t e ------------- 1600 // ----------- S t a t e -------------
1490 // -- x0 : actual number of arguments 1601 // -- x0 : actual number of arguments
1491 // -- x1 : function (passed through to callee) 1602 // -- x1 : function (passed through to callee)
1492 // -- x2 : expected number of arguments 1603 // -- x2 : expected number of arguments
1493 // ----------------------------------- 1604 // -----------------------------------
1494 // Check the stack for overflow. 1605 // Check the stack for overflow.
1495 // We are not trying to catch interruptions (e.g. debug break and 1606 // We are not trying to catch interruptions (e.g. debug break and
1496 // preemption) here, so the "real stack limit" is checked. 1607 // preemption) here, so the "real stack limit" is checked.
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1669 __ Unreachable(); 1780 __ Unreachable();
1670 } 1781 }
1671 } 1782 }
1672 1783
1673 1784
1674 #undef __ 1785 #undef __
1675 1786
1676 } } // namespace v8::internal 1787 } } // namespace v8::internal
1677 1788
1678 #endif // V8_TARGET_ARCH_ARM 1789 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/builtins-arm.cc ('k') | src/bootstrapper.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698