| 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 |