OLD | NEW |
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 2052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2063 | 2063 |
2064 // receiver = iter; f = 'next'; arg = received; | 2064 // receiver = iter; f = 'next'; arg = received; |
2065 __ bind(&l_next); | 2065 __ bind(&l_next); |
2066 __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next" | 2066 __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next" |
2067 __ push(rcx); | 2067 __ push(rcx); |
2068 __ push(Operand(rsp, 2 * kPointerSize)); // iter | 2068 __ push(Operand(rsp, 2 * kPointerSize)); // iter |
2069 __ push(rax); // received | 2069 __ push(rax); // received |
2070 | 2070 |
2071 // result = receiver[f](arg); | 2071 // result = receiver[f](arg); |
2072 __ bind(&l_call); | 2072 __ bind(&l_call); |
2073 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 2073 __ movp(rdx, Operand(rsp, kPointerSize)); |
2074 CallIC(ic); | 2074 __ movp(rax, Operand(rsp, 2 * kPointerSize)); |
| 2075 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2076 CallIC(ic, NOT_CONTEXTUAL, TypeFeedbackId::None()); |
| 2077 __ movp(rdi, rax); |
| 2078 __ movp(Operand(rsp, 2 * kPointerSize), rdi); |
| 2079 CallFunctionStub stub(1, CALL_AS_METHOD); |
| 2080 __ CallStub(&stub); |
| 2081 |
2075 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2082 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2076 __ Drop(1); // The key is still on the stack; drop it. | 2083 __ Drop(1); // The function is still on the stack; drop it. |
2077 | 2084 |
2078 // if (!result.done) goto l_try; | 2085 // if (!result.done) goto l_try; |
2079 __ bind(&l_loop); | 2086 __ bind(&l_loop); |
2080 __ push(rax); // save result | 2087 __ push(rax); // save result |
2081 __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done" | 2088 __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done" |
2082 CallLoadIC(NOT_CONTEXTUAL); // result.done in rax | 2089 CallLoadIC(NOT_CONTEXTUAL); // result.done in rax |
2083 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 2090 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
2084 CallIC(bool_ic); | 2091 CallIC(bool_ic); |
2085 __ testq(result_register(), result_register()); | 2092 __ testq(result_register(), result_register()); |
2086 __ j(zero, &l_try); | 2093 __ j(zero, &l_try); |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2531 | 2538 |
2532 void FullCodeGenerator::CallIC(Handle<Code> code, | 2539 void FullCodeGenerator::CallIC(Handle<Code> code, |
2533 ContextualMode mode, | 2540 ContextualMode mode, |
2534 TypeFeedbackId ast_id) { | 2541 TypeFeedbackId ast_id) { |
2535 ic_total_count_++; | 2542 ic_total_count_++; |
2536 ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); | 2543 ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); |
2537 __ call(code, RelocInfo::CODE_TARGET, ast_id); | 2544 __ call(code, RelocInfo::CODE_TARGET, ast_id); |
2538 } | 2545 } |
2539 | 2546 |
2540 | 2547 |
2541 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2548 // Code common for calls using the IC. |
2542 Handle<Object> name, | 2549 void FullCodeGenerator::EmitCallWithIC(Call* expr) { |
2543 ContextualMode mode) { | 2550 Expression* callee = expr->expression(); |
2544 // Code common for calls using the IC. | |
2545 ZoneList<Expression*>* args = expr->arguments(); | 2551 ZoneList<Expression*>* args = expr->arguments(); |
2546 int arg_count = args->length(); | 2552 int arg_count = args->length(); |
| 2553 |
| 2554 CallFunctionFlags flags; |
| 2555 // Get the target function; |
| 2556 if (callee->IsVariableProxy()) { |
| 2557 { StackValueContext context(this); |
| 2558 EmitVariableLoad(callee->AsVariableProxy()); |
| 2559 PrepareForBailout(callee, NO_REGISTERS); |
| 2560 } |
| 2561 // Push undefined as receiver. This is patched in the method prologue if it |
| 2562 // is a classic mode method. |
| 2563 __ Push(isolate()->factory()->undefined_value()); |
| 2564 flags = NO_CALL_FUNCTION_FLAGS; |
| 2565 } else { |
| 2566 // Load the function from the receiver. |
| 2567 ASSERT(callee->IsProperty()); |
| 2568 __ movp(rax, Operand(rsp, 0)); |
| 2569 EmitNamedPropertyLoad(callee->AsProperty()); |
| 2570 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2571 // Push the target function under the receiver. |
| 2572 __ push(Operand(rsp, 0)); |
| 2573 __ movp(Operand(rsp, kPointerSize), rax); |
| 2574 flags = CALL_AS_METHOD; |
| 2575 } |
| 2576 |
| 2577 // Load the arguments. |
2547 { PreservePositionScope scope(masm()->positions_recorder()); | 2578 { PreservePositionScope scope(masm()->positions_recorder()); |
2548 for (int i = 0; i < arg_count; i++) { | 2579 for (int i = 0; i < arg_count; i++) { |
2549 VisitForStackValue(args->at(i)); | 2580 VisitForStackValue(args->at(i)); |
2550 } | 2581 } |
2551 __ Move(rcx, name); | |
2552 } | 2582 } |
| 2583 |
2553 // Record source position for debugger. | 2584 // Record source position for debugger. |
2554 SetSourcePosition(expr->position()); | 2585 SetSourcePosition(expr->position()); |
2555 // Call the IC initialization code. | 2586 CallFunctionStub stub(arg_count, flags); |
2556 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); | 2587 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); |
2557 TypeFeedbackId ast_id = mode == CONTEXTUAL | 2588 __ CallStub(&stub); |
2558 ? TypeFeedbackId::None() | 2589 |
2559 : expr->CallFeedbackId(); | |
2560 CallIC(ic, mode, ast_id); | |
2561 RecordJSReturnSite(expr); | 2590 RecordJSReturnSite(expr); |
| 2591 |
2562 // Restore context register. | 2592 // Restore context register. |
2563 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2593 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2564 context()->Plug(rax); | 2594 |
| 2595 context()->DropAndPlug(1, rax); |
2565 } | 2596 } |
2566 | 2597 |
2567 | 2598 |
| 2599 // Common code for calls using the IC. |
2568 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2600 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
2569 Expression* key) { | 2601 Expression* key) { |
2570 // Load the key. | 2602 // Load the key. |
2571 VisitForAccumulatorValue(key); | 2603 VisitForAccumulatorValue(key); |
2572 | 2604 |
2573 // Swap the name of the function and the receiver on the stack to follow | 2605 Expression* callee = expr->expression(); |
2574 // the calling convention for call ICs. | 2606 ZoneList<Expression*>* args = expr->arguments(); |
2575 __ pop(rcx); | 2607 int arg_count = args->length(); |
2576 __ push(rax); | 2608 |
2577 __ push(rcx); | 2609 // Load the function from the receiver. |
| 2610 ASSERT(callee->IsProperty()); |
| 2611 __ movp(rdx, Operand(rsp, 0)); |
| 2612 EmitKeyedPropertyLoad(callee->AsProperty()); |
| 2613 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2614 |
| 2615 // Push the target function under the receiver. |
| 2616 __ push(Operand(rsp, 0)); |
| 2617 __ movp(Operand(rsp, kPointerSize), rax); |
2578 | 2618 |
2579 // Load the arguments. | 2619 // Load the arguments. |
2580 ZoneList<Expression*>* args = expr->arguments(); | |
2581 int arg_count = args->length(); | |
2582 { PreservePositionScope scope(masm()->positions_recorder()); | 2620 { PreservePositionScope scope(masm()->positions_recorder()); |
2583 for (int i = 0; i < arg_count; i++) { | 2621 for (int i = 0; i < arg_count; i++) { |
2584 VisitForStackValue(args->at(i)); | 2622 VisitForStackValue(args->at(i)); |
2585 } | 2623 } |
2586 } | 2624 } |
| 2625 |
2587 // Record source position for debugger. | 2626 // Record source position for debugger. |
2588 SetSourcePosition(expr->position()); | 2627 SetSourcePosition(expr->position()); |
2589 // Call the IC initialization code. | 2628 CallFunctionStub stub(arg_count, CALL_AS_METHOD); |
2590 Handle<Code> ic = | 2629 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); |
2591 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2630 __ CallStub(&stub); |
2592 __ movp(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. | 2631 |
2593 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); | |
2594 RecordJSReturnSite(expr); | 2632 RecordJSReturnSite(expr); |
2595 // Restore context register. | 2633 // Restore context register. |
2596 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2634 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2597 context()->DropAndPlug(1, rax); // Drop the key still on the stack. | 2635 |
| 2636 context()->DropAndPlug(1, rax); |
2598 } | 2637 } |
2599 | 2638 |
2600 | 2639 |
2601 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2640 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
2602 // Code common for calls using the call stub. | 2641 // Code common for calls using the call stub. |
2603 ZoneList<Expression*>* args = expr->arguments(); | 2642 ZoneList<Expression*>* args = expr->arguments(); |
2604 int arg_count = args->length(); | 2643 int arg_count = args->length(); |
2605 { PreservePositionScope scope(masm()->positions_recorder()); | 2644 { PreservePositionScope scope(masm()->positions_recorder()); |
2606 for (int i = 0; i < arg_count; i++) { | 2645 for (int i = 0; i < arg_count; i++) { |
2607 VisitForStackValue(args->at(i)); | 2646 VisitForStackValue(args->at(i)); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2690 // Record source position for debugger. | 2729 // Record source position for debugger. |
2691 SetSourcePosition(expr->position()); | 2730 SetSourcePosition(expr->position()); |
2692 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); | 2731 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); |
2693 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); | 2732 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); |
2694 __ CallStub(&stub); | 2733 __ CallStub(&stub); |
2695 RecordJSReturnSite(expr); | 2734 RecordJSReturnSite(expr); |
2696 // Restore context register. | 2735 // Restore context register. |
2697 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2736 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2698 context()->DropAndPlug(1, rax); | 2737 context()->DropAndPlug(1, rax); |
2699 } else if (call_type == Call::GLOBAL_CALL) { | 2738 } else if (call_type == Call::GLOBAL_CALL) { |
2700 // Call to a global variable. Push global object as receiver for the | 2739 EmitCallWithIC(expr); |
2701 // call IC lookup. | 2740 |
2702 __ push(GlobalObjectOperand()); | |
2703 VariableProxy* proxy = callee->AsVariableProxy(); | |
2704 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); | |
2705 } else if (call_type == Call::LOOKUP_SLOT_CALL) { | 2741 } else if (call_type == Call::LOOKUP_SLOT_CALL) { |
2706 // Call to a lookup slot (dynamically introduced variable). | 2742 // Call to a lookup slot (dynamically introduced variable). |
2707 VariableProxy* proxy = callee->AsVariableProxy(); | 2743 VariableProxy* proxy = callee->AsVariableProxy(); |
2708 Label slow, done; | 2744 Label slow, done; |
2709 | 2745 |
2710 { PreservePositionScope scope(masm()->positions_recorder()); | 2746 { PreservePositionScope scope(masm()->positions_recorder()); |
2711 // Generate code for loading from variables potentially shadowed by | 2747 // Generate code for loading from variables potentially shadowed by |
2712 // eval-introduced variables. | 2748 // eval-introduced variables. |
2713 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2749 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
2714 } | 2750 } |
(...skipping 22 matching lines...) Expand all Loading... |
2737 | 2773 |
2738 // The receiver is either the global receiver or an object found by | 2774 // The receiver is either the global receiver or an object found by |
2739 // LoadContextSlot. | 2775 // LoadContextSlot. |
2740 EmitCallWithStub(expr); | 2776 EmitCallWithStub(expr); |
2741 } else if (call_type == Call::PROPERTY_CALL) { | 2777 } else if (call_type == Call::PROPERTY_CALL) { |
2742 Property* property = callee->AsProperty(); | 2778 Property* property = callee->AsProperty(); |
2743 { PreservePositionScope scope(masm()->positions_recorder()); | 2779 { PreservePositionScope scope(masm()->positions_recorder()); |
2744 VisitForStackValue(property->obj()); | 2780 VisitForStackValue(property->obj()); |
2745 } | 2781 } |
2746 if (property->key()->IsPropertyName()) { | 2782 if (property->key()->IsPropertyName()) { |
2747 EmitCallWithIC(expr, | 2783 EmitCallWithIC(expr); |
2748 property->key()->AsLiteral()->value(), | |
2749 NOT_CONTEXTUAL); | |
2750 } else { | 2784 } else { |
2751 EmitKeyedCallWithIC(expr, property->key()); | 2785 EmitKeyedCallWithIC(expr, property->key()); |
2752 } | 2786 } |
2753 } else { | 2787 } else { |
2754 ASSERT(call_type == Call::OTHER_CALL); | 2788 ASSERT(call_type == Call::OTHER_CALL); |
2755 // Call to an arbitrary expression not handled specially above. | 2789 // Call to an arbitrary expression not handled specially above. |
2756 { PreservePositionScope scope(masm()->positions_recorder()); | 2790 { PreservePositionScope scope(masm()->positions_recorder()); |
2757 VisitForStackValue(callee); | 2791 VisitForStackValue(callee); |
2758 } | 2792 } |
2759 __ PushRoot(Heap::kUndefinedValueRootIndex); | 2793 __ PushRoot(Heap::kUndefinedValueRootIndex); |
(...skipping 1324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4084 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 4118 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
4085 Handle<String> name = expr->name(); | 4119 Handle<String> name = expr->name(); |
4086 if (name->length() > 0 && name->Get(0) == '_') { | 4120 if (name->length() > 0 && name->Get(0) == '_') { |
4087 Comment cmnt(masm_, "[ InlineRuntimeCall"); | 4121 Comment cmnt(masm_, "[ InlineRuntimeCall"); |
4088 EmitInlineRuntimeCall(expr); | 4122 EmitInlineRuntimeCall(expr); |
4089 return; | 4123 return; |
4090 } | 4124 } |
4091 | 4125 |
4092 Comment cmnt(masm_, "[ CallRuntime"); | 4126 Comment cmnt(masm_, "[ CallRuntime"); |
4093 ZoneList<Expression*>* args = expr->arguments(); | 4127 ZoneList<Expression*>* args = expr->arguments(); |
| 4128 int arg_count = args->length(); |
4094 | 4129 |
4095 if (expr->is_jsruntime()) { | 4130 if (expr->is_jsruntime()) { |
4096 // Prepare for calling JS runtime function. | 4131 // Push the builtins object as receiver. |
4097 __ movp(rax, GlobalObjectOperand()); | 4132 __ movp(rax, GlobalObjectOperand()); |
4098 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); | 4133 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); |
4099 } | |
4100 | 4134 |
4101 // Push the arguments ("left-to-right"). | 4135 // Load the function from the receiver. |
4102 int arg_count = args->length(); | 4136 __ movp(rax, Operand(rsp, 0)); |
4103 for (int i = 0; i < arg_count; i++) { | 4137 __ Move(rcx, expr->name()); |
4104 VisitForStackValue(args->at(i)); | 4138 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); |
4105 } | |
4106 | 4139 |
4107 if (expr->is_jsruntime()) { | 4140 // Push the target function under the receiver. |
4108 // Call the JS runtime function using a call IC. | 4141 __ push(Operand(rsp, 0)); |
4109 __ Move(rcx, expr->name()); | 4142 __ movp(Operand(rsp, kPointerSize), rax); |
4110 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); | 4143 |
4111 CallIC(ic, NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); | 4144 // Push the arguments ("left-to-right"). |
| 4145 for (int i = 0; i < arg_count; i++) { |
| 4146 VisitForStackValue(args->at(i)); |
| 4147 } |
| 4148 |
| 4149 // Record source position of the IC call. |
| 4150 SetSourcePosition(expr->position()); |
| 4151 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); |
| 4152 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); |
| 4153 __ CallStub(&stub); |
| 4154 |
4112 // Restore context register. | 4155 // Restore context register. |
4113 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 4156 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 4157 context()->DropAndPlug(1, rax); |
| 4158 |
4114 } else { | 4159 } else { |
| 4160 // Push the arguments ("left-to-right"). |
| 4161 for (int i = 0; i < arg_count; i++) { |
| 4162 VisitForStackValue(args->at(i)); |
| 4163 } |
| 4164 |
| 4165 // Call the C runtime. |
4115 __ CallRuntime(expr->function(), arg_count); | 4166 __ CallRuntime(expr->function(), arg_count); |
| 4167 context()->Plug(rax); |
4116 } | 4168 } |
4117 context()->Plug(rax); | |
4118 } | 4169 } |
4119 | 4170 |
4120 | 4171 |
4121 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 4172 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
4122 switch (expr->op()) { | 4173 switch (expr->op()) { |
4123 case Token::DELETE: { | 4174 case Token::DELETE: { |
4124 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4175 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
4125 Property* property = expr->expression()->AsProperty(); | 4176 Property* property = expr->expression()->AsProperty(); |
4126 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4177 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
4127 | 4178 |
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4856 | 4907 |
4857 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4908 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
4858 Assembler::target_address_at(call_target_address)); | 4909 Assembler::target_address_at(call_target_address)); |
4859 return OSR_AFTER_STACK_CHECK; | 4910 return OSR_AFTER_STACK_CHECK; |
4860 } | 4911 } |
4861 | 4912 |
4862 | 4913 |
4863 } } // namespace v8::internal | 4914 } } // namespace v8::internal |
4864 | 4915 |
4865 #endif // V8_TARGET_ARCH_X64 | 4916 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |