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

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 21123008: Introduce StackArgumentsAccessor class for X64 (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Introduce StackArguments class Created 7 years, 4 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 | Annotate | Revision Log
« src/x64/macro-assembler-x64.h ('K') | « src/x64/macro-assembler-x64.h ('k') | no next file » | 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 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 // These arguments are set by CheckPrototypes and GenerateFastApiCall. 407 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
408 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 408 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
409 // ----------- S t a t e ------------- 409 // ----------- S t a t e -------------
410 // -- rsp[0] : return address 410 // -- rsp[0] : return address
411 // -- rsp[8] : last argument in the internal frame of the caller 411 // -- rsp[8] : last argument in the internal frame of the caller
412 // ----------------------------------- 412 // -----------------------------------
413 __ movq(scratch, StackOperandForReturnAddress(0)); 413 __ movq(scratch, StackOperandForReturnAddress(0));
414 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); 414 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
415 __ movq(StackOperandForReturnAddress(0), scratch); 415 __ movq(StackOperandForReturnAddress(0), scratch);
416 __ Move(scratch, Smi::FromInt(0)); 416 __ Move(scratch, Smi::FromInt(0));
417 for (int i = 1; i <= kFastApiCallArguments; i++) { 417 StackArguments stack_arguments(kFastApiCallArguments);
danno 2013/08/05 15:17:56 Here and elsewhere, how about just using the varia
haitao.feng 2013/08/06 11:49:55 Done.
418 __ movq(Operand(rsp, i * kPointerSize), scratch); 418 for (int i = 0; i < kFastApiCallArguments; i++) {
419 __ movq(stack_arguments[i], scratch);
419 } 420 }
420 } 421 }
421 422
422 423
423 // Undoes the effects of ReserveSpaceForFastApiCall. 424 // Undoes the effects of ReserveSpaceForFastApiCall.
424 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 425 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
425 // ----------- S t a t e ------------- 426 // ----------- S t a t e -------------
426 // -- rsp[0] : return address. 427 // -- rsp[0] : return address.
427 // -- rsp[8] : last fast api call extra argument. 428 // -- rsp[8] : last fast api call extra argument.
428 // -- ... 429 // -- ...
(...skipping 28 matching lines...) Expand all
457 // -- rsp[56] : last argument 458 // -- rsp[56] : last argument
458 // -- ... 459 // -- ...
459 // -- rsp[(argc + 6) * 8] : first argument 460 // -- rsp[(argc + 6) * 8] : first argument
460 // -- rsp[(argc + 7) * 8] : receiver 461 // -- rsp[(argc + 7) * 8] : receiver
461 // ----------------------------------- 462 // -----------------------------------
462 // Get the function and setup the context. 463 // Get the function and setup the context.
463 Handle<JSFunction> function = optimization.constant_function(); 464 Handle<JSFunction> function = optimization.constant_function();
464 __ LoadHeapObject(rdi, function); 465 __ LoadHeapObject(rdi, function);
465 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 466 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
466 467
468 StackArguments stack_arguments(argc + kFastApiCallArguments, 1);
469
467 // Pass the additional arguments. 470 // Pass the additional arguments.
468 __ movq(Operand(rsp, 2 * kPointerSize), rdi); 471 __ movq(stack_arguments[-2], rdi);
danno 2013/08/05 15:17:56 Again, is it possible to avoid the negative argume
haitao.feng 2013/08/06 11:49:55 Done. Compute from argument[0] by using argc.
469 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 472 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
470 Handle<Object> call_data(api_call_info->data(), masm->isolate()); 473 Handle<Object> call_data(api_call_info->data(), masm->isolate());
471 if (masm->isolate()->heap()->InNewSpace(*call_data)) { 474 if (masm->isolate()->heap()->InNewSpace(*call_data)) {
472 __ Move(rcx, api_call_info); 475 __ Move(rcx, api_call_info);
473 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); 476 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
474 __ movq(Operand(rsp, 3 * kPointerSize), rbx); 477 __ movq(stack_arguments[-3], rbx);
475 } else { 478 } else {
476 __ Move(Operand(rsp, 3 * kPointerSize), call_data); 479 __ Move(stack_arguments[-3], call_data);
477 } 480 }
478 __ movq(kScratchRegister, 481 __ movq(kScratchRegister,
479 ExternalReference::isolate_address(masm->isolate())); 482 ExternalReference::isolate_address(masm->isolate()));
480 __ movq(Operand(rsp, 4 * kPointerSize), kScratchRegister); 483 __ movq(stack_arguments[-4], kScratchRegister);
481 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 484 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
482 __ movq(Operand(rsp, 5 * kPointerSize), kScratchRegister); 485 __ movq(stack_arguments[-5], kScratchRegister);
483 __ movq(Operand(rsp, 6 * kPointerSize), kScratchRegister); 486 __ movq(stack_arguments[-6], kScratchRegister);
484 487
485 // Prepare arguments. 488 // Prepare arguments.
486 STATIC_ASSERT(kFastApiCallArguments == 6); 489 STATIC_ASSERT(kFastApiCallArguments == 6);
487 __ lea(rbx, Operand(rsp, kFastApiCallArguments * kPointerSize)); 490 __ lea(rbx, Operand(rsp, kFastApiCallArguments * kPointerSize));
488 491
489 // Function address is a foreign pointer outside V8's heap. 492 // Function address is a foreign pointer outside V8's heap.
490 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 493 Address function_address = v8::ToCData<Address>(api_call_info->callback());
491 bool returns_handle = 494 bool returns_handle =
492 !CallbackTable::ReturnsVoid(masm->isolate(), function_address); 495 !CallbackTable::ReturnsVoid(masm->isolate(), function_address);
493 496
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 1071 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1069 && !scratch2.is(scratch1)); 1072 && !scratch2.is(scratch1));
1070 1073
1071 // Keep track of the current object in register reg. On the first 1074 // Keep track of the current object in register reg. On the first
1072 // iteration, reg is an alias for object_reg, on later iterations, 1075 // iteration, reg is an alias for object_reg, on later iterations,
1073 // it is an alias for holder_reg. 1076 // it is an alias for holder_reg.
1074 Register reg = object_reg; 1077 Register reg = object_reg;
1075 int depth = 0; 1078 int depth = 0;
1076 1079
1077 if (save_at_depth == depth) { 1080 if (save_at_depth == depth) {
1078 __ movq(Operand(rsp, kPointerSize), object_reg); 1081 __ movq(Operand(rsp, kPCOnStackSize), object_reg);
1079 } 1082 }
1080 1083
1081 // Check the maps in the prototype chain. 1084 // Check the maps in the prototype chain.
1082 // Traverse the prototype chain from the object and do map checks. 1085 // Traverse the prototype chain from the object and do map checks.
1083 Handle<JSObject> current = object; 1086 Handle<JSObject> current = object;
1084 while (!current.is_identical_to(holder)) { 1087 while (!current.is_identical_to(holder)) {
1085 ++depth; 1088 ++depth;
1086 1089
1087 // Only global objects and objects that do not require access 1090 // Only global objects and objects that do not require access
1088 // checks are allowed in stubs. 1091 // checks are allowed in stubs.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1128 // The prototype is in new space; we cannot store a reference to it 1131 // The prototype is in new space; we cannot store a reference to it
1129 // in the code. Load it from the map. 1132 // in the code. Load it from the map.
1130 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 1133 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
1131 } else { 1134 } else {
1132 // The prototype is in old space; load it directly. 1135 // The prototype is in old space; load it directly.
1133 __ Move(reg, prototype); 1136 __ Move(reg, prototype);
1134 } 1137 }
1135 } 1138 }
1136 1139
1137 if (save_at_depth == depth) { 1140 if (save_at_depth == depth) {
1138 __ movq(Operand(rsp, kPointerSize), reg); 1141 __ movq(Operand(rsp, kPCOnStackSize), reg);
1139 } 1142 }
1140 1143
1141 // Go to the next object in the prototype chain. 1144 // Go to the next object in the prototype chain.
1142 current = prototype; 1145 current = prototype;
1143 } 1146 }
1144 ASSERT(current.is_identical_to(holder)); 1147 ASSERT(current.is_identical_to(holder));
1145 1148
1146 // Log the check depth. 1149 // Log the check depth.
1147 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 1150 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1148 1151
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
1463 } 1466 }
1464 } 1467 }
1465 1468
1466 1469
1467 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, 1470 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
1468 Handle<JSObject> holder, 1471 Handle<JSObject> holder,
1469 Handle<Name> name, 1472 Handle<Name> name,
1470 Label* miss) { 1473 Label* miss) {
1471 ASSERT(holder->IsGlobalObject()); 1474 ASSERT(holder->IsGlobalObject());
1472 1475
1473 // Get the number of arguments. 1476 StackArguments stack_arguments(arguments(), 1);
1474 const int argc = arguments().immediate(); 1477 __ movq(rdx, stack_arguments.GetReceiver());
1475
1476 // Get the receiver from the stack.
1477 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1478 1478
1479 1479
1480 // Check that the maps haven't changed. 1480 // Check that the maps haven't changed.
1481 __ JumpIfSmi(rdx, miss); 1481 __ JumpIfSmi(rdx, miss);
1482 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss); 1482 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss);
1483 } 1483 }
1484 1484
1485 1485
1486 void CallStubCompiler::GenerateLoadFunctionFromCell( 1486 void CallStubCompiler::GenerateLoadFunctionFromCell(
1487 Handle<Cell> cell, 1487 Handle<Cell> cell,
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1531 // rsp[8] : argument argc 1531 // rsp[8] : argument argc
1532 // rsp[16] : argument argc - 1 1532 // rsp[16] : argument argc - 1
1533 // ... 1533 // ...
1534 // rsp[argc * 8] : argument 1 1534 // rsp[argc * 8] : argument 1
1535 // rsp[(argc + 1) * 8] : argument 0 = receiver 1535 // rsp[(argc + 1) * 8] : argument 0 = receiver
1536 // ----------------------------------- 1536 // -----------------------------------
1537 Label miss; 1537 Label miss;
1538 1538
1539 GenerateNameCheck(name, &miss); 1539 GenerateNameCheck(name, &miss);
1540 1540
1541 // Get the receiver from the stack. 1541 StackArguments stack_arguments(arguments(), 1);
1542 const int argc = arguments().immediate(); 1542 __ movq(rdx, stack_arguments.GetReceiver());
1543 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1544 1543
1545 // Check that the receiver isn't a smi. 1544 // Check that the receiver isn't a smi.
1546 __ JumpIfSmi(rdx, &miss); 1545 __ JumpIfSmi(rdx, &miss);
1547 1546
1548 // Do the right check and compute the holder register. 1547 // Do the right check and compute the holder register.
1549 Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi, 1548 Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi,
1550 name, &miss); 1549 name, &miss);
1551 1550
1552 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), 1551 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder),
1553 index.translate(holder), Representation::Tagged()); 1552 index.translate(holder), Representation::Tagged());
1554 1553
1555 // Check that the function really is a function. 1554 // Check that the function really is a function.
1556 __ JumpIfSmi(rdi, &miss); 1555 __ JumpIfSmi(rdi, &miss);
1557 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); 1556 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx);
1558 __ j(not_equal, &miss); 1557 __ j(not_equal, &miss);
1559 1558
1560 // Patch the receiver on the stack with the global proxy if 1559 // Patch the receiver on the stack with the global proxy if
1561 // necessary. 1560 // necessary.
1562 if (object->IsGlobalObject()) { 1561 if (object->IsGlobalObject()) {
1563 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 1562 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
1564 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 1563 __ movq(stack_arguments.GetReceiver(), rdx);
1565 } 1564 }
1566 1565
1567 // Invoke the function. 1566 // Invoke the function.
1568 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1567 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1569 ? CALL_AS_FUNCTION 1568 ? CALL_AS_FUNCTION
1570 : CALL_AS_METHOD; 1569 : CALL_AS_METHOD;
1571 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, 1570 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
1572 NullCallWrapper(), call_kind); 1571 NullCallWrapper(), call_kind);
1573 1572
1574 // Handle call cache miss. 1573 // Handle call cache miss.
1575 __ bind(&miss); 1574 __ bind(&miss);
1576 GenerateMissBranch(); 1575 GenerateMissBranch();
1577 1576
1578 // Return the generated code. 1577 // Return the generated code.
1579 return GetCode(Code::FIELD, name); 1578 return GetCode(Code::FIELD, name);
1580 } 1579 }
1581 1580
1582 1581
1583 Handle<Code> CallStubCompiler::CompileArrayCodeCall( 1582 Handle<Code> CallStubCompiler::CompileArrayCodeCall(
1584 Handle<Object> object, 1583 Handle<Object> object,
1585 Handle<JSObject> holder, 1584 Handle<JSObject> holder,
1586 Handle<Cell> cell, 1585 Handle<Cell> cell,
1587 Handle<JSFunction> function, 1586 Handle<JSFunction> function,
1588 Handle<String> name, 1587 Handle<String> name,
1589 Code::StubType type) { 1588 Code::StubType type) {
1590 Label miss; 1589 Label miss;
1591 1590
1592 // Check that function is still array 1591 // Check that function is still array
1593 const int argc = arguments().immediate(); 1592 const int argc = arguments().immediate();
1593 StackArguments stack_arguments(argc, 1);
1594 GenerateNameCheck(name, &miss); 1594 GenerateNameCheck(name, &miss);
1595 1595
1596 if (cell.is_null()) { 1596 if (cell.is_null()) {
1597 // Get the receiver from the stack. 1597 __ movq(rdx, stack_arguments.GetReceiver());
1598 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1599 1598
1600 // Check that the receiver isn't a smi. 1599 // Check that the receiver isn't a smi.
1601 __ JumpIfSmi(rdx, &miss); 1600 __ JumpIfSmi(rdx, &miss);
1602 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 1601 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
1603 name, &miss); 1602 name, &miss);
1604 } else { 1603 } else {
1605 ASSERT(cell->value() == *function); 1604 ASSERT(cell->value() == *function);
1606 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 1605 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
1607 &miss); 1606 &miss);
1608 GenerateLoadFunctionFromCell(cell, function, &miss); 1607 GenerateLoadFunctionFromCell(cell, function, &miss);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1640 // -- ... 1639 // -- ...
1641 // -- rsp[(argc + 1) * 8] : receiver 1640 // -- rsp[(argc + 1) * 8] : receiver
1642 // ----------------------------------- 1641 // -----------------------------------
1643 1642
1644 // If object is not an array, bail out to regular call. 1643 // If object is not an array, bail out to regular call.
1645 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 1644 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
1646 1645
1647 Label miss; 1646 Label miss;
1648 GenerateNameCheck(name, &miss); 1647 GenerateNameCheck(name, &miss);
1649 1648
1650 // Get the receiver from the stack.
1651 const int argc = arguments().immediate(); 1649 const int argc = arguments().immediate();
1652 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1650 StackArguments stack_arguments(argc, 1);
1651 __ movq(rdx, stack_arguments.GetReceiver());
1653 1652
1654 // Check that the receiver isn't a smi. 1653 // Check that the receiver isn't a smi.
1655 __ JumpIfSmi(rdx, &miss); 1654 __ JumpIfSmi(rdx, &miss);
1656 1655
1657 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 1656 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
1658 name, &miss); 1657 name, &miss);
1659 1658
1660 if (argc == 0) { 1659 if (argc == 0) {
1661 // Noop, return the length. 1660 // Noop, return the length.
1662 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); 1661 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
(...skipping 18 matching lines...) Expand all
1681 __ addl(rax, Immediate(argc)); 1680 __ addl(rax, Immediate(argc));
1682 1681
1683 // Get the elements' length into rcx. 1682 // Get the elements' length into rcx.
1684 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); 1683 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
1685 1684
1686 // Check if we could survive without allocation. 1685 // Check if we could survive without allocation.
1687 __ cmpl(rax, rcx); 1686 __ cmpl(rax, rcx);
1688 __ j(greater, &attempt_to_grow_elements); 1687 __ j(greater, &attempt_to_grow_elements);
1689 1688
1690 // Check if value is a smi. 1689 // Check if value is a smi.
1691 __ movq(rcx, Operand(rsp, argc * kPointerSize)); 1690 __ movq(rcx, stack_arguments[1]);
1692 __ JumpIfNotSmi(rcx, &with_write_barrier); 1691 __ JumpIfNotSmi(rcx, &with_write_barrier);
1693 1692
1694 // Save new length. 1693 // Save new length.
1695 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); 1694 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1696 1695
1697 // Store the value. 1696 // Store the value.
1698 __ movq(FieldOperand(rdi, 1697 __ movq(FieldOperand(rdi,
1699 rax, 1698 rax,
1700 times_pointer_size, 1699 times_pointer_size,
1701 FixedArray::kHeaderSize - argc * kPointerSize), 1700 FixedArray::kHeaderSize - argc * kPointerSize),
(...skipping 14 matching lines...) Expand all
1716 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); 1715 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
1717 __ addl(rax, Immediate(argc)); 1716 __ addl(rax, Immediate(argc));
1718 1717
1719 // Get the elements' length into rcx. 1718 // Get the elements' length into rcx.
1720 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); 1719 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
1721 1720
1722 // Check if we could survive without allocation. 1721 // Check if we could survive without allocation.
1723 __ cmpl(rax, rcx); 1722 __ cmpl(rax, rcx);
1724 __ j(greater, &call_builtin); 1723 __ j(greater, &call_builtin);
1725 1724
1726 __ movq(rcx, Operand(rsp, argc * kPointerSize)); 1725 __ movq(rcx, stack_arguments[1]);
1727 __ StoreNumberToDoubleElements( 1726 __ StoreNumberToDoubleElements(
1728 rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize); 1727 rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize);
1729 1728
1730 // Save new length. 1729 // Save new length.
1731 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); 1730 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1732 __ Integer32ToSmi(rax, rax); // Return new length as smi. 1731 __ Integer32ToSmi(rax, rax); // Return new length as smi.
1733 __ ret((argc + 1) * kPointerSize); 1732 __ ret((argc + 1) * kPointerSize);
1734 1733
1735 __ bind(&with_write_barrier); 1734 __ bind(&with_write_barrier);
1736 1735
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1793 OMIT_SMI_CHECK); 1792 OMIT_SMI_CHECK);
1794 1793
1795 __ Integer32ToSmi(rax, rax); // Return new length as smi. 1794 __ Integer32ToSmi(rax, rax); // Return new length as smi.
1796 __ ret((argc + 1) * kPointerSize); 1795 __ ret((argc + 1) * kPointerSize);
1797 1796
1798 __ bind(&attempt_to_grow_elements); 1797 __ bind(&attempt_to_grow_elements);
1799 if (!FLAG_inline_new) { 1798 if (!FLAG_inline_new) {
1800 __ jmp(&call_builtin); 1799 __ jmp(&call_builtin);
1801 } 1800 }
1802 1801
1803 __ movq(rbx, Operand(rsp, argc * kPointerSize)); 1802 __ movq(rbx, stack_arguments[1]);
1804 // Growing elements that are SMI-only requires special handling in case 1803 // Growing elements that are SMI-only requires special handling in case
1805 // the new element is non-Smi. For now, delegate to the builtin. 1804 // the new element is non-Smi. For now, delegate to the builtin.
1806 Label no_fast_elements_check; 1805 Label no_fast_elements_check;
1807 __ JumpIfSmi(rbx, &no_fast_elements_check); 1806 __ JumpIfSmi(rbx, &no_fast_elements_check);
1808 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); 1807 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
1809 __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar); 1808 __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar);
1810 __ bind(&no_fast_elements_check); 1809 __ bind(&no_fast_elements_check);
1811 1810
1812 ExternalReference new_space_allocation_top = 1811 ExternalReference new_space_allocation_top =
1813 ExternalReference::new_space_allocation_top_address(isolate()); 1812 ExternalReference::new_space_allocation_top_address(isolate());
(...skipping 28 matching lines...) Expand all
1842 } 1841 }
1843 1842
1844 // We know the elements array is in new space so we don't need the 1843 // We know the elements array is in new space so we don't need the
1845 // remembered set, but we just pushed a value onto it so we may have to 1844 // remembered set, but we just pushed a value onto it so we may have to
1846 // tell the incremental marker to rescan the object that we just grew. We 1845 // tell the incremental marker to rescan the object that we just grew. We
1847 // don't need to worry about the holes because they are in old space and 1846 // don't need to worry about the holes because they are in old space and
1848 // already marked black. 1847 // already marked black.
1849 __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); 1848 __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
1850 1849
1851 // Restore receiver to rdx as finish sequence assumes it's here. 1850 // Restore receiver to rdx as finish sequence assumes it's here.
1852 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1851 __ movq(rdx, stack_arguments.GetReceiver());
1853 1852
1854 // Increment element's and array's sizes. 1853 // Increment element's and array's sizes.
1855 __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset), 1854 __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset),
1856 Smi::FromInt(kAllocationDelta)); 1855 Smi::FromInt(kAllocationDelta));
1857 1856
1858 // Make new length a smi before returning it. 1857 // Make new length a smi before returning it.
1859 __ Integer32ToSmi(rax, rax); 1858 __ Integer32ToSmi(rax, rax);
1860 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); 1859 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1861 1860
1862 __ ret((argc + 1) * kPointerSize); 1861 __ ret((argc + 1) * kPointerSize);
(...skipping 28 matching lines...) Expand all
1891 // -- ... 1890 // -- ...
1892 // -- rsp[(argc + 1) * 8] : receiver 1891 // -- rsp[(argc + 1) * 8] : receiver
1893 // ----------------------------------- 1892 // -----------------------------------
1894 1893
1895 // If object is not an array, bail out to regular call. 1894 // If object is not an array, bail out to regular call.
1896 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 1895 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
1897 1896
1898 Label miss, return_undefined, call_builtin; 1897 Label miss, return_undefined, call_builtin;
1899 GenerateNameCheck(name, &miss); 1898 GenerateNameCheck(name, &miss);
1900 1899
1901 // Get the receiver from the stack.
1902 const int argc = arguments().immediate(); 1900 const int argc = arguments().immediate();
1903 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1901 StackArguments stack_arguments(argc, 1);
1902 __ movq(rdx, stack_arguments.GetReceiver());
1904 1903
1905 // Check that the receiver isn't a smi. 1904 // Check that the receiver isn't a smi.
1906 __ JumpIfSmi(rdx, &miss); 1905 __ JumpIfSmi(rdx, &miss);
1907 1906
1908 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 1907 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
1909 name, &miss); 1908 name, &miss);
1910 1909
1911 // Get the elements array of the object. 1910 // Get the elements array of the object.
1912 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); 1911 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
1913 1912
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1971 // -- rsp[0] : return address 1970 // -- rsp[0] : return address
1972 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 1971 // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1973 // -- ... 1972 // -- ...
1974 // -- rsp[(argc + 1) * 8] : receiver 1973 // -- rsp[(argc + 1) * 8] : receiver
1975 // ----------------------------------- 1974 // -----------------------------------
1976 1975
1977 // If object is not a string, bail out to regular call. 1976 // If object is not a string, bail out to regular call.
1978 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 1977 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
1979 1978
1980 const int argc = arguments().immediate(); 1979 const int argc = arguments().immediate();
1980 StackArguments stack_arguments(argc, 1);
1981 1981
1982 Label miss; 1982 Label miss;
1983 Label name_miss; 1983 Label name_miss;
1984 Label index_out_of_range; 1984 Label index_out_of_range;
1985 Label* index_out_of_range_label = &index_out_of_range; 1985 Label* index_out_of_range_label = &index_out_of_range;
1986 if (kind_ == Code::CALL_IC && 1986 if (kind_ == Code::CALL_IC &&
1987 (CallICBase::StringStubState::decode(extra_state_) == 1987 (CallICBase::StringStubState::decode(extra_state_) ==
1988 DEFAULT_STRING_STUB)) { 1988 DEFAULT_STRING_STUB)) {
1989 index_out_of_range_label = &miss; 1989 index_out_of_range_label = &miss;
1990 } 1990 }
1991 GenerateNameCheck(name, &name_miss); 1991 GenerateNameCheck(name, &name_miss);
1992 1992
1993 // Check that the maps starting from the prototype haven't changed. 1993 // Check that the maps starting from the prototype haven't changed.
1994 GenerateDirectLoadGlobalFunctionPrototype(masm(), 1994 GenerateDirectLoadGlobalFunctionPrototype(masm(),
1995 Context::STRING_FUNCTION_INDEX, 1995 Context::STRING_FUNCTION_INDEX,
1996 rax, 1996 rax,
1997 &miss); 1997 &miss);
1998 ASSERT(!object.is_identical_to(holder)); 1998 ASSERT(!object.is_identical_to(holder));
1999 CheckPrototypes( 1999 CheckPrototypes(
2000 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), 2000 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
2001 rax, holder, rbx, rdx, rdi, name, &miss); 2001 rax, holder, rbx, rdx, rdi, name, &miss);
2002 2002
2003 Register receiver = rbx; 2003 Register receiver = rbx;
2004 Register index = rdi; 2004 Register index = rdi;
2005 Register result = rax; 2005 Register result = rax;
2006 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); 2006 __ movq(receiver, stack_arguments.GetReceiver());
2007 if (argc > 0) { 2007 if (argc > 0) {
2008 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); 2008 __ movq(index, stack_arguments[1]);
2009 } else { 2009 } else {
2010 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 2010 __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
2011 } 2011 }
2012 2012
2013 StringCharCodeAtGenerator generator(receiver, 2013 StringCharCodeAtGenerator generator(receiver,
2014 index, 2014 index,
2015 result, 2015 result,
2016 &miss, // When not a string. 2016 &miss, // When not a string.
2017 &miss, // When not a number. 2017 &miss, // When not a number.
2018 index_out_of_range_label, 2018 index_out_of_range_label,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2052 // -- rsp[0] : return address 2052 // -- rsp[0] : return address
2053 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 2053 // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
2054 // -- ... 2054 // -- ...
2055 // -- rsp[(argc + 1) * 8] : receiver 2055 // -- rsp[(argc + 1) * 8] : receiver
2056 // ----------------------------------- 2056 // -----------------------------------
2057 2057
2058 // If object is not a string, bail out to regular call. 2058 // If object is not a string, bail out to regular call.
2059 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 2059 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
2060 2060
2061 const int argc = arguments().immediate(); 2061 const int argc = arguments().immediate();
2062 StackArguments stack_arguments(argc, 1);
2063
2062 Label miss; 2064 Label miss;
2063 Label name_miss; 2065 Label name_miss;
2064 Label index_out_of_range; 2066 Label index_out_of_range;
2065 Label* index_out_of_range_label = &index_out_of_range; 2067 Label* index_out_of_range_label = &index_out_of_range;
2066 if (kind_ == Code::CALL_IC && 2068 if (kind_ == Code::CALL_IC &&
2067 (CallICBase::StringStubState::decode(extra_state_) == 2069 (CallICBase::StringStubState::decode(extra_state_) ==
2068 DEFAULT_STRING_STUB)) { 2070 DEFAULT_STRING_STUB)) {
2069 index_out_of_range_label = &miss; 2071 index_out_of_range_label = &miss;
2070 } 2072 }
2071 GenerateNameCheck(name, &name_miss); 2073 GenerateNameCheck(name, &name_miss);
2072 2074
2073 // Check that the maps starting from the prototype haven't changed. 2075 // Check that the maps starting from the prototype haven't changed.
2074 GenerateDirectLoadGlobalFunctionPrototype(masm(), 2076 GenerateDirectLoadGlobalFunctionPrototype(masm(),
2075 Context::STRING_FUNCTION_INDEX, 2077 Context::STRING_FUNCTION_INDEX,
2076 rax, 2078 rax,
2077 &miss); 2079 &miss);
2078 ASSERT(!object.is_identical_to(holder)); 2080 ASSERT(!object.is_identical_to(holder));
2079 CheckPrototypes( 2081 CheckPrototypes(
2080 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), 2082 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
2081 rax, holder, rbx, rdx, rdi, name, &miss); 2083 rax, holder, rbx, rdx, rdi, name, &miss);
2082 2084
2083 Register receiver = rax; 2085 Register receiver = rax;
2084 Register index = rdi; 2086 Register index = rdi;
2085 Register scratch = rdx; 2087 Register scratch = rdx;
2086 Register result = rax; 2088 Register result = rax;
2087 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); 2089 __ movq(receiver, stack_arguments.GetReceiver());
2088 if (argc > 0) { 2090 if (argc > 0) {
2089 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); 2091 __ movq(index, stack_arguments[1]);
2090 } else { 2092 } else {
2091 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 2093 __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
2092 } 2094 }
2093 2095
2094 StringCharAtGenerator generator(receiver, 2096 StringCharAtGenerator generator(receiver,
2095 index, 2097 index,
2096 scratch, 2098 scratch,
2097 result, 2099 result,
2098 &miss, // When not a string. 2100 &miss, // When not a string.
2099 &miss, // When not a number. 2101 &miss, // When not a number.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2132 // -- rcx : function name 2134 // -- rcx : function name
2133 // -- rsp[0] : return address 2135 // -- rsp[0] : return address
2134 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 2136 // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
2135 // -- ... 2137 // -- ...
2136 // -- rsp[(argc + 1) * 8] : receiver 2138 // -- rsp[(argc + 1) * 8] : receiver
2137 // ----------------------------------- 2139 // -----------------------------------
2138 2140
2139 // If the object is not a JSObject or we got an unexpected number of 2141 // If the object is not a JSObject or we got an unexpected number of
2140 // arguments, bail out to the regular call. 2142 // arguments, bail out to the regular call.
2141 const int argc = arguments().immediate(); 2143 const int argc = arguments().immediate();
2144 StackArguments stack_arguments(argc, 1);
2142 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 2145 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2143 2146
2144 Label miss; 2147 Label miss;
2145 GenerateNameCheck(name, &miss); 2148 GenerateNameCheck(name, &miss);
2146 2149
2147 if (cell.is_null()) { 2150 if (cell.is_null()) {
2148 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); 2151 __ movq(rdx, stack_arguments[-2]);
2149 __ JumpIfSmi(rdx, &miss); 2152 __ JumpIfSmi(rdx, &miss);
2150 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 2153 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
2151 name, &miss); 2154 name, &miss);
2152 } else { 2155 } else {
2153 ASSERT(cell->value() == *function); 2156 ASSERT(cell->value() == *function);
2154 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 2157 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
2155 &miss); 2158 &miss);
2156 GenerateLoadFunctionFromCell(cell, function, &miss); 2159 GenerateLoadFunctionFromCell(cell, function, &miss);
2157 } 2160 }
2158 2161
2159 // Load the char code argument. 2162 // Load the char code argument.
2160 Register code = rbx; 2163 Register code = rbx;
2161 __ movq(code, Operand(rsp, 1 * kPointerSize)); 2164 __ movq(code, stack_arguments[-1]);
2162 2165
2163 // Check the code is a smi. 2166 // Check the code is a smi.
2164 Label slow; 2167 Label slow;
2165 __ JumpIfNotSmi(code, &slow); 2168 __ JumpIfNotSmi(code, &slow);
2166 2169
2167 // Convert the smi code to uint16. 2170 // Convert the smi code to uint16.
2168 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); 2171 __ SmiAndConstant(code, code, Smi::FromInt(0xffff));
2169 2172
2170 StringCharFromCodeGenerator generator(code, rax); 2173 StringCharFromCodeGenerator generator(code, rax);
2171 generator.GenerateFast(masm()); 2174 generator.GenerateFast(masm());
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2216 // -- rcx : function name 2219 // -- rcx : function name
2217 // -- rsp[0] : return address 2220 // -- rsp[0] : return address
2218 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 2221 // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
2219 // -- ... 2222 // -- ...
2220 // -- rsp[(argc + 1) * 8] : receiver 2223 // -- rsp[(argc + 1) * 8] : receiver
2221 // ----------------------------------- 2224 // -----------------------------------
2222 2225
2223 // If the object is not a JSObject or we got an unexpected number of 2226 // If the object is not a JSObject or we got an unexpected number of
2224 // arguments, bail out to the regular call. 2227 // arguments, bail out to the regular call.
2225 const int argc = arguments().immediate(); 2228 const int argc = arguments().immediate();
2229 StackArguments stack_arguments(argc, 1);
2226 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 2230 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2227 2231
2228 Label miss; 2232 Label miss;
2229 GenerateNameCheck(name, &miss); 2233 GenerateNameCheck(name, &miss);
2230 2234
2231 if (cell.is_null()) { 2235 if (cell.is_null()) {
2232 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); 2236 __ movq(rdx, stack_arguments[-2]);
2233 __ JumpIfSmi(rdx, &miss); 2237 __ JumpIfSmi(rdx, &miss);
2234 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 2238 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
2235 name, &miss); 2239 name, &miss);
2236 } else { 2240 } else {
2237 ASSERT(cell->value() == *function); 2241 ASSERT(cell->value() == *function);
2238 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 2242 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
2239 &miss); 2243 &miss);
2240 GenerateLoadFunctionFromCell(cell, function, &miss); 2244 GenerateLoadFunctionFromCell(cell, function, &miss);
2241 } 2245 }
2242 // Load the (only) argument into rax. 2246 // Load the (only) argument into rax.
2243 __ movq(rax, Operand(rsp, 1 * kPointerSize)); 2247 __ movq(rax, stack_arguments[-1]);
2244 2248
2245 // Check if the argument is a smi. 2249 // Check if the argument is a smi.
2246 Label not_smi; 2250 Label not_smi;
2247 STATIC_ASSERT(kSmiTag == 0); 2251 STATIC_ASSERT(kSmiTag == 0);
2248 __ JumpIfNotSmi(rax, &not_smi); 2252 __ JumpIfNotSmi(rax, &not_smi);
2249 __ SmiToInteger32(rax, rax); 2253 __ SmiToInteger32(rax, rax);
2250 2254
2251 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 2255 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
2252 // otherwise. 2256 // otherwise.
2253 __ movl(rbx, rax); 2257 __ movl(rbx, rax);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
2324 if (object->IsGlobalObject()) return Handle<Code>::null(); 2328 if (object->IsGlobalObject()) return Handle<Code>::null();
2325 if (!cell.is_null()) return Handle<Code>::null(); 2329 if (!cell.is_null()) return Handle<Code>::null();
2326 if (!object->IsJSObject()) return Handle<Code>::null(); 2330 if (!object->IsJSObject()) return Handle<Code>::null();
2327 int depth = optimization.GetPrototypeDepthOfExpectedType( 2331 int depth = optimization.GetPrototypeDepthOfExpectedType(
2328 Handle<JSObject>::cast(object), holder); 2332 Handle<JSObject>::cast(object), holder);
2329 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 2333 if (depth == kInvalidProtoDepth) return Handle<Code>::null();
2330 2334
2331 Label miss, miss_before_stack_reserved; 2335 Label miss, miss_before_stack_reserved;
2332 GenerateNameCheck(name, &miss_before_stack_reserved); 2336 GenerateNameCheck(name, &miss_before_stack_reserved);
2333 2337
2334 // Get the receiver from the stack.
2335 const int argc = arguments().immediate(); 2338 const int argc = arguments().immediate();
2336 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 2339 StackArguments stack_arguments(argc, 1);
2340 __ movq(rdx, stack_arguments.GetReceiver());
2337 2341
2338 // Check that the receiver isn't a smi. 2342 // Check that the receiver isn't a smi.
2339 __ JumpIfSmi(rdx, &miss_before_stack_reserved); 2343 __ JumpIfSmi(rdx, &miss_before_stack_reserved);
2340 2344
2341 Counters* counters = isolate()->counters(); 2345 Counters* counters = isolate()->counters();
2342 __ IncrementCounter(counters->call_const(), 1); 2346 __ IncrementCounter(counters->call_const(), 1);
2343 __ IncrementCounter(counters->call_const_fast_api(), 1); 2347 __ IncrementCounter(counters->call_const_fast_api(), 1);
2344 2348
2345 // Allocate space for v8::Arguments implicit values. Must be initialized 2349 // Allocate space for v8::Arguments implicit values. Must be initialized
2346 // before calling any runtime function. 2350 // before calling any runtime function.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2378 // rsp[0] : return address 2382 // rsp[0] : return address
2379 // rsp[8] : argument argc 2383 // rsp[8] : argument argc
2380 // rsp[16] : argument argc - 1 2384 // rsp[16] : argument argc - 1
2381 // ... 2385 // ...
2382 // rsp[argc * 8] : argument 1 2386 // rsp[argc * 8] : argument 1
2383 // rsp[(argc + 1) * 8] : argument 0 = receiver 2387 // rsp[(argc + 1) * 8] : argument 0 = receiver
2384 // ----------------------------------- 2388 // -----------------------------------
2385 Label miss; 2389 Label miss;
2386 GenerateNameCheck(name, &miss); 2390 GenerateNameCheck(name, &miss);
2387 2391
2388 // Get the receiver from the stack. 2392 StackArguments stack_arguments(arguments(), 1);
2389 const int argc = arguments().immediate(); 2393 __ movq(rdx, stack_arguments.GetReceiver());
2390 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
2391 2394
2392 // Check that the receiver isn't a smi. 2395 // Check that the receiver isn't a smi.
2393 if (check != NUMBER_CHECK) { 2396 if (check != NUMBER_CHECK) {
2394 __ JumpIfSmi(rdx, &miss); 2397 __ JumpIfSmi(rdx, &miss);
2395 } 2398 }
2396 2399
2397 // Make sure that it's okay not to patch the on stack receiver 2400 // Make sure that it's okay not to patch the on stack receiver
2398 // unless we're doing a receiver map check. 2401 // unless we're doing a receiver map check.
2399 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2402 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2400 2403
2401 Counters* counters = isolate()->counters(); 2404 Counters* counters = isolate()->counters();
2402 switch (check) { 2405 switch (check) {
2403 case RECEIVER_MAP_CHECK: 2406 case RECEIVER_MAP_CHECK:
2404 __ IncrementCounter(counters->call_const(), 1); 2407 __ IncrementCounter(counters->call_const(), 1);
2405 2408
2406 // Check that the maps haven't changed. 2409 // Check that the maps haven't changed.
2407 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, 2410 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax,
2408 rdi, name, &miss); 2411 rdi, name, &miss);
2409 2412
2410 // Patch the receiver on the stack with the global proxy if 2413 // Patch the receiver on the stack with the global proxy if
2411 // necessary. 2414 // necessary.
2412 if (object->IsGlobalObject()) { 2415 if (object->IsGlobalObject()) {
2413 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 2416 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
2414 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 2417 __ movq(stack_arguments.GetReceiver(), rdx);
2415 } 2418 }
2416 break; 2419 break;
2417 2420
2418 case STRING_CHECK: 2421 case STRING_CHECK:
2419 // Check that the object is a string. 2422 // Check that the object is a string.
2420 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); 2423 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax);
2421 __ j(above_equal, &miss); 2424 __ j(above_equal, &miss);
2422 // Check that the maps starting from the prototype haven't changed. 2425 // Check that the maps starting from the prototype haven't changed.
2423 GenerateDirectLoadGlobalFunctionPrototype( 2426 GenerateDirectLoadGlobalFunctionPrototype(
2424 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); 2427 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
2524 // rsp[0] : return address 2527 // rsp[0] : return address
2525 // rsp[8] : argument argc 2528 // rsp[8] : argument argc
2526 // rsp[16] : argument argc - 1 2529 // rsp[16] : argument argc - 1
2527 // ... 2530 // ...
2528 // rsp[argc * 8] : argument 1 2531 // rsp[argc * 8] : argument 1
2529 // rsp[(argc + 1) * 8] : argument 0 = receiver 2532 // rsp[(argc + 1) * 8] : argument 0 = receiver
2530 // ----------------------------------- 2533 // -----------------------------------
2531 Label miss; 2534 Label miss;
2532 GenerateNameCheck(name, &miss); 2535 GenerateNameCheck(name, &miss);
2533 2536
2534 // Get the number of arguments.
2535 const int argc = arguments().immediate();
2536 2537
2537 LookupResult lookup(isolate()); 2538 LookupResult lookup(isolate());
2538 LookupPostInterceptor(holder, name, &lookup); 2539 LookupPostInterceptor(holder, name, &lookup);
2539 2540
2540 // Get the receiver from the stack. 2541 // Get the receiver from the stack.
2541 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 2542 StackArguments stack_arguments(arguments(), 1);
2543 __ movq(rdx, stack_arguments.GetReceiver());
2542 2544
2543 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); 2545 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_);
2544 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, 2546 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax,
2545 &miss); 2547 &miss);
2546 2548
2547 // Restore receiver. 2549 // Restore receiver.
2548 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 2550 __ movq(rdx, stack_arguments.GetReceiver());
2549 2551
2550 // Check that the function really is a function. 2552 // Check that the function really is a function.
2551 __ JumpIfSmi(rax, &miss); 2553 __ JumpIfSmi(rax, &miss);
2552 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 2554 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2553 __ j(not_equal, &miss); 2555 __ j(not_equal, &miss);
2554 2556
2555 // Patch the receiver on the stack with the global proxy if 2557 // Patch the receiver on the stack with the global proxy if
2556 // necessary. 2558 // necessary.
2557 if (object->IsGlobalObject()) { 2559 if (object->IsGlobalObject()) {
2558 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 2560 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
2559 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 2561 __ movq(stack_arguments.GetReceiver(), rdx);
2560 } 2562 }
2561 2563
2562 // Invoke the function. 2564 // Invoke the function.
2563 __ movq(rdi, rax); 2565 __ movq(rdi, rax);
2564 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2566 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2565 ? CALL_AS_FUNCTION 2567 ? CALL_AS_FUNCTION
2566 : CALL_AS_METHOD; 2568 : CALL_AS_METHOD;
2567 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, 2569 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
2568 NullCallWrapper(), call_kind); 2570 NullCallWrapper(), call_kind);
2569 2571
(...skipping 26 matching lines...) Expand all
2596 Handle<Code> code = CompileCustomCall( 2598 Handle<Code> code = CompileCustomCall(
2597 object, holder, cell, function, Handle<String>::cast(name), 2599 object, holder, cell, function, Handle<String>::cast(name),
2598 Code::NORMAL); 2600 Code::NORMAL);
2599 // A null handle means bail out to the regular compiler code below. 2601 // A null handle means bail out to the regular compiler code below.
2600 if (!code.is_null()) return code; 2602 if (!code.is_null()) return code;
2601 } 2603 }
2602 2604
2603 Label miss; 2605 Label miss;
2604 GenerateNameCheck(name, &miss); 2606 GenerateNameCheck(name, &miss);
2605 2607
2606 // Get the number of arguments. 2608 StackArguments stack_arguments(arguments(), 1);
2607 const int argc = arguments().immediate();
2608 GenerateGlobalReceiverCheck(object, holder, name, &miss); 2609 GenerateGlobalReceiverCheck(object, holder, name, &miss);
2609 GenerateLoadFunctionFromCell(cell, function, &miss); 2610 GenerateLoadFunctionFromCell(cell, function, &miss);
2610 2611
2611 // Patch the receiver on the stack with the global proxy. 2612 // Patch the receiver on the stack with the global proxy.
2612 if (object->IsGlobalObject()) { 2613 if (object->IsGlobalObject()) {
2613 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 2614 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
2614 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 2615 __ movq(stack_arguments.GetReceiver(), rdx);
2615 } 2616 }
2616 2617
2617 // Set up the context (function already in rdi). 2618 // Set up the context (function already in rdi).
2618 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 2619 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
2619 2620
2620 // Jump to the cached code (tail call). 2621 // Jump to the cached code (tail call).
2621 Counters* counters = isolate()->counters(); 2622 Counters* counters = isolate()->counters();
2622 __ IncrementCounter(counters->call_global_inline(), 1); 2623 __ IncrementCounter(counters->call_global_inline(), 1);
2623 ParameterCount expected(function->shared()->formal_parameter_count()); 2624 ParameterCount expected(function->shared()->formal_parameter_count());
2624 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2625 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
(...skipping 889 matching lines...) Expand 10 before | Expand all | Expand 10 after
3514 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); 3515 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
3515 } 3516 }
3516 } 3517 }
3517 3518
3518 3519
3519 #undef __ 3520 #undef __
3520 3521
3521 } } // namespace v8::internal 3522 } } // namespace v8::internal
3522 3523
3523 #endif // V8_TARGET_ARCH_X64 3524 #endif // V8_TARGET_ARCH_X64
OLDNEW
« src/x64/macro-assembler-x64.h ('K') | « src/x64/macro-assembler-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698